aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet/mii-bitbang.c
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2007-10-01 15:20:57 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:54:04 -0400
commit2b5b3a604a672be1d41728ed9e448ca3c9c23242 (patch)
treef396075face85b4a686ef59adc4a9df0120dd01f /drivers/net/fs_enet/mii-bitbang.c
parente2ec4581adf7e288c193e981c39ca01cdb20a272 (diff)
fs_enet: Convert mii-bitbang to use the generic bitbang MDIO code.
Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/fs_enet/mii-bitbang.c')
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c270
1 files changed, 54 insertions, 216 deletions
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 7cf132f0f952..b8e4a736a130 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -15,15 +15,13 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/ioport.h> 16#include <linux/ioport.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/interrupt.h>
19#include <linux/init.h> 18#include <linux/init.h>
20#include <linux/delay.h> 19#include <linux/interrupt.h>
21#include <linux/netdevice.h> 20#include <linux/netdevice.h>
22#include <linux/etherdevice.h> 21#include <linux/etherdevice.h>
23#include <linux/mii.h> 22#include <linux/mii.h>
24#include <linux/ethtool.h>
25#include <linux/bitops.h>
26#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/mdio-bitbang.h>
27 25
28#ifdef CONFIG_PPC_CPM_NEW_BINDING 26#ifdef CONFIG_PPC_CPM_NEW_BINDING
29#include <linux/of_platform.h> 27#include <linux/of_platform.h>
@@ -32,11 +30,11 @@
32#include "fs_enet.h" 30#include "fs_enet.h"
33 31
34struct bb_info { 32struct bb_info {
33 struct mdiobb_ctrl ctrl;
35 __be32 __iomem *dir; 34 __be32 __iomem *dir;
36 __be32 __iomem *dat; 35 __be32 __iomem *dat;
37 u32 mdio_msk; 36 u32 mdio_msk;
38 u32 mdc_msk; 37 u32 mdc_msk;
39 int delay;
40}; 38};
41 39
42/* FIXME: If any other users of GPIO crop up, then these will have to 40/* FIXME: If any other users of GPIO crop up, then these will have to
@@ -59,212 +57,58 @@ static inline int bb_read(u32 __iomem *p, u32 m)
59 return (in_be32(p) & m) != 0; 57 return (in_be32(p) & m) != 0;
60} 58}
61 59
62static inline void mdio_active(struct bb_info *bitbang) 60static inline void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
63{ 61{
64 bb_set(bitbang->dir, bitbang->mdio_msk); 62 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
65}
66 63
67static inline void mdio_tristate(struct bb_info *bitbang) 64 if (dir)
68{ 65 bb_set(bitbang->dir, bitbang->mdio_msk);
69 bb_clr(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);
70} 71}
71 72
72static inline int mdio_read(struct bb_info *bitbang) 73static inline int mdio_read(struct mdiobb_ctrl *ctrl)
73{ 74{
75 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
74 return bb_read(bitbang->dat, bitbang->mdio_msk); 76 return bb_read(bitbang->dat, bitbang->mdio_msk);
75} 77}
76 78
77static inline void mdio(struct bb_info *bitbang, int what) 79static inline void mdio(struct mdiobb_ctrl *ctrl, int what)
78{ 80{
81 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
82
79 if (what) 83 if (what)
80 bb_set(bitbang->dat, bitbang->mdio_msk); 84 bb_set(bitbang->dat, bitbang->mdio_msk);
81 else 85 else
82 bb_clr(bitbang->dat, bitbang->mdio_msk); 86 bb_clr(bitbang->dat, bitbang->mdio_msk);
87
88 /* Read back to flush the write. */
89 in_be32(bitbang->dat);
83} 90}
84 91
85static inline void mdc(struct bb_info *bitbang, int what) 92static inline void mdc(struct mdiobb_ctrl *ctrl, int what)
86{ 93{
94 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
95
87 if (what) 96 if (what)
88 bb_set(bitbang->dat, bitbang->mdc_msk); 97 bb_set(bitbang->dat, bitbang->mdc_msk);
89 else 98 else
90 bb_clr(bitbang->dat, bitbang->mdc_msk); 99 bb_clr(bitbang->dat, bitbang->mdc_msk);
91}
92
93static inline void mii_delay(struct bb_info *bitbang)
94{
95 udelay(bitbang->delay);
96}
97
98/* Utility to send the preamble, address, and register (common to read and write). */
99static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
100{
101 int j;
102
103 /*
104 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
105 * The IEEE spec says this is a PHY optional requirement. The AMD
106 * 79C874 requires one after power up and one after a MII communications
107 * error. This means that we are doing more preambles than we need,
108 * but it is safer and will be much more robust.
109 */
110
111 mdio_active(bitbang);
112 mdio(bitbang, 1);
113 for (j = 0; j < 32; j++) {
114 mdc(bitbang, 0);
115 mii_delay(bitbang);
116 mdc(bitbang, 1);
117 mii_delay(bitbang);
118 }
119
120 /* send the start bit (01) and the read opcode (10) or write (10) */
121 mdc(bitbang, 0);
122 mdio(bitbang, 0);
123 mii_delay(bitbang);
124 mdc(bitbang, 1);
125 mii_delay(bitbang);
126 mdc(bitbang, 0);
127 mdio(bitbang, 1);
128 mii_delay(bitbang);
129 mdc(bitbang, 1);
130 mii_delay(bitbang);
131 mdc(bitbang, 0);
132 mdio(bitbang, read);
133 mii_delay(bitbang);
134 mdc(bitbang, 1);
135 mii_delay(bitbang);
136 mdc(bitbang, 0);
137 mdio(bitbang, !read);
138 mii_delay(bitbang);
139 mdc(bitbang, 1);
140 mii_delay(bitbang);
141
142 /* send the PHY address */
143 for (j = 0; j < 5; j++) {
144 mdc(bitbang, 0);
145 mdio(bitbang, (addr & 0x10) != 0);
146 mii_delay(bitbang);
147 mdc(bitbang, 1);
148 mii_delay(bitbang);
149 addr <<= 1;
150 }
151 100
152 /* send the register address */ 101 /* Read back to flush the write. */
153 for (j = 0; j < 5; j++) { 102 in_be32(bitbang->dat);
154 mdc(bitbang, 0);
155 mdio(bitbang, (reg & 0x10) != 0);
156 mii_delay(bitbang);
157 mdc(bitbang, 1);
158 mii_delay(bitbang);
159 reg <<= 1;
160 }
161} 103}
162 104
163static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location) 105static struct mdiobb_ops bb_ops = {
164{ 106 .owner = THIS_MODULE,
165 u16 rdreg; 107 .set_mdc = mdc,
166 int ret, j; 108 .set_mdio_dir = mdio_dir,
167 u8 addr = phy_id & 0xff; 109 .set_mdio_data = mdio,
168 u8 reg = location & 0xff; 110 .get_mdio_data = mdio_read,
169 struct bb_info* bitbang = bus->priv; 111};
170
171 bitbang_pre(bitbang, 1, addr, reg);
172
173 /* tri-state our MDIO I/O pin so we can read */
174 mdc(bitbang, 0);
175 mdio_tristate(bitbang);
176 mii_delay(bitbang);
177 mdc(bitbang, 1);
178 mii_delay(bitbang);
179
180 /* check the turnaround bit: the PHY should be driving it to zero */
181 if (mdio_read(bitbang) != 0) {
182 /* PHY didn't drive TA low */
183 for (j = 0; j < 32; j++) {
184 mdc(bitbang, 0);
185 mii_delay(bitbang);
186 mdc(bitbang, 1);
187 mii_delay(bitbang);
188 }
189 ret = -1;
190 goto out;
191 }
192
193 mdc(bitbang, 0);
194 mii_delay(bitbang);
195
196 /* read 16 bits of register data, MSB first */
197 rdreg = 0;
198 for (j = 0; j < 16; j++) {
199 mdc(bitbang, 1);
200 mii_delay(bitbang);
201 rdreg <<= 1;
202 rdreg |= mdio_read(bitbang);
203 mdc(bitbang, 0);
204 mii_delay(bitbang);
205 }
206
207 mdc(bitbang, 1);
208 mii_delay(bitbang);
209 mdc(bitbang, 0);
210 mii_delay(bitbang);
211 mdc(bitbang, 1);
212 mii_delay(bitbang);
213
214 ret = rdreg;
215out:
216 return ret;
217}
218
219static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
220{
221 int j;
222 struct bb_info* bitbang = bus->priv;
223
224 u8 addr = phy_id & 0xff;
225 u8 reg = location & 0xff;
226 u16 value = val & 0xffff;
227
228 bitbang_pre(bitbang, 0, addr, reg);
229
230 /* send the turnaround (10) */
231 mdc(bitbang, 0);
232 mdio(bitbang, 1);
233 mii_delay(bitbang);
234 mdc(bitbang, 1);
235 mii_delay(bitbang);
236 mdc(bitbang, 0);
237 mdio(bitbang, 0);
238 mii_delay(bitbang);
239 mdc(bitbang, 1);
240 mii_delay(bitbang);
241
242 /* write 16 bits of register data, MSB first */
243 for (j = 0; j < 16; j++) {
244 mdc(bitbang, 0);
245 mdio(bitbang, (value & 0x8000) != 0);
246 mii_delay(bitbang);
247 mdc(bitbang, 1);
248 mii_delay(bitbang);
249 value <<= 1;
250 }
251
252 /*
253 * Tri-state the MDIO line.
254 */
255 mdio_tristate(bitbang);
256 mdc(bitbang, 0);
257 mii_delay(bitbang);
258 mdc(bitbang, 1);
259 mii_delay(bitbang);
260 return 0;
261}
262
263static int fs_enet_mii_bb_reset(struct mii_bus *bus)
264{
265 /*nothing here - dunno how to reset it*/
266 return 0;
267}
268 112
269#ifdef CONFIG_PPC_CPM_NEW_BINDING 113#ifdef CONFIG_PPC_CPM_NEW_BINDING
270static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, 114static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
@@ -305,7 +149,6 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
305 bitbang->dat = bitbang->dir + 4; 149 bitbang->dat = bitbang->dir + 4;
306 bitbang->mdio_msk = 1 << (31 - mdio_pin); 150 bitbang->mdio_msk = 1 << (31 - mdio_pin);
307 bitbang->mdc_msk = 1 << (31 - mdc_pin); 151 bitbang->mdc_msk = 1 << (31 - mdc_pin);
308 bitbang->delay = 1; /* 1 us between operations */
309 152
310 return 0; 153 return 0;
311} 154}
@@ -336,23 +179,21 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
336 int ret = -ENOMEM; 179 int ret = -ENOMEM;
337 int i; 180 int i;
338 181
339 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
340 if (!new_bus)
341 goto out;
342
343 bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); 182 bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
344 if (!bitbang) 183 if (!bitbang)
345 goto out_free_bus; 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;
346 191
347 new_bus->priv = bitbang;
348 new_bus->name = "CPM2 Bitbanged MII", 192 new_bus->name = "CPM2 Bitbanged MII",
349 new_bus->read = &fs_enet_mii_bb_read,
350 new_bus->write = &fs_enet_mii_bb_write,
351 new_bus->reset = &fs_enet_mii_bb_reset,
352 193
353 ret = fs_mii_bitbang_init(new_bus, ofdev->node); 194 ret = fs_mii_bitbang_init(new_bus, ofdev->node);
354 if (ret) 195 if (ret)
355 goto out_free_bitbang; 196 goto out_free_bus;
356 197
357 new_bus->phy_mask = ~0; 198 new_bus->phy_mask = ~0;
358 new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 199 new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
@@ -380,10 +221,10 @@ out_free_irqs:
380 kfree(new_bus->irq); 221 kfree(new_bus->irq);
381out_unmap_regs: 222out_unmap_regs:
382 iounmap(bitbang->dir); 223 iounmap(bitbang->dir);
383out_free_bitbang:
384 kfree(bitbang);
385out_free_bus: 224out_free_bus:
386 kfree(new_bus); 225 kfree(new_bus);
226out_free_priv:
227 free_mdio_bitbang(new_bus);
387out: 228out:
388 return ret; 229 return ret;
389} 230}
@@ -394,6 +235,7 @@ static int fs_enet_mdio_remove(struct of_device *ofdev)
394 struct bb_info *bitbang = bus->priv; 235 struct bb_info *bitbang = bus->priv;
395 236
396 mdiobus_unregister(bus); 237 mdiobus_unregister(bus);
238 free_mdio_bitbang(bus);
397 dev_set_drvdata(&ofdev->dev, NULL); 239 dev_set_drvdata(&ofdev->dev, NULL);
398 kfree(bus->irq); 240 kfree(bus->irq);
399 iounmap(bitbang->dir); 241 iounmap(bitbang->dir);
@@ -417,12 +259,12 @@ static struct of_platform_driver fs_enet_bb_mdio_driver = {
417 .remove = fs_enet_mdio_remove, 259 .remove = fs_enet_mdio_remove,
418}; 260};
419 261
420int fs_enet_mdio_bb_init(void) 262static int fs_enet_mdio_bb_init(void)
421{ 263{
422 return of_register_platform_driver(&fs_enet_bb_mdio_driver); 264 return of_register_platform_driver(&fs_enet_bb_mdio_driver);
423} 265}
424 266
425void fs_enet_mdio_bb_exit(void) 267static void fs_enet_mdio_bb_exit(void)
426{ 268{
427 of_unregister_platform_driver(&fs_enet_bb_mdio_driver); 269 of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
428} 270}
@@ -437,7 +279,6 @@ static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
437 bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset; 279 bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
438 bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit); 280 bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
439 bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit); 281 bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
440 bitbang->delay = fmpi->delay;
441 282
442 return 0; 283 return 0;
443} 284}
@@ -453,20 +294,19 @@ static int __devinit fs_enet_mdio_probe(struct device *dev)
453 if (NULL == dev) 294 if (NULL == dev)
454 return -EINVAL; 295 return -EINVAL;
455 296
456 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); 297 bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
457 298
458 if (NULL == new_bus) 299 if (NULL == bitbang)
459 return -ENOMEM; 300 return -ENOMEM;
460 301
461 bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); 302 bitbang->ctrl.ops = &bb_ops;
462 303
463 if (NULL == bitbang) 304 new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
305
306 if (NULL == new_bus)
464 return -ENOMEM; 307 return -ENOMEM;
465 308
466 new_bus->name = "BB MII Bus", 309 new_bus->name = "BB MII Bus",
467 new_bus->read = &fs_enet_mii_bb_read,
468 new_bus->write = &fs_enet_mii_bb_write,
469 new_bus->reset = &fs_enet_mii_bb_reset,
470 new_bus->id = pdev->id; 310 new_bus->id = pdev->id;
471 311
472 new_bus->phy_mask = ~0x9; 312 new_bus->phy_mask = ~0x9;
@@ -498,8 +338,8 @@ static int __devinit fs_enet_mdio_probe(struct device *dev)
498 return 0; 338 return 0;
499 339
500bus_register_fail: 340bus_register_fail:
341 free_mdio_bitbang(new_bus);
501 kfree(bitbang); 342 kfree(bitbang);
502 kfree(new_bus);
503 343
504 return err; 344 return err;
505} 345}
@@ -512,9 +352,7 @@ static int fs_enet_mdio_remove(struct device *dev)
512 352
513 dev_set_drvdata(dev, NULL); 353 dev_set_drvdata(dev, NULL);
514 354
515 iounmap((void *) (&bus->priv)); 355 free_mdio_bitbang(bus);
516 bus->priv = NULL;
517 kfree(bus);
518 356
519 return 0; 357 return 0;
520} 358}
@@ -535,4 +373,4 @@ void fs_enet_mdio_bb_exit(void)
535{ 373{
536 driver_unregister(&fs_enet_bb_mdio_driver); 374 driver_unregister(&fs_enet_bb_mdio_driver);
537} 375}
538 376#endif