1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88E6xxx Switch Global 2 Registers support
5 * Copyright (c) 2008 Marvell Semiconductor
7 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
8 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
10 * Copyright (c) 2017 National Instruments
11 * Brandon Streiff <brandon.streiff@ni.com>
14 #include <linux/bitfield.h>
18 /* Offset 0x16: AVB Command Register
19 * Offset 0x17: AVB Data Register
21 * There are two different versions of this register interface:
22 * "6352": 3-bit "op" field, 4-bit "port" field.
23 * "6390": 2-bit "op" field, 5-bit "port" field.
25 * The "op" codes are different between the two, as well as the special
26 * port fields for global PTP and TAI configuration.
29 /* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words.
30 * The hardware supports snapshotting up to four contiguous registers.
32 static int mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip
*chip
)
34 int bit
= __bf_shf(MV88E6352_G2_AVB_CMD_BUSY
);
36 return mv88e6xxx_g2_wait_bit(chip
, MV88E6352_G2_AVB_CMD
, bit
, 0);
39 static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip
*chip
, u16 readop
,
45 err
= mv88e6xxx_g2_avb_wait(chip
);
49 /* Hardware can only snapshot four words. */
53 err
= mv88e6xxx_g2_write(chip
, MV88E6352_G2_AVB_CMD
,
54 MV88E6352_G2_AVB_CMD_BUSY
| readop
);
58 err
= mv88e6xxx_g2_avb_wait(chip
);
62 for (i
= 0; i
< len
; ++i
) {
63 err
= mv88e6xxx_g2_read(chip
, MV88E6352_G2_AVB_DATA
,
72 /* mv88e6xxx_g2_avb_write -- Write one 16-bit word. */
73 static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip
*chip
, u16 writeop
,
78 err
= mv88e6xxx_g2_avb_wait(chip
);
82 err
= mv88e6xxx_g2_write(chip
, MV88E6352_G2_AVB_DATA
, data
);
86 err
= mv88e6xxx_g2_write(chip
, MV88E6352_G2_AVB_CMD
,
87 MV88E6352_G2_AVB_CMD_BUSY
| writeop
);
89 return mv88e6xxx_g2_avb_wait(chip
);
92 static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip
*chip
,
93 int port
, int addr
, u16
*data
,
96 u16 readop
= (len
== 1 ? MV88E6352_G2_AVB_CMD_OP_READ
:
97 MV88E6352_G2_AVB_CMD_OP_READ_INCR
) |
98 (port
<< 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP
<< 5) |
101 return mv88e6xxx_g2_avb_read(chip
, readop
, data
, len
);
104 static int mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip
*chip
,
105 int port
, int addr
, u16 data
)
107 u16 writeop
= MV88E6352_G2_AVB_CMD_OP_WRITE
| (port
<< 8) |
108 (MV88E6352_G2_AVB_CMD_BLOCK_PTP
<< 5) | addr
;
110 return mv88e6xxx_g2_avb_write(chip
, writeop
, data
);
113 static int mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip
*chip
, int addr
,
116 return mv88e6352_g2_avb_port_ptp_read(chip
,
117 MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL
,
121 static int mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip
*chip
, int addr
,
124 return mv88e6352_g2_avb_port_ptp_write(chip
,
125 MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL
,
129 static int mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip
*chip
, int addr
,
132 return mv88e6352_g2_avb_port_ptp_read(chip
,
133 MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL
,
137 static int mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip
*chip
, int addr
,
140 return mv88e6352_g2_avb_port_ptp_write(chip
,
141 MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL
,
145 const struct mv88e6xxx_avb_ops mv88e6352_avb_ops
= {
146 .port_ptp_read
= mv88e6352_g2_avb_port_ptp_read
,
147 .port_ptp_write
= mv88e6352_g2_avb_port_ptp_write
,
148 .ptp_read
= mv88e6352_g2_avb_ptp_read
,
149 .ptp_write
= mv88e6352_g2_avb_ptp_write
,
150 .tai_read
= mv88e6352_g2_avb_tai_read
,
151 .tai_write
= mv88e6352_g2_avb_tai_write
,
154 static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip
*chip
, int addr
,
157 return mv88e6352_g2_avb_port_ptp_read(chip
,
158 MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL
,
162 static int mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip
*chip
, int addr
,
165 return mv88e6352_g2_avb_port_ptp_write(chip
,
166 MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL
,
170 const struct mv88e6xxx_avb_ops mv88e6165_avb_ops
= {
171 .port_ptp_read
= mv88e6352_g2_avb_port_ptp_read
,
172 .port_ptp_write
= mv88e6352_g2_avb_port_ptp_write
,
173 .ptp_read
= mv88e6352_g2_avb_ptp_read
,
174 .ptp_write
= mv88e6352_g2_avb_ptp_write
,
175 .tai_read
= mv88e6165_g2_avb_tai_read
,
176 .tai_write
= mv88e6165_g2_avb_tai_write
,
179 static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip
*chip
,
180 int port
, int addr
, u16
*data
,
183 u16 readop
= (len
== 1 ? MV88E6390_G2_AVB_CMD_OP_READ
:
184 MV88E6390_G2_AVB_CMD_OP_READ_INCR
) |
185 (port
<< 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP
<< 5) |
188 return mv88e6xxx_g2_avb_read(chip
, readop
, data
, len
);
191 static int mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip
*chip
,
192 int port
, int addr
, u16 data
)
194 u16 writeop
= MV88E6390_G2_AVB_CMD_OP_WRITE
| (port
<< 8) |
195 (MV88E6352_G2_AVB_CMD_BLOCK_PTP
<< 5) | addr
;
197 return mv88e6xxx_g2_avb_write(chip
, writeop
, data
);
200 static int mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip
*chip
, int addr
,
203 return mv88e6390_g2_avb_port_ptp_read(chip
,
204 MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL
,
208 static int mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip
*chip
, int addr
,
211 return mv88e6390_g2_avb_port_ptp_write(chip
,
212 MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL
,
216 static int mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip
*chip
, int addr
,
219 return mv88e6390_g2_avb_port_ptp_read(chip
,
220 MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL
,
224 static int mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip
*chip
, int addr
,
227 return mv88e6390_g2_avb_port_ptp_write(chip
,
228 MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL
,
232 const struct mv88e6xxx_avb_ops mv88e6390_avb_ops
= {
233 .port_ptp_read
= mv88e6390_g2_avb_port_ptp_read
,
234 .port_ptp_write
= mv88e6390_g2_avb_port_ptp_write
,
235 .ptp_read
= mv88e6390_g2_avb_ptp_read
,
236 .ptp_write
= mv88e6390_g2_avb_ptp_write
,
237 .tai_read
= mv88e6390_g2_avb_tai_read
,
238 .tai_write
= mv88e6390_g2_avb_tai_write
,