From: Ahmad Fatoum The power supplies powering the IC may not necessarily be enabled by the time the driver probes. The binding has been extended to describe the different power rails, so have the driver enable them in case they are specified. Signed-off-by: Alvin Šipraga Signed-off-by: Ahmad Fatoum Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel --- drivers/net/dsa/realtek/realtek.h | 2 ++ drivers/net/dsa/realtek/rtl8365mb_main.c | 5 +++ drivers/net/dsa/realtek/rtl83xx.c | 40 ++++++++++++++++++++---- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h index 6e0148cee8d8..ba31605423b1 100644 --- a/drivers/net/dsa/realtek/realtek.h +++ b/drivers/net/dsa/realtek/realtek.h @@ -166,6 +166,8 @@ struct realtek_variant { u8 cmd_read; u8 cmd_write; size_t chip_data_sz; + /* NULL-terminated list of regulator supply names, or NULL */ + const char *const *supplies; }; /* RTL8366 library helpers */ diff --git a/drivers/net/dsa/realtek/rtl8365mb_main.c b/drivers/net/dsa/realtek/rtl8365mb_main.c index 728231d8f94c..52ec4e91306c 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", NULL, +}; + const struct realtek_variant rtl8365mb_variant = { .ds_ops = &rtl8365mb_switch_ops, .ops = &rtl8365mb_ops, @@ -3342,6 +3346,7 @@ const struct realtek_variant rtl8365mb_variant = { .cmd_read = 0xb9, .cmd_write = 0xb8, .chip_data_sz = sizeof(struct rtl8365mb), + .supplies = 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 35df809a5951..fb6aaaa60aa3 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 @@ -113,6 +114,24 @@ int rtl83xx_setup_user_mdio(struct dsa_switch *ds) } EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, "REALTEK_DSA"); +static int rtl83xx_enable_supplies(struct device *dev, + const char *const *supplies) +{ + int i, ret, count = 0; + + for (i = 0; supplies && supplies[i]; i++) { + ret = devm_regulator_get_enable_optional(dev, supplies[i]); + if (ret == -ENODEV) + continue; + if (ret) + return dev_err_probe(dev, ret, "failed to enable %s supply\n", + supplies[i]); + count++; + } + + return count; +} + /** * rtl83xx_probe() - probe a Realtek switch * @dev: the device being probed @@ -145,6 +164,7 @@ rtl83xx_probe(struct device *dev, .lock = rtl83xx_lock, .unlock = rtl83xx_unlock, }; + int num_supplies; int ret; var = of_device_get_match_data(dev); @@ -195,17 +215,22 @@ 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 current is forced into its pins. + */ + num_supplies = rtl83xx_enable_supplies(dev, var->supplies); + if (num_supplies < 0) + return ERR_PTR(num_supplies); + 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); @@ -214,10 +239,13 @@ rtl83xx_probe(struct device *dev, dev_dbg(dev, "asserted RESET\n"); msleep(REALTEK_HW_STOP_DELAY); rtl83xx_reset_deassert(priv); - msleep(REALTEK_HW_START_DELAY); dev_dbg(dev, "deasserted RESET\n"); } + /* Wait for the chip to come up only if we powered and/or reset it. */ + if (priv->reset_ctl || priv->reset || num_supplies) + msleep(REALTEK_HW_START_DELAY); + return priv; } EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, "REALTEK_DSA"); -- 2.47.3