Skip to content

Commit 6ccf50d

Browse files
Fabio Estevamdavem330
authored andcommitted
net: dsa: mv88e6xxx: Avoid EEPROM timeout when EEPROM is absent
Since commit 23d775f ("net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset") the following error is seen on a imx8mn board with a 88E6320 switch: mv88e6085 30be0000.ethernet-1:00: Timeout waiting for EEPROM done This board does not have an EEPROM attached to the switch though. This problem is well explained by Andrew Lunn: "If there is an EEPROM, and the EEPROM contains a lot of data, it could be that when we perform a hardware reset towards the end of probe, it interrupts an I2C bus transaction, leaving the I2C bus in a bad state, and future reads of the EEPROM do not work. The work around for this was to poll the EEInt status and wait for it to go true before performing the hardware reset. However, we have discovered that for some boards which do not have an EEPROM, EEInt never indicates complete. As a result, mv88e6xxx_g1_wait_eeprom_done() spins for a second and then prints a warning. We probably need a different solution than calling mv88e6xxx_g1_wait_eeprom_done(). The datasheet for 6352 documents the EEPROM Command register: bit 15 is: EEPROM Unit Busy. This bit must be set to a one to start an EEPROM operation (see EEOp below). Only one EEPROM operation can be executing at one time so this bit must be zero before setting it to a one. When the requested EEPROM operation completes this bit will automatically be cleared to a zero. The transition of this bit from a one to a zero can be used to generate an interrupt (the EEInt in Global 1, offset 0x00). and more interesting is bit 11: Register Loader Running. This bit is set to one whenever the register loader is busy executing instructions contained in the EEPROM." Change to using mv88e6xxx_g2_eeprom_wait() to fix the timeout error when the EEPROM chip is not present. Fixes: 23d775f ("net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset") Suggested-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Fabio Estevam <festevam@denx.de> Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent caa0578 commit 6ccf50d

File tree

5 files changed

+6
-35
lines changed

5 files changed

+6
-35
lines changed

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,14 +2958,16 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
29582958
* from the wrong location resulting in the switch booting
29592959
* to wrong mode and inoperable.
29602960
*/
2961-
mv88e6xxx_g1_wait_eeprom_done(chip);
2961+
if (chip->info->ops->get_eeprom)
2962+
mv88e6xxx_g2_eeprom_wait(chip);
29622963

29632964
gpiod_set_value_cansleep(gpiod, 1);
29642965
usleep_range(10000, 20000);
29652966
gpiod_set_value_cansleep(gpiod, 0);
29662967
usleep_range(10000, 20000);
29672968

2968-
mv88e6xxx_g1_wait_eeprom_done(chip);
2969+
if (chip->info->ops->get_eeprom)
2970+
mv88e6xxx_g2_eeprom_wait(chip);
29692971
}
29702972
}
29712973

drivers/net/dsa/mv88e6xxx/global1.c

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -75,37 +75,6 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
7575
return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
7676
}
7777

78-
void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip)
79-
{
80-
const unsigned long timeout = jiffies + 1 * HZ;
81-
u16 val;
82-
int err;
83-
84-
/* Wait up to 1 second for the switch to finish reading the
85-
* EEPROM.
86-
*/
87-
while (time_before(jiffies, timeout)) {
88-
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
89-
if (err) {
90-
dev_err(chip->dev, "Error reading status");
91-
return;
92-
}
93-
94-
/* If the switch is still resetting, it may not
95-
* respond on the bus, and so MDIO read returns
96-
* 0xffff. Differentiate between that, and waiting for
97-
* the EEPROM to be done by bit 0 being set.
98-
*/
99-
if (val != 0xffff &&
100-
val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE))
101-
return;
102-
103-
usleep_range(1000, 2000);
104-
}
105-
106-
dev_err(chip->dev, "Timeout waiting for EEPROM done");
107-
}
108-
10978
/* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
11079
* Offset 0x02: Switch MAC Address Register Bytes 2 & 3
11180
* Offset 0x03: Switch MAC Address Register Bytes 4 & 5

drivers/net/dsa/mv88e6xxx/global1.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,6 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
282282
int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
283283
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
284284
int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip);
285-
void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip);
286285

287286
int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
288287
int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);

drivers/net/dsa/mv88e6xxx/global2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
340340
* Offset 0x15: EEPROM Addr (for 8-bit data access)
341341
*/
342342

343-
static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
343+
int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
344344
{
345345
int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY);
346346
int err;

drivers/net/dsa/mv88e6xxx/global2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip);
365365

366366
int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
367367
int port);
368+
int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip);
368369

369370
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
370371
extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;

0 commit comments

Comments
 (0)