aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet/mii-bitbang.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fs_enet/mii-bitbang.c')
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c449
1 files changed, 226 insertions, 223 deletions
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 24a5e2e23d18..0b9b8b5c847c 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -13,7 +13,6 @@
13 */ 13 */
14 14
15 15
16#include <linux/config.h>
17#include <linux/module.h> 16#include <linux/module.h>
18#include <linux/types.h> 17#include <linux/types.h>
19#include <linux/kernel.h> 18#include <linux/kernel.h>
@@ -34,6 +33,7 @@
34#include <linux/mii.h> 33#include <linux/mii.h>
35#include <linux/ethtool.h> 34#include <linux/ethtool.h>
36#include <linux/bitops.h> 35#include <linux/bitops.h>
36#include <linux/platform_device.h>
37 37
38#include <asm/pgtable.h> 38#include <asm/pgtable.h>
39#include <asm/irq.h> 39#include <asm/irq.h>
@@ -41,129 +41,25 @@
41 41
42#include "fs_enet.h" 42#include "fs_enet.h"
43 43
44#ifdef CONFIG_8xx 44static int bitbang_prep_bit(u8 **datp, u8 *mskp,
45static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) 45 struct fs_mii_bit *mii_bit)
46{ 46{
47 immap_t *im = (immap_t *)fs_enet_immap; 47 void *dat;
48 void *dir, *dat, *ppar;
49 int adv; 48 int adv;
50 u8 msk; 49 u8 msk;
51 50
52 switch (port) { 51 dat = (void*) mii_bit->offset;
53 case fsiop_porta:
54 dir = &im->im_ioport.iop_padir;
55 dat = &im->im_ioport.iop_padat;
56 ppar = &im->im_ioport.iop_papar;
57 break;
58
59 case fsiop_portb:
60 dir = &im->im_cpm.cp_pbdir;
61 dat = &im->im_cpm.cp_pbdat;
62 ppar = &im->im_cpm.cp_pbpar;
63 break;
64
65 case fsiop_portc:
66 dir = &im->im_ioport.iop_pcdir;
67 dat = &im->im_ioport.iop_pcdat;
68 ppar = &im->im_ioport.iop_pcpar;
69 break;
70
71 case fsiop_portd:
72 dir = &im->im_ioport.iop_pddir;
73 dat = &im->im_ioport.iop_pddat;
74 ppar = &im->im_ioport.iop_pdpar;
75 break;
76
77 case fsiop_porte:
78 dir = &im->im_cpm.cp_pedir;
79 dat = &im->im_cpm.cp_pedat;
80 ppar = &im->im_cpm.cp_pepar;
81 break;
82
83 default:
84 printk(KERN_ERR DRV_MODULE_NAME
85 "Illegal port value %d!\n", port);
86 return -EINVAL;
87 }
88
89 adv = bit >> 3;
90 dir = (char *)dir + adv;
91 dat = (char *)dat + adv;
92 ppar = (char *)ppar + adv;
93
94 msk = 1 << (7 - (bit & 7));
95 if ((in_8(ppar) & msk) != 0) {
96 printk(KERN_ERR DRV_MODULE_NAME
97 "pin %d on port %d is not general purpose!\n", bit, port);
98 return -EINVAL;
99 }
100
101 *dirp = dir;
102 *datp = dat;
103 *mskp = msk;
104
105 return 0;
106}
107#endif
108
109#ifdef CONFIG_8260
110static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
111{
112 iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
113 void *dir, *dat, *ppar;
114 int adv;
115 u8 msk;
116
117 switch (port) {
118 case fsiop_porta:
119 dir = &io->iop_pdira;
120 dat = &io->iop_pdata;
121 ppar = &io->iop_ppara;
122 break;
123
124 case fsiop_portb:
125 dir = &io->iop_pdirb;
126 dat = &io->iop_pdatb;
127 ppar = &io->iop_pparb;
128 break;
129
130 case fsiop_portc:
131 dir = &io->iop_pdirc;
132 dat = &io->iop_pdatc;
133 ppar = &io->iop_pparc;
134 break;
135
136 case fsiop_portd:
137 dir = &io->iop_pdird;
138 dat = &io->iop_pdatd;
139 ppar = &io->iop_ppard;
140 break;
141
142 default:
143 printk(KERN_ERR DRV_MODULE_NAME
144 "Illegal port value %d!\n", port);
145 return -EINVAL;
146 }
147 52
148 adv = bit >> 3; 53 adv = mii_bit->bit >> 3;
149 dir = (char *)dir + adv;
150 dat = (char *)dat + adv; 54 dat = (char *)dat + adv;
151 ppar = (char *)ppar + adv;
152 55
153 msk = 1 << (7 - (bit & 7)); 56 msk = 1 << (7 - (mii_bit->bit & 7));
154 if ((in_8(ppar) & msk) != 0) {
155 printk(KERN_ERR DRV_MODULE_NAME
156 "pin %d on port %d is not general purpose!\n", bit, port);
157 return -EINVAL;
158 }
159 57
160 *dirp = dir;
161 *datp = dat; 58 *datp = dat;
162 *mskp = msk; 59 *mskp = msk;
163 60
164 return 0; 61 return 0;
165} 62}
166#endif
167 63
168static inline void bb_set(u8 *p, u8 m) 64static inline void bb_set(u8 *p, u8 m)
169{ 65{
@@ -180,44 +76,44 @@ static inline int bb_read(u8 *p, u8 m)
180 return (in_8(p) & m) != 0; 76 return (in_8(p) & m) != 0;
181} 77}
182 78
183static inline void mdio_active(struct fs_enet_mii_bus *bus) 79static inline void mdio_active(struct bb_info *bitbang)
184{ 80{
185 bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); 81 bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
186} 82}
187 83
188static inline void mdio_tristate(struct fs_enet_mii_bus *bus) 84static inline void mdio_tristate(struct bb_info *bitbang )
189{ 85{
190 bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); 86 bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
191} 87}
192 88
193static inline int mdio_read(struct fs_enet_mii_bus *bus) 89static inline int mdio_read(struct bb_info *bitbang )
194{ 90{
195 return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); 91 return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
196} 92}
197 93
198static inline void mdio(struct fs_enet_mii_bus *bus, int what) 94static inline void mdio(struct bb_info *bitbang , int what)
199{ 95{
200 if (what) 96 if (what)
201 bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); 97 bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
202 else 98 else
203 bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); 99 bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
204} 100}
205 101
206static inline void mdc(struct fs_enet_mii_bus *bus, int what) 102static inline void mdc(struct bb_info *bitbang , int what)
207{ 103{
208 if (what) 104 if (what)
209 bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); 105 bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
210 else 106 else
211 bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); 107 bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
212} 108}
213 109
214static inline void mii_delay(struct fs_enet_mii_bus *bus) 110static inline void mii_delay(struct bb_info *bitbang )
215{ 111{
216 udelay(bus->bus_info->i.bitbang.delay); 112 udelay(bitbang->delay);
217} 113}
218 114
219/* Utility to send the preamble, address, and register (common to read and write). */ 115/* Utility to send the preamble, address, and register (common to read and write). */
220static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg) 116static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
221{ 117{
222 int j; 118 int j;
223 119
@@ -229,177 +125,284 @@ static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
229 * but it is safer and will be much more robust. 125 * but it is safer and will be much more robust.
230 */ 126 */
231 127
232 mdio_active(bus); 128 mdio_active(bitbang);
233 mdio(bus, 1); 129 mdio(bitbang, 1);
234 for (j = 0; j < 32; j++) { 130 for (j = 0; j < 32; j++) {
235 mdc(bus, 0); 131 mdc(bitbang, 0);
236 mii_delay(bus); 132 mii_delay(bitbang);
237 mdc(bus, 1); 133 mdc(bitbang, 1);
238 mii_delay(bus); 134 mii_delay(bitbang);
239 } 135 }
240 136
241 /* send the start bit (01) and the read opcode (10) or write (10) */ 137 /* send the start bit (01) and the read opcode (10) or write (10) */
242 mdc(bus, 0); 138 mdc(bitbang, 0);
243 mdio(bus, 0); 139 mdio(bitbang, 0);
244 mii_delay(bus); 140 mii_delay(bitbang);
245 mdc(bus, 1); 141 mdc(bitbang, 1);
246 mii_delay(bus); 142 mii_delay(bitbang);
247 mdc(bus, 0); 143 mdc(bitbang, 0);
248 mdio(bus, 1); 144 mdio(bitbang, 1);
249 mii_delay(bus); 145 mii_delay(bitbang);
250 mdc(bus, 1); 146 mdc(bitbang, 1);
251 mii_delay(bus); 147 mii_delay(bitbang);
252 mdc(bus, 0); 148 mdc(bitbang, 0);
253 mdio(bus, read); 149 mdio(bitbang, read);
254 mii_delay(bus); 150 mii_delay(bitbang);
255 mdc(bus, 1); 151 mdc(bitbang, 1);
256 mii_delay(bus); 152 mii_delay(bitbang);
257 mdc(bus, 0); 153 mdc(bitbang, 0);
258 mdio(bus, !read); 154 mdio(bitbang, !read);
259 mii_delay(bus); 155 mii_delay(bitbang);
260 mdc(bus, 1); 156 mdc(bitbang, 1);
261 mii_delay(bus); 157 mii_delay(bitbang);
262 158
263 /* send the PHY address */ 159 /* send the PHY address */
264 for (j = 0; j < 5; j++) { 160 for (j = 0; j < 5; j++) {
265 mdc(bus, 0); 161 mdc(bitbang, 0);
266 mdio(bus, (addr & 0x10) != 0); 162 mdio(bitbang, (addr & 0x10) != 0);
267 mii_delay(bus); 163 mii_delay(bitbang);
268 mdc(bus, 1); 164 mdc(bitbang, 1);
269 mii_delay(bus); 165 mii_delay(bitbang);
270 addr <<= 1; 166 addr <<= 1;
271 } 167 }
272 168
273 /* send the register address */ 169 /* send the register address */
274 for (j = 0; j < 5; j++) { 170 for (j = 0; j < 5; j++) {
275 mdc(bus, 0); 171 mdc(bitbang, 0);
276 mdio(bus, (reg & 0x10) != 0); 172 mdio(bitbang, (reg & 0x10) != 0);
277 mii_delay(bus); 173 mii_delay(bitbang);
278 mdc(bus, 1); 174 mdc(bitbang, 1);
279 mii_delay(bus); 175 mii_delay(bitbang);
280 reg <<= 1; 176 reg <<= 1;
281 } 177 }
282} 178}
283 179
284static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) 180static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location)
285{ 181{
286 u16 rdreg; 182 u16 rdreg;
287 int ret, j; 183 int ret, j;
288 u8 addr = phy_id & 0xff; 184 u8 addr = phy_id & 0xff;
289 u8 reg = location & 0xff; 185 u8 reg = location & 0xff;
186 struct bb_info* bitbang = bus->priv;
290 187
291 bitbang_pre(bus, 1, addr, reg); 188 bitbang_pre(bitbang, 1, addr, reg);
292 189
293 /* tri-state our MDIO I/O pin so we can read */ 190 /* tri-state our MDIO I/O pin so we can read */
294 mdc(bus, 0); 191 mdc(bitbang, 0);
295 mdio_tristate(bus); 192 mdio_tristate(bitbang);
296 mii_delay(bus); 193 mii_delay(bitbang);
297 mdc(bus, 1); 194 mdc(bitbang, 1);
298 mii_delay(bus); 195 mii_delay(bitbang);
299 196
300 /* check the turnaround bit: the PHY should be driving it to zero */ 197 /* check the turnaround bit: the PHY should be driving it to zero */
301 if (mdio_read(bus) != 0) { 198 if (mdio_read(bitbang) != 0) {
302 /* PHY didn't drive TA low */ 199 /* PHY didn't drive TA low */
303 for (j = 0; j < 32; j++) { 200 for (j = 0; j < 32; j++) {
304 mdc(bus, 0); 201 mdc(bitbang, 0);
305 mii_delay(bus); 202 mii_delay(bitbang);
306 mdc(bus, 1); 203 mdc(bitbang, 1);
307 mii_delay(bus); 204 mii_delay(bitbang);
308 } 205 }
309 ret = -1; 206 ret = -1;
310 goto out; 207 goto out;
311 } 208 }
312 209
313 mdc(bus, 0); 210 mdc(bitbang, 0);
314 mii_delay(bus); 211 mii_delay(bitbang);
315 212
316 /* read 16 bits of register data, MSB first */ 213 /* read 16 bits of register data, MSB first */
317 rdreg = 0; 214 rdreg = 0;
318 for (j = 0; j < 16; j++) { 215 for (j = 0; j < 16; j++) {
319 mdc(bus, 1); 216 mdc(bitbang, 1);
320 mii_delay(bus); 217 mii_delay(bitbang);
321 rdreg <<= 1; 218 rdreg <<= 1;
322 rdreg |= mdio_read(bus); 219 rdreg |= mdio_read(bitbang);
323 mdc(bus, 0); 220 mdc(bitbang, 0);
324 mii_delay(bus); 221 mii_delay(bitbang);
325 } 222 }
326 223
327 mdc(bus, 1); 224 mdc(bitbang, 1);
328 mii_delay(bus); 225 mii_delay(bitbang);
329 mdc(bus, 0); 226 mdc(bitbang, 0);
330 mii_delay(bus); 227 mii_delay(bitbang);
331 mdc(bus, 1); 228 mdc(bitbang, 1);
332 mii_delay(bus); 229 mii_delay(bitbang);
333 230
334 ret = rdreg; 231 ret = rdreg;
335out: 232out:
336 return ret; 233 return ret;
337} 234}
338 235
339static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val) 236static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
340{ 237{
341 int j; 238 int j;
239 struct bb_info* bitbang = bus->priv;
240
342 u8 addr = phy_id & 0xff; 241 u8 addr = phy_id & 0xff;
343 u8 reg = location & 0xff; 242 u8 reg = location & 0xff;
344 u16 value = val & 0xffff; 243 u16 value = val & 0xffff;
345 244
346 bitbang_pre(bus, 0, addr, reg); 245 bitbang_pre(bitbang, 0, addr, reg);
347 246
348 /* send the turnaround (10) */ 247 /* send the turnaround (10) */
349 mdc(bus, 0); 248 mdc(bitbang, 0);
350 mdio(bus, 1); 249 mdio(bitbang, 1);
351 mii_delay(bus); 250 mii_delay(bitbang);
352 mdc(bus, 1); 251 mdc(bitbang, 1);
353 mii_delay(bus); 252 mii_delay(bitbang);
354 mdc(bus, 0); 253 mdc(bitbang, 0);
355 mdio(bus, 0); 254 mdio(bitbang, 0);
356 mii_delay(bus); 255 mii_delay(bitbang);
357 mdc(bus, 1); 256 mdc(bitbang, 1);
358 mii_delay(bus); 257 mii_delay(bitbang);
359 258
360 /* write 16 bits of register data, MSB first */ 259 /* write 16 bits of register data, MSB first */
361 for (j = 0; j < 16; j++) { 260 for (j = 0; j < 16; j++) {
362 mdc(bus, 0); 261 mdc(bitbang, 0);
363 mdio(bus, (value & 0x8000) != 0); 262 mdio(bitbang, (value & 0x8000) != 0);
364 mii_delay(bus); 263 mii_delay(bitbang);
365 mdc(bus, 1); 264 mdc(bitbang, 1);
366 mii_delay(bus); 265 mii_delay(bitbang);
367 value <<= 1; 266 value <<= 1;
368 } 267 }
369 268
370 /* 269 /*
371 * Tri-state the MDIO line. 270 * Tri-state the MDIO line.
372 */ 271 */
373 mdio_tristate(bus); 272 mdio_tristate(bitbang);
374 mdc(bus, 0); 273 mdc(bitbang, 0);
375 mii_delay(bus); 274 mii_delay(bitbang);
376 mdc(bus, 1); 275 mdc(bitbang, 1);
377 mii_delay(bus); 276 mii_delay(bitbang);
277 return 0;
378} 278}
379 279
380int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus) 280static int fs_enet_mii_bb_reset(struct mii_bus *bus)
281{
282 /*nothing here - dunno how to reset it*/
283 return 0;
284}
285
286static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
381{ 287{
382 const struct fs_mii_bus_info *bi = bus->bus_info;
383 int r; 288 int r;
384 289
385 r = bitbang_prep_bit(&bus->bitbang.mdio_dir, 290 bitbang->delay = fmpi->delay;
386 &bus->bitbang.mdio_dat, 291
387 &bus->bitbang.mdio_msk, 292 r = bitbang_prep_bit(&bitbang->mdio_dir,
388 bi->i.bitbang.mdio_port, 293 &bitbang->mdio_dir_msk,
389 bi->i.bitbang.mdio_bit); 294 &fmpi->mdio_dir);
390 if (r != 0) 295 if (r != 0)
391 return r; 296 return r;
392 297
393 r = bitbang_prep_bit(&bus->bitbang.mdc_dir, 298 r = bitbang_prep_bit(&bitbang->mdio_dat,
394 &bus->bitbang.mdc_dat, 299 &bitbang->mdio_dat_msk,
395 &bus->bitbang.mdc_msk, 300 &fmpi->mdio_dat);
396 bi->i.bitbang.mdc_port,
397 bi->i.bitbang.mdc_bit);
398 if (r != 0) 301 if (r != 0)
399 return r; 302 return r;
400 303
401 bus->mii_read = mii_read; 304 r = bitbang_prep_bit(&bitbang->mdc_dat,
402 bus->mii_write = mii_write; 305 &bitbang->mdc_msk,
306 &fmpi->mdc_dat);
307 if (r != 0)
308 return r;
403 309
404 return 0; 310 return 0;
405} 311}
312
313
314static int __devinit fs_enet_mdio_probe(struct device *dev)
315{
316 struct platform_device *pdev = to_platform_device(dev);
317 struct fs_mii_bb_platform_info *pdata;
318 struct mii_bus *new_bus;
319 struct bb_info *bitbang;
320 int err = 0;
321
322 if (NULL == dev)
323 return -EINVAL;
324
325 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
326
327 if (NULL == new_bus)
328 return -ENOMEM;
329
330 bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
331
332 if (NULL == bitbang)
333 return -ENOMEM;
334
335 new_bus->name = "BB MII Bus",
336 new_bus->read = &fs_enet_mii_bb_read,
337 new_bus->write = &fs_enet_mii_bb_write,
338 new_bus->reset = &fs_enet_mii_bb_reset,
339 new_bus->id = pdev->id;
340
341 new_bus->phy_mask = ~0x9;
342 pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
343
344 if (NULL == pdata) {
345 printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
346 return -ENODEV;
347 }
348
349 /*set up workspace*/
350 fs_mii_bitbang_init(bitbang, pdata);
351
352 new_bus->priv = bitbang;
353
354 new_bus->irq = pdata->irq;
355
356 new_bus->dev = dev;
357 dev_set_drvdata(dev, new_bus);
358
359 err = mdiobus_register(new_bus);
360
361 if (0 != err) {
362 printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
363 new_bus->name);
364 goto bus_register_fail;
365 }
366
367 return 0;
368
369bus_register_fail:
370 kfree(bitbang);
371 kfree(new_bus);
372
373 return err;
374}
375
376
377static int fs_enet_mdio_remove(struct device *dev)
378{
379 struct mii_bus *bus = dev_get_drvdata(dev);
380
381 mdiobus_unregister(bus);
382
383 dev_set_drvdata(dev, NULL);
384
385 iounmap((void *) (&bus->priv));
386 bus->priv = NULL;
387 kfree(bus);
388
389 return 0;
390}
391
392static struct device_driver fs_enet_bb_mdio_driver = {
393 .name = "fsl-bb-mdio",
394 .bus = &platform_bus_type,
395 .probe = fs_enet_mdio_probe,
396 .remove = fs_enet_mdio_remove,
397};
398
399int fs_enet_mdio_bb_init(void)
400{
401 return driver_register(&fs_enet_bb_mdio_driver);
402}
403
404void fs_enet_mdio_bb_exit(void)
405{
406 driver_unregister(&fs_enet_bb_mdio_driver);
407}
408