At reset, some KSZ switches use strap-based configuration. 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. Add a strap description that can be used by the driver to drive the strap pins during reset. It consists of a 'reset' pinmux configuration and a set of strap GPIOs. Since the pins used and the nature of the configuration differ from one KSZ switch to another, GPIO names aren't used. Signed-off-by: Bastien Curutchet (Schneider Electric) --- Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml index eb4607460db7f32a4dffd416e44b61c2674f731e..f40a5e3cd0e4d39c809a1fb6697bc3bc64f35fec 100644 --- a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml +++ b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml @@ -37,6 +37,13 @@ properties: - microchip,ksz8567 - microchip,lan9646 + pinctrl-names: + items: + - const: default + - const: reset + description: + Used during reset for strap configuration. + reset-gpios: description: Should be a gpio specifier for a reset line. @@ -80,6 +87,11 @@ properties: enum: [2000, 4000, 8000, 12000, 16000, 20000, 24000, 28000] default: 8000 + strap-gpios: + description: + Strap pins to drive during reset. For KSZ8463, the first GPIO drives the + RXDO line, the second one drives the RXD1 line. + interrupts: maxItems: 1 -- 2.51.0 At reset, some KSZ switches use strap based configuration. 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. Introduce a configure_strap() function, called during the device reset. It relies on the 'strap-gpios' OF property and the 'reset' pinmux configuration to drive the configuration pins to the proper state. Support the KSZ8463's strap configuration that enforces SPI as communication bus, since it is the only bus supported by the driver. Signed-off-by: Bastien Curutchet (Schneider Electric) --- drivers/net/dsa/microchip/ksz_common.c | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 7292bfe2f7cac3a0d88bb51339cc287f56ca1d1f..0ab201a3c336b99ba92d87c003ba48f7f82a098a 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -5338,6 +5339,44 @@ static int ksz_parse_drive_strength(struct ksz_device *dev) return 0; } +static int ksz_configure_strap(struct ksz_device *dev) +{ + struct pinctrl_state *state = NULL; + struct pinctrl *pinctrl; + int ret; + + if (of_device_is_compatible(dev->dev->of_node, "microchip,ksz8463")) { + struct gpio_desc *rxd0; + struct gpio_desc *rxd1; + + rxd0 = devm_gpiod_get_index_optional(dev->dev, "strap", 0, GPIOD_OUT_LOW); + if (IS_ERR(rxd0)) + return PTR_ERR(rxd0); + + rxd1 = devm_gpiod_get_index_optional(dev->dev, "strap", 1, GPIOD_OUT_HIGH); + if (IS_ERR(rxd1)) + return PTR_ERR(rxd1); + + /* If at least one strap definition is missing we don't do anything */ + if (!rxd0 || !rxd1) + return 0; + + pinctrl = devm_pinctrl_get(dev->dev); + if (IS_ERR(pinctrl)) + return PTR_ERR(pinctrl); + + state = pinctrl_lookup_state(pinctrl, "reset"); + if (IS_ERR(state)) + return PTR_ERR(state); + + ret = pinctrl_select_state(pinctrl, state); + if (ret) + return ret; + } + + return 0; +} + int ksz_switch_register(struct ksz_device *dev) { const struct ksz_chip_data *info; @@ -5353,10 +5392,18 @@ int ksz_switch_register(struct ksz_device *dev) return PTR_ERR(dev->reset_gpio); if (dev->reset_gpio) { + ret = ksz_configure_strap(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); + + ret = pinctrl_select_default_state(dev->dev); + if (ret) + return ret; } mutex_init(&dev->dev_mutex); -- 2.51.0