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