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 */ 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 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*24cbdb91SNathan Rossi return mv88e6xxx_port_wait_bit(chip, 44*24cbdb91SNathan Rossi MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, 4560907013SMarek Behún MV88E6XXX_PORT_RESERVED_1A, bit, 0); 4660907013SMarek Behún } 4760907013SMarek Behún 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