1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Marvell 88E6xxx Switch Hidden Registers support
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2008 Marvell Semiconductor
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/bitfield.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "chip.h"
13*4882a593Smuzhiyun #include "port.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /* The mv88e6390 and mv88e6341 have some hidden registers used for debug and
16*4882a593Smuzhiyun * development. The errata also makes use of them.
17*4882a593Smuzhiyun */
mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip * chip,int block,int port,int reg,u16 val)18*4882a593Smuzhiyun int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
19*4882a593Smuzhiyun int port, int reg, u16 val)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun u16 ctrl;
22*4882a593Smuzhiyun int err;
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
25*4882a593Smuzhiyun MV88E6XXX_PORT_RESERVED_1A, val);
26*4882a593Smuzhiyun if (err)
27*4882a593Smuzhiyun return err;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
30*4882a593Smuzhiyun MV88E6XXX_PORT_RESERVED_1A_WRITE |
31*4882a593Smuzhiyun block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
32*4882a593Smuzhiyun port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
33*4882a593Smuzhiyun reg;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun return mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
36*4882a593Smuzhiyun MV88E6XXX_PORT_RESERVED_1A, ctrl);
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip * chip)39*4882a593Smuzhiyun int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY);
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun return mv88e6xxx_wait_bit(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
44*4882a593Smuzhiyun MV88E6XXX_PORT_RESERVED_1A, bit, 0);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip * chip,int block,int port,int reg,u16 * val)47*4882a593Smuzhiyun int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
48*4882a593Smuzhiyun int reg, u16 *val)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun u16 ctrl;
51*4882a593Smuzhiyun int err;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
54*4882a593Smuzhiyun MV88E6XXX_PORT_RESERVED_1A_READ |
55*4882a593Smuzhiyun block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
56*4882a593Smuzhiyun port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
57*4882a593Smuzhiyun reg;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
60*4882a593Smuzhiyun MV88E6XXX_PORT_RESERVED_1A, ctrl);
61*4882a593Smuzhiyun if (err)
62*4882a593Smuzhiyun return err;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun err = mv88e6xxx_port_hidden_wait(chip);
65*4882a593Smuzhiyun if (err)
66*4882a593Smuzhiyun return err;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun return mv88e6xxx_port_read(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
69*4882a593Smuzhiyun MV88E6XXX_PORT_RESERVED_1A, val);
70*4882a593Smuzhiyun }
71