Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
[linux-2.6] / drivers / net / fs_enet / mii-bitbang.c
1 /*
2  * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
3  *
4  * Copyright (c) 2003 Intracom S.A.
5  *  by Pantelis Antoniou <panto@intracom.gr>
6  *
7  * 2005 (c) MontaVista Software, Inc.
8  * Vitaly Bordug <vbordug@ru.mvista.com>
9  *
10  * This file is licensed under the terms of the GNU General Public License
11  * version 2. This program is licensed "as is" without any warranty of any
12  * kind, whether express or implied.
13  */
14
15 #include <linux/module.h>
16 #include <linux/ioport.h>
17 #include <linux/slab.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/netdevice.h>
21 #include <linux/etherdevice.h>
22 #include <linux/mii.h>
23 #include <linux/platform_device.h>
24 #include <linux/mdio-bitbang.h>
25
26 #ifdef CONFIG_PPC_CPM_NEW_BINDING
27 #include <linux/of_platform.h>
28 #endif
29
30 #include "fs_enet.h"
31
32 struct bb_info {
33         struct mdiobb_ctrl ctrl;
34         __be32 __iomem *dir;
35         __be32 __iomem *dat;
36         u32 mdio_msk;
37         u32 mdc_msk;
38 };
39
40 /* FIXME: If any other users of GPIO crop up, then these will have to
41  * have some sort of global synchronization to avoid races with other
42  * pins on the same port.  The ideal solution would probably be to
43  * bind the ports to a GPIO driver, and have this be a client of it.
44  */
45 static inline void bb_set(u32 __iomem *p, u32 m)
46 {
47         out_be32(p, in_be32(p) | m);
48 }
49
50 static inline void bb_clr(u32 __iomem *p, u32 m)
51 {
52         out_be32(p, in_be32(p) & ~m);
53 }
54
55 static inline int bb_read(u32 __iomem *p, u32 m)
56 {
57         return (in_be32(p) & m) != 0;
58 }
59
60 static inline void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
61 {
62         struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
63
64         if (dir)
65                 bb_set(bitbang->dir, bitbang->mdio_msk);
66         else
67                 bb_clr(bitbang->dir, bitbang->mdio_msk);
68
69         /* Read back to flush the write. */
70         in_be32(bitbang->dir);
71 }
72
73 static inline int mdio_read(struct mdiobb_ctrl *ctrl)
74 {
75         struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
76         return bb_read(bitbang->dat, bitbang->mdio_msk);
77 }
78
79 static inline void mdio(struct mdiobb_ctrl *ctrl, int what)
80 {
81         struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
82
83         if (what)
84                 bb_set(bitbang->dat, bitbang->mdio_msk);
85         else
86                 bb_clr(bitbang->dat, bitbang->mdio_msk);
87
88         /* Read back to flush the write. */
89         in_be32(bitbang->dat);
90 }
91
92 static inline void mdc(struct mdiobb_ctrl *ctrl, int what)
93 {
94         struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
95
96         if (what)
97                 bb_set(bitbang->dat, bitbang->mdc_msk);
98         else
99                 bb_clr(bitbang->dat, bitbang->mdc_msk);
100
101         /* Read back to flush the write. */
102         in_be32(bitbang->dat);
103 }
104
105 static struct mdiobb_ops bb_ops = {
106         .owner = THIS_MODULE,
107         .set_mdc = mdc,
108         .set_mdio_dir = mdio_dir,
109         .set_mdio_data = mdio,
110         .get_mdio_data = mdio_read,
111 };
112
113 #ifdef CONFIG_PPC_CPM_NEW_BINDING
114 static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
115                                          struct device_node *np)
116 {
117         struct resource res;
118         const u32 *data;
119         int mdio_pin, mdc_pin, len;
120         struct bb_info *bitbang = bus->priv;
121
122         int ret = of_address_to_resource(np, 0, &res);
123         if (ret)
124                 return ret;
125
126         if (res.end - res.start < 13)
127                 return -ENODEV;
128
129         /* This should really encode the pin number as well, but all
130          * we get is an int, and the odds of multiple bitbang mdio buses
131          * is low enough that it's not worth going too crazy.
132          */
133         bus->id = res.start;
134
135         data = of_get_property(np, "fsl,mdio-pin", &len);
136         if (!data || len != 4)
137                 return -ENODEV;
138         mdio_pin = *data;
139
140         data = of_get_property(np, "fsl,mdc-pin", &len);
141         if (!data || len != 4)
142                 return -ENODEV;
143         mdc_pin = *data;
144
145         bitbang->dir = ioremap(res.start, res.end - res.start + 1);
146         if (!bitbang->dir)
147                 return -ENOMEM;
148
149         bitbang->dat = bitbang->dir + 4;
150         bitbang->mdio_msk = 1 << (31 - mdio_pin);
151         bitbang->mdc_msk = 1 << (31 - mdc_pin);
152
153         return 0;
154 }
155
156 static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
157 {
158         const u32 *data;
159         int len, id, irq;
160
161         data = of_get_property(np, "reg", &len);
162         if (!data || len != 4)
163                 return;
164
165         id = *data;
166         bus->phy_mask &= ~(1 << id);
167
168         irq = of_irq_to_resource(np, 0, NULL);
169         if (irq != NO_IRQ)
170                 bus->irq[id] = irq;
171 }
172
173 static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
174                                         const struct of_device_id *match)
175 {
176         struct device_node *np = NULL;
177         struct mii_bus *new_bus;
178         struct bb_info *bitbang;
179         int ret = -ENOMEM;
180         int i;
181
182         bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
183         if (!bitbang)
184                 goto out;
185
186         bitbang->ctrl.ops = &bb_ops;
187
188         new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
189         if (!new_bus)
190                 goto out_free_priv;
191
192         new_bus->name = "CPM2 Bitbanged MII",
193
194         ret = fs_mii_bitbang_init(new_bus, ofdev->node);
195         if (ret)
196                 goto out_free_bus;
197
198         new_bus->phy_mask = ~0;
199         new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
200         if (!new_bus->irq)
201                 goto out_unmap_regs;
202
203         for (i = 0; i < PHY_MAX_ADDR; i++)
204                 new_bus->irq[i] = -1;
205
206         while ((np = of_get_next_child(ofdev->node, np)))
207                 if (!strcmp(np->type, "ethernet-phy"))
208                         add_phy(new_bus, np);
209
210         new_bus->dev = &ofdev->dev;
211         dev_set_drvdata(&ofdev->dev, new_bus);
212
213         ret = mdiobus_register(new_bus);
214         if (ret)
215                 goto out_free_irqs;
216
217         return 0;
218
219 out_free_irqs:
220         dev_set_drvdata(&ofdev->dev, NULL);
221         kfree(new_bus->irq);
222 out_unmap_regs:
223         iounmap(bitbang->dir);
224 out_free_bus:
225         kfree(new_bus);
226 out_free_priv:
227         free_mdio_bitbang(new_bus);
228 out:
229         return ret;
230 }
231
232 static int fs_enet_mdio_remove(struct of_device *ofdev)
233 {
234         struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
235         struct bb_info *bitbang = bus->priv;
236
237         mdiobus_unregister(bus);
238         free_mdio_bitbang(bus);
239         dev_set_drvdata(&ofdev->dev, NULL);
240         kfree(bus->irq);
241         iounmap(bitbang->dir);
242         kfree(bitbang);
243         kfree(bus);
244
245         return 0;
246 }
247
248 static struct of_device_id fs_enet_mdio_bb_match[] = {
249         {
250                 .compatible = "fsl,cpm2-mdio-bitbang",
251         },
252         {},
253 };
254
255 static struct of_platform_driver fs_enet_bb_mdio_driver = {
256         .name = "fsl-bb-mdio",
257         .match_table = fs_enet_mdio_bb_match,
258         .probe = fs_enet_mdio_probe,
259         .remove = fs_enet_mdio_remove,
260 };
261
262 static int fs_enet_mdio_bb_init(void)
263 {
264         return of_register_platform_driver(&fs_enet_bb_mdio_driver);
265 }
266
267 static void fs_enet_mdio_bb_exit(void)
268 {
269         of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
270 }
271
272 module_init(fs_enet_mdio_bb_init);
273 module_exit(fs_enet_mdio_bb_exit);
274 #else
275 static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
276                                          struct fs_mii_bb_platform_info *fmpi)
277 {
278         bitbang->dir = (u32 __iomem *)fmpi->mdio_dir.offset;
279         bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
280         bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
281         bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
282
283         return 0;
284 }
285
286 static int __devinit fs_enet_mdio_probe(struct device *dev)
287 {
288         struct platform_device *pdev = to_platform_device(dev);
289         struct fs_mii_bb_platform_info *pdata;
290         struct mii_bus *new_bus;
291         struct bb_info *bitbang;
292         int err = 0;
293
294         if (NULL == dev)
295                 return -EINVAL;
296
297         bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
298
299         if (NULL == bitbang)
300                 return -ENOMEM;
301
302         bitbang->ctrl.ops = &bb_ops;
303
304         new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
305
306         if (NULL == new_bus)
307                 return -ENOMEM;
308
309         new_bus->name = "BB MII Bus",
310         new_bus->id = pdev->id;
311
312         new_bus->phy_mask = ~0x9;
313         pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
314
315         if (NULL == pdata) {
316                 printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
317                 return -ENODEV;
318         }
319
320         /*set up workspace*/
321         fs_mii_bitbang_init(bitbang, pdata);
322
323         new_bus->priv = bitbang;
324
325         new_bus->irq = pdata->irq;
326
327         new_bus->dev = dev;
328         dev_set_drvdata(dev, new_bus);
329
330         err = mdiobus_register(new_bus);
331
332         if (0 != err) {
333                 printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
334                                 new_bus->name);
335                 goto bus_register_fail;
336         }
337
338         return 0;
339
340 bus_register_fail:
341         free_mdio_bitbang(new_bus);
342         kfree(bitbang);
343
344         return err;
345 }
346
347 static int fs_enet_mdio_remove(struct device *dev)
348 {
349         struct mii_bus *bus = dev_get_drvdata(dev);
350
351         mdiobus_unregister(bus);
352
353         dev_set_drvdata(dev, NULL);
354
355         free_mdio_bitbang(bus);
356
357         return 0;
358 }
359
360 static struct device_driver fs_enet_bb_mdio_driver = {
361         .name = "fsl-bb-mdio",
362         .bus = &platform_bus_type,
363         .probe = fs_enet_mdio_probe,
364         .remove = fs_enet_mdio_remove,
365 };
366
367 int fs_enet_mdio_bb_init(void)
368 {
369         return driver_register(&fs_enet_bb_mdio_driver);
370 }
371
372 void fs_enet_mdio_bb_exit(void)
373 {
374         driver_unregister(&fs_enet_bb_mdio_driver);
375 }
376 #endif