diff options
| author | Bastien Curutchet <bastien.curutchet@bootlin.com> | 2025-09-18 11:33:52 +0300 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2025-09-23 02:31:18 +0300 |
| commit | a0b977a3d19368b235f2a6c06e800fb25452029b (patch) | |
| tree | f232c14dfc4eaccae5960a9964ad6c52b236c4c0 /drivers/net/dsa/microchip/ksz_common.c | |
| parent | e469b87e0fb0d1209edb6c291474b1a1afa45bd5 (diff) | |
| download | linux-a0b977a3d19368b235f2a6c06e800fb25452029b.tar.xz | |
net: dsa: microchip: Set SPI as bus interface during reset for KSZ8463
At reset, the KSZ8463 uses a strap-based configuration to set SPI as
bus interface. SPI is the only bus supported by the driver. If the
required pull-ups/pull-downs are missing (by mistake or by design to
save power) the pins may float and the configuration can go wrong
preventing any communication with the switch.
Introduce a ksz8463_configure_straps_spi() function called during the
device reset. It relies on the 'straps-rxd-gpios' OF property and the
'reset' pinmux configuration to enforce SPI as bus interface.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
Link: https://patch.msgid.link/20250918-ksz-strap-pins-v3-3-16662e881728@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/dsa/microchip/ksz_common.c')
| -rw-r--r-- | drivers/net/dsa/microchip/ksz_common.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 9568cc391fe3..a962055bfdbd 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -23,6 +23,7 @@ #include <linux/of_mdio.h> #include <linux/of_net.h> #include <linux/micrel_phy.h> +#include <linux/pinctrl/consumer.h> #include <net/dsa.h> #include <net/ieee8021q.h> #include <net/pkt_cls.h> @@ -5345,6 +5346,38 @@ static int ksz_parse_drive_strength(struct ksz_device *dev) return 0; } +static int ksz8463_configure_straps_spi(struct ksz_device *dev) +{ + struct pinctrl *pinctrl; + struct gpio_desc *rxd0; + struct gpio_desc *rxd1; + + rxd0 = devm_gpiod_get_index_optional(dev->dev, "straps-rxd", 0, GPIOD_OUT_LOW); + if (IS_ERR(rxd0)) + return PTR_ERR(rxd0); + + rxd1 = devm_gpiod_get_index_optional(dev->dev, "straps-rxd", 1, GPIOD_OUT_HIGH); + if (IS_ERR(rxd1)) + return PTR_ERR(rxd1); + + if (!rxd0 && !rxd1) + return 0; + + if ((rxd0 && !rxd1) || (rxd1 && !rxd0)) + return -EINVAL; + + pinctrl = devm_pinctrl_get_select(dev->dev, "reset"); + if (IS_ERR(pinctrl)) + return PTR_ERR(pinctrl); + + return 0; +} + +static int ksz8463_release_straps_spi(struct ksz_device *dev) +{ + return pinctrl_select_default_state(dev->dev); +} + int ksz_switch_register(struct ksz_device *dev) { const struct ksz_chip_data *info; @@ -5360,10 +5393,22 @@ int ksz_switch_register(struct ksz_device *dev) return PTR_ERR(dev->reset_gpio); if (dev->reset_gpio) { + if (of_device_is_compatible(dev->dev->of_node, "microchip,ksz8463")) { + ret = ksz8463_configure_straps_spi(dev); + if (ret) + return ret; + } + gpiod_set_value_cansleep(dev->reset_gpio, 1); usleep_range(10000, 12000); gpiod_set_value_cansleep(dev->reset_gpio, 0); msleep(100); + + if (of_device_is_compatible(dev->dev->of_node, "microchip,ksz8463")) { + ret = ksz8463_release_straps_spi(dev); + if (ret) + return ret; + } } mutex_init(&dev->dev_mutex); |
