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:33 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: link
Be 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.