diff --git a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml index eb4607460db7..a8c8009414ae 100644 --- a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml +++ b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml @@ -10,9 +10,6 @@ maintainers: - Marek Vasut - Woojung Huh -allOf: - - $ref: /schemas/spi/spi-peripheral-props.yaml# - properties: # See Documentation/devicetree/bindings/net/dsa/dsa.yaml for a list of additional # required and optional properties. @@ -37,6 +34,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. @@ -107,38 +111,53 @@ required: - compatible - reg -if: - not: - properties: - compatible: - enum: - - microchip,ksz8863 - - microchip,ksz8873 -then: - $ref: dsa.yaml#/$defs/ethernet-ports -else: - patternProperties: - "^(ethernet-)?ports$": +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + + - if: + not: + properties: + compatible: + enum: + - microchip,ksz8863 + - microchip,ksz8873 + then: + $ref: dsa.yaml#/$defs/ethernet-ports + else: patternProperties: - "^(ethernet-)?port@[0-2]$": - $ref: dsa-port.yaml# - unevaluatedProperties: false - properties: - microchip,rmii-clk-internal: - $ref: /schemas/types.yaml#/definitions/flag - description: - When ksz88x3 is acting as clock provier (via REFCLKO) it - can select between internal and external RMII reference - clock. Internal reference clock means that the clock for - the RMII of ksz88x3 is provided by the ksz88x3 internally - and the REFCLKI pin is unconnected. For the external - reference clock, the clock needs to be fed back to ksz88x3 - via REFCLKI. - If microchip,rmii-clk-internal is set, ksz88x3 will provide - rmii reference clock internally, otherwise reference clock - should be provided externally. - dependencies: - microchip,rmii-clk-internal: [ethernet] + "^(ethernet-)?ports$": + patternProperties: + "^(ethernet-)?port@[0-2]$": + $ref: dsa-port.yaml# + unevaluatedProperties: false + properties: + microchip,rmii-clk-internal: + $ref: /schemas/types.yaml#/definitions/flag + description: + When ksz88x3 is acting as clock provier (via REFCLKO) it + can select between internal and external RMII reference + clock. Internal reference clock means that the clock for + the RMII of ksz88x3 is provided by the ksz88x3 internally + and the REFCLKI pin is unconnected. For the external + reference clock, the clock needs to be fed back to ksz88x3 + via REFCLKI. + If microchip,rmii-clk-internal is set, ksz88x3 will provide + rmii reference clock internally, otherwise reference clock + should be provided externally. + dependencies: + microchip,rmii-clk-internal: [ethernet] + - if: + properties: + compatible: + contains: + const: microchip,ksz8463 + then: + properties: + straps-rxd-gpios: + description: + RXD0 and RXD1 pins, used to select SPI as bus interface. + minItems: 2 + maxItems: 2 unevaluatedProperties: false 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 #include #include +#include #include #include #include @@ -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);