mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-05 06:46:59 +07:00
net: dsa: mv88x6xxx: mv88e6390 errata
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>
This commit is contained in:
parent
001e465f09
commit
ea89098ef9
@ -2403,6 +2403,107 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
|
||||
return mv88e6xxx_g1_stats_clear(chip);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
@ -2415,6 +2516,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;
|
||||
}
|
||||
|
||||
/* Cache the cmode of each port. */
|
||||
for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
|
||||
if (chip->info->ops->port_get_cmode) {
|
||||
@ -3226,6 +3333,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,
|
||||
@ -3269,6 +3377,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,
|
||||
@ -3312,6 +3421,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,
|
||||
@ -3404,6 +3514,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,
|
||||
@ -3709,6 +3820,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,
|
||||
@ -3756,6 +3868,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,
|
||||
|
@ -300,6 +300,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);
|
||||
|
||||
int (*ieee_pri_map)(struct mv88e6xxx_chip *chip);
|
||||
int (*ip_pri_map)(struct mv88e6xxx_chip *chip);
|
||||
|
||||
|
@ -251,6 +251,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…
Reference in New Issue
Block a user