diff --git a/Documentation/devicetree/bindings/net/dsa/realtek.yaml b/Documentation/devicetree/bindings/net/dsa/realtek.yaml index 473facd87a62..b7bb60af623c 100644 --- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml +++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml @@ -8,6 +8,20 @@ title: Realtek switches for unmanaged switches allOf: - $ref: dsa.yaml#/$defs/ethernet-ports + - if: + not: + properties: + compatible: + contains: + const: realtek,rtl8365mb + then: + properties: + avddh-supply: false + avddl-supply: false + dvddio-supply: false + dvddio1-supply: false + dvddl-supply: false + pllvddl-supply: false maintainers: - Linus Walleij @@ -62,6 +76,24 @@ properties: resets: maxItems: 1 + avddh-supply: + description: AVDDH high-voltage analog supply. + + avddl-supply: + description: AVDDL low-voltage analog supply. + + dvddio-supply: + description: DVDDIO digital I/O supply. + + dvddio1-supply: + description: DVDDIO_1 secondary digital I/O supply for the RGMII bank. + + dvddl-supply: + description: DVDDL digital core supply. + + pllvddl-supply: + description: PLLVDDL PLL analog supply. + realtek,disable-leds: type: boolean description: | @@ -243,6 +275,7 @@ examples: platform { ethernet-switch { compatible = "realtek,rtl8365mb"; + avddh-supply = <&avddh>; mdc-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>; mdio-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h index 6e0148cee8d8..75a127545e5d 100644 --- a/drivers/net/dsa/realtek/realtek.h +++ b/drivers/net/dsa/realtek/realtek.h @@ -166,6 +166,9 @@ struct realtek_variant { u8 cmd_read; u8 cmd_write; size_t chip_data_sz; + /* Regulator supplies to enable at probe, or NULL */ + const char *const *supplies; + int num_supplies; }; /* RTL8366 library helpers */ diff --git a/drivers/net/dsa/realtek/rtl8365mb_main.c b/drivers/net/dsa/realtek/rtl8365mb_main.c index 728231d8f94c..4c305756116c 100644 --- a/drivers/net/dsa/realtek/rtl8365mb_main.c +++ b/drivers/net/dsa/realtek/rtl8365mb_main.c @@ -3334,6 +3334,10 @@ static const struct realtek_ops rtl8365mb_ops = { .phy_write = rtl8365mb_phy_write, }; +static const char *const rtl8365mb_supplies[] = { + "avddh", "avddl", "dvddio", "dvddio1", "dvddl", "pllvddl", +}; + const struct realtek_variant rtl8365mb_variant = { .ds_ops = &rtl8365mb_switch_ops, .ops = &rtl8365mb_ops, @@ -3342,6 +3346,8 @@ const struct realtek_variant rtl8365mb_variant = { .cmd_read = 0xb9, .cmd_write = 0xb8, .chip_data_sz = sizeof(struct rtl8365mb), + .supplies = rtl8365mb_supplies, + .num_supplies = ARRAY_SIZE(rtl8365mb_supplies), }; static const struct of_device_id rtl8365mb_of_match[] = { diff --git a/drivers/net/dsa/realtek/rtl83xx.c b/drivers/net/dsa/realtek/rtl83xx.c index a96beea72ef5..8121ec12fd8b 100644 --- a/drivers/net/dsa/realtek/rtl83xx.c +++ b/drivers/net/dsa/realtek/rtl83xx.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -195,17 +196,24 @@ rtl83xx_probe(struct device *dev, priv->leds_disabled = of_property_read_bool(dev->of_node, "realtek,disable-leds"); - /* TODO: if power is software controlled, set up any regulators here */ + /* Enable the supplies before the reset line is requested and driven, + * so the chip is powered before its pins are driven. + */ + if (var->num_supplies) { + ret = devm_regulator_bulk_get_enable(dev, var->num_supplies, + var->supplies); + if (ret) + return dev_err_ptr_probe(dev, ret, "failed to enable supplies\n"); + } + priv->reset_ctl = devm_reset_control_get_optional(dev, NULL); if (IS_ERR(priv->reset_ctl)) return dev_err_cast_probe(dev, priv->reset_ctl, "failed to get reset control\n"); priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(priv->reset)) { - dev_err(dev, "failed to get RESET GPIO\n"); - return ERR_CAST(priv->reset); - } + if (IS_ERR(priv->reset)) + return dev_err_cast_probe(dev, priv->reset, "failed to get RESET GPIO\n"); dev_set_drvdata(dev, priv); @@ -216,6 +224,11 @@ rtl83xx_probe(struct device *dev, rtl83xx_reset_deassert(priv); msleep(REALTEK_HW_START_DELAY); dev_dbg(dev, "deasserted RESET\n"); + } else if (var->num_supplies) { + /* Powered but no reset line: still wait for the chip to boot + * before the first register access. + */ + msleep(REALTEK_HW_START_DELAY); } return priv;