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