aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2014-04-15 22:16:41 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-16 15:09:51 -0400
commit1d2514818a2c3d94dd250e6027cb928a4e192548 (patch)
treec4ff94f2b9df1d5b96c5c46b2bc4d02b1167ed04
parent78cdb079685cd8365acaf9fce896137e7d60e1c1 (diff)
net: mdio-gpio: Add support for active low gpio pins
Some systems using mdio-gpio may use active-low gpio pins (eg with inverters or FETs connected to all or some of the gpio pins). Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/mdio-gpio.c19
-rw-r--r--include/linux/mdio-gpio.h3
2 files changed, 16 insertions, 6 deletions
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index e853066c805a..fac211a5001e 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -33,28 +33,32 @@
33struct mdio_gpio_info { 33struct mdio_gpio_info {
34 struct mdiobb_ctrl ctrl; 34 struct mdiobb_ctrl ctrl;
35 int mdc, mdio; 35 int mdc, mdio;
36 int mdc_active_low, mdio_active_low;
36}; 37};
37 38
38static void *mdio_gpio_of_get_data(struct platform_device *pdev) 39static void *mdio_gpio_of_get_data(struct platform_device *pdev)
39{ 40{
40 struct device_node *np = pdev->dev.of_node; 41 struct device_node *np = pdev->dev.of_node;
41 struct mdio_gpio_platform_data *pdata; 42 struct mdio_gpio_platform_data *pdata;
43 enum of_gpio_flags flags;
42 int ret; 44 int ret;
43 45
44 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 46 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
45 if (!pdata) 47 if (!pdata)
46 return NULL; 48 return NULL;
47 49
48 ret = of_get_gpio(np, 0); 50 ret = of_get_gpio_flags(np, 0, &flags);
49 if (ret < 0) 51 if (ret < 0)
50 return NULL; 52 return NULL;
51 53
52 pdata->mdc = ret; 54 pdata->mdc = ret;
55 pdata->mdc_active_low = flags & OF_GPIO_ACTIVE_LOW;
53 56
54 ret = of_get_gpio(np, 1); 57 ret = of_get_gpio_flags(np, 1, &flags);
55 if (ret < 0) 58 if (ret < 0)
56 return NULL; 59 return NULL;
57 pdata->mdio = ret; 60 pdata->mdio = ret;
61 pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW;
58 62
59 return pdata; 63 return pdata;
60} 64}
@@ -65,7 +69,8 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
65 container_of(ctrl, struct mdio_gpio_info, ctrl); 69 container_of(ctrl, struct mdio_gpio_info, ctrl);
66 70
67 if (dir) 71 if (dir)
68 gpio_direction_output(bitbang->mdio, 1); 72 gpio_direction_output(bitbang->mdio,
73 1 ^ bitbang->mdio_active_low);
69 else 74 else
70 gpio_direction_input(bitbang->mdio); 75 gpio_direction_input(bitbang->mdio);
71} 76}
@@ -75,7 +80,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
75 struct mdio_gpio_info *bitbang = 80 struct mdio_gpio_info *bitbang =
76 container_of(ctrl, struct mdio_gpio_info, ctrl); 81 container_of(ctrl, struct mdio_gpio_info, ctrl);
77 82
78 return gpio_get_value(bitbang->mdio); 83 return gpio_get_value(bitbang->mdio) ^ bitbang->mdio_active_low;
79} 84}
80 85
81static void mdio_set(struct mdiobb_ctrl *ctrl, int what) 86static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -83,7 +88,7 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
83 struct mdio_gpio_info *bitbang = 88 struct mdio_gpio_info *bitbang =
84 container_of(ctrl, struct mdio_gpio_info, ctrl); 89 container_of(ctrl, struct mdio_gpio_info, ctrl);
85 90
86 gpio_set_value(bitbang->mdio, what); 91 gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low);
87} 92}
88 93
89static void mdc_set(struct mdiobb_ctrl *ctrl, int what) 94static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -91,7 +96,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
91 struct mdio_gpio_info *bitbang = 96 struct mdio_gpio_info *bitbang =
92 container_of(ctrl, struct mdio_gpio_info, ctrl); 97 container_of(ctrl, struct mdio_gpio_info, ctrl);
93 98
94 gpio_set_value(bitbang->mdc, what); 99 gpio_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low);
95} 100}
96 101
97static struct mdiobb_ops mdio_gpio_ops = { 102static struct mdiobb_ops mdio_gpio_ops = {
@@ -117,7 +122,9 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
117 bitbang->ctrl.ops = &mdio_gpio_ops; 122 bitbang->ctrl.ops = &mdio_gpio_ops;
118 bitbang->ctrl.reset = pdata->reset; 123 bitbang->ctrl.reset = pdata->reset;
119 bitbang->mdc = pdata->mdc; 124 bitbang->mdc = pdata->mdc;
125 bitbang->mdc_active_low = pdata->mdc_active_low;
120 bitbang->mdio = pdata->mdio; 126 bitbang->mdio = pdata->mdio;
127 bitbang->mdio_active_low = pdata->mdio_active_low;
121 128
122 new_bus = alloc_mdio_bitbang(&bitbang->ctrl); 129 new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
123 if (!new_bus) 130 if (!new_bus)
diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h
index 7c9fe3c2be73..57e57fe6055c 100644
--- a/include/linux/mdio-gpio.h
+++ b/include/linux/mdio-gpio.h
@@ -18,6 +18,9 @@ struct mdio_gpio_platform_data {
18 unsigned int mdc; 18 unsigned int mdc;
19 unsigned int mdio; 19 unsigned int mdio;
20 20
21 bool mdc_active_low;
22 bool mdio_active_low;
23
21 unsigned int phy_mask; 24 unsigned int phy_mask;
22 int irqs[PHY_MAX_ADDR]; 25 int irqs[PHY_MAX_ADDR];
23 /* reset callback */ 26 /* reset callback */