diff options
author | Matt Waddel <Matt.Waddel@freescale.com> | 2006-06-26 23:10:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-27 21:26:37 -0400 |
commit | 6b2652936b9e61df47664a8dde46872a74d7dba2 (patch) | |
tree | b36ac6dc08719436b3dc3b8aecf0e0bd1b821d60 /drivers/net | |
parent | 677177c5319f7079c22d04926c23b31166d7d405 (diff) |
[PATCH] m68knommu: FEC driver support for the ColdFire 523x CPU family
Add support for the FEC module in the ColdFire 532x CPU family.
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/fec.c | 198 |
1 files changed, 179 insertions, 19 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 16fc12fe933c..0ba9f77603f6 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
@@ -51,7 +51,7 @@ | |||
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 | defined(CONFIG_M520x) || defined(CONFIG_M532x) |
55 | #include <asm/coldfire.h> | 55 | #include <asm/coldfire.h> |
56 | #include <asm/mcfsim.h> | 56 | #include <asm/mcfsim.h> |
57 | #include "fec.h" | 57 | #include "fec.h" |
@@ -80,6 +80,8 @@ static unsigned int fec_hw[] = { | |||
80 | (MCF_MBAR + 0x1000), | 80 | (MCF_MBAR + 0x1000), |
81 | #elif defined(CONFIG_M520x) | 81 | #elif defined(CONFIG_M520x) |
82 | (MCF_MBAR+0x30000), | 82 | (MCF_MBAR+0x30000), |
83 | #elif defined(CONFIG_M532x) | ||
84 | (MCF_MBAR+0xfc030000), | ||
83 | #else | 85 | #else |
84 | &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), | 86 | &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), |
85 | #endif | 87 | #endif |
@@ -143,7 +145,7 @@ typedef struct { | |||
143 | #define TX_RING_MOD_MASK 15 /* for this to work */ | 145 | #define TX_RING_MOD_MASK 15 /* for this to work */ |
144 | 146 | ||
145 | #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) | 147 | #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) |
146 | #error "FEC: descriptor ring size contants too large" | 148 | #error "FEC: descriptor ring size constants too large" |
147 | #endif | 149 | #endif |
148 | 150 | ||
149 | /* Interrupt events/masks. | 151 | /* Interrupt events/masks. |
@@ -167,12 +169,12 @@ typedef struct { | |||
167 | 169 | ||
168 | 170 | ||
169 | /* | 171 | /* |
170 | * The 5270/5271/5280/5282 RX control register also contains maximum frame | 172 | * The 5270/5271/5280/5282/532x RX control register also contains maximum frame |
171 | * size bits. Other FEC hardware does not, so we need to take that into | 173 | * size bits. Other FEC hardware does not, so we need to take that into |
172 | * account when setting it. | 174 | * account when setting it. |
173 | */ | 175 | */ |
174 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ | 176 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ |
175 | defined(CONFIG_M520x) | 177 | defined(CONFIG_M520x) || defined(CONFIG_M532x) |
176 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) | 178 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) |
177 | #else | 179 | #else |
178 | #define OPT_FRAME_SIZE 0 | 180 | #define OPT_FRAME_SIZE 0 |
@@ -1216,7 +1218,7 @@ static phy_info_t const * const phy_info[] = { | |||
1216 | }; | 1218 | }; |
1217 | 1219 | ||
1218 | /* ------------------------------------------------------------------------- */ | 1220 | /* ------------------------------------------------------------------------- */ |
1219 | 1221 | #if !defined(CONFIG_M532x) | |
1220 | #ifdef CONFIG_RPXCLASSIC | 1222 | #ifdef CONFIG_RPXCLASSIC |
1221 | static void | 1223 | static void |
1222 | mii_link_interrupt(void *dev_id); | 1224 | mii_link_interrupt(void *dev_id); |
@@ -1224,6 +1226,7 @@ mii_link_interrupt(void *dev_id); | |||
1224 | static irqreturn_t | 1226 | static irqreturn_t |
1225 | mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs); | 1227 | mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs); |
1226 | #endif | 1228 | #endif |
1229 | #endif | ||
1227 | 1230 | ||
1228 | #if defined(CONFIG_M5272) | 1231 | #if defined(CONFIG_M5272) |
1229 | 1232 | ||
@@ -1618,6 +1621,159 @@ static void __inline__ fec_uncache(unsigned long addr) | |||
1618 | 1621 | ||
1619 | /* ------------------------------------------------------------------------- */ | 1622 | /* ------------------------------------------------------------------------- */ |
1620 | 1623 | ||
1624 | #elif defined(CONFIG_M532x) | ||
1625 | /* | ||
1626 | * Code specific for M532x | ||
1627 | */ | ||
1628 | static void __inline__ fec_request_intrs(struct net_device *dev) | ||
1629 | { | ||
1630 | struct fec_enet_private *fep; | ||
1631 | int b; | ||
1632 | static const struct idesc { | ||
1633 | char *name; | ||
1634 | unsigned short irq; | ||
1635 | } *idp, id[] = { | ||
1636 | { "fec(TXF)", 36 }, | ||
1637 | { "fec(TXB)", 37 }, | ||
1638 | { "fec(TXFIFO)", 38 }, | ||
1639 | { "fec(TXCR)", 39 }, | ||
1640 | { "fec(RXF)", 40 }, | ||
1641 | { "fec(RXB)", 41 }, | ||
1642 | { "fec(MII)", 42 }, | ||
1643 | { "fec(LC)", 43 }, | ||
1644 | { "fec(HBERR)", 44 }, | ||
1645 | { "fec(GRA)", 45 }, | ||
1646 | { "fec(EBERR)", 46 }, | ||
1647 | { "fec(BABT)", 47 }, | ||
1648 | { "fec(BABR)", 48 }, | ||
1649 | { NULL }, | ||
1650 | }; | ||
1651 | |||
1652 | fep = netdev_priv(dev); | ||
1653 | b = (fep->index) ? 128 : 64; | ||
1654 | |||
1655 | /* Setup interrupt handlers. */ | ||
1656 | for (idp = id; idp->name; idp++) { | ||
1657 | if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0) | ||
1658 | printk("FEC: Could not allocate %s IRQ(%d)!\n", | ||
1659 | idp->name, b+idp->irq); | ||
1660 | } | ||
1661 | |||
1662 | /* Unmask interrupts */ | ||
1663 | MCF_INTC0_ICR36 = 0x2; | ||
1664 | MCF_INTC0_ICR37 = 0x2; | ||
1665 | MCF_INTC0_ICR38 = 0x2; | ||
1666 | MCF_INTC0_ICR39 = 0x2; | ||
1667 | MCF_INTC0_ICR40 = 0x2; | ||
1668 | MCF_INTC0_ICR41 = 0x2; | ||
1669 | MCF_INTC0_ICR42 = 0x2; | ||
1670 | MCF_INTC0_ICR43 = 0x2; | ||
1671 | MCF_INTC0_ICR44 = 0x2; | ||
1672 | MCF_INTC0_ICR45 = 0x2; | ||
1673 | MCF_INTC0_ICR46 = 0x2; | ||
1674 | MCF_INTC0_ICR47 = 0x2; | ||
1675 | MCF_INTC0_ICR48 = 0x2; | ||
1676 | |||
1677 | MCF_INTC0_IMRH &= ~( | ||
1678 | MCF_INTC_IMRH_INT_MASK36 | | ||
1679 | MCF_INTC_IMRH_INT_MASK37 | | ||
1680 | MCF_INTC_IMRH_INT_MASK38 | | ||
1681 | MCF_INTC_IMRH_INT_MASK39 | | ||
1682 | MCF_INTC_IMRH_INT_MASK40 | | ||
1683 | MCF_INTC_IMRH_INT_MASK41 | | ||
1684 | MCF_INTC_IMRH_INT_MASK42 | | ||
1685 | MCF_INTC_IMRH_INT_MASK43 | | ||
1686 | MCF_INTC_IMRH_INT_MASK44 | | ||
1687 | MCF_INTC_IMRH_INT_MASK45 | | ||
1688 | MCF_INTC_IMRH_INT_MASK46 | | ||
1689 | MCF_INTC_IMRH_INT_MASK47 | | ||
1690 | MCF_INTC_IMRH_INT_MASK48 ); | ||
1691 | |||
1692 | /* Set up gpio outputs for MII lines */ | ||
1693 | MCF_GPIO_PAR_FECI2C |= (0 | | ||
1694 | MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC | | ||
1695 | MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO); | ||
1696 | MCF_GPIO_PAR_FEC = (0 | | ||
1697 | MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | | ||
1698 | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC); | ||
1699 | } | ||
1700 | |||
1701 | static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) | ||
1702 | { | ||
1703 | volatile fec_t *fecp; | ||
1704 | |||
1705 | fecp = fep->hwp; | ||
1706 | fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; | ||
1707 | fecp->fec_x_cntrl = 0x00; | ||
1708 | |||
1709 | /* | ||
1710 | * Set MII speed to 2.5 MHz | ||
1711 | */ | ||
1712 | fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2; | ||
1713 | fecp->fec_mii_speed = fep->phy_speed; | ||
1714 | |||
1715 | fec_restart(dev, 0); | ||
1716 | } | ||
1717 | |||
1718 | static void __inline__ fec_get_mac(struct net_device *dev) | ||
1719 | { | ||
1720 | struct fec_enet_private *fep = netdev_priv(dev); | ||
1721 | volatile fec_t *fecp; | ||
1722 | unsigned char *iap, tmpaddr[ETH_ALEN]; | ||
1723 | |||
1724 | fecp = fep->hwp; | ||
1725 | |||
1726 | if (FEC_FLASHMAC) { | ||
1727 | /* | ||
1728 | * Get MAC address from FLASH. | ||
1729 | * If it is all 1's or 0's, use the default. | ||
1730 | */ | ||
1731 | iap = FEC_FLASHMAC; | ||
1732 | if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && | ||
1733 | (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) | ||
1734 | iap = fec_mac_default; | ||
1735 | if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && | ||
1736 | (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) | ||
1737 | iap = fec_mac_default; | ||
1738 | } else { | ||
1739 | *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; | ||
1740 | *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); | ||
1741 | iap = &tmpaddr[0]; | ||
1742 | } | ||
1743 | |||
1744 | memcpy(dev->dev_addr, iap, ETH_ALEN); | ||
1745 | |||
1746 | /* Adjust MAC if using default MAC address */ | ||
1747 | if (iap == fec_mac_default) | ||
1748 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | ||
1749 | } | ||
1750 | |||
1751 | static void __inline__ fec_enable_phy_intr(void) | ||
1752 | { | ||
1753 | } | ||
1754 | |||
1755 | static void __inline__ fec_disable_phy_intr(void) | ||
1756 | { | ||
1757 | } | ||
1758 | |||
1759 | static void __inline__ fec_phy_ack_intr(void) | ||
1760 | { | ||
1761 | } | ||
1762 | |||
1763 | static void __inline__ fec_localhw_setup(void) | ||
1764 | { | ||
1765 | } | ||
1766 | |||
1767 | /* | ||
1768 | * Do not need to make region uncached on 532x. | ||
1769 | */ | ||
1770 | static void __inline__ fec_uncache(unsigned long addr) | ||
1771 | { | ||
1772 | } | ||
1773 | |||
1774 | /* ------------------------------------------------------------------------- */ | ||
1775 | |||
1776 | |||
1621 | #else | 1777 | #else |
1622 | 1778 | ||
1623 | /* | 1779 | /* |
@@ -1985,9 +2141,12 @@ fec_enet_open(struct net_device *dev) | |||
1985 | mii_do_cmd(dev, fep->phy->config); | 2141 | mii_do_cmd(dev, fep->phy->config); |
1986 | mii_do_cmd(dev, phy_cmd_config); /* display configuration */ | 2142 | mii_do_cmd(dev, phy_cmd_config); /* display configuration */ |
1987 | 2143 | ||
1988 | /* FIXME: use netif_carrier_{on,off} ; this polls | 2144 | /* Poll until the PHY tells us its configuration |
1989 | * until link is up which is wrong... could be | 2145 | * (not link state). |
1990 | * 30 seconds or more we are trapped in here. -jgarzik | 2146 | * Request is initiated by mii_do_cmd above, but answer |
2147 | * comes by interrupt. | ||
2148 | * This should take about 25 usec per register at 2.5 MHz, | ||
2149 | * and we read approximately 5 registers. | ||
1991 | */ | 2150 | */ |
1992 | while(!fep->sequence_done) | 2151 | while(!fep->sequence_done) |
1993 | schedule(); | 2152 | schedule(); |
@@ -2253,15 +2412,11 @@ int __init fec_enet_init(struct net_device *dev) | |||
2253 | */ | 2412 | */ |
2254 | fec_request_intrs(dev); | 2413 | fec_request_intrs(dev); |
2255 | 2414 | ||
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; | 2415 | fecp->fec_hash_table_high = 0; |
2261 | fecp->fec_hash_table_low = 0; | 2416 | fecp->fec_hash_table_low = 0; |
2262 | fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; | 2417 | fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; |
2263 | fecp->fec_ecntrl = 2; | 2418 | fecp->fec_ecntrl = 2; |
2264 | fecp->fec_r_des_active = 0x01000000; | 2419 | fecp->fec_r_des_active = 0; |
2265 | 2420 | ||
2266 | dev->base_addr = (unsigned long)fecp; | 2421 | dev->base_addr = (unsigned long)fecp; |
2267 | 2422 | ||
@@ -2281,6 +2436,11 @@ int __init fec_enet_init(struct net_device *dev) | |||
2281 | /* setup MII interface */ | 2436 | /* setup MII interface */ |
2282 | fec_set_mii(dev, fep); | 2437 | fec_set_mii(dev, fep); |
2283 | 2438 | ||
2439 | /* Clear and enable interrupts */ | ||
2440 | fecp->fec_ievent = 0xffc00000; | ||
2441 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
2442 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
2443 | |||
2284 | /* Queue up command to detect the PHY and initialize the | 2444 | /* Queue up command to detect the PHY and initialize the |
2285 | * remainder of the interface. | 2445 | * remainder of the interface. |
2286 | */ | 2446 | */ |
@@ -2312,11 +2472,6 @@ fec_restart(struct net_device *dev, int duplex) | |||
2312 | fecp->fec_ecntrl = 1; | 2472 | fecp->fec_ecntrl = 1; |
2313 | udelay(10); | 2473 | udelay(10); |
2314 | 2474 | ||
2315 | /* Enable interrupts we wish to service. | ||
2316 | */ | ||
2317 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
2318 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
2319 | |||
2320 | /* Clear any outstanding interrupt. | 2475 | /* Clear any outstanding interrupt. |
2321 | */ | 2476 | */ |
2322 | fecp->fec_ievent = 0xffc00000; | 2477 | fecp->fec_ievent = 0xffc00000; |
@@ -2408,7 +2563,12 @@ fec_restart(struct net_device *dev, int duplex) | |||
2408 | /* And last, enable the transmit and receive processing. | 2563 | /* And last, enable the transmit and receive processing. |
2409 | */ | 2564 | */ |
2410 | fecp->fec_ecntrl = 2; | 2565 | fecp->fec_ecntrl = 2; |
2411 | fecp->fec_r_des_active = 0x01000000; | 2566 | fecp->fec_r_des_active = 0; |
2567 | |||
2568 | /* Enable interrupts we wish to service. | ||
2569 | */ | ||
2570 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
2571 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
2412 | } | 2572 | } |
2413 | 2573 | ||
2414 | static void | 2574 | static void |