mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
net: dsa: mv88x6xxx: mv88e6390 errata
[ Upstream commit ea89098ef9a574bceca00d3b5df14aaf0b3f9ccf ] The 6390 copper ports have an errata which require poking magic values into undocumented magic registers and then performing a software reset. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
f1ce6ee14a
commit
ffd2e8a3f6
@ -1979,6 +1979,107 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The mv88e6390 has some hidden registers used for debug and
|
||||
* development. The errata also makes use of them.
|
||||
*/
|
||||
static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
|
||||
int reg, u16 val)
|
||||
{
|
||||
u16 ctrl;
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
|
||||
PORT_RESERVED_1A, val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
|
||||
PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
|
||||
reg;
|
||||
|
||||
return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
|
||||
PORT_RESERVED_1A, ctrl);
|
||||
}
|
||||
|
||||
static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
|
||||
PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
|
||||
}
|
||||
|
||||
|
||||
static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
|
||||
int reg, u16 *val)
|
||||
{
|
||||
u16 ctrl;
|
||||
int err;
|
||||
|
||||
ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
|
||||
PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
|
||||
reg;
|
||||
|
||||
err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
|
||||
PORT_RESERVED_1A, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mv88e6390_hidden_wait(chip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
|
||||
PORT_RESERVED_1A, val);
|
||||
}
|
||||
|
||||
/* Check if the errata has already been applied. */
|
||||
static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
int port;
|
||||
int err;
|
||||
u16 val;
|
||||
|
||||
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
|
||||
err = mv88e6390_hidden_read(chip, port, 0, &val);
|
||||
if (err) {
|
||||
dev_err(chip->dev,
|
||||
"Error reading hidden register: %d\n", err);
|
||||
return false;
|
||||
}
|
||||
if (val != 0x01c0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The 6390 copper ports have an errata which require poking magic
|
||||
* values into undocumented hidden registers and then performing a
|
||||
* software reset.
|
||||
*/
|
||||
static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
int port;
|
||||
int err;
|
||||
|
||||
if (mv88e6390_setup_errata_applied(chip))
|
||||
return 0;
|
||||
|
||||
/* Set the ports into blocking mode */
|
||||
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
|
||||
err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
|
||||
err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return mv88e6xxx_software_reset(chip);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
@ -1990,6 +2091,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
|
||||
|
||||
mutex_lock(&chip->reg_lock);
|
||||
|
||||
if (chip->info->ops->setup_errata) {
|
||||
err = chip->info->ops->setup_errata(chip);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Setup Switch Port Registers */
|
||||
for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
|
||||
err = mv88e6xxx_setup_port(chip, i);
|
||||
@ -2652,6 +2759,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6190_ops = {
|
||||
/* MV88E6XXX_FAMILY_6390 */
|
||||
.setup_errata = mv88e6390_setup_errata,
|
||||
.irl_init_all = mv88e6390_g2_irl_init_all,
|
||||
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
|
||||
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
|
||||
@ -2687,6 +2795,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6190x_ops = {
|
||||
/* MV88E6XXX_FAMILY_6390 */
|
||||
.setup_errata = mv88e6390_setup_errata,
|
||||
.irl_init_all = mv88e6390_g2_irl_init_all,
|
||||
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
|
||||
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
|
||||
@ -2722,6 +2831,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6191_ops = {
|
||||
/* MV88E6XXX_FAMILY_6390 */
|
||||
.setup_errata = mv88e6390_setup_errata,
|
||||
.irl_init_all = mv88e6390_g2_irl_init_all,
|
||||
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
|
||||
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
|
||||
@ -2793,6 +2903,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6290_ops = {
|
||||
/* MV88E6XXX_FAMILY_6390 */
|
||||
.setup_errata = mv88e6390_setup_errata,
|
||||
.irl_init_all = mv88e6390_g2_irl_init_all,
|
||||
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
|
||||
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
|
||||
@ -3030,6 +3141,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6390_ops = {
|
||||
/* MV88E6XXX_FAMILY_6390 */
|
||||
.setup_errata = mv88e6390_setup_errata,
|
||||
.irl_init_all = mv88e6390_g2_irl_init_all,
|
||||
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
|
||||
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
|
||||
@ -3068,6 +3180,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6390x_ops = {
|
||||
/* MV88E6XXX_FAMILY_6390 */
|
||||
.setup_errata = mv88e6390_setup_errata,
|
||||
.irl_init_all = mv88e6390_g2_irl_init_all,
|
||||
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
|
||||
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
|
||||
|
@ -222,6 +222,11 @@ struct mv88e6xxx_mdio_bus {
|
||||
};
|
||||
|
||||
struct mv88e6xxx_ops {
|
||||
/* Switch Setup Errata, called early in the switch setup to
|
||||
* allow any errata actions to be performed
|
||||
*/
|
||||
int (*setup_errata)(struct mv88e6xxx_chip *chip);
|
||||
|
||||
/* Ingress Rate Limit unit (IRL) operations */
|
||||
int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port);
|
||||
|
||||
|
@ -236,6 +236,16 @@
|
||||
/* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
|
||||
#define MV88E6095_PORT_IEEE_PRIO_REMAP_4567 0x19
|
||||
|
||||
/* Offset 0x1a: Magic undocumented errata register */
|
||||
#define PORT_RESERVED_1A 0x1a
|
||||
#define PORT_RESERVED_1A_BUSY BIT(15)
|
||||
#define PORT_RESERVED_1A_WRITE BIT(14)
|
||||
#define PORT_RESERVED_1A_READ 0
|
||||
#define PORT_RESERVED_1A_PORT_SHIFT 5
|
||||
#define PORT_RESERVED_1A_BLOCK (0xf << 10)
|
||||
#define PORT_RESERVED_1A_CTRL_PORT 4
|
||||
#define PORT_RESERVED_1A_DATA_PORT 5
|
||||
|
||||
int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
|
||||
u16 *val);
|
||||
int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
|
||||
|
Loading…
x
Reference in New Issue
Block a user