net: dsa: mv88e6xxx: Add support for model-specific pre- and post-reset handlers
authorMatthias Schiffer <matthias.schiffer@ew.tq-group.com>
Tue, 23 Apr 2024 07:47:48 +0000 (09:47 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 25 Apr 2024 10:24:06 +0000 (11:24 +0100)
Instead of calling mv88e6xxx_g2_eeprom_wait() directly from
mv88e6xxx_hardware_reset(), add configurable pre- and post-reset hard
reset handlers. Initially, the handlers are set to
mv88e6xxx_g2_eeprom_wait() for all families that have get/set_eeprom()
to match the existing behavior. No functional change intended (except
for additional error messages on failure).

Fixes: 6ccf50d4d474 ("net: dsa: mv88e6xxx: Avoid EEPROM timeout when EEPROM is absent")
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h

index e950a634a3c737dd52b8b3aa545c1137ad8b2d0e..4bdb3f2d469e33557b4db386aa1f65b8c1e6eaa8 100644 (file)
@@ -3086,6 +3086,7 @@ static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
 static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
 {
        struct gpio_desc *gpiod = chip->reset;
+       int err;
 
        /* If there is a GPIO connected to the reset pin, toggle it */
        if (gpiod) {
@@ -3094,17 +3095,26 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
                 * mid-byte, causing the first EEPROM read after the reset
                 * from the wrong location resulting in the switch booting
                 * to wrong mode and inoperable.
+                * For this reason, switch families with EEPROM support
+                * generally wait for EEPROM loads to complete as their pre-
+                * and post-reset handlers.
                 */
-               if (chip->info->ops->get_eeprom)
-                       mv88e6xxx_g2_eeprom_wait(chip);
+               if (chip->info->ops->hardware_reset_pre) {
+                       err = chip->info->ops->hardware_reset_pre(chip);
+                       if (err)
+                               dev_err(chip->dev, "pre-reset error: %d\n", err);
+               }
 
                gpiod_set_value_cansleep(gpiod, 1);
                usleep_range(10000, 20000);
                gpiod_set_value_cansleep(gpiod, 0);
                usleep_range(10000, 20000);
 
-               if (chip->info->ops->get_eeprom)
-                       mv88e6xxx_g2_eeprom_wait(chip);
+               if (chip->info->ops->hardware_reset_post) {
+                       err = chip->info->ops->hardware_reset_post(chip);
+                       if (err)
+                               dev_err(chip->dev, "post-reset error: %d\n", err);
+               }
        }
 }
 
@@ -4334,6 +4344,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4524,6 +4536,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4624,6 +4638,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4718,6 +4734,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4776,6 +4794,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4832,6 +4852,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4891,6 +4913,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4944,6 +4968,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
        .watchdog_ops = &mv88e6250_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6250_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -4991,6 +5017,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -5050,6 +5078,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -5096,6 +5126,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
        .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -5146,6 +5178,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -5301,6 +5335,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -5363,6 +5399,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -5425,6 +5463,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -5490,6 +5530,8 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
        .watchdog_ops = &mv88e6393x_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
index 85eb293381a7e2e8d1c7803dbc99ee61e6f129d2..c34caf9815c5cb12a889adc2645765ad1b3c1199 100644 (file)
@@ -487,6 +487,12 @@ struct mv88e6xxx_ops {
        int (*ppu_enable)(struct mv88e6xxx_chip *chip);
        int (*ppu_disable)(struct mv88e6xxx_chip *chip);
 
+       /* Additional handlers to run before and after hard reset, to make sure
+        * that the switch and EEPROM are in a good state.
+        */
+       int (*hardware_reset_pre)(struct mv88e6xxx_chip *chip);
+       int (*hardware_reset_post)(struct mv88e6xxx_chip *chip);
+
        /* Switch Software Reset */
        int (*reset)(struct mv88e6xxx_chip *chip);