aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet/mac-fec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fs_enet/mac-fec.c')
-rw-r--r--drivers/net/fs_enet/mac-fec.c143
1 files changed, 18 insertions, 125 deletions
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 3dad69dfdb2c..c2c5fd419bd0 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -12,7 +12,6 @@
12 * kind, whether express or implied. 12 * kind, whether express or implied.
13 */ 13 */
14 14
15#include <linux/config.h>
16#include <linux/module.h> 15#include <linux/module.h>
17#include <linux/kernel.h> 16#include <linux/kernel.h>
18#include <linux/types.h> 17#include <linux/types.h>
@@ -47,6 +46,7 @@
47#endif 46#endif
48 47
49#include "fs_enet.h" 48#include "fs_enet.h"
49#include "fec.h"
50 50
51/*************************************************/ 51/*************************************************/
52 52
@@ -76,50 +76,8 @@
76/* clear bits */ 76/* clear bits */
77#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v)) 77#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
78 78
79
80/* CRC polynomium used by the FEC for the multicast group filtering */
81#define FEC_CRC_POLY 0x04C11DB7
82
83#define FEC_MAX_MULTICAST_ADDRS 64
84
85/* Interrupt events/masks.
86*/
87#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
88#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
89#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
90#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
91#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
92#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
93#define FEC_ENET_RXF 0x02000000U /* Full frame received */
94#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
95#define FEC_ENET_MII 0x00800000U /* MII interrupt */
96#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
97
98#define FEC_ECNTRL_PINMUX 0x00000004
99#define FEC_ECNTRL_ETHER_EN 0x00000002
100#define FEC_ECNTRL_RESET 0x00000001
101
102#define FEC_RCNTRL_BC_REJ 0x00000010
103#define FEC_RCNTRL_PROM 0x00000008
104#define FEC_RCNTRL_MII_MODE 0x00000004
105#define FEC_RCNTRL_DRT 0x00000002
106#define FEC_RCNTRL_LOOP 0x00000001
107
108#define FEC_TCNTRL_FDEN 0x00000004
109#define FEC_TCNTRL_HBC 0x00000002
110#define FEC_TCNTRL_GTS 0x00000001
111
112
113/* Make MII read/write commands for the FEC.
114*/
115#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
116#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
117#define mk_mii_end 0
118
119#define FEC_MII_LOOPS 10000
120
121/* 79/*
122 * Delay to wait for FEC reset command to complete (in us) 80 * Delay to wait for FEC reset command to complete (in us)
123 */ 81 */
124#define FEC_RESET_DELAY 50 82#define FEC_RESET_DELAY 50
125 83
@@ -304,13 +262,15 @@ static void restart(struct net_device *dev)
304 int r; 262 int r;
305 u32 addrhi, addrlo; 263 u32 addrhi, addrlo;
306 264
265 struct mii_bus* mii = fep->phydev->bus;
266 struct fec_info* fec_inf = mii->priv;
267
307 r = whack_reset(fep->fec.fecp); 268 r = whack_reset(fep->fec.fecp);
308 if (r != 0) 269 if (r != 0)
309 printk(KERN_ERR DRV_MODULE_NAME 270 printk(KERN_ERR DRV_MODULE_NAME
310 ": %s FEC Reset FAILED!\n", dev->name); 271 ": %s FEC Reset FAILED!\n", dev->name);
311
312 /* 272 /*
313 * Set station address. 273 * Set station address.
314 */ 274 */
315 addrhi = ((u32) dev->dev_addr[0] << 24) | 275 addrhi = ((u32) dev->dev_addr[0] << 24) |
316 ((u32) dev->dev_addr[1] << 16) | 276 ((u32) dev->dev_addr[1] << 16) |
@@ -351,12 +311,12 @@ static void restart(struct net_device *dev)
351 FW(fecp, fun_code, 0x78000000); 311 FW(fecp, fun_code, 0x78000000);
352 312
353 /* 313 /*
354 * Set MII speed. 314 * Set MII speed.
355 */ 315 */
356 FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed); 316 FW(fecp, mii_speed, fec_inf->mii_speed);
357 317
358 /* 318 /*
359 * Clear any outstanding interrupt. 319 * Clear any outstanding interrupt.
360 */ 320 */
361 FW(fecp, ievent, 0xffc0); 321 FW(fecp, ievent, 0xffc0);
362 FW(fecp, ivec, (fep->interrupt / 2) << 29); 322 FW(fecp, ivec, (fep->interrupt / 2) << 29);
@@ -391,11 +351,12 @@ static void restart(struct net_device *dev)
391 } 351 }
392#endif 352#endif
393 353
354
394 FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ 355 FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
395 /* 356 /*
396 * adjust to duplex mode 357 * adjust to duplex mode
397 */ 358 */
398 if (fep->duplex) { 359 if (fep->phydev->duplex) {
399 FC(fecp, r_cntrl, FEC_RCNTRL_DRT); 360 FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
400 FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ 361 FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
401 } else { 362 } else {
@@ -419,9 +380,11 @@ static void restart(struct net_device *dev)
419static void stop(struct net_device *dev) 380static void stop(struct net_device *dev)
420{ 381{
421 struct fs_enet_private *fep = netdev_priv(dev); 382 struct fs_enet_private *fep = netdev_priv(dev);
383 const struct fs_platform_info *fpi = fep->fpi;
422 fec_t *fecp = fep->fec.fecp; 384 fec_t *fecp = fep->fec.fecp;
423 struct fs_enet_mii_bus *bus = fep->mii_bus; 385
424 const struct fs_mii_bus_info *bi = bus->bus_info; 386 struct fec_info* feci= fep->phydev->bus->priv;
387
425 int i; 388 int i;
426 389
427 if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) 390 if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
@@ -445,11 +408,11 @@ static void stop(struct net_device *dev)
445 fs_cleanup_bds(dev); 408 fs_cleanup_bds(dev);
446 409
447 /* shut down FEC1? that's where the mii bus is */ 410 /* shut down FEC1? that's where the mii bus is */
448 if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) { 411 if (fpi->has_phy) {
449 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ 412 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
450 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); 413 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
451 FW(fecp, ievent, FEC_ENET_MII); 414 FW(fecp, ievent, FEC_ENET_MII);
452 FW(fecp, mii_speed, bus->fec.mii_speed); 415 FW(fecp, mii_speed, feci->mii_speed);
453 } 416 }
454} 417}
455 418
@@ -584,73 +547,3 @@ const struct fs_ops fs_fec_ops = {
584 .free_bd = free_bd, 547 .free_bd = free_bd,
585}; 548};
586 549
587/***********************************************************************/
588
589static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
590{
591 fec_t *fecp = bus->fec.fecp;
592 int i, ret = -1;
593
594 if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
595 BUG();
596
597 /* Add PHY address to register command. */
598 FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
599
600 for (i = 0; i < FEC_MII_LOOPS; i++)
601 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
602 break;
603
604 if (i < FEC_MII_LOOPS) {
605 FW(fecp, ievent, FEC_ENET_MII);
606 ret = FR(fecp, mii_data) & 0xffff;
607 }
608
609 return ret;
610}
611
612static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
613{
614 fec_t *fecp = bus->fec.fecp;
615 int i;
616
617 /* this must never happen */
618 if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
619 BUG();
620
621 /* Add PHY address to register command. */
622 FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
623
624 for (i = 0; i < FEC_MII_LOOPS; i++)
625 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
626 break;
627
628 if (i < FEC_MII_LOOPS)
629 FW(fecp, ievent, FEC_ENET_MII);
630}
631
632int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
633{
634 bd_t *bd = (bd_t *)__res;
635 const struct fs_mii_bus_info *bi = bus->bus_info;
636 fec_t *fecp;
637
638 if (bi->id != 0)
639 return -1;
640
641 bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
642 bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
643 & 0x3F) << 1;
644
645 fecp = bus->fec.fecp;
646
647 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
648 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
649 FW(fecp, ievent, FEC_ENET_MII);
650 FW(fecp, mii_speed, bus->fec.mii_speed);
651
652 bus->mii_read = mii_read;
653 bus->mii_write = mii_write;
654
655 return 0;
656}