xref: /OK3568_Linux_fs/kernel/drivers/net/dsa/mv88e6xxx/global2_avb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Marvell 88E6xxx Switch Global 2 Registers support
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2008 Marvell Semiconductor
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
8*4882a593Smuzhiyun  *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Copyright (c) 2017 National Instruments
11*4882a593Smuzhiyun  *	Brandon Streiff <brandon.streiff@ni.com>
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/bitfield.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "global2.h"
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun /* Offset 0x16: AVB Command Register
19*4882a593Smuzhiyun  * Offset 0x17: AVB Data Register
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * There are two different versions of this register interface:
22*4882a593Smuzhiyun  *    "6352": 3-bit "op" field, 4-bit "port" field.
23*4882a593Smuzhiyun  *    "6390": 2-bit "op" field, 5-bit "port" field.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * The "op" codes are different between the two, as well as the special
26*4882a593Smuzhiyun  * port fields for global PTP and TAI configuration.
27*4882a593Smuzhiyun  */
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words.
30*4882a593Smuzhiyun  * The hardware supports snapshotting up to four contiguous registers.
31*4882a593Smuzhiyun  */
mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip * chip)32*4882a593Smuzhiyun static int mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip *chip)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	int bit = __bf_shf(MV88E6352_G2_AVB_CMD_BUSY);
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	return mv88e6xxx_g2_wait_bit(chip, MV88E6352_G2_AVB_CMD, bit, 0);
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip * chip,u16 readop,u16 * data,int len)39*4882a593Smuzhiyun static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip *chip, u16 readop,
40*4882a593Smuzhiyun 				 u16 *data, int len)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	int err;
43*4882a593Smuzhiyun 	int i;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	err = mv88e6xxx_g2_avb_wait(chip);
46*4882a593Smuzhiyun 	if (err)
47*4882a593Smuzhiyun 		return err;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	/* Hardware can only snapshot four words. */
50*4882a593Smuzhiyun 	if (len > 4)
51*4882a593Smuzhiyun 		return -E2BIG;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
54*4882a593Smuzhiyun 				 MV88E6352_G2_AVB_CMD_BUSY | readop);
55*4882a593Smuzhiyun 	if (err)
56*4882a593Smuzhiyun 		return err;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	err = mv88e6xxx_g2_avb_wait(chip);
59*4882a593Smuzhiyun 	if (err)
60*4882a593Smuzhiyun 		return err;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	for (i = 0; i < len; ++i) {
63*4882a593Smuzhiyun 		err = mv88e6xxx_g2_read(chip, MV88E6352_G2_AVB_DATA,
64*4882a593Smuzhiyun 					&data[i]);
65*4882a593Smuzhiyun 		if (err)
66*4882a593Smuzhiyun 			return err;
67*4882a593Smuzhiyun 	}
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	return 0;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun /* mv88e6xxx_g2_avb_write -- Write one 16-bit word. */
mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip * chip,u16 writeop,u16 data)73*4882a593Smuzhiyun static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip *chip, u16 writeop,
74*4882a593Smuzhiyun 				  u16 data)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	int err;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	err = mv88e6xxx_g2_avb_wait(chip);
79*4882a593Smuzhiyun 	if (err)
80*4882a593Smuzhiyun 		return err;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_DATA, data);
83*4882a593Smuzhiyun 	if (err)
84*4882a593Smuzhiyun 		return err;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
87*4882a593Smuzhiyun 				 MV88E6352_G2_AVB_CMD_BUSY | writeop);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	return mv88e6xxx_g2_avb_wait(chip);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip * chip,int port,int addr,u16 * data,int len)92*4882a593Smuzhiyun static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
93*4882a593Smuzhiyun 					  int port, int addr, u16 *data,
94*4882a593Smuzhiyun 					  int len)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	u16 readop = (len == 1 ? MV88E6352_G2_AVB_CMD_OP_READ :
97*4882a593Smuzhiyun 				 MV88E6352_G2_AVB_CMD_OP_READ_INCR) |
98*4882a593Smuzhiyun 		     (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
99*4882a593Smuzhiyun 		     addr;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	return mv88e6xxx_g2_avb_read(chip, readop, data, len);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip * chip,int port,int addr,u16 data)104*4882a593Smuzhiyun static int mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
105*4882a593Smuzhiyun 					   int port, int addr, u16 data)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	u16 writeop = MV88E6352_G2_AVB_CMD_OP_WRITE | (port << 8) |
108*4882a593Smuzhiyun 		      (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	return mv88e6xxx_g2_avb_write(chip, writeop, data);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)113*4882a593Smuzhiyun static int mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
114*4882a593Smuzhiyun 				     u16 *data, int len)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	return mv88e6352_g2_avb_port_ptp_read(chip,
117*4882a593Smuzhiyun 					MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
118*4882a593Smuzhiyun 					addr, data, len);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip * chip,int addr,u16 data)121*4882a593Smuzhiyun static int mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
122*4882a593Smuzhiyun 				      u16 data)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	return mv88e6352_g2_avb_port_ptp_write(chip,
125*4882a593Smuzhiyun 					MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
126*4882a593Smuzhiyun 					addr, data);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)129*4882a593Smuzhiyun static int mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
130*4882a593Smuzhiyun 				     u16 *data, int len)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	return mv88e6352_g2_avb_port_ptp_read(chip,
133*4882a593Smuzhiyun 					MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
134*4882a593Smuzhiyun 					addr, data, len);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip * chip,int addr,u16 data)137*4882a593Smuzhiyun static int mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
138*4882a593Smuzhiyun 				      u16 data)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	return mv88e6352_g2_avb_port_ptp_write(chip,
141*4882a593Smuzhiyun 					MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
142*4882a593Smuzhiyun 					addr, data);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {
146*4882a593Smuzhiyun 	.port_ptp_read		= mv88e6352_g2_avb_port_ptp_read,
147*4882a593Smuzhiyun 	.port_ptp_write		= mv88e6352_g2_avb_port_ptp_write,
148*4882a593Smuzhiyun 	.ptp_read		= mv88e6352_g2_avb_ptp_read,
149*4882a593Smuzhiyun 	.ptp_write		= mv88e6352_g2_avb_ptp_write,
150*4882a593Smuzhiyun 	.tai_read		= mv88e6352_g2_avb_tai_read,
151*4882a593Smuzhiyun 	.tai_write		= mv88e6352_g2_avb_tai_write,
152*4882a593Smuzhiyun };
153*4882a593Smuzhiyun 
mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)154*4882a593Smuzhiyun static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
155*4882a593Smuzhiyun 				     u16 *data, int len)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	return mv88e6352_g2_avb_port_ptp_read(chip,
158*4882a593Smuzhiyun 					MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
159*4882a593Smuzhiyun 					addr, data, len);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip * chip,int addr,u16 data)162*4882a593Smuzhiyun static int mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
163*4882a593Smuzhiyun 				      u16 data)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	return mv88e6352_g2_avb_port_ptp_write(chip,
166*4882a593Smuzhiyun 					MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
167*4882a593Smuzhiyun 					addr, data);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {
171*4882a593Smuzhiyun 	.port_ptp_read		= mv88e6352_g2_avb_port_ptp_read,
172*4882a593Smuzhiyun 	.port_ptp_write		= mv88e6352_g2_avb_port_ptp_write,
173*4882a593Smuzhiyun 	.ptp_read		= mv88e6352_g2_avb_ptp_read,
174*4882a593Smuzhiyun 	.ptp_write		= mv88e6352_g2_avb_ptp_write,
175*4882a593Smuzhiyun 	.tai_read		= mv88e6165_g2_avb_tai_read,
176*4882a593Smuzhiyun 	.tai_write		= mv88e6165_g2_avb_tai_write,
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip * chip,int port,int addr,u16 * data,int len)179*4882a593Smuzhiyun static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
180*4882a593Smuzhiyun 					  int port, int addr, u16 *data,
181*4882a593Smuzhiyun 					  int len)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	u16 readop = (len == 1 ? MV88E6390_G2_AVB_CMD_OP_READ :
184*4882a593Smuzhiyun 				 MV88E6390_G2_AVB_CMD_OP_READ_INCR) |
185*4882a593Smuzhiyun 		     (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
186*4882a593Smuzhiyun 		     addr;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	return mv88e6xxx_g2_avb_read(chip, readop, data, len);
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip * chip,int port,int addr,u16 data)191*4882a593Smuzhiyun static int mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
192*4882a593Smuzhiyun 					   int port, int addr, u16 data)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	u16 writeop = MV88E6390_G2_AVB_CMD_OP_WRITE | (port << 8) |
195*4882a593Smuzhiyun 		      (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return mv88e6xxx_g2_avb_write(chip, writeop, data);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)200*4882a593Smuzhiyun static int mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
201*4882a593Smuzhiyun 				     u16 *data, int len)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	return mv88e6390_g2_avb_port_ptp_read(chip,
204*4882a593Smuzhiyun 					MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
205*4882a593Smuzhiyun 					addr, data, len);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip * chip,int addr,u16 data)208*4882a593Smuzhiyun static int mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
209*4882a593Smuzhiyun 				      u16 data)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	return mv88e6390_g2_avb_port_ptp_write(chip,
212*4882a593Smuzhiyun 					MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
213*4882a593Smuzhiyun 					addr, data);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)216*4882a593Smuzhiyun static int mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
217*4882a593Smuzhiyun 				     u16 *data, int len)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	return mv88e6390_g2_avb_port_ptp_read(chip,
220*4882a593Smuzhiyun 					MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
221*4882a593Smuzhiyun 					addr, data, len);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun 
mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip * chip,int addr,u16 data)224*4882a593Smuzhiyun static int mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
225*4882a593Smuzhiyun 				      u16 data)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	return mv88e6390_g2_avb_port_ptp_write(chip,
228*4882a593Smuzhiyun 					MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
229*4882a593Smuzhiyun 					addr, data);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun const struct mv88e6xxx_avb_ops mv88e6390_avb_ops = {
233*4882a593Smuzhiyun 	.port_ptp_read		= mv88e6390_g2_avb_port_ptp_read,
234*4882a593Smuzhiyun 	.port_ptp_write		= mv88e6390_g2_avb_port_ptp_write,
235*4882a593Smuzhiyun 	.ptp_read		= mv88e6390_g2_avb_ptp_read,
236*4882a593Smuzhiyun 	.ptp_write		= mv88e6390_g2_avb_ptp_write,
237*4882a593Smuzhiyun 	.tai_read		= mv88e6390_g2_avb_tai_read,
238*4882a593Smuzhiyun 	.tai_write		= mv88e6390_g2_avb_tai_write,
239*4882a593Smuzhiyun };
240