net: dsa: Centralize Marvell switch reset
Marvell switches are all reset in nearly the same way. The only difference is if the PPU should be enabled or not. Move this code into the shared mv88x6xxx.c. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
44e50ddbc7
Коммит
143a83073a
|
@ -52,40 +52,6 @@ static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv88e6123_61_65_switch_reset(struct dsa_switch *ds)
|
|
||||||
{
|
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
||||||
int i;
|
|
||||||
int ret;
|
|
||||||
unsigned long timeout;
|
|
||||||
|
|
||||||
/* Set all ports to the disabled state. */
|
|
||||||
for (i = 0; i < ps->num_ports; i++) {
|
|
||||||
ret = REG_READ(REG_PORT(i), 0x04);
|
|
||||||
REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for transmit queues to drain. */
|
|
||||||
usleep_range(2000, 4000);
|
|
||||||
|
|
||||||
/* Reset the switch. */
|
|
||||||
REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
|
|
||||||
|
|
||||||
/* Wait up to one second for reset to complete. */
|
|
||||||
timeout = jiffies + 1 * HZ;
|
|
||||||
while (time_before(jiffies, timeout)) {
|
|
||||||
ret = REG_READ(REG_GLOBAL, 0x00);
|
|
||||||
if ((ret & 0xc800) == 0xc800)
|
|
||||||
break;
|
|
||||||
|
|
||||||
usleep_range(1000, 2000);
|
|
||||||
}
|
|
||||||
if (time_after(jiffies, timeout))
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
|
static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -292,7 +258,7 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mv88e6123_61_65_switch_reset(ds);
|
ret = mv88e6xxx_switch_reset(ds, false);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -42,40 +42,6 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv88e6131_switch_reset(struct dsa_switch *ds)
|
|
||||||
{
|
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
||||||
int i;
|
|
||||||
int ret;
|
|
||||||
unsigned long timeout;
|
|
||||||
|
|
||||||
/* Set all ports to the disabled state. */
|
|
||||||
for (i = 0; i < ps->num_ports; i++) {
|
|
||||||
ret = REG_READ(REG_PORT(i), 0x04);
|
|
||||||
REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for transmit queues to drain. */
|
|
||||||
usleep_range(2000, 4000);
|
|
||||||
|
|
||||||
/* Reset the switch. */
|
|
||||||
REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
|
|
||||||
|
|
||||||
/* Wait up to one second for reset to complete. */
|
|
||||||
timeout = jiffies + 1 * HZ;
|
|
||||||
while (time_before(jiffies, timeout)) {
|
|
||||||
ret = REG_READ(REG_GLOBAL, 0x00);
|
|
||||||
if ((ret & 0xc800) == 0xc800)
|
|
||||||
break;
|
|
||||||
|
|
||||||
usleep_range(1000, 2000);
|
|
||||||
}
|
|
||||||
if (time_after(jiffies, timeout))
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6131_setup_global(struct dsa_switch *ds)
|
static int mv88e6131_setup_global(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -281,7 +247,7 @@ static int mv88e6131_setup(struct dsa_switch *ds)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mv88e6131_switch_reset(ds);
|
ret = mv88e6xxx_switch_reset(ds, false);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -36,52 +36,6 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv88e6171_switch_reset(struct dsa_switch *ds)
|
|
||||||
{
|
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
||||||
int i;
|
|
||||||
int ret;
|
|
||||||
unsigned long timeout;
|
|
||||||
|
|
||||||
/* Set all ports to the disabled state. */
|
|
||||||
for (i = 0; i < ps->num_ports; i++) {
|
|
||||||
ret = REG_READ(REG_PORT(i), 0x04);
|
|
||||||
REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for transmit queues to drain. */
|
|
||||||
usleep_range(2000, 4000);
|
|
||||||
|
|
||||||
/* Reset the switch. Keep PPU active. The PPU needs to be
|
|
||||||
* active to support indirect phy register accesses through
|
|
||||||
* global registers 0x18 and 0x19.
|
|
||||||
*/
|
|
||||||
REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
|
|
||||||
|
|
||||||
/* Wait up to one second for reset to complete. */
|
|
||||||
timeout = jiffies + 1 * HZ;
|
|
||||||
while (time_before(jiffies, timeout)) {
|
|
||||||
ret = REG_READ(REG_GLOBAL, 0x00);
|
|
||||||
if ((ret & 0xc800) == 0xc800)
|
|
||||||
break;
|
|
||||||
|
|
||||||
usleep_range(1000, 2000);
|
|
||||||
}
|
|
||||||
if (time_after(jiffies, timeout))
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
|
|
||||||
/* Enable ports not under DSA, e.g. WAN port */
|
|
||||||
for (i = 0; i < ps->num_ports; i++) {
|
|
||||||
if (dsa_is_cpu_port(ds, i) || ds->phys_port_mask & (1 << i))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ret = REG_READ(REG_PORT(i), 0x04);
|
|
||||||
REG_WRITE(REG_PORT(i), 0x04, ret | 0x03);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6171_setup_global(struct dsa_switch *ds)
|
static int mv88e6171_setup_global(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
@ -282,7 +236,7 @@ static int mv88e6171_setup(struct dsa_switch *ds)
|
||||||
|
|
||||||
ps->num_ports = 7;
|
ps->num_ports = 7;
|
||||||
|
|
||||||
ret = mv88e6171_switch_reset(ds);
|
ret = mv88e6xxx_switch_reset(ds, true);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -45,42 +45,6 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv88e6352_switch_reset(struct dsa_switch *ds)
|
|
||||||
{
|
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
||||||
unsigned long timeout;
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Set all ports to the disabled state. */
|
|
||||||
for (i = 0; i < ps->num_ports; i++) {
|
|
||||||
ret = REG_READ(REG_PORT(i), 0x04);
|
|
||||||
REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for transmit queues to drain. */
|
|
||||||
usleep_range(2000, 4000);
|
|
||||||
|
|
||||||
/* Reset the switch. Keep PPU active (bit 14, undocumented).
|
|
||||||
* The PPU needs to be active to support indirect phy register
|
|
||||||
* accesses through global registers 0x18 and 0x19.
|
|
||||||
*/
|
|
||||||
REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
|
|
||||||
|
|
||||||
/* Wait up to one second for reset to complete. */
|
|
||||||
timeout = jiffies + 1 * HZ;
|
|
||||||
while (time_before(jiffies, timeout)) {
|
|
||||||
ret = REG_READ(REG_GLOBAL, 0x00);
|
|
||||||
if ((ret & 0x8800) == 0x8800)
|
|
||||||
break;
|
|
||||||
usleep_range(1000, 2000);
|
|
||||||
}
|
|
||||||
if (time_after(jiffies, timeout))
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6352_setup_global(struct dsa_switch *ds)
|
static int mv88e6352_setup_global(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
@ -373,7 +337,7 @@ static int mv88e6352_setup(struct dsa_switch *ds)
|
||||||
|
|
||||||
mutex_init(&ps->eeprom_mutex);
|
mutex_init(&ps->eeprom_mutex);
|
||||||
|
|
||||||
ret = mv88e6352_switch_reset(ds);
|
ret = mv88e6xxx_switch_reset(ds, true);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -1161,6 +1161,46 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
|
||||||
|
{
|
||||||
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
|
||||||
|
unsigned long timeout;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Set all ports to the disabled state. */
|
||||||
|
for (i = 0; i < ps->num_ports; i++) {
|
||||||
|
ret = REG_READ(REG_PORT(i), 0x04);
|
||||||
|
REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for transmit queues to drain. */
|
||||||
|
usleep_range(2000, 4000);
|
||||||
|
|
||||||
|
/* Reset the switch. Keep the PPU active if requested. The PPU
|
||||||
|
* needs to be active to support indirect phy register access
|
||||||
|
* through global registers 0x18 and 0x19.
|
||||||
|
*/
|
||||||
|
if (ppu_active)
|
||||||
|
REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
|
||||||
|
else
|
||||||
|
REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
|
||||||
|
|
||||||
|
/* Wait up to one second for reset to complete. */
|
||||||
|
timeout = jiffies + 1 * HZ;
|
||||||
|
while (time_before(jiffies, timeout)) {
|
||||||
|
ret = REG_READ(REG_GLOBAL, 0x00);
|
||||||
|
if ((ret & is_reset) == is_reset)
|
||||||
|
break;
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
}
|
||||||
|
if (time_after(jiffies, timeout))
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init mv88e6xxx_init(void)
|
static int __init mv88e6xxx_init(void)
|
||||||
{
|
{
|
||||||
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
|
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
|
||||||
|
|
|
@ -129,6 +129,7 @@ struct mv88e6xxx_hw_stat {
|
||||||
int reg;
|
int reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
|
||||||
int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port);
|
int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port);
|
||||||
int mv88e6xxx_setup_common(struct dsa_switch *ds);
|
int mv88e6xxx_setup_common(struct dsa_switch *ds);
|
||||||
int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
|
int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче