Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
[pandora-kernel.git] / drivers / net / fec_8xx / fec_mii.c
1 /*
2  * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
3  *
4  * Copyright (c) 2003 Intracom S.A. 
5  *  by Pantelis Antoniou <panto@intracom.gr>
6  *
7  * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
8  * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
9  *
10  * Released under the GPL
11  */
12
13 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <linux/ptrace.h>
18 #include <linux/errno.h>
19 #include <linux/ioport.h>
20 #include <linux/slab.h>
21 #include <linux/interrupt.h>
22 #include <linux/pci.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/netdevice.h>
26 #include <linux/etherdevice.h>
27 #include <linux/skbuff.h>
28 #include <linux/spinlock.h>
29 #include <linux/mii.h>
30 #include <linux/ethtool.h>
31 #include <linux/bitops.h>
32
33 #include <asm/8xx_immap.h>
34 #include <asm/pgtable.h>
35 #include <asm/mpc8xx.h>
36 #include <asm/irq.h>
37 #include <asm/uaccess.h>
38 #include <asm/commproc.h>
39
40 /*************************************************/
41
42 #include "fec_8xx.h"
43
44 /*************************************************/
45
46 /* Make MII read/write commands for the FEC.
47 */
48 #define mk_mii_read(REG)        (0x60020000 | ((REG & 0x1f) << 18))
49 #define mk_mii_write(REG, VAL)  (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
50 #define mk_mii_end              0
51
52 /*************************************************/
53
54 /* XXX both FECs use the MII interface of FEC1 */
55 static DEFINE_SPINLOCK(fec_mii_lock);
56
57 #define FEC_MII_LOOPS   10000
58
59 int fec_mii_read(struct net_device *dev, int phy_id, int location)
60 {
61         struct fec_enet_private *fep = netdev_priv(dev);
62         fec_t *fecp;
63         int i, ret = -1;
64         unsigned long flags;
65
66         /* XXX MII interface is only connected to FEC1 */
67         fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
68
69         spin_lock_irqsave(&fec_mii_lock, flags);
70
71         if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
72                 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
73                 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
74                 FW(fecp, ievent, FEC_ENET_MII);
75         }
76
77         /* Add PHY address to register command.  */
78         FW(fecp, mii_speed, fep->fec_phy_speed);
79         FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
80
81         for (i = 0; i < FEC_MII_LOOPS; i++)
82                 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
83                         break;
84
85         if (i < FEC_MII_LOOPS) {
86                 FW(fecp, ievent, FEC_ENET_MII);
87                 ret = FR(fecp, mii_data) & 0xffff;
88         }
89
90         spin_unlock_irqrestore(&fec_mii_lock, flags);
91
92         return ret;
93 }
94
95 void fec_mii_write(struct net_device *dev, int phy_id, int location, int value)
96 {
97         struct fec_enet_private *fep = netdev_priv(dev);
98         fec_t *fecp;
99         unsigned long flags;
100         int i;
101
102         /* XXX MII interface is only connected to FEC1 */
103         fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
104
105         spin_lock_irqsave(&fec_mii_lock, flags);
106
107         if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
108                 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
109                 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
110                 FW(fecp, ievent, FEC_ENET_MII);
111         }
112
113         /* Add PHY address to register command.  */
114         FW(fecp, mii_speed, fep->fec_phy_speed);        /* always adapt mii speed */
115         FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
116
117         for (i = 0; i < FEC_MII_LOOPS; i++)
118                 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
119                         break;
120
121         if (i < FEC_MII_LOOPS)
122                 FW(fecp, ievent, FEC_ENET_MII);
123
124         spin_unlock_irqrestore(&fec_mii_lock, flags);
125 }
126
127 /*************************************************/
128
129 #ifdef CONFIG_FEC_8XX_GENERIC_PHY
130
131 /*
132  * Generic PHY support.
133  * Should work for all PHYs, but link change is detected by polling
134  */
135
136 static void generic_timer_callback(unsigned long data)
137 {
138         struct net_device *dev = (struct net_device *)data;
139         struct fec_enet_private *fep = netdev_priv(dev);
140
141         fep->phy_timer_list.expires = jiffies + HZ / 2;
142
143         add_timer(&fep->phy_timer_list);
144
145         fec_mii_link_status_change_check(dev, 0);
146 }
147
148 static void generic_startup(struct net_device *dev)
149 {
150         struct fec_enet_private *fep = netdev_priv(dev);
151
152         fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
153         fep->phy_timer_list.data = (unsigned long)dev;
154         fep->phy_timer_list.function = generic_timer_callback;
155         add_timer(&fep->phy_timer_list);
156 }
157
158 static void generic_shutdown(struct net_device *dev)
159 {
160         struct fec_enet_private *fep = netdev_priv(dev);
161
162         del_timer_sync(&fep->phy_timer_list);
163 }
164
165 #endif
166
167 #ifdef CONFIG_FEC_8XX_DM9161_PHY
168
169 /* ------------------------------------------------------------------------- */
170 /* The Davicom DM9161 is used on the NETTA board                             */
171
172 /* register definitions */
173
174 #define MII_DM9161_ACR          16      /* Aux. Config Register         */
175 #define MII_DM9161_ACSR         17      /* Aux. Config/Status Register  */
176 #define MII_DM9161_10TCSR       18      /* 10BaseT Config/Status Reg.   */
177 #define MII_DM9161_INTR         21      /* Interrupt Register           */
178 #define MII_DM9161_RECR         22      /* Receive Error Counter Reg.   */
179 #define MII_DM9161_DISCR        23      /* Disconnect Counter Register  */
180
181 static void dm9161_startup(struct net_device *dev)
182 {
183         struct fec_enet_private *fep = netdev_priv(dev);
184
185         fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
186 }
187
188 static void dm9161_ack_int(struct net_device *dev)
189 {
190         struct fec_enet_private *fep = netdev_priv(dev);
191
192         fec_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
193 }
194
195 static void dm9161_shutdown(struct net_device *dev)
196 {
197         struct fec_enet_private *fep = netdev_priv(dev);
198
199         fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
200 }
201
202 #endif
203
204 #ifdef CONFIG_FEC_8XX_LXT971_PHY
205
206 /* Support for LXT971/972 PHY */
207
208 #define MII_LXT971_PCR          16 /* Port Control Register */
209 #define MII_LXT971_SR2          17 /* Status Register 2 */
210 #define MII_LXT971_IER          18 /* Interrupt Enable Register */
211 #define MII_LXT971_ISR          19 /* Interrupt Status Register */
212 #define MII_LXT971_LCR          20 /* LED Control Register */
213 #define MII_LXT971_TCR          30 /* Transmit Control Register */
214
215 static void lxt971_startup(struct net_device *dev)
216 {
217         struct fec_enet_private *fep = netdev_priv(dev);
218
219         fec_mii_write(dev, fep->mii_if.phy_id, MII_LXT971_IER, 0x00F2);
220 }
221
222 static void lxt971_ack_int(struct net_device *dev)
223 {
224         struct fec_enet_private *fep = netdev_priv(dev);
225
226         fec_mii_read(dev, fep->mii_if.phy_id, MII_LXT971_ISR);
227 }
228
229 static void lxt971_shutdown(struct net_device *dev)
230 {
231         struct fec_enet_private *fep = netdev_priv(dev);
232
233         fec_mii_write(dev, fep->mii_if.phy_id, MII_LXT971_IER, 0x0000);
234 }
235 #endif
236
237 /**********************************************************************************/
238
239 static const struct phy_info phy_info[] = {
240 #ifdef CONFIG_FEC_8XX_DM9161_PHY
241         {
242          .id = 0x00181b88,
243          .name = "DM9161",
244          .startup = dm9161_startup,
245          .ack_int = dm9161_ack_int,
246          .shutdown = dm9161_shutdown,
247          },
248 #endif
249 #ifdef CONFIG_FEC_8XX_LXT971_PHY
250         {
251          .id = 0x0001378e,
252          .name = "LXT971/972",
253          .startup = lxt971_startup,
254          .ack_int = lxt971_ack_int,
255          .shutdown = lxt971_shutdown,
256         },
257 #endif
258 #ifdef CONFIG_FEC_8XX_GENERIC_PHY
259         {
260          .id = 0,
261          .name = "GENERIC",
262          .startup = generic_startup,
263          .shutdown = generic_shutdown,
264          },
265 #endif
266 };
267
268 /**********************************************************************************/
269
270 int fec_mii_phy_id_detect(struct net_device *dev)
271 {
272         struct fec_enet_private *fep = netdev_priv(dev);
273         const struct fec_platform_info *fpi = fep->fpi;
274         int i, r, start, end, phytype, physubtype;
275         const struct phy_info *phy;
276         int phy_hwid, phy_id;
277
278         /* if no MDIO */
279         if (fpi->use_mdio == 0)
280                 return -1;
281
282         phy_hwid = -1;
283         fep->phy = NULL;
284
285         /* auto-detect? */
286         if (fpi->phy_addr == -1) {
287                 start = 0;
288                 end = 32;
289         } else {                /* direct */
290                 start = fpi->phy_addr;
291                 end = start + 1;
292         }
293
294         for (phy_id = start; phy_id < end; phy_id++) {
295                 r = fec_mii_read(dev, phy_id, MII_PHYSID1);
296                 if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
297                         continue;
298                 r = fec_mii_read(dev, phy_id, MII_PHYSID2);
299                 if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
300                         continue;
301                 phy_hwid = (phytype << 16) | physubtype;
302                 if (phy_hwid != -1)
303                         break;
304         }
305
306         if (phy_hwid == -1) {
307                 printk(KERN_ERR DRV_MODULE_NAME
308                        ": %s No PHY detected!\n", dev->name);
309                 return -1;
310         }
311
312         for (i = 0, phy = phy_info; i < sizeof(phy_info) / sizeof(phy_info[0]);
313              i++, phy++)
314                 if (phy->id == (phy_hwid >> 4) || phy->id == 0)
315                         break;
316
317         if (i >= sizeof(phy_info) / sizeof(phy_info[0])) {
318                 printk(KERN_ERR DRV_MODULE_NAME
319                        ": %s PHY id 0x%08x is not supported!\n",
320                        dev->name, phy_hwid);
321                 return -1;
322         }
323
324         fep->phy = phy;
325
326         printk(KERN_INFO DRV_MODULE_NAME
327                ": %s Phy @ 0x%x, type %s (0x%08x)\n",
328                dev->name, phy_id, fep->phy->name, phy_hwid);
329
330         return phy_id;
331 }
332
333 void fec_mii_startup(struct net_device *dev)
334 {
335         struct fec_enet_private *fep = netdev_priv(dev);
336         const struct fec_platform_info *fpi = fep->fpi;
337
338         if (!fpi->use_mdio || fep->phy == NULL)
339                 return;
340
341         if (fep->phy->startup == NULL)
342                 return;
343
344         (*fep->phy->startup) (dev);
345 }
346
347 void fec_mii_shutdown(struct net_device *dev)
348 {
349         struct fec_enet_private *fep = netdev_priv(dev);
350         const struct fec_platform_info *fpi = fep->fpi;
351
352         if (!fpi->use_mdio || fep->phy == NULL)
353                 return;
354
355         if (fep->phy->shutdown == NULL)
356                 return;
357
358         (*fep->phy->shutdown) (dev);
359 }
360
361 void fec_mii_ack_int(struct net_device *dev)
362 {
363         struct fec_enet_private *fep = netdev_priv(dev);
364         const struct fec_platform_info *fpi = fep->fpi;
365
366         if (!fpi->use_mdio || fep->phy == NULL)
367                 return;
368
369         if (fep->phy->ack_int == NULL)
370                 return;
371
372         (*fep->phy->ack_int) (dev);
373 }
374
375 /* helper function */
376 static int mii_negotiated(struct mii_if_info *mii)
377 {
378         int advert, lpa, val;
379
380         if (!mii_link_ok(mii))
381                 return 0;
382
383         val = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_BMSR);
384         if ((val & BMSR_ANEGCOMPLETE) == 0)
385                 return 0;
386
387         advert = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_ADVERTISE);
388         lpa = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_LPA);
389
390         return mii_nway_result(advert & lpa);
391 }
392
393 void fec_mii_link_status_change_check(struct net_device *dev, int init_media)
394 {
395         struct fec_enet_private *fep = netdev_priv(dev);
396         unsigned int media;
397         unsigned long flags;
398
399         if (mii_check_media(&fep->mii_if, netif_msg_link(fep), init_media) == 0)
400                 return;
401
402         media = mii_negotiated(&fep->mii_if);
403
404         if (netif_carrier_ok(dev)) {
405                 spin_lock_irqsave(&fep->lock, flags);
406                 fec_restart(dev, !!(media & ADVERTISE_FULL),
407                             (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) ?
408                             100 : 10);
409                 spin_unlock_irqrestore(&fep->lock, flags);
410
411                 netif_start_queue(dev);
412         } else {
413                 netif_stop_queue(dev);
414
415                 spin_lock_irqsave(&fep->lock, flags);
416                 fec_stop(dev);
417                 spin_unlock_irqrestore(&fep->lock, flags);
418
419         }
420 }