Merge ../linux-2.6 by hand
[pandora-kernel.git] / 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
16 #include <linux/config.h>
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/string.h>
22 #include <linux/ptrace.h>
23 #include <linux/errno.h>
24 #include <linux/ioport.h>
25 #include <linux/slab.h>
26 #include <linux/interrupt.h>
27 #include <linux/pci.h>
28 #include <linux/init.h>
29 #include <linux/delay.h>
30 #include <linux/netdevice.h>
31 #include <linux/etherdevice.h>
32 #include <linux/skbuff.h>
33 #include <linux/spinlock.h>
34 #include <linux/mii.h>
35 #include <linux/ethtool.h>
36 #include <linux/bitops.h>
37
38 #include <asm/pgtable.h>
39 #include <asm/irq.h>
40 #include <asm/uaccess.h>
41
42 #include "fs_enet.h"
43
44 #ifdef CONFIG_8xx
45 static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
46 {
47         immap_t *im = (immap_t *)fs_enet_immap;
48         void *dir, *dat, *ppar;
49         int adv;
50         u8 msk;
51
52         switch (port) {
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
110 static 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
148         adv = bit >> 3;
149         dir = (char *)dir + adv;
150         dat = (char *)dat + adv;
151         ppar = (char *)ppar + adv;
152
153         msk = 1 << (7 - (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
160         *dirp = dir;
161         *datp = dat;
162         *mskp = msk;
163
164         return 0;
165 }
166 #endif
167
168 static inline void bb_set(u8 *p, u8 m)
169 {
170         out_8(p, in_8(p) | m);
171 }
172
173 static inline void bb_clr(u8 *p, u8 m)
174 {
175         out_8(p, in_8(p) & ~m);
176 }
177
178 static inline int bb_read(u8 *p, u8 m)
179 {
180         return (in_8(p) & m) != 0;
181 }
182
183 static inline void mdio_active(struct fs_enet_mii_bus *bus)
184 {
185         bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
186 }
187
188 static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
189 {
190         bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
191 }
192
193 static inline int mdio_read(struct fs_enet_mii_bus *bus)
194 {
195         return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
196 }
197
198 static inline void mdio(struct fs_enet_mii_bus *bus, int what)
199 {
200         if (what)
201                 bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
202         else
203                 bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
204 }
205
206 static inline void mdc(struct fs_enet_mii_bus *bus, int what)
207 {
208         if (what)
209                 bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
210         else
211                 bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
212 }
213
214 static inline void mii_delay(struct fs_enet_mii_bus *bus)
215 {
216         udelay(bus->bus_info->i.bitbang.delay);
217 }
218
219 /* Utility to send the preamble, address, and register (common to read and write). */
220 static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
221 {
222         int j;
223
224         /*
225          * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
226          * The IEEE spec says this is a PHY optional requirement.  The AMD
227          * 79C874 requires one after power up and one after a MII communications
228          * error.  This means that we are doing more preambles than we need,
229          * but it is safer and will be much more robust.
230          */
231
232         mdio_active(bus);
233         mdio(bus, 1);
234         for (j = 0; j < 32; j++) {
235                 mdc(bus, 0);
236                 mii_delay(bus);
237                 mdc(bus, 1);
238                 mii_delay(bus);
239         }
240
241         /* send the start bit (01) and the read opcode (10) or write (10) */
242         mdc(bus, 0);
243         mdio(bus, 0);
244         mii_delay(bus);
245         mdc(bus, 1);
246         mii_delay(bus);
247         mdc(bus, 0);
248         mdio(bus, 1);
249         mii_delay(bus);
250         mdc(bus, 1);
251         mii_delay(bus);
252         mdc(bus, 0);
253         mdio(bus, read);
254         mii_delay(bus);
255         mdc(bus, 1);
256         mii_delay(bus);
257         mdc(bus, 0);
258         mdio(bus, !read);
259         mii_delay(bus);
260         mdc(bus, 1);
261         mii_delay(bus);
262
263         /* send the PHY address */
264         for (j = 0; j < 5; j++) {
265                 mdc(bus, 0);
266                 mdio(bus, (addr & 0x10) != 0);
267                 mii_delay(bus);
268                 mdc(bus, 1);
269                 mii_delay(bus);
270                 addr <<= 1;
271         }
272
273         /* send the register address */
274         for (j = 0; j < 5; j++) {
275                 mdc(bus, 0);
276                 mdio(bus, (reg & 0x10) != 0);
277                 mii_delay(bus);
278                 mdc(bus, 1);
279                 mii_delay(bus);
280                 reg <<= 1;
281         }
282 }
283
284 static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
285 {
286         u16 rdreg;
287         int ret, j;
288         u8 addr = phy_id & 0xff;
289         u8 reg = location & 0xff;
290
291         bitbang_pre(bus, 1, addr, reg);
292
293         /* tri-state our MDIO I/O pin so we can read */
294         mdc(bus, 0);
295         mdio_tristate(bus);
296         mii_delay(bus);
297         mdc(bus, 1);
298         mii_delay(bus);
299
300         /* check the turnaround bit: the PHY should be driving it to zero */
301         if (mdio_read(bus) != 0) {
302                 /* PHY didn't drive TA low */
303                 for (j = 0; j < 32; j++) {
304                         mdc(bus, 0);
305                         mii_delay(bus);
306                         mdc(bus, 1);
307                         mii_delay(bus);
308                 }
309                 ret = -1;
310                 goto out;
311         }
312
313         mdc(bus, 0);
314         mii_delay(bus);
315
316         /* read 16 bits of register data, MSB first */
317         rdreg = 0;
318         for (j = 0; j < 16; j++) {
319                 mdc(bus, 1);
320                 mii_delay(bus);
321                 rdreg <<= 1;
322                 rdreg |= mdio_read(bus);
323                 mdc(bus, 0);
324                 mii_delay(bus);
325         }
326
327         mdc(bus, 1);
328         mii_delay(bus);
329         mdc(bus, 0);
330         mii_delay(bus);
331         mdc(bus, 1);
332         mii_delay(bus);
333
334         ret = rdreg;
335 out:
336         return ret;
337 }
338
339 static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
340 {
341         int j;
342         u8 addr = phy_id & 0xff;
343         u8 reg = location & 0xff;
344         u16 value = val & 0xffff;
345
346         bitbang_pre(bus, 0, addr, reg);
347
348         /* send the turnaround (10) */
349         mdc(bus, 0);
350         mdio(bus, 1);
351         mii_delay(bus);
352         mdc(bus, 1);
353         mii_delay(bus);
354         mdc(bus, 0);
355         mdio(bus, 0);
356         mii_delay(bus);
357         mdc(bus, 1);
358         mii_delay(bus);
359
360         /* write 16 bits of register data, MSB first */
361         for (j = 0; j < 16; j++) {
362                 mdc(bus, 0);
363                 mdio(bus, (value & 0x8000) != 0);
364                 mii_delay(bus);
365                 mdc(bus, 1);
366                 mii_delay(bus);
367                 value <<= 1;
368         }
369
370         /*
371          * Tri-state the MDIO line.
372          */
373         mdio_tristate(bus);
374         mdc(bus, 0);
375         mii_delay(bus);
376         mdc(bus, 1);
377         mii_delay(bus);
378 }
379
380 int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
381 {
382         const struct fs_mii_bus_info *bi = bus->bus_info;
383         int r;
384
385         r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
386                          &bus->bitbang.mdio_dat,
387                          &bus->bitbang.mdio_msk,
388                          bi->i.bitbang.mdio_port,
389                          bi->i.bitbang.mdio_bit);
390         if (r != 0)
391                 return r;
392
393         r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
394                          &bus->bitbang.mdc_dat,
395                          &bus->bitbang.mdc_msk,
396                          bi->i.bitbang.mdc_port,
397                          bi->i.bitbang.mdc_bit);
398         if (r != 0)
399                 return r;
400
401         bus->mii_read = mii_read;
402         bus->mii_write = mii_write;
403
404         return 0;
405 }