summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2024-10-04 14:36:54 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-10-17 16:24:35 +0300
commit28a2c3e51d097975521ca9ffbd8b82ea7b8cdc14 (patch)
tree6f576415840fc0840f68e5e29295572437f7d1c9
parent3be342e0332a7c83eb26fbb22bf156fdca467a5d (diff)
downloadlinux-28a2c3e51d097975521ca9ffbd8b82ea7b8cdc14.tar.xz
net: dsa: lan9303: ensure chip reset and wait for READY status
commit 5c14e51d2d7df49fe0d4e64a12c58d2542f452ff upstream. Accessing device registers seems to be not reliable, the chip revision is sometimes detected wrongly (0 instead of expected 1). Ensure that the chip reset is performed via reset GPIO and then wait for 'Device Ready' status in HW_CFG register before doing any register initializations. Cc: stable@vger.kernel.org Fixes: a1292595e006 ("net: dsa: add new DSA switch driver for the SMSC-LAN9303") Signed-off-by: Anatolij Gustschin <agust@denx.de> [alex: reworked using read_poll_timeout()] Signed-off-by: Alexander Sverdlin <alexander.sverdlin@siemens.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Link: https://patch.msgid.link/20241004113655.3436296-1-alexander.sverdlin@siemens.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/dsa/lan9303-core.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index 24ef219e6f56..8b05a70c0ff3 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <linux/gpio/consumer.h>
#include <linux/regmap.h>
+#include <linux/iopoll.h>
#include <linux/mutex.h>
#include <linux/mii.h>
#include <linux/of.h>
@@ -839,6 +840,8 @@ static void lan9303_handle_reset(struct lan9303 *chip)
if (!chip->reset_gpio)
return;
+ gpiod_set_value_cansleep(chip->reset_gpio, 1);
+
if (chip->reset_duration != 0)
msleep(chip->reset_duration);
@@ -864,8 +867,34 @@ static int lan9303_disable_processing(struct lan9303 *chip)
static int lan9303_check_device(struct lan9303 *chip)
{
int ret;
+ int err;
u32 reg;
+ /* In I2C-managed configurations this polling loop will clash with
+ * switch's reading of EEPROM right after reset and this behaviour is
+ * not configurable. While lan9303_read() already has quite long retry
+ * timeout, seems not all cases are being detected as arbitration error.
+ *
+ * According to datasheet, EEPROM loader has 30ms timeout (in case of
+ * missing EEPROM).
+ *
+ * Loading of the largest supported EEPROM is expected to take at least
+ * 5.9s.
+ */
+ err = read_poll_timeout(lan9303_read, ret,
+ !ret && reg & LAN9303_HW_CFG_READY,
+ 20000, 6000000, false,
+ chip->regmap, LAN9303_HW_CFG, &reg);
+ if (ret) {
+ dev_err(chip->dev, "failed to read HW_CFG reg: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+ if (err) {
+ dev_err(chip->dev, "HW_CFG not ready: 0x%08x\n", reg);
+ return err;
+ }
+
ret = lan9303_read(chip->regmap, LAN9303_CHIP_REV, &reg);
if (ret) {
dev_err(chip->dev, "failed to read chip revision register: %d\n",