[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241004090332.3252564-1-alexander.sverdlin@siemens.com>
Date: Fri, 4 Oct 2024 11:03:31 +0200
From: "A. Sverdlin" <alexander.sverdlin@...mens.com>
To: netdev@...r.kernel.org
Cc: Anatolij Gustschin <agust@...x.de>,
Andrew Lunn <andrew@...n.ch>,
Florian Fainelli <f.fainelli@...il.com>,
Vladimir Oltean <olteanv@...il.com>,
Alexander Sverdlin <alexander.sverdlin@...mens.com>
Subject: [PATCH net v3] net: dsa: lan9303: ensure chip reset and wait for READY status
From: Anatolij Gustschin <agust@...x.de>
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.
Signed-off-by: Anatolij Gustschin <agust@...x.de>
[alex: reworked using read_poll_timeout()]
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@...mens.com>
---
Changelog:
v3: comment style, use "!ret" in stop condition, user-readable error code
v2: use read_poll_timeout()
drivers/net/dsa/lan9303-core.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index 268949939636a..f478b55d4d297 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);
@@ -866,6 +869,30 @@ static int lan9303_check_device(struct lan9303 *chip)
int ret;
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.
+ */
+ if (read_poll_timeout(lan9303_read, ret,
+ !ret && reg & LAN9303_HW_CFG_READY,
+ 20000, 6000000, false,
+ chip->regmap, LAN9303_HW_CFG, ®)) {
+ dev_err(chip->dev, "HW_CFG not ready: 0x%08x\n", reg);
+ return -ETIMEDOUT;
+ }
+ if (ret) {
+ dev_err(chip->dev, "failed to read HW_CFG reg: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
ret = lan9303_read(chip->regmap, LAN9303_CHIP_REV, ®);
if (ret) {
dev_err(chip->dev, "failed to read chip revision register: %d\n",
--
2.46.2
Powered by blists - more mailing lists