diff options
author | Guenter Roeck <linux@roeck-us.net> | 2014-04-15 22:16:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-16 15:09:51 -0400 |
commit | f1d54c47502f42f5c4b89dacbe845ecd87ca002e (patch) | |
tree | c1599c41838c6af66e2474daba28537ef0a6397c /drivers/net/phy | |
parent | 1d2514818a2c3d94dd250e6027cb928a4e192548 (diff) |
net: mdio-gpio: Add support for separate MDI and MDO gpio pins
This is for a system with fixed assignments of input and output pins
(various variants of Kontron COMe).
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/mdio-gpio.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index fac211a5001e..9c4defdec67b 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c | |||
@@ -32,8 +32,8 @@ | |||
32 | 32 | ||
33 | struct mdio_gpio_info { | 33 | struct mdio_gpio_info { |
34 | struct mdiobb_ctrl ctrl; | 34 | struct mdiobb_ctrl ctrl; |
35 | int mdc, mdio; | 35 | int mdc, mdio, mdo; |
36 | int mdc_active_low, mdio_active_low; | 36 | int mdc_active_low, mdio_active_low, mdo_active_low; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static void *mdio_gpio_of_get_data(struct platform_device *pdev) | 39 | static void *mdio_gpio_of_get_data(struct platform_device *pdev) |
@@ -60,6 +60,12 @@ static void *mdio_gpio_of_get_data(struct platform_device *pdev) | |||
60 | pdata->mdio = ret; | 60 | pdata->mdio = ret; |
61 | pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW; | 61 | pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW; |
62 | 62 | ||
63 | ret = of_get_gpio_flags(np, 2, &flags); | ||
64 | if (ret > 0) { | ||
65 | pdata->mdo = ret; | ||
66 | pdata->mdo_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
67 | } | ||
68 | |||
63 | return pdata; | 69 | return pdata; |
64 | } | 70 | } |
65 | 71 | ||
@@ -68,6 +74,16 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) | |||
68 | struct mdio_gpio_info *bitbang = | 74 | struct mdio_gpio_info *bitbang = |
69 | container_of(ctrl, struct mdio_gpio_info, ctrl); | 75 | container_of(ctrl, struct mdio_gpio_info, ctrl); |
70 | 76 | ||
77 | if (bitbang->mdo) { | ||
78 | /* Separate output pin. Always set its value to high | ||
79 | * when changing direction. If direction is input, | ||
80 | * assume the pin serves as pull-up. If direction is | ||
81 | * output, the default value is high. | ||
82 | */ | ||
83 | gpio_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low); | ||
84 | return; | ||
85 | } | ||
86 | |||
71 | if (dir) | 87 | if (dir) |
72 | gpio_direction_output(bitbang->mdio, | 88 | gpio_direction_output(bitbang->mdio, |
73 | 1 ^ bitbang->mdio_active_low); | 89 | 1 ^ bitbang->mdio_active_low); |
@@ -88,7 +104,10 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what) | |||
88 | struct mdio_gpio_info *bitbang = | 104 | struct mdio_gpio_info *bitbang = |
89 | container_of(ctrl, struct mdio_gpio_info, ctrl); | 105 | container_of(ctrl, struct mdio_gpio_info, ctrl); |
90 | 106 | ||
91 | gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low); | 107 | if (bitbang->mdo) |
108 | gpio_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low); | ||
109 | else | ||
110 | gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low); | ||
92 | } | 111 | } |
93 | 112 | ||
94 | static void mdc_set(struct mdiobb_ctrl *ctrl, int what) | 113 | static void mdc_set(struct mdiobb_ctrl *ctrl, int what) |
@@ -125,6 +144,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, | |||
125 | bitbang->mdc_active_low = pdata->mdc_active_low; | 144 | bitbang->mdc_active_low = pdata->mdc_active_low; |
126 | bitbang->mdio = pdata->mdio; | 145 | bitbang->mdio = pdata->mdio; |
127 | bitbang->mdio_active_low = pdata->mdio_active_low; | 146 | bitbang->mdio_active_low = pdata->mdio_active_low; |
147 | bitbang->mdo = pdata->mdo; | ||
148 | bitbang->mdo_active_low = pdata->mdo_active_low; | ||
128 | 149 | ||
129 | new_bus = alloc_mdio_bitbang(&bitbang->ctrl); | 150 | new_bus = alloc_mdio_bitbang(&bitbang->ctrl); |
130 | if (!new_bus) | 151 | if (!new_bus) |
@@ -151,6 +172,13 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, | |||
151 | if (devm_gpio_request(dev, bitbang->mdio, "mdio")) | 172 | if (devm_gpio_request(dev, bitbang->mdio, "mdio")) |
152 | goto out_free_bus; | 173 | goto out_free_bus; |
153 | 174 | ||
175 | if (bitbang->mdo) { | ||
176 | if (devm_gpio_request(dev, bitbang->mdo, "mdo")) | ||
177 | goto out_free_bus; | ||
178 | gpio_direction_output(bitbang->mdo, 1); | ||
179 | gpio_direction_input(bitbang->mdio); | ||
180 | } | ||
181 | |||
154 | gpio_direction_output(bitbang->mdc, 0); | 182 | gpio_direction_output(bitbang->mdc, 0); |
155 | 183 | ||
156 | dev_set_drvdata(dev, new_bus); | 184 | dev_set_drvdata(dev, new_bus); |