aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/mdio-gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/mdio-gpio.c')
-rw-r--r--drivers/net/phy/mdio-gpio.c77
1 files changed, 36 insertions, 41 deletions
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 33984b737233..22cdd451fb82 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -30,6 +30,7 @@
30 30
31#ifdef CONFIG_OF_GPIO 31#ifdef CONFIG_OF_GPIO
32#include <linux/of_gpio.h> 32#include <linux/of_gpio.h>
33#include <linux/of_mdio.h>
33#include <linux/of_platform.h> 34#include <linux/of_platform.h>
34#endif 35#endif
35 36
@@ -81,13 +82,12 @@ static struct mdiobb_ops mdio_gpio_ops = {
81 .get_mdio_data = mdio_get, 82 .get_mdio_data = mdio_get,
82}; 83};
83 84
84static int __devinit mdio_gpio_bus_init(struct device *dev, 85static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
85 struct mdio_gpio_platform_data *pdata, 86 struct mdio_gpio_platform_data *pdata,
86 int bus_id) 87 int bus_id)
87{ 88{
88 struct mii_bus *new_bus; 89 struct mii_bus *new_bus;
89 struct mdio_gpio_info *bitbang; 90 struct mdio_gpio_info *bitbang;
90 int ret = -ENOMEM;
91 int i; 91 int i;
92 92
93 bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL); 93 bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
@@ -104,8 +104,6 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
104 104
105 new_bus->name = "GPIO Bitbanged MDIO", 105 new_bus->name = "GPIO Bitbanged MDIO",
106 106
107 ret = -ENODEV;
108
109 new_bus->phy_mask = pdata->phy_mask; 107 new_bus->phy_mask = pdata->phy_mask;
110 new_bus->irq = pdata->irqs; 108 new_bus->irq = pdata->irqs;
111 new_bus->parent = dev; 109 new_bus->parent = dev;
@@ -129,15 +127,8 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
129 127
130 dev_set_drvdata(dev, new_bus); 128 dev_set_drvdata(dev, new_bus);
131 129
132 ret = mdiobus_register(new_bus); 130 return new_bus;
133 if (ret)
134 goto out_free_all;
135
136 return 0;
137 131
138out_free_all:
139 dev_set_drvdata(dev, NULL);
140 gpio_free(bitbang->mdio);
141out_free_mdc: 132out_free_mdc:
142 gpio_free(bitbang->mdc); 133 gpio_free(bitbang->mdc);
143out_free_bus: 134out_free_bus:
@@ -145,30 +136,47 @@ out_free_bus:
145out_free_bitbang: 136out_free_bitbang:
146 kfree(bitbang); 137 kfree(bitbang);
147out: 138out:
148 return ret; 139 return NULL;
149} 140}
150 141
151static void __devexit mdio_gpio_bus_destroy(struct device *dev) 142static void __devinit mdio_gpio_bus_deinit(struct device *dev)
152{ 143{
153 struct mii_bus *bus = dev_get_drvdata(dev); 144 struct mii_bus *bus = dev_get_drvdata(dev);
154 struct mdio_gpio_info *bitbang = bus->priv; 145 struct mdio_gpio_info *bitbang = bus->priv;
155 146
156 mdiobus_unregister(bus);
157 free_mdio_bitbang(bus);
158 dev_set_drvdata(dev, NULL); 147 dev_set_drvdata(dev, NULL);
159 gpio_free(bitbang->mdc);
160 gpio_free(bitbang->mdio); 148 gpio_free(bitbang->mdio);
149 gpio_free(bitbang->mdc);
150 free_mdio_bitbang(bus);
161 kfree(bitbang); 151 kfree(bitbang);
162} 152}
163 153
154static void __devexit mdio_gpio_bus_destroy(struct device *dev)
155{
156 struct mii_bus *bus = dev_get_drvdata(dev);
157
158 mdiobus_unregister(bus);
159 mdio_gpio_bus_deinit(dev);
160}
161
164static int __devinit mdio_gpio_probe(struct platform_device *pdev) 162static int __devinit mdio_gpio_probe(struct platform_device *pdev)
165{ 163{
166 struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data; 164 struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data;
165 struct mii_bus *new_bus;
166 int ret;
167 167
168 if (!pdata) 168 if (!pdata)
169 return -ENODEV; 169 return -ENODEV;
170 170
171 return mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id); 171 new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
172 if (!new_bus)
173 return -ENODEV;
174
175 ret = mdiobus_register(new_bus);
176 if (ret)
177 mdio_gpio_bus_deinit(&pdev->dev);
178
179 return ret;
172} 180}
173 181
174static int __devexit mdio_gpio_remove(struct platform_device *pdev) 182static int __devexit mdio_gpio_remove(struct platform_device *pdev)
@@ -179,29 +187,12 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev)
179} 187}
180 188
181#ifdef CONFIG_OF_GPIO 189#ifdef CONFIG_OF_GPIO
182static void __devinit add_phy(struct mdio_gpio_platform_data *pdata,
183 struct device_node *np)
184{
185 const u32 *data;
186 int len, id, irq;
187
188 data = of_get_property(np, "reg", &len);
189 if (!data || len != 4)
190 return;
191
192 id = *data;
193 pdata->phy_mask &= ~(1 << id);
194
195 irq = of_irq_to_resource(np, 0, NULL);
196 if (irq)
197 pdata->irqs[id] = irq;
198}
199 190
200static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, 191static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
201 const struct of_device_id *match) 192 const struct of_device_id *match)
202{ 193{
203 struct device_node *np = NULL;
204 struct mdio_gpio_platform_data *pdata; 194 struct mdio_gpio_platform_data *pdata;
195 struct mii_bus *new_bus;
205 int ret; 196 int ret;
206 197
207 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 198 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
@@ -215,14 +206,18 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
215 206
216 ret = of_get_gpio(ofdev->node, 1); 207 ret = of_get_gpio(ofdev->node, 1);
217 if (ret < 0) 208 if (ret < 0)
218 goto out_free; 209 goto out_free;
219 pdata->mdio = ret; 210 pdata->mdio = ret;
220 211
221 while ((np = of_get_next_child(ofdev->node, np))) 212 new_bus = mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
222 if (!strcmp(np->type, "ethernet-phy")) 213 if (!new_bus)
223 add_phy(pdata, np); 214 return -ENODEV;
224 215
225 return mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc); 216 ret = of_mdiobus_register(new_bus, ofdev->node);
217 if (ret)
218 mdio_gpio_bus_deinit(&ofdev->dev);
219
220 return ret;
226 221
227out_free: 222out_free:
228 kfree(pdata); 223 kfree(pdata);