| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- From c562ab80fe383e6fa49dbe38257421cf37f0e4b3 Mon Sep 17 00:00:00 2001
- From: Kurt Mahan <[email protected]>
- Date: Wed, 31 Oct 2007 17:07:25 -0600
- Subject: [PATCH] MCF5445x FEC support.
- LTIBName: m5445x-fec
- Signed-off-by: Kurt Mahan <[email protected]>
- ---
- drivers/net/Kconfig | 8 ++-
- drivers/net/fec.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++----
- drivers/net/fec.h | 2 +-
- 3 files changed, 198 insertions(+), 19 deletions(-)
- --- a/drivers/net/Kconfig
- +++ b/drivers/net/Kconfig
- @@ -1973,7 +1973,7 @@ config 68360_ENET
-
- config FEC
- bool "FEC ethernet controller (of ColdFire CPUs)"
- - depends on M523x || M527x || M5272 || M528x || M520x
- + depends on M523x || M527x || M5272 || M528x || M520x || M54455
- help
- Say Y here if you want to use the built-in 10/100 Fast ethernet
- controller on some Motorola ColdFire processors.
- @@ -1985,6 +1985,12 @@ config FEC2
- Say Y here if you want to use the second built-in 10/100 Fast
- ethernet controller on some Motorola ColdFire processors.
-
- +config FEC_SHARED_PHY
- + bool "Shared PHY interface(on some ColdFire designs)"
- + depends on FEC2
- + help
- + Say Y here if both PHYs are controlled via a single channel.
- +
- config FEC_MPC52xx
- tristate "MPC52xx FEC driver"
- depends on PPC_MERGE && PPC_MPC52xx && PPC_BESTCOMM_FEC
- --- a/drivers/net/fec.c
- +++ b/drivers/net/fec.c
- @@ -51,7 +51,9 @@
-
- #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
- defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
- - defined(CONFIG_M520x) || defined(CONFIG_M532x)
- + defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
- + defined(CONFIG_M54455)
- +
- #include <asm/coldfire.h>
- #include <asm/mcfsim.h>
- #include "fec.h"
- @@ -82,6 +84,11 @@ static unsigned int fec_hw[] = {
- (MCF_MBAR+0x30000),
- #elif defined(CONFIG_M532x)
- (MCF_MBAR+0xfc030000),
- +#elif defined(CONFIG_M54455)
- + (MCF_MBAR+0xfc030000),
- +#if defined(CONFIG_FEC2)
- + (MCF_MBAR+0xfc034000),
- +#endif
- #else
- &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
- #endif
- @@ -172,7 +179,7 @@ typedef struct {
- * account when setting it.
- */
- #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- - defined(CONFIG_M520x) || defined(CONFIG_M532x)
- + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_M54455)
- #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
- #else
- #define OPT_FRAME_SIZE 0
- @@ -213,6 +220,7 @@ struct fec_enet_private {
- uint phy_speed;
- phy_info_t const *phy;
- struct work_struct phy_task;
- + volatile fec_t *phy_hwp;
-
- uint sequence_done;
- uint mii_phy_task_queued;
- @@ -349,7 +357,8 @@ fec_enet_start_xmit(struct sk_buff *skb,
- if (bdp->cbd_bufaddr & 0x3) {
- unsigned int index;
- index = bdp - fep->tx_bd_base;
- - memcpy(fep->tx_bounce[index], (void *) bdp->cbd_bufaddr, bdp->cbd_datlen);
- + memcpy(fep->tx_bounce[index],
- + (void *)skb->data, bdp->cbd_datlen);
- bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
- }
-
- @@ -702,7 +711,7 @@ fec_enet_mii(struct net_device *dev)
- uint mii_reg;
-
- fep = netdev_priv(dev);
- - ep = fep->hwp;
- + ep = fep->phy_hwp;
- mii_reg = ep->fec_mii_data;
-
- spin_lock(&fep->lock);
- @@ -753,7 +762,7 @@ mii_queue(struct net_device *dev, int re
- mii_tail = mip;
- } else {
- mii_head = mii_tail = mip;
- - fep->hwp->fec_mii_data = regval;
- + fep->phy_hwp->fec_mii_data = regval;
- }
- } else {
- retval = 1;
- @@ -1151,8 +1160,7 @@ static phy_info_t const phy_info_ks8721b
- };
-
- /* ------------------------------------------------------------------------- */
- -/* register definitions for the DP83848 */
- -
- +/* register definitions for the DP83848 and DP83849 */
- #define MII_DP8384X_PHYSTST 16 /* PHY Status Register */
-
- static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev)
- @@ -1186,27 +1194,50 @@ static void mii_parse_dp8384x_sr2(uint m
- *s |= PHY_STAT_FAULT;
- }
-
- +static phy_cmd_t const phy_cmd_dp8384x_ack_int[] = {
- + { mk_mii_end, }
- + };
- +
- +static phy_cmd_t const phy_cmd_dp8384x_shutdown[] = {
- + { mk_mii_end, }
- + };
- +
- static phy_info_t phy_info_dp83848= {
- - 0x020005c9,
- - "DP83848",
- + .id = 0x020005c9,
- + .name = "DP83848",
-
- - (const phy_cmd_t []) { /* config */
- + .config = (const phy_cmd_t []) { /* config */
- { mk_mii_read(MII_REG_CR), mii_parse_cr },
- { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
- { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 },
- { mk_mii_end, }
- },
- - (const phy_cmd_t []) { /* startup - enable interrupts */
- + .startup = (const phy_cmd_t []) { /* startup - enable interrupts */
- { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
- { mk_mii_read(MII_REG_SR), mii_parse_sr },
- { mk_mii_end, }
- },
- - (const phy_cmd_t []) { /* ack_int - never happens, no interrupt */
- + .ack_int = phy_cmd_dp8384x_ack_int,
- + .shutdown = phy_cmd_dp8384x_shutdown,
- +};
- +
- +static phy_info_t phy_info_dp83849 = {
- + .id = 0x020005ca,
- + .name = "DP83849",
- +
- + .config = (const phy_cmd_t []) { /* config */
- + { mk_mii_read(MII_REG_CR), mii_parse_cr },
- + { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
- + { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 },
- { mk_mii_end, }
- },
- - (const phy_cmd_t []) { /* shutdown */
- + .startup = (const phy_cmd_t []) { /* startup - enable interrupts */
- + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
- + { mk_mii_read(MII_REG_SR), mii_parse_sr },
- { mk_mii_end, }
- },
- + .ack_int = phy_cmd_dp8384x_ack_int,
- + .shutdown = phy_cmd_dp8384x_shutdown,
- };
-
- /* ------------------------------------------------------------------------- */
- @@ -1218,6 +1249,7 @@ static phy_info_t const * const phy_info
- &phy_info_am79c874,
- &phy_info_ks8721bl,
- &phy_info_dp83848,
- + &phy_info_dp83849,
- NULL
- };
-
- @@ -1799,6 +1831,138 @@ static void __inline__ fec_uncache(unsig
-
- /* ------------------------------------------------------------------------- */
-
- +#elif defined(CONFIG_M54455)
- +/*
- + * Code specific for M54455
- + */
- +
- +static void __inline__ fec_request_intrs(struct net_device *dev)
- +{
- + struct fec_enet_private *fep;
- + int b;
- + static const struct idesc {
- + char *name;
- + unsigned short irq;
- + } *idp, id[] = {
- + { "fec(TXF)", 36 },
- + { "fec(TXB)", 37 },
- + { "fec(TXFIFO)", 38 },
- + { "fec(TXCR)", 39 },
- + { "fec(RXF)", 40 },
- + { "fec(RXB)", 41 },
- + { "fec(MII)", 42 },
- + { "fec(LC)", 43 },
- + { "fec(HBERR)", 44 },
- + { "fec(GRA)", 45 },
- + { "fec(EBERR)", 46 },
- + { "fec(BABT)", 47 },
- + { "fec(BABR)", 48 },
- + { NULL },
- + };
- +
- + fep = netdev_priv(dev);
- + b = (fep->index) ? 77 : 64;
- +
- + /* Setup interrupt handlers. */
- + for (idp = id; idp->name; idp++) {
- + if (request_irq(b+idp->irq, fec_enet_interrupt, 0,
- + idp->name, dev) != 0)
- + printk(KERN_ERR "FEC: Could not alloc %s IRQ(%d)!\n",
- + idp->name, b+idp->irq);
- + }
- +
- + if (fep->index) {
- + /* Configure RMII */
- + MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
- + MCF_GPIO_PAR_FEC_FEC1_MASK) |
- + MCF_GPIO_PAR_FEC_FEC1_RMII_GPIO;
- + } else {
- + /* Configure RMII */
- + MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
- + MCF_GPIO_PAR_FEC_FEC0_MASK) |
- + MCF_GPIO_PAR_FEC_FEC0_RMII_GPIO;
- + }
- +
- + /* Set up gpio outputs for MII lines on FEC0 */
- + MCF_GPIO_PAR_FECI2C |= (0 |
- + MCF_GPIO_PAR_FECI2C_MDIO0_MDIO0 |
- + MCF_GPIO_PAR_FECI2C_MDC0_MDC0);
- +}
- +
- +static void __inline__ fec_set_mii(struct net_device *dev,
- + struct fec_enet_private *fep)
- +{
- + volatile fec_t *fecp;
- +
- + fecp = fep->hwp;
- + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
- + fecp->fec_x_cntrl = 0x00;
- +
- + /*
- + * Set MII speed to 2.5 MHz
- + */
- + fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
- + fecp->fec_mii_speed = fep->phy_speed;
- +
- + fec_restart(dev, 0);
- +}
- +
- +static void __inline__ fec_get_mac(struct net_device *dev)
- +{
- + struct fec_enet_private *fep = netdev_priv(dev);
- + volatile fec_t *fecp;
- + unsigned char *iap, tmpaddr[ETH_ALEN];
- +
- + fecp = fep->hwp;
- +
- + if (FEC_FLASHMAC) {
- + /*
- + * Get MAC address from FLASH.
- + * If it is all 1's or 0's, use the default.
- + */
- + iap = FEC_FLASHMAC;
- + if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
- + (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
- + iap = fec_mac_default;
- + if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&
- + (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
- + iap = fec_mac_default;
- + } else {
- + *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;
- + *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);
- + iap = &tmpaddr[0];
- + }
- +
- + memcpy(dev->dev_addr, iap, ETH_ALEN);
- +
- + /* Adjust MAC if using default MAC address */
- + if (iap == fec_mac_default)
- + dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] +
- + fep->index;
- +}
- +
- +static void __inline__ fec_enable_phy_intr(void)
- +{
- +}
- +
- +static void __inline__ fec_disable_phy_intr(void)
- +{
- +}
- +
- +static void __inline__ fec_phy_ack_intr(void)
- +{
- +}
- +
- +static void __inline__ fec_localhw_setup(void)
- +{
- +}
- +
- +static void __inline__ fec_uncache(unsigned long addr)
- +{
- +}
- +
- +/* ------------------------------------------------------------------------- */
- +
-
- #else
-
- @@ -2305,7 +2469,7 @@ fec_set_mac_address(struct net_device *d
-
- }
-
- -/* Initialize the FEC Ethernet on 860T (or ColdFire 5272).
- +/* Initialize the FEC Ethernet.
- */
- /*
- * XXX: We need to clean up on failure exits here.
- @@ -2326,7 +2490,7 @@ int __init fec_enet_init(struct net_devi
-
- /* Allocate memory for buffer descriptors.
- */
- - mem_addr = __get_free_page(GFP_KERNEL);
- + mem_addr = __get_free_page(GFP_DMA);
- if (mem_addr == 0) {
- printk("FEC: allocate descriptor memory failed?\n");
- return -ENOMEM;
- @@ -2339,6 +2503,11 @@ int __init fec_enet_init(struct net_devi
- fep->index = index;
- fep->hwp = fecp;
- fep->netdev = dev;
- +#ifdef CONFIG_FEC_SHARED_PHY
- + fep->phy_hwp = (volatile fec_t *) fec_hw[index & ~1];
- +#else
- + fep->phy_hwp = fecp;
- +#endif
-
- /* Whack a reset. We should wait for this.
- */
- @@ -2375,7 +2544,7 @@ int __init fec_enet_init(struct net_devi
-
- /* Allocate a page.
- */
- - mem_addr = __get_free_page(GFP_KERNEL);
- + mem_addr = __get_free_page(GFP_DMA);
- /* XXX: missing check for allocation failure */
-
- fec_uncache(mem_addr);
- @@ -2400,7 +2569,7 @@ int __init fec_enet_init(struct net_devi
- bdp = fep->tx_bd_base;
- for (i=0, j=FEC_ENET_TX_FRPPG; i<TX_RING_SIZE; i++) {
- if (j >= FEC_ENET_TX_FRPPG) {
- - mem_addr = __get_free_page(GFP_KERNEL);
- + mem_addr = __get_free_page(GFP_DMA);
- j = 1;
- } else {
- mem_addr += FEC_ENET_TX_FRSIZE;
- @@ -2462,7 +2631,11 @@ int __init fec_enet_init(struct net_devi
- * remainder of the interface.
- */
- fep->phy_id_done = 0;
- +#ifndef CONFIG_FEC_SHARED_PHY
- fep->phy_addr = 0;
- +#else
- + fep->phy_addr = fep->index;
- +#endif
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
-
- index++;
- --- a/drivers/net/fec.h
- +++ b/drivers/net/fec.h
- @@ -14,7 +14,7 @@
- /****************************************************************************/
-
- #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- - defined(CONFIG_M520x) || defined(CONFIG_M532x)
- + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_M54455)
- /*
- * Just figures, Motorola would have to change the offsets for
- * registers in the same peripheral device on different models
|