Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[linux-2.6] / drivers / net / fs_enet / fs_enet-mii.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  * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
11  * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
12  *
13  * This file is licensed under the terms of the GNU General Public License 
14  * version 2. This program is licensed "as is" without any warranty of any 
15  * kind, whether express or implied.
16  */
17
18
19 #include <linux/config.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/string.h>
25 #include <linux/ptrace.h>
26 #include <linux/errno.h>
27 #include <linux/ioport.h>
28 #include <linux/slab.h>
29 #include <linux/interrupt.h>
30 #include <linux/pci.h>
31 #include <linux/init.h>
32 #include <linux/delay.h>
33 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
35 #include <linux/skbuff.h>
36 #include <linux/spinlock.h>
37 #include <linux/mii.h>
38 #include <linux/ethtool.h>
39 #include <linux/bitops.h>
40
41 #include <asm/pgtable.h>
42 #include <asm/irq.h>
43 #include <asm/uaccess.h>
44
45 #include "fs_enet.h"
46
47 /*************************************************/
48
49 /*
50  * Generic PHY support.
51  * Should work for all PHYs, but link change is detected by polling
52  */
53
54 static void generic_timer_callback(unsigned long data)
55 {
56         struct net_device *dev = (struct net_device *)data;
57         struct fs_enet_private *fep = netdev_priv(dev);
58
59         fep->phy_timer_list.expires = jiffies + HZ / 2;
60
61         add_timer(&fep->phy_timer_list);
62
63         fs_mii_link_status_change_check(dev, 0);
64 }
65
66 static void generic_startup(struct net_device *dev)
67 {
68         struct fs_enet_private *fep = netdev_priv(dev);
69
70         fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
71         fep->phy_timer_list.data = (unsigned long)dev;
72         fep->phy_timer_list.function = generic_timer_callback;
73         add_timer(&fep->phy_timer_list);
74 }
75
76 static void generic_shutdown(struct net_device *dev)
77 {
78         struct fs_enet_private *fep = netdev_priv(dev);
79
80         del_timer_sync(&fep->phy_timer_list);
81 }
82
83 /* ------------------------------------------------------------------------- */
84 /* The Davicom DM9161 is used on the NETTA board                             */
85
86 /* register definitions */
87
88 #define MII_DM9161_ANAR         4       /* Aux. Config Register         */
89 #define MII_DM9161_ACR          16      /* Aux. Config Register         */
90 #define MII_DM9161_ACSR         17      /* Aux. Config/Status Register  */
91 #define MII_DM9161_10TCSR       18      /* 10BaseT Config/Status Reg.   */
92 #define MII_DM9161_INTR         21      /* Interrupt Register           */
93 #define MII_DM9161_RECR         22      /* Receive Error Counter Reg.   */
94 #define MII_DM9161_DISCR        23      /* Disconnect Counter Register  */
95
96 static void dm9161_startup(struct net_device *dev)
97 {
98         struct fs_enet_private *fep = netdev_priv(dev);
99
100         fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
101         /* Start autonegotiation */
102         fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
103
104         set_current_state(TASK_UNINTERRUPTIBLE);
105         schedule_timeout(HZ*8);
106 }
107
108 static void dm9161_ack_int(struct net_device *dev)
109 {
110         struct fs_enet_private *fep = netdev_priv(dev);
111
112         fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
113 }
114
115 static void dm9161_shutdown(struct net_device *dev)
116 {
117         struct fs_enet_private *fep = netdev_priv(dev);
118
119         fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
120 }
121
122 /**********************************************************************************/
123
124 static const struct phy_info phy_info[] = {
125         {
126                 .id = 0x00181b88,
127                 .name = "DM9161",
128                 .startup = dm9161_startup,
129                 .ack_int = dm9161_ack_int,
130                 .shutdown = dm9161_shutdown,
131         }, {
132                 .id = 0,
133                 .name = "GENERIC",
134                 .startup = generic_startup,
135                 .shutdown = generic_shutdown,
136         },
137 };
138
139 /**********************************************************************************/
140
141 static int phy_id_detect(struct net_device *dev)
142 {
143         struct fs_enet_private *fep = netdev_priv(dev);
144         const struct fs_platform_info *fpi = fep->fpi;
145         struct fs_enet_mii_bus *bus = fep->mii_bus;
146         int i, r, start, end, phytype, physubtype;
147         const struct phy_info *phy;
148         int phy_hwid, phy_id;
149
150         phy_hwid = -1;
151         fep->phy = NULL;
152
153         /* auto-detect? */
154         if (fpi->phy_addr == -1) {
155                 start = 1;
156                 end = 32;
157         } else {                /* direct */
158                 start = fpi->phy_addr;
159                 end = start + 1;
160         }
161
162         for (phy_id = start; phy_id < end; phy_id++) {
163                 /* skip already used phy addresses on this bus */ 
164                 if (bus->usage_map & (1 << phy_id))
165                         continue;
166                 r = fs_mii_read(dev, phy_id, MII_PHYSID1);
167                 if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
168                         continue;
169                 r = fs_mii_read(dev, phy_id, MII_PHYSID2);
170                 if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
171                         continue;
172                 phy_hwid = (phytype << 16) | physubtype;
173                 if (phy_hwid != -1)
174                         break;
175         }
176
177         if (phy_hwid == -1) {
178                 printk(KERN_ERR DRV_MODULE_NAME
179                        ": %s No PHY detected! range=0x%02x-0x%02x\n",
180                         dev->name, start, end);
181                 return -1;
182         }
183
184         for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
185                 if (phy->id == (phy_hwid >> 4) || phy->id == 0)
186                         break;
187
188         if (i >= ARRAY_SIZE(phy_info)) {
189                 printk(KERN_ERR DRV_MODULE_NAME
190                        ": %s PHY id 0x%08x is not supported!\n",
191                        dev->name, phy_hwid);
192                 return -1;
193         }
194
195         fep->phy = phy;
196
197         /* mark this address as used */
198         bus->usage_map |= (1 << phy_id);
199
200         printk(KERN_INFO DRV_MODULE_NAME
201                ": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
202                dev->name, phy_id, fep->phy->name, phy_hwid,
203                fpi->phy_addr == -1 ? " (auto-detected)" : "");
204
205         return phy_id;
206 }
207
208 void fs_mii_startup(struct net_device *dev)
209 {
210         struct fs_enet_private *fep = netdev_priv(dev);
211
212         if (fep->phy->startup)
213                 (*fep->phy->startup) (dev);
214 }
215
216 void fs_mii_shutdown(struct net_device *dev)
217 {
218         struct fs_enet_private *fep = netdev_priv(dev);
219
220         if (fep->phy->shutdown)
221                 (*fep->phy->shutdown) (dev);
222 }
223
224 void fs_mii_ack_int(struct net_device *dev)
225 {
226         struct fs_enet_private *fep = netdev_priv(dev);
227
228         if (fep->phy->ack_int)
229                 (*fep->phy->ack_int) (dev);
230 }
231
232 #define MII_LINK        0x0001
233 #define MII_HALF        0x0002
234 #define MII_FULL        0x0004
235 #define MII_BASE4       0x0008
236 #define MII_10M         0x0010
237 #define MII_100M        0x0020
238 #define MII_1G          0x0040
239 #define MII_10G         0x0080
240
241 /* return full mii info at one gulp, with a usable form */
242 static unsigned int mii_full_status(struct mii_if_info *mii)
243 {
244         unsigned int status;
245         int bmsr, adv, lpa, neg;
246         struct fs_enet_private* fep = netdev_priv(mii->dev);
247         
248         /* first, a dummy read, needed to latch some MII phys */
249         (void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
250         bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
251
252         /* no link */
253         if ((bmsr & BMSR_LSTATUS) == 0)
254                 return 0;
255
256         status = MII_LINK;
257         
258         /* Lets look what ANEG says if it's supported - otherwize we shall
259            take the right values from the platform info*/
260         if(!mii->force_media) {
261                 /* autoneg not completed; don't bother */
262                 if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
263                         return 0;
264
265                 adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
266                 lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
267
268                 neg = lpa & adv;
269         } else {
270                 neg = fep->fpi->bus_info->lpa;
271         }
272
273         if (neg & LPA_100FULL)
274                 status |= MII_FULL | MII_100M;
275         else if (neg & LPA_100BASE4)
276                 status |= MII_FULL | MII_BASE4 | MII_100M;
277         else if (neg & LPA_100HALF)
278                 status |= MII_HALF | MII_100M;
279         else if (neg & LPA_10FULL)
280                 status |= MII_FULL | MII_10M;
281         else
282                 status |= MII_HALF | MII_10M;
283         
284         return status;
285 }
286
287 void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
288 {
289         struct fs_enet_private *fep = netdev_priv(dev);
290         struct mii_if_info *mii = &fep->mii_if;
291         unsigned int mii_status;
292         int ok_to_print, link, duplex, speed;
293         unsigned long flags;
294
295         ok_to_print = netif_msg_link(fep);
296
297         mii_status = mii_full_status(mii);
298
299         if (!init_media && mii_status == fep->last_mii_status)
300                 return;
301
302         fep->last_mii_status = mii_status;
303
304         link = !!(mii_status & MII_LINK);
305         duplex = !!(mii_status & MII_FULL);
306         speed = (mii_status & MII_100M) ? 100 : 10;
307
308         if (link == 0) {
309                 netif_carrier_off(mii->dev);
310                 netif_stop_queue(dev);
311                 if (!init_media) {
312                         spin_lock_irqsave(&fep->lock, flags);
313                         (*fep->ops->stop)(dev);
314                         spin_unlock_irqrestore(&fep->lock, flags);
315                 }
316
317                 if (ok_to_print)
318                         printk(KERN_INFO "%s: link down\n", mii->dev->name);
319
320         } else {
321
322                 mii->full_duplex = duplex;
323
324                 netif_carrier_on(mii->dev);
325
326                 spin_lock_irqsave(&fep->lock, flags);
327                 fep->duplex = duplex;
328                 fep->speed = speed;
329                 (*fep->ops->restart)(dev);
330                 spin_unlock_irqrestore(&fep->lock, flags);
331
332                 netif_start_queue(dev);
333
334                 if (ok_to_print)
335                         printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
336                                dev->name, speed, duplex ? "full" : "half");
337         }
338 }
339
340 /**********************************************************************************/
341
342 int fs_mii_read(struct net_device *dev, int phy_id, int location)
343 {
344         struct fs_enet_private *fep = netdev_priv(dev);
345         struct fs_enet_mii_bus *bus = fep->mii_bus;
346
347         unsigned long flags;
348         int ret;
349
350         spin_lock_irqsave(&bus->mii_lock, flags);
351         ret = (*bus->mii_read)(bus, phy_id, location);
352         spin_unlock_irqrestore(&bus->mii_lock, flags);
353
354         return ret;
355 }
356
357 void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
358 {
359         struct fs_enet_private *fep = netdev_priv(dev);
360         struct fs_enet_mii_bus *bus = fep->mii_bus;
361         unsigned long flags;
362
363         spin_lock_irqsave(&bus->mii_lock, flags);
364         (*bus->mii_write)(bus, phy_id, location, value);
365         spin_unlock_irqrestore(&bus->mii_lock, flags);
366 }
367
368 /*****************************************************************************/
369
370 /* list of all registered mii buses */
371 static LIST_HEAD(fs_mii_bus_list);
372
373 static struct fs_enet_mii_bus *lookup_bus(int method, int id)
374 {
375         struct list_head *ptr;
376         struct fs_enet_mii_bus *bus;
377
378         list_for_each(ptr, &fs_mii_bus_list) {
379                 bus = list_entry(ptr, struct fs_enet_mii_bus, list);
380                 if (bus->bus_info->method == method &&
381                         bus->bus_info->id == id)
382                         return bus;
383         }
384         return NULL;
385 }
386
387 static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
388 {
389         struct fs_enet_mii_bus *bus;
390         int ret = 0;
391
392         bus = kmalloc(sizeof(*bus), GFP_KERNEL);
393         if (bus == NULL) {
394                 ret = -ENOMEM;
395                 goto err;
396         }
397         memset(bus, 0, sizeof(*bus));
398         spin_lock_init(&bus->mii_lock);
399         bus->bus_info = bi;
400         bus->refs = 0;
401         bus->usage_map = 0;
402
403         /* perform initialization */
404         switch (bi->method) {
405
406                 case fsmii_fixed:
407                         ret = fs_mii_fixed_init(bus);
408                         if (ret != 0)
409                                 goto err;
410                         break;
411
412                 case fsmii_bitbang:
413                         ret = fs_mii_bitbang_init(bus);
414                         if (ret != 0)
415                                 goto err;
416                         break;
417 #ifdef CONFIG_FS_ENET_HAS_FEC
418                 case fsmii_fec:
419                         ret = fs_mii_fec_init(bus);
420                         if (ret != 0)
421                                 goto err;
422                         break;
423 #endif
424                 default:
425                         ret = -EINVAL;
426                         goto err;
427         }
428
429         list_add(&bus->list, &fs_mii_bus_list);
430
431         return bus;
432
433 err:
434         if (bus)
435                 kfree(bus);
436         return ERR_PTR(ret);
437 }
438
439 static void destroy_bus(struct fs_enet_mii_bus *bus)
440 {
441         /* remove from bus list */
442         list_del(&bus->list);
443
444         /* nothing more needed */
445         kfree(bus);
446 }
447
448 int fs_mii_connect(struct net_device *dev)
449 {
450         struct fs_enet_private *fep = netdev_priv(dev);
451         const struct fs_platform_info *fpi = fep->fpi;
452         struct fs_enet_mii_bus *bus = NULL;
453
454         /* check method validity */
455         switch (fpi->bus_info->method) {
456                 case fsmii_fixed:
457                 case fsmii_bitbang:
458                         break;
459 #ifdef CONFIG_FS_ENET_HAS_FEC
460                 case fsmii_fec:
461                         break;
462 #endif
463                 default:
464                         printk(KERN_ERR DRV_MODULE_NAME
465                                ": %s Unknown MII bus method (%d)!\n",
466                                dev->name, fpi->bus_info->method);
467                         return -EINVAL; 
468         }
469
470         bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
471
472         /* if not found create new bus */
473         if (bus == NULL) {
474                 bus = create_bus(fpi->bus_info);
475                 if (IS_ERR(bus)) {
476                         printk(KERN_ERR DRV_MODULE_NAME
477                                ": %s MII bus creation failure!\n", dev->name);
478                         return PTR_ERR(bus);
479                 }
480         }
481
482         bus->refs++;
483
484         fep->mii_bus = bus;
485
486         fep->mii_if.dev = dev;
487         fep->mii_if.phy_id_mask = 0x1f;
488         fep->mii_if.reg_num_mask = 0x1f;
489         fep->mii_if.mdio_read = fs_mii_read;
490         fep->mii_if.mdio_write = fs_mii_write;
491         fep->mii_if.force_media = fpi->bus_info->disable_aneg;
492         fep->mii_if.phy_id = phy_id_detect(dev);
493
494         return 0;
495 }
496
497 void fs_mii_disconnect(struct net_device *dev)
498 {
499         struct fs_enet_private *fep = netdev_priv(dev);
500         struct fs_enet_mii_bus *bus = NULL;
501
502         bus = fep->mii_bus;
503         fep->mii_bus = NULL;
504
505         if (--bus->refs <= 0)
506                 destroy_bus(bus);
507 }