160907013SMarek Behún // SPDX-License-Identifier: GPL-2.0-or-later
260907013SMarek Behún /*
360907013SMarek Behún  * Marvell 88E6xxx Switch Hidden Registers support
460907013SMarek Behún  *
560907013SMarek Behún  * Copyright (c) 2008 Marvell Semiconductor
660907013SMarek Behún  *
760907013SMarek Behún  * Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch>
860907013SMarek Behún  */
960907013SMarek Behún 
1060907013SMarek Behún #include <linux/bitfield.h>
1160907013SMarek Behún 
1260907013SMarek Behún #include "chip.h"
1360907013SMarek Behún #include "port.h"
1460907013SMarek Behún 
1560907013SMarek Behún /* The mv88e6390 and mv88e6341 have some hidden registers used for debug and
1660907013SMarek Behún  * development. The errata also makes use of them.
1760907013SMarek Behún  */
mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip * chip,int block,int port,int reg,u16 val)1860907013SMarek Behún int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
1960907013SMarek Behún 				int port, int reg, u16 val)
2060907013SMarek Behún {
2160907013SMarek Behún 	u16 ctrl;
2260907013SMarek Behún 	int err;
2360907013SMarek Behún 
2460907013SMarek Behún 	err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
2560907013SMarek Behún 				   MV88E6XXX_PORT_RESERVED_1A, val);
2660907013SMarek Behún 	if (err)
2760907013SMarek Behún 		return err;
2860907013SMarek Behún 
2960907013SMarek Behún 	ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
3060907013SMarek Behún 	       MV88E6XXX_PORT_RESERVED_1A_WRITE |
3160907013SMarek Behún 	       block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
3260907013SMarek Behún 	       port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
3360907013SMarek Behún 	       reg;
3460907013SMarek Behún 
3560907013SMarek Behún 	return mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
3660907013SMarek Behún 				    MV88E6XXX_PORT_RESERVED_1A, ctrl);
3760907013SMarek Behún }
3860907013SMarek Behún 
mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip * chip)3960907013SMarek Behún int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip)
4060907013SMarek Behún {
4160907013SMarek Behún 	int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY);
4260907013SMarek Behún 
43*ede22fc0SNathan Rossi 	return mv88e6xxx_port_wait_bit(chip,
44*ede22fc0SNathan Rossi 				       MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
4560907013SMarek Behún 				       MV88E6XXX_PORT_RESERVED_1A, bit, 0);
4660907013SMarek Behún }
4760907013SMarek Behún 
mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip * chip,int block,int port,int reg,u16 * val)4860907013SMarek Behún int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
4960907013SMarek Behún 			       int reg, u16 *val)
5060907013SMarek Behún {
5160907013SMarek Behún 	u16 ctrl;
5260907013SMarek Behún 	int err;
5360907013SMarek Behún 
5460907013SMarek Behún 	ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
5560907013SMarek Behún 	       MV88E6XXX_PORT_RESERVED_1A_READ |
5660907013SMarek Behún 	       block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
5760907013SMarek Behún 	       port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
5860907013SMarek Behún 	       reg;
5960907013SMarek Behún 
6060907013SMarek Behún 	err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
6160907013SMarek Behún 				   MV88E6XXX_PORT_RESERVED_1A, ctrl);
6260907013SMarek Behún 	if (err)
6360907013SMarek Behún 		return err;
6460907013SMarek Behún 
6560907013SMarek Behún 	err = mv88e6xxx_port_hidden_wait(chip);
6660907013SMarek Behún 	if (err)
6760907013SMarek Behún 		return err;
6860907013SMarek Behún 
6960907013SMarek Behún 	return mv88e6xxx_port_read(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
7060907013SMarek Behún 				   MV88E6XXX_PORT_RESERVED_1A, val);
7160907013SMarek Behún }
72