From: Roger Quadros <rogerq@ti.com> To: <davem@davemloft.net> Cc: <tony@atomide.com>, <nsekhar@ti.com>, <jsarha@ti.com>, <netdev@vger.kernel.org>, <linux-omap@vger.kernel.org>, <linux-kernel@vger.kernel.org>, Roger Quadros <rogerq@ti.com> Subject: [PATCH] net: davinci_mdio: add GPIO reset logic Date: Wed, 5 Apr 2017 11:33:57 +0300 [thread overview] Message-ID: <1491381237-24635-1-git-send-email-rogerq@ti.com> (raw) Some boards [1] leave the PHYs at an invalid state during system power-up or reset thus causing unreliability issues with the PHY like not being detected by the mdio bus or link not functional. To work around these boards have a GPIO connected to the PHY's reset pin. Implement GPIO reset handling for such cases. [1] - am572x-idk, am571x-idk, a437x-idk. Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com> --- .../devicetree/bindings/net/davinci-mdio.txt | 2 + drivers/net/ethernet/ti/davinci_mdio.c | 68 +++++++++++++++++++--- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/net/davinci-mdio.txt b/Documentation/devicetree/bindings/net/davinci-mdio.txt index 621156c..fd6ebe7 100644 --- a/Documentation/devicetree/bindings/net/davinci-mdio.txt +++ b/Documentation/devicetree/bindings/net/davinci-mdio.txt @@ -12,6 +12,8 @@ Required properties: Optional properties: - ti,hwmods : Must be "davinci_mdio" +- reset-gpios : array of GPIO specifier for PHY hardware reset control +- reset-delay-us : reset assertion time [in microseconds] Note: "ti,hwmods" field is used to fetch the base address and irq resources from TI, omap hwmod data base during device registration. diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 33df340..c6f9e55 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -40,6 +40,9 @@ #include <linux/of_device.h> #include <linux/of_mdio.h> #include <linux/pinctrl/consumer.h> +#include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/of_gpio.h> /* * This timeout definition is a worst-case ultra defensive measure against @@ -53,6 +56,8 @@ #define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ +#define DEFAULT_GPIO_RESET_DELAY 10 /* in microseconds */ + struct davinci_mdio_of_param { int autosuspend_delay_ms; }; @@ -104,6 +109,9 @@ struct davinci_mdio_data { */ bool skip_scan; u32 clk_div; + struct gpio_desc **gpio_reset; + int num_gpios; + int reset_delay_us; }; static void davinci_mdio_init_clk(struct davinci_mdio_data *data) @@ -142,6 +150,20 @@ static void davinci_mdio_enable(struct davinci_mdio_data *data) __raw_writel(data->clk_div | CONTROL_ENABLE, &data->regs->control); } +static void __davinci_gpio_reset(struct davinci_mdio_data *data) +{ + int i; + + for (i = 0; i < data->num_gpios; i++) { + if (!data->gpio_reset[i]) + continue; + + gpiod_set_value_cansleep(data->gpio_reset[i], 1); + udelay(data->reset_delay_us); + gpiod_set_value_cansleep(data->gpio_reset[i], 0); + } +} + static int davinci_mdio_reset(struct mii_bus *bus) { struct davinci_mdio_data *data = bus->priv; @@ -317,20 +339,50 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id, } #if IS_ENABLED(CONFIG_OF) -static int davinci_mdio_probe_dt(struct mdio_platform_data *data, - struct platform_device *pdev) +static int davinci_mdio_probe_dt(struct davinci_mdio_data *data, + struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; u32 prop; - - if (!node) - return -EINVAL; + int error; + int i; + struct gpio_desc *gpiod; if (of_property_read_u32(node, "bus_freq", &prop)) { dev_err(&pdev->dev, "Missing bus_freq property in the DT.\n"); - return -EINVAL; + data->pdata = default_pdata; + } else { + data->pdata.bus_freq = prop; + } + + i = of_gpio_named_count(node, "reset-gpios"); + if (i > 0) { + data->num_gpios = i; + data->gpio_reset = devm_kcalloc(&pdev->dev, i, + sizeof(struct gpio_desc *), + GFP_KERNEL); + if (!data->gpio_reset) + return -ENOMEM; + + for (i = 0; i < data->num_gpios; i++) { + gpiod = devm_gpiod_get_index(&pdev->dev, "reset", i, + GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) { + error = PTR_ERR(gpiod); + if (error == -ENOENT) + continue; + else + return error; + } + data->gpio_reset[i] = gpiod; + } + + if (of_property_read_u32(node, "reset-delay-us", + &data->reset_delay_us)) + data->reset_delay_us = DEFAULT_GPIO_RESET_DELAY; + + __davinci_gpio_reset(data); } - data->bus_freq = prop; return 0; } @@ -372,7 +424,7 @@ static int davinci_mdio_probe(struct platform_device *pdev) if (dev->of_node) { const struct of_device_id *of_id; - ret = davinci_mdio_probe_dt(&data->pdata, pdev); + ret = davinci_mdio_probe_dt(data, pdev); if (ret) return ret; snprintf(data->bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); -- 2.7.4
WARNING: multiple messages have this Message-ID (diff)
From: Roger Quadros <rogerq@ti.com> To: davem@davemloft.net Cc: tony@atomide.com, nsekhar@ti.com, jsarha@ti.com, netdev@vger.kernel.org, linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org, Roger Quadros <rogerq@ti.com> Subject: [PATCH] net: davinci_mdio: add GPIO reset logic Date: Wed, 5 Apr 2017 11:33:57 +0300 [thread overview] Message-ID: <1491381237-24635-1-git-send-email-rogerq@ti.com> (raw) Some boards [1] leave the PHYs at an invalid state during system power-up or reset thus causing unreliability issues with the PHY like not being detected by the mdio bus or link not functional. To work around these boards have a GPIO connected to the PHY's reset pin. Implement GPIO reset handling for such cases. [1] - am572x-idk, am571x-idk, a437x-idk. Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com> --- .../devicetree/bindings/net/davinci-mdio.txt | 2 + drivers/net/ethernet/ti/davinci_mdio.c | 68 +++++++++++++++++++--- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/net/davinci-mdio.txt b/Documentation/devicetree/bindings/net/davinci-mdio.txt index 621156c..fd6ebe7 100644 --- a/Documentation/devicetree/bindings/net/davinci-mdio.txt +++ b/Documentation/devicetree/bindings/net/davinci-mdio.txt @@ -12,6 +12,8 @@ Required properties: Optional properties: - ti,hwmods : Must be "davinci_mdio" +- reset-gpios : array of GPIO specifier for PHY hardware reset control +- reset-delay-us : reset assertion time [in microseconds] Note: "ti,hwmods" field is used to fetch the base address and irq resources from TI, omap hwmod data base during device registration. diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 33df340..c6f9e55 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -40,6 +40,9 @@ #include <linux/of_device.h> #include <linux/of_mdio.h> #include <linux/pinctrl/consumer.h> +#include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/of_gpio.h> /* * This timeout definition is a worst-case ultra defensive measure against @@ -53,6 +56,8 @@ #define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ +#define DEFAULT_GPIO_RESET_DELAY 10 /* in microseconds */ + struct davinci_mdio_of_param { int autosuspend_delay_ms; }; @@ -104,6 +109,9 @@ struct davinci_mdio_data { */ bool skip_scan; u32 clk_div; + struct gpio_desc **gpio_reset; + int num_gpios; + int reset_delay_us; }; static void davinci_mdio_init_clk(struct davinci_mdio_data *data) @@ -142,6 +150,20 @@ static void davinci_mdio_enable(struct davinci_mdio_data *data) __raw_writel(data->clk_div | CONTROL_ENABLE, &data->regs->control); } +static void __davinci_gpio_reset(struct davinci_mdio_data *data) +{ + int i; + + for (i = 0; i < data->num_gpios; i++) { + if (!data->gpio_reset[i]) + continue; + + gpiod_set_value_cansleep(data->gpio_reset[i], 1); + udelay(data->reset_delay_us); + gpiod_set_value_cansleep(data->gpio_reset[i], 0); + } +} + static int davinci_mdio_reset(struct mii_bus *bus) { struct davinci_mdio_data *data = bus->priv; @@ -317,20 +339,50 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id, } #if IS_ENABLED(CONFIG_OF) -static int davinci_mdio_probe_dt(struct mdio_platform_data *data, - struct platform_device *pdev) +static int davinci_mdio_probe_dt(struct davinci_mdio_data *data, + struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; u32 prop; - - if (!node) - return -EINVAL; + int error; + int i; + struct gpio_desc *gpiod; if (of_property_read_u32(node, "bus_freq", &prop)) { dev_err(&pdev->dev, "Missing bus_freq property in the DT.\n"); - return -EINVAL; + data->pdata = default_pdata; + } else { + data->pdata.bus_freq = prop; + } + + i = of_gpio_named_count(node, "reset-gpios"); + if (i > 0) { + data->num_gpios = i; + data->gpio_reset = devm_kcalloc(&pdev->dev, i, + sizeof(struct gpio_desc *), + GFP_KERNEL); + if (!data->gpio_reset) + return -ENOMEM; + + for (i = 0; i < data->num_gpios; i++) { + gpiod = devm_gpiod_get_index(&pdev->dev, "reset", i, + GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) { + error = PTR_ERR(gpiod); + if (error == -ENOENT) + continue; + else + return error; + } + data->gpio_reset[i] = gpiod; + } + + if (of_property_read_u32(node, "reset-delay-us", + &data->reset_delay_us)) + data->reset_delay_us = DEFAULT_GPIO_RESET_DELAY; + + __davinci_gpio_reset(data); } - data->bus_freq = prop; return 0; } @@ -372,7 +424,7 @@ static int davinci_mdio_probe(struct platform_device *pdev) if (dev->of_node) { const struct of_device_id *of_id; - ret = davinci_mdio_probe_dt(&data->pdata, pdev); + ret = davinci_mdio_probe_dt(data, pdev); if (ret) return ret; snprintf(data->bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); -- 2.7.4
next reply other threads:[~2017-04-05 8:34 UTC|newest] Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-04-05 8:33 Roger Quadros [this message] 2017-04-05 8:33 ` [PATCH] net: davinci_mdio: add GPIO reset logic Roger Quadros 2017-04-05 15:03 ` Andrew Lunn 2017-04-06 9:15 ` Roger Quadros 2017-04-06 9:15 ` Roger Quadros 2017-04-06 12:05 ` Andrew Lunn 2017-04-06 16:48 ` Roger Quadros 2017-04-06 16:48 ` Roger Quadros 2017-04-08 13:55 ` David Miller 2017-04-08 15:10 ` Andrew Lunn 2017-04-08 15:18 ` Florian Fainelli 2017-04-10 7:52 ` Roger Quadros 2017-04-10 7:52 ` Roger Quadros 2017-04-19 9:24 ` [PATCH] mdio_bus: Issue GPIO RESET to PHYs Roger Quadros 2017-04-19 9:24 ` Roger Quadros 2017-04-19 11:39 ` Andrew Lunn 2017-04-19 11:56 ` Roger Quadros 2017-04-19 11:56 ` Roger Quadros 2017-04-19 13:38 ` Andrew Lunn 2017-04-20 7:58 ` Roger Quadros 2017-04-20 7:58 ` Roger Quadros 2017-04-20 8:39 ` [PATCH v2] " Roger Quadros 2017-04-20 8:39 ` Roger Quadros 2017-04-20 13:13 ` Andrew Lunn 2017-04-20 13:56 ` Roger Quadros 2017-04-20 13:56 ` Roger Quadros 2017-04-20 14:11 ` [PATCH v3 net-next] " Roger Quadros 2017-04-20 14:11 ` Roger Quadros 2017-04-21 1:12 ` Andrew Lunn 2017-04-21 1:23 ` Florian Fainelli 2017-04-21 1:38 ` Andrew Lunn 2017-04-21 8:04 ` Roger Quadros 2017-04-21 8:04 ` Roger Quadros 2017-04-21 13:15 ` [PATCH v4 " Roger Quadros 2017-04-21 13:15 ` Roger Quadros 2017-04-21 13:31 ` Lars-Peter Clausen 2017-04-23 23:35 ` Andrew Lunn 2017-04-24 9:04 ` Roger Quadros 2017-04-24 9:04 ` Roger Quadros 2017-04-24 16:32 ` Florian Fainelli 2017-04-25 16:22 ` Lars-Peter Clausen 2017-04-25 16:31 ` Florian Fainelli 2017-04-26 10:46 ` Roger Quadros 2017-04-26 10:46 ` Roger Quadros 2017-04-26 12:27 ` Andrew Lunn 2017-04-26 10:43 ` Roger Quadros 2017-04-26 10:43 ` Roger Quadros 2017-04-24 16:40 ` David Miller
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1491381237-24635-1-git-send-email-rogerq@ti.com \ --to=rogerq@ti.com \ --cc=davem@davemloft.net \ --cc=jsarha@ti.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-omap@vger.kernel.org \ --cc=netdev@vger.kernel.org \ --cc=nsekhar@ti.com \ --cc=tony@atomide.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.