diff options
| -rw-r--r-- | drivers/net/fec.c | 240 |
1 files changed, 218 insertions, 22 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 85504fb900da..bd6983d1afba 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
| @@ -18,8 +18,8 @@ | |||
| 18 | * Much better multiple PHY support by Magnus Damm. | 18 | * Much better multiple PHY support by Magnus Damm. |
| 19 | * Copyright (c) 2000 Ericsson Radio Systems AB. | 19 | * Copyright (c) 2000 Ericsson Radio Systems AB. |
| 20 | * | 20 | * |
| 21 | * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282. | 21 | * Support for FEC controller of ColdFire processors. |
| 22 | * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com) | 22 | * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com) |
| 23 | * | 23 | * |
| 24 | * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) | 24 | * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) |
| 25 | * Copyright (c) 2004-2005 Macq Electronique SA. | 25 | * Copyright (c) 2004-2005 Macq Electronique SA. |
| @@ -50,7 +50,8 @@ | |||
| 50 | #include <asm/pgtable.h> | 50 | #include <asm/pgtable.h> |
| 51 | 51 | ||
| 52 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ | 52 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ |
| 53 | defined(CONFIG_M5272) || defined(CONFIG_M528x) | 53 | defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ |
| 54 | defined(CONFIG_M520x) | ||
| 54 | #include <asm/coldfire.h> | 55 | #include <asm/coldfire.h> |
| 55 | #include <asm/mcfsim.h> | 56 | #include <asm/mcfsim.h> |
| 56 | #include "fec.h" | 57 | #include "fec.h" |
| @@ -77,6 +78,8 @@ static unsigned int fec_hw[] = { | |||
| 77 | (MCF_MBAR + 0x1800), | 78 | (MCF_MBAR + 0x1800), |
| 78 | #elif defined(CONFIG_M523x) || defined(CONFIG_M528x) | 79 | #elif defined(CONFIG_M523x) || defined(CONFIG_M528x) |
| 79 | (MCF_MBAR + 0x1000), | 80 | (MCF_MBAR + 0x1000), |
| 81 | #elif defined(CONFIG_M520x) | ||
| 82 | (MCF_MBAR+0x30000), | ||
| 80 | #else | 83 | #else |
| 81 | &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), | 84 | &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), |
| 82 | #endif | 85 | #endif |
| @@ -139,6 +142,10 @@ typedef struct { | |||
| 139 | #define TX_RING_SIZE 16 /* Must be power of two */ | 142 | #define TX_RING_SIZE 16 /* Must be power of two */ |
| 140 | #define TX_RING_MOD_MASK 15 /* for this to work */ | 143 | #define TX_RING_MOD_MASK 15 /* for this to work */ |
| 141 | 144 | ||
| 145 | #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) | ||
| 146 | #error "FEC: descriptor ring size contants too large" | ||
| 147 | #endif | ||
| 148 | |||
| 142 | /* Interrupt events/masks. | 149 | /* Interrupt events/masks. |
| 143 | */ | 150 | */ |
| 144 | #define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ | 151 | #define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ |
| @@ -164,7 +171,8 @@ typedef struct { | |||
| 164 | * size bits. Other FEC hardware does not, so we need to take that into | 171 | * size bits. Other FEC hardware does not, so we need to take that into |
| 165 | * account when setting it. | 172 | * account when setting it. |
| 166 | */ | 173 | */ |
| 167 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) | 174 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ |
| 175 | defined(CONFIG_M520x) | ||
| 168 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) | 176 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) |
| 169 | #else | 177 | #else |
| 170 | #define OPT_FRAME_SIZE 0 | 178 | #define OPT_FRAME_SIZE 0 |
| @@ -1137,6 +1145,65 @@ static phy_info_t const phy_info_ks8721bl = { | |||
| 1137 | }; | 1145 | }; |
| 1138 | 1146 | ||
| 1139 | /* ------------------------------------------------------------------------- */ | 1147 | /* ------------------------------------------------------------------------- */ |
| 1148 | /* register definitions for the DP83848 */ | ||
| 1149 | |||
| 1150 | #define MII_DP8384X_PHYSTST 16 /* PHY Status Register */ | ||
| 1151 | |||
| 1152 | static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev) | ||
| 1153 | { | ||
| 1154 | struct fec_enet_private *fep = dev->priv; | ||
| 1155 | volatile uint *s = &(fep->phy_status); | ||
| 1156 | |||
| 1157 | *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); | ||
| 1158 | |||
| 1159 | /* Link up */ | ||
| 1160 | if (mii_reg & 0x0001) { | ||
| 1161 | fep->link = 1; | ||
| 1162 | *s |= PHY_STAT_LINK; | ||
| 1163 | } else | ||
| 1164 | fep->link = 0; | ||
| 1165 | /* Status of link */ | ||
| 1166 | if (mii_reg & 0x0010) /* Autonegotioation complete */ | ||
| 1167 | *s |= PHY_STAT_ANC; | ||
| 1168 | if (mii_reg & 0x0002) { /* 10MBps? */ | ||
| 1169 | if (mii_reg & 0x0004) /* Full Duplex? */ | ||
| 1170 | *s |= PHY_STAT_10FDX; | ||
| 1171 | else | ||
| 1172 | *s |= PHY_STAT_10HDX; | ||
| 1173 | } else { /* 100 Mbps? */ | ||
| 1174 | if (mii_reg & 0x0004) /* Full Duplex? */ | ||
| 1175 | *s |= PHY_STAT_100FDX; | ||
| 1176 | else | ||
| 1177 | *s |= PHY_STAT_100HDX; | ||
| 1178 | } | ||
| 1179 | if (mii_reg & 0x0008) | ||
| 1180 | *s |= PHY_STAT_FAULT; | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | static phy_info_t phy_info_dp83848= { | ||
| 1184 | 0x020005c9, | ||
| 1185 | "DP83848", | ||
| 1186 | |||
| 1187 | (const phy_cmd_t []) { /* config */ | ||
| 1188 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | ||
| 1189 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | ||
| 1190 | { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 }, | ||
| 1191 | { mk_mii_end, } | ||
| 1192 | }, | ||
| 1193 | (const phy_cmd_t []) { /* startup - enable interrupts */ | ||
| 1194 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 1195 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 1196 | { mk_mii_end, } | ||
| 1197 | }, | ||
| 1198 | (const phy_cmd_t []) { /* ack_int - never happens, no interrupt */ | ||
| 1199 | { mk_mii_end, } | ||
| 1200 | }, | ||
| 1201 | (const phy_cmd_t []) { /* shutdown */ | ||
| 1202 | { mk_mii_end, } | ||
| 1203 | }, | ||
| 1204 | }; | ||
| 1205 | |||
| 1206 | /* ------------------------------------------------------------------------- */ | ||
| 1140 | 1207 | ||
| 1141 | static phy_info_t const * const phy_info[] = { | 1208 | static phy_info_t const * const phy_info[] = { |
| 1142 | &phy_info_lxt970, | 1209 | &phy_info_lxt970, |
| @@ -1144,6 +1211,7 @@ static phy_info_t const * const phy_info[] = { | |||
| 1144 | &phy_info_qs6612, | 1211 | &phy_info_qs6612, |
| 1145 | &phy_info_am79c874, | 1212 | &phy_info_am79c874, |
| 1146 | &phy_info_ks8721bl, | 1213 | &phy_info_ks8721bl, |
| 1214 | &phy_info_dp83848, | ||
| 1147 | NULL | 1215 | NULL |
| 1148 | }; | 1216 | }; |
| 1149 | 1217 | ||
| @@ -1422,6 +1490,134 @@ static void __inline__ fec_uncache(unsigned long addr) | |||
| 1422 | 1490 | ||
| 1423 | /* ------------------------------------------------------------------------- */ | 1491 | /* ------------------------------------------------------------------------- */ |
| 1424 | 1492 | ||
| 1493 | #elif defined(CONFIG_M520x) | ||
| 1494 | |||
| 1495 | /* | ||
| 1496 | * Code specific to Coldfire 520x | ||
| 1497 | */ | ||
| 1498 | static void __inline__ fec_request_intrs(struct net_device *dev) | ||
| 1499 | { | ||
| 1500 | struct fec_enet_private *fep; | ||
| 1501 | int b; | ||
| 1502 | static const struct idesc { | ||
| 1503 | char *name; | ||
| 1504 | unsigned short irq; | ||
| 1505 | } *idp, id[] = { | ||
| 1506 | { "fec(TXF)", 23 }, | ||
| 1507 | { "fec(TXB)", 24 }, | ||
| 1508 | { "fec(TXFIFO)", 25 }, | ||
| 1509 | { "fec(TXCR)", 26 }, | ||
| 1510 | { "fec(RXF)", 27 }, | ||
| 1511 | { "fec(RXB)", 28 }, | ||
| 1512 | { "fec(MII)", 29 }, | ||
| 1513 | { "fec(LC)", 30 }, | ||
| 1514 | { "fec(HBERR)", 31 }, | ||
| 1515 | { "fec(GRA)", 32 }, | ||
| 1516 | { "fec(EBERR)", 33 }, | ||
| 1517 | { "fec(BABT)", 34 }, | ||
| 1518 | { "fec(BABR)", 35 }, | ||
| 1519 | { NULL }, | ||
| 1520 | }; | ||
| 1521 | |||
| 1522 | fep = netdev_priv(dev); | ||
| 1523 | b = 64 + 13; | ||
| 1524 | |||
| 1525 | /* Setup interrupt handlers. */ | ||
| 1526 | for (idp = id; idp->name; idp++) { | ||
| 1527 | if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0) | ||
| 1528 | printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq); | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | /* Unmask interrupts at ColdFire interrupt controller */ | ||
| 1532 | { | ||
| 1533 | volatile unsigned char *icrp; | ||
| 1534 | volatile unsigned long *imrp; | ||
| 1535 | |||
| 1536 | icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 + | ||
| 1537 | MCFINTC_ICR0); | ||
| 1538 | for (b = 36; (b < 49); b++) | ||
| 1539 | icrp[b] = 0x04; | ||
| 1540 | imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + | ||
| 1541 | MCFINTC_IMRH); | ||
| 1542 | *imrp &= ~0x0001FFF0; | ||
| 1543 | } | ||
| 1544 | *(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FEC) |= 0xf0; | ||
| 1545 | *(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C) |= 0x0f; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) | ||
| 1549 | { | ||
| 1550 | volatile fec_t *fecp; | ||
| 1551 | |||
| 1552 | fecp = fep->hwp; | ||
| 1553 | fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; | ||
| 1554 | fecp->fec_x_cntrl = 0x00; | ||
| 1555 | |||
| 1556 | /* | ||
| 1557 | * Set MII speed to 2.5 MHz | ||
| 1558 | * See 5282 manual section 17.5.4.7: MSCR | ||
| 1559 | */ | ||
| 1560 | fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2; | ||
| 1561 | fecp->fec_mii_speed = fep->phy_speed; | ||
| 1562 | |||
| 1563 | fec_restart(dev, 0); | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | static void __inline__ fec_get_mac(struct net_device *dev) | ||
| 1567 | { | ||
| 1568 | struct fec_enet_private *fep = netdev_priv(dev); | ||
| 1569 | volatile fec_t *fecp; | ||
| 1570 | unsigned char *iap, tmpaddr[ETH_ALEN]; | ||
| 1571 | |||
| 1572 | fecp = fep->hwp; | ||
| 1573 | |||
| 1574 | if (FEC_FLASHMAC) { | ||
| 1575 | /* | ||
| 1576 | * Get MAC address from FLASH. | ||
| 1577 | * If it is all 1's or 0's, use the default. | ||
| 1578 | */ | ||
| 1579 | iap = FEC_FLASHMAC; | ||
| 1580 | if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && | ||
| 1581 | (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) | ||
| 1582 | iap = fec_mac_default; | ||
| 1583 | if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && | ||
| 1584 | (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) | ||
| 1585 | iap = fec_mac_default; | ||
| 1586 | } else { | ||
| 1587 | *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; | ||
| 1588 | *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); | ||
| 1589 | iap = &tmpaddr[0]; | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | memcpy(dev->dev_addr, iap, ETH_ALEN); | ||
| 1593 | |||
| 1594 | /* Adjust MAC if using default MAC address */ | ||
| 1595 | if (iap == fec_mac_default) | ||
| 1596 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | static void __inline__ fec_enable_phy_intr(void) | ||
| 1600 | { | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | static void __inline__ fec_disable_phy_intr(void) | ||
| 1604 | { | ||
| 1605 | } | ||
| 1606 | |||
| 1607 | static void __inline__ fec_phy_ack_intr(void) | ||
| 1608 | { | ||
| 1609 | } | ||
| 1610 | |||
| 1611 | static void __inline__ fec_localhw_setup(void) | ||
| 1612 | { | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | static void __inline__ fec_uncache(unsigned long addr) | ||
| 1616 | { | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | /* ------------------------------------------------------------------------- */ | ||
| 1620 | |||
| 1425 | #else | 1621 | #else |
| 1426 | 1622 | ||
| 1427 | /* | 1623 | /* |
| @@ -1952,6 +2148,14 @@ int __init fec_enet_init(struct net_device *dev) | |||
| 1952 | if (index >= FEC_MAX_PORTS) | 2148 | if (index >= FEC_MAX_PORTS) |
| 1953 | return -ENXIO; | 2149 | return -ENXIO; |
| 1954 | 2150 | ||
| 2151 | /* Allocate memory for buffer descriptors. | ||
| 2152 | */ | ||
| 2153 | mem_addr = __get_free_page(GFP_KERNEL); | ||
| 2154 | if (mem_addr == 0) { | ||
| 2155 | printk("FEC: allocate descriptor memory failed?\n"); | ||
| 2156 | return -ENOMEM; | ||
| 2157 | } | ||
| 2158 | |||
| 1955 | /* Create an Ethernet device instance. | 2159 | /* Create an Ethernet device instance. |
| 1956 | */ | 2160 | */ |
| 1957 | fecp = (volatile fec_t *) fec_hw[index]; | 2161 | fecp = (volatile fec_t *) fec_hw[index]; |
| @@ -1964,16 +2168,6 @@ int __init fec_enet_init(struct net_device *dev) | |||
| 1964 | fecp->fec_ecntrl = 1; | 2168 | fecp->fec_ecntrl = 1; |
| 1965 | udelay(10); | 2169 | udelay(10); |
| 1966 | 2170 | ||
| 1967 | /* Clear and enable interrupts */ | ||
| 1968 | fecp->fec_ievent = 0xffc00000; | ||
| 1969 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
| 1970 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
| 1971 | fecp->fec_hash_table_high = 0; | ||
| 1972 | fecp->fec_hash_table_low = 0; | ||
| 1973 | fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; | ||
| 1974 | fecp->fec_ecntrl = 2; | ||
| 1975 | fecp->fec_r_des_active = 0x01000000; | ||
| 1976 | |||
| 1977 | /* Set the Ethernet address. If using multiple Enets on the 8xx, | 2171 | /* Set the Ethernet address. If using multiple Enets on the 8xx, |
| 1978 | * this needs some work to get unique addresses. | 2172 | * this needs some work to get unique addresses. |
| 1979 | * | 2173 | * |
| @@ -1982,14 +2176,6 @@ int __init fec_enet_init(struct net_device *dev) | |||
| 1982 | */ | 2176 | */ |
| 1983 | fec_get_mac(dev); | 2177 | fec_get_mac(dev); |
| 1984 | 2178 | ||
| 1985 | /* Allocate memory for buffer descriptors. | ||
| 1986 | */ | ||
| 1987 | if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) { | ||
| 1988 | printk("FEC init error. Need more space.\n"); | ||
| 1989 | printk("FEC initialization failed.\n"); | ||
| 1990 | return 1; | ||
| 1991 | } | ||
| 1992 | mem_addr = __get_free_page(GFP_KERNEL); | ||
| 1993 | cbd_base = (cbd_t *)mem_addr; | 2179 | cbd_base = (cbd_t *)mem_addr; |
| 1994 | /* XXX: missing check for allocation failure */ | 2180 | /* XXX: missing check for allocation failure */ |
| 1995 | 2181 | ||
| @@ -2067,6 +2253,16 @@ int __init fec_enet_init(struct net_device *dev) | |||
| 2067 | */ | 2253 | */ |
| 2068 | fec_request_intrs(dev); | 2254 | fec_request_intrs(dev); |
| 2069 | 2255 | ||
| 2256 | /* Clear and enable interrupts */ | ||
| 2257 | fecp->fec_ievent = 0xffc00000; | ||
| 2258 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
| 2259 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
| 2260 | fecp->fec_hash_table_high = 0; | ||
| 2261 | fecp->fec_hash_table_low = 0; | ||
| 2262 | fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; | ||
| 2263 | fecp->fec_ecntrl = 2; | ||
| 2264 | fecp->fec_r_des_active = 0x01000000; | ||
| 2265 | |||
| 2070 | dev->base_addr = (unsigned long)fecp; | 2266 | dev->base_addr = (unsigned long)fecp; |
| 2071 | 2267 | ||
| 2072 | /* The FEC Ethernet specific entries in the device structure. */ | 2268 | /* The FEC Ethernet specific entries in the device structure. */ |
