12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20d632c3dSBrandon Streiff /*
30d632c3dSBrandon Streiff  * Marvell 88E6xxx Switch Global 2 Registers support
40d632c3dSBrandon Streiff  *
50d632c3dSBrandon Streiff  * Copyright (c) 2008 Marvell Semiconductor
60d632c3dSBrandon Streiff  *
70d632c3dSBrandon Streiff  * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
80d632c3dSBrandon Streiff  *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
90d632c3dSBrandon Streiff  *
100d632c3dSBrandon Streiff  * Copyright (c) 2017 National Instruments
110d632c3dSBrandon Streiff  *	Brandon Streiff <brandon.streiff@ni.com>
120d632c3dSBrandon Streiff  */
130d632c3dSBrandon Streiff 
1428ae1e96SVivien Didelot #include <linux/bitfield.h>
1528ae1e96SVivien Didelot 
160d632c3dSBrandon Streiff #include "global2.h"
170d632c3dSBrandon Streiff 
180d632c3dSBrandon Streiff /* Offset 0x16: AVB Command Register
190d632c3dSBrandon Streiff  * Offset 0x17: AVB Data Register
200d632c3dSBrandon Streiff  *
210d632c3dSBrandon Streiff  * There are two different versions of this register interface:
220d632c3dSBrandon Streiff  *    "6352": 3-bit "op" field, 4-bit "port" field.
230d632c3dSBrandon Streiff  *    "6390": 2-bit "op" field, 5-bit "port" field.
240d632c3dSBrandon Streiff  *
250d632c3dSBrandon Streiff  * The "op" codes are different between the two, as well as the special
260d632c3dSBrandon Streiff  * port fields for global PTP and TAI configuration.
270d632c3dSBrandon Streiff  */
280d632c3dSBrandon Streiff 
290d632c3dSBrandon Streiff /* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words.
300d632c3dSBrandon Streiff  * The hardware supports snapshotting up to four contiguous registers.
310d632c3dSBrandon Streiff  */
mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip * chip)3228ae1e96SVivien Didelot static int mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip *chip)
3328ae1e96SVivien Didelot {
3428ae1e96SVivien Didelot 	int bit = __bf_shf(MV88E6352_G2_AVB_CMD_BUSY);
3528ae1e96SVivien Didelot 
3628ae1e96SVivien Didelot 	return mv88e6xxx_g2_wait_bit(chip, MV88E6352_G2_AVB_CMD, bit, 0);
3728ae1e96SVivien Didelot }
3828ae1e96SVivien Didelot 
mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip * chip,u16 readop,u16 * data,int len)390d632c3dSBrandon Streiff static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip *chip, u16 readop,
400d632c3dSBrandon Streiff 				 u16 *data, int len)
410d632c3dSBrandon Streiff {
420d632c3dSBrandon Streiff 	int err;
430d632c3dSBrandon Streiff 	int i;
440d632c3dSBrandon Streiff 
4528ae1e96SVivien Didelot 	err = mv88e6xxx_g2_avb_wait(chip);
4628ae1e96SVivien Didelot 	if (err)
4728ae1e96SVivien Didelot 		return err;
4828ae1e96SVivien Didelot 
490d632c3dSBrandon Streiff 	/* Hardware can only snapshot four words. */
500d632c3dSBrandon Streiff 	if (len > 4)
510d632c3dSBrandon Streiff 		return -E2BIG;
520d632c3dSBrandon Streiff 
5328ae1e96SVivien Didelot 	err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
5428ae1e96SVivien Didelot 				 MV88E6352_G2_AVB_CMD_BUSY | readop);
5528ae1e96SVivien Didelot 	if (err)
5628ae1e96SVivien Didelot 		return err;
5728ae1e96SVivien Didelot 
5828ae1e96SVivien Didelot 	err = mv88e6xxx_g2_avb_wait(chip);
590d632c3dSBrandon Streiff 	if (err)
600d632c3dSBrandon Streiff 		return err;
610d632c3dSBrandon Streiff 
620d632c3dSBrandon Streiff 	for (i = 0; i < len; ++i) {
630d632c3dSBrandon Streiff 		err = mv88e6xxx_g2_read(chip, MV88E6352_G2_AVB_DATA,
640d632c3dSBrandon Streiff 					&data[i]);
650d632c3dSBrandon Streiff 		if (err)
660d632c3dSBrandon Streiff 			return err;
670d632c3dSBrandon Streiff 	}
680d632c3dSBrandon Streiff 
690d632c3dSBrandon Streiff 	return 0;
700d632c3dSBrandon Streiff }
710d632c3dSBrandon Streiff 
720d632c3dSBrandon Streiff /* mv88e6xxx_g2_avb_write -- Write one 16-bit word. */
mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip * chip,u16 writeop,u16 data)730d632c3dSBrandon Streiff static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip *chip, u16 writeop,
740d632c3dSBrandon Streiff 				  u16 data)
750d632c3dSBrandon Streiff {
760d632c3dSBrandon Streiff 	int err;
770d632c3dSBrandon Streiff 
7828ae1e96SVivien Didelot 	err = mv88e6xxx_g2_avb_wait(chip);
7928ae1e96SVivien Didelot 	if (err)
8028ae1e96SVivien Didelot 		return err;
8128ae1e96SVivien Didelot 
820d632c3dSBrandon Streiff 	err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_DATA, data);
830d632c3dSBrandon Streiff 	if (err)
840d632c3dSBrandon Streiff 		return err;
850d632c3dSBrandon Streiff 
8628ae1e96SVivien Didelot 	err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
8728ae1e96SVivien Didelot 				 MV88E6352_G2_AVB_CMD_BUSY | writeop);
8828ae1e96SVivien Didelot 
8928ae1e96SVivien Didelot 	return mv88e6xxx_g2_avb_wait(chip);
900d632c3dSBrandon Streiff }
910d632c3dSBrandon Streiff 
mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip * chip,int port,int addr,u16 * data,int len)920d632c3dSBrandon Streiff static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
930d632c3dSBrandon Streiff 					  int port, int addr, u16 *data,
940d632c3dSBrandon Streiff 					  int len)
950d632c3dSBrandon Streiff {
960d632c3dSBrandon Streiff 	u16 readop = (len == 1 ? MV88E6352_G2_AVB_CMD_OP_READ :
970d632c3dSBrandon Streiff 				 MV88E6352_G2_AVB_CMD_OP_READ_INCR) |
980d632c3dSBrandon Streiff 		     (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
990d632c3dSBrandon Streiff 		     addr;
1000d632c3dSBrandon Streiff 
1010d632c3dSBrandon Streiff 	return mv88e6xxx_g2_avb_read(chip, readop, data, len);
1020d632c3dSBrandon Streiff }
1030d632c3dSBrandon Streiff 
mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip * chip,int port,int addr,u16 data)1040d632c3dSBrandon Streiff static int mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
1050d632c3dSBrandon Streiff 					   int port, int addr, u16 data)
1060d632c3dSBrandon Streiff {
1070d632c3dSBrandon Streiff 	u16 writeop = MV88E6352_G2_AVB_CMD_OP_WRITE | (port << 8) |
1080d632c3dSBrandon Streiff 		      (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
1090d632c3dSBrandon Streiff 
1100d632c3dSBrandon Streiff 	return mv88e6xxx_g2_avb_write(chip, writeop, data);
1110d632c3dSBrandon Streiff }
1120d632c3dSBrandon Streiff 
mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)1130d632c3dSBrandon Streiff static int mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
1140d632c3dSBrandon Streiff 				     u16 *data, int len)
1150d632c3dSBrandon Streiff {
1160d632c3dSBrandon Streiff 	return mv88e6352_g2_avb_port_ptp_read(chip,
1170d632c3dSBrandon Streiff 					MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
1180d632c3dSBrandon Streiff 					addr, data, len);
1190d632c3dSBrandon Streiff }
1200d632c3dSBrandon Streiff 
mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip * chip,int addr,u16 data)1210d632c3dSBrandon Streiff static int mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
1220d632c3dSBrandon Streiff 				      u16 data)
1230d632c3dSBrandon Streiff {
1240d632c3dSBrandon Streiff 	return mv88e6352_g2_avb_port_ptp_write(chip,
1250d632c3dSBrandon Streiff 					MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
1260d632c3dSBrandon Streiff 					addr, data);
1270d632c3dSBrandon Streiff }
1280d632c3dSBrandon Streiff 
mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)1290d632c3dSBrandon Streiff static int mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
1300d632c3dSBrandon Streiff 				     u16 *data, int len)
1310d632c3dSBrandon Streiff {
1320d632c3dSBrandon Streiff 	return mv88e6352_g2_avb_port_ptp_read(chip,
1330d632c3dSBrandon Streiff 					MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
1340d632c3dSBrandon Streiff 					addr, data, len);
1350d632c3dSBrandon Streiff }
1360d632c3dSBrandon Streiff 
mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip * chip,int addr,u16 data)1370d632c3dSBrandon Streiff static int mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
1380d632c3dSBrandon Streiff 				      u16 data)
1390d632c3dSBrandon Streiff {
1400d632c3dSBrandon Streiff 	return mv88e6352_g2_avb_port_ptp_write(chip,
1410d632c3dSBrandon Streiff 					MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
1420d632c3dSBrandon Streiff 					addr, data);
1430d632c3dSBrandon Streiff }
1440d632c3dSBrandon Streiff 
1450d632c3dSBrandon Streiff const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {
1460d632c3dSBrandon Streiff 	.port_ptp_read		= mv88e6352_g2_avb_port_ptp_read,
1470d632c3dSBrandon Streiff 	.port_ptp_write		= mv88e6352_g2_avb_port_ptp_write,
1480d632c3dSBrandon Streiff 	.ptp_read		= mv88e6352_g2_avb_ptp_read,
1490d632c3dSBrandon Streiff 	.ptp_write		= mv88e6352_g2_avb_ptp_write,
1500d632c3dSBrandon Streiff 	.tai_read		= mv88e6352_g2_avb_tai_read,
1510d632c3dSBrandon Streiff 	.tai_write		= mv88e6352_g2_avb_tai_write,
1520d632c3dSBrandon Streiff };
1530d632c3dSBrandon Streiff 
mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)154a469a612SAndrew Lunn static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
155a469a612SAndrew Lunn 				     u16 *data, int len)
156a469a612SAndrew Lunn {
157a469a612SAndrew Lunn 	return mv88e6352_g2_avb_port_ptp_read(chip,
158a469a612SAndrew Lunn 					MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
159a469a612SAndrew Lunn 					addr, data, len);
160a469a612SAndrew Lunn }
161a469a612SAndrew Lunn 
mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip * chip,int addr,u16 data)162a469a612SAndrew Lunn static int mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
163a469a612SAndrew Lunn 				      u16 data)
164a469a612SAndrew Lunn {
165a469a612SAndrew Lunn 	return mv88e6352_g2_avb_port_ptp_write(chip,
166a469a612SAndrew Lunn 					MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
167a469a612SAndrew Lunn 					addr, data);
168a469a612SAndrew Lunn }
169a469a612SAndrew Lunn 
170a469a612SAndrew Lunn const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {
171a469a612SAndrew Lunn 	.port_ptp_read		= mv88e6352_g2_avb_port_ptp_read,
172a469a612SAndrew Lunn 	.port_ptp_write		= mv88e6352_g2_avb_port_ptp_write,
173a469a612SAndrew Lunn 	.ptp_read		= mv88e6352_g2_avb_ptp_read,
174a469a612SAndrew Lunn 	.ptp_write		= mv88e6352_g2_avb_ptp_write,
175a469a612SAndrew Lunn 	.tai_read		= mv88e6165_g2_avb_tai_read,
176a469a612SAndrew Lunn 	.tai_write		= mv88e6165_g2_avb_tai_write,
177a469a612SAndrew Lunn };
178a469a612SAndrew Lunn 
mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip * chip,int port,int addr,u16 * data,int len)1790d632c3dSBrandon Streiff static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
1800d632c3dSBrandon Streiff 					  int port, int addr, u16 *data,
1810d632c3dSBrandon Streiff 					  int len)
1820d632c3dSBrandon Streiff {
1830d632c3dSBrandon Streiff 	u16 readop = (len == 1 ? MV88E6390_G2_AVB_CMD_OP_READ :
1840d632c3dSBrandon Streiff 				 MV88E6390_G2_AVB_CMD_OP_READ_INCR) |
1850d632c3dSBrandon Streiff 		     (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
1860d632c3dSBrandon Streiff 		     addr;
1870d632c3dSBrandon Streiff 
1880d632c3dSBrandon Streiff 	return mv88e6xxx_g2_avb_read(chip, readop, data, len);
1890d632c3dSBrandon Streiff }
1900d632c3dSBrandon Streiff 
mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip * chip,int port,int addr,u16 data)1910d632c3dSBrandon Streiff static int mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
1920d632c3dSBrandon Streiff 					   int port, int addr, u16 data)
1930d632c3dSBrandon Streiff {
1940d632c3dSBrandon Streiff 	u16 writeop = MV88E6390_G2_AVB_CMD_OP_WRITE | (port << 8) |
1950d632c3dSBrandon Streiff 		      (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
1960d632c3dSBrandon Streiff 
1970d632c3dSBrandon Streiff 	return mv88e6xxx_g2_avb_write(chip, writeop, data);
1980d632c3dSBrandon Streiff }
1990d632c3dSBrandon Streiff 
mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)2000d632c3dSBrandon Streiff static int mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
2010d632c3dSBrandon Streiff 				     u16 *data, int len)
2020d632c3dSBrandon Streiff {
2030d632c3dSBrandon Streiff 	return mv88e6390_g2_avb_port_ptp_read(chip,
2040d632c3dSBrandon Streiff 					MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
2050d632c3dSBrandon Streiff 					addr, data, len);
2060d632c3dSBrandon Streiff }
2070d632c3dSBrandon Streiff 
mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip * chip,int addr,u16 data)2080d632c3dSBrandon Streiff static int mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
2090d632c3dSBrandon Streiff 				      u16 data)
2100d632c3dSBrandon Streiff {
2110d632c3dSBrandon Streiff 	return mv88e6390_g2_avb_port_ptp_write(chip,
2120d632c3dSBrandon Streiff 					MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
2130d632c3dSBrandon Streiff 					addr, data);
2140d632c3dSBrandon Streiff }
2150d632c3dSBrandon Streiff 
mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip * chip,int addr,u16 * data,int len)2160d632c3dSBrandon Streiff static int mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
2170d632c3dSBrandon Streiff 				     u16 *data, int len)
2180d632c3dSBrandon Streiff {
2190d632c3dSBrandon Streiff 	return mv88e6390_g2_avb_port_ptp_read(chip,
2200d632c3dSBrandon Streiff 					MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
2210d632c3dSBrandon Streiff 					addr, data, len);
2220d632c3dSBrandon Streiff }
2230d632c3dSBrandon Streiff 
mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip * chip,int addr,u16 data)2240d632c3dSBrandon Streiff static int mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
2250d632c3dSBrandon Streiff 				      u16 data)
2260d632c3dSBrandon Streiff {
2270d632c3dSBrandon Streiff 	return mv88e6390_g2_avb_port_ptp_write(chip,
2280d632c3dSBrandon Streiff 					MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
2290d632c3dSBrandon Streiff 					addr, data);
2300d632c3dSBrandon Streiff }
2310d632c3dSBrandon Streiff 
2320d632c3dSBrandon Streiff const struct mv88e6xxx_avb_ops mv88e6390_avb_ops = {
2330d632c3dSBrandon Streiff 	.port_ptp_read		= mv88e6390_g2_avb_port_ptp_read,
2340d632c3dSBrandon Streiff 	.port_ptp_write		= mv88e6390_g2_avb_port_ptp_write,
2350d632c3dSBrandon Streiff 	.ptp_read		= mv88e6390_g2_avb_ptp_read,
2360d632c3dSBrandon Streiff 	.ptp_write		= mv88e6390_g2_avb_ptp_write,
2370d632c3dSBrandon Streiff 	.tai_read		= mv88e6390_g2_avb_tai_read,
2380d632c3dSBrandon Streiff 	.tai_write		= mv88e6390_g2_avb_tai_write,
2390d632c3dSBrandon Streiff };
240