diff options
Diffstat (limited to 'target/linux/coldfire/patches/010-m5445x_fec.patch')
-rw-r--r-- | target/linux/coldfire/patches/010-m5445x_fec.patch | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/target/linux/coldfire/patches/010-m5445x_fec.patch b/target/linux/coldfire/patches/010-m5445x_fec.patch new file mode 100644 index 0000000000..0a87bd4cde --- /dev/null +++ b/target/linux/coldfire/patches/010-m5445x_fec.patch @@ -0,0 +1,392 @@ +From c562ab80fe383e6fa49dbe38257421cf37f0e4b3 Mon Sep 17 00:00:00 2001 +From: Kurt Mahan <kmahan@freescale.com> +Date: Wed, 31 Oct 2007 17:07:25 -0600 +Subject: [PATCH] MCF5445x FEC support. + +LTIBName: m5445x-fec +Signed-off-by: Kurt Mahan <kmahan@freescale.com> +--- + 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 |