* FEC patches
@ 2009-01-29 9:03 Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: remove unused #else branches Sascha Hauer
2009-01-30 0:04 ` FEC patches David Miller
0 siblings, 2 replies; 14+ messages in thread
From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller, Greg Ungerer
Hi David,
Please merge the following patches. The only change since I last sent
them is that I added CONFIG_M520x to the list of supported architectures
as Greg requested.
Regards
Sascha
If you prefer to pull them via git, you can do it here:
The following changes since commit 5ee810072175042775e39bdd3eaaa68884c27805:
Linus Torvalds (1):
Fix "multiple definition of `debugfs_create_size_t'"
are available in the git repository at:
git://pasiphae.extern.pengutronix.de/git/imx/linux-2.6.git fec-pu
Sascha Hauer (9):
fec: remove unused #else branches
fec: remove empty functions
fec: use linux/*.h instead of asm/*.h
fec: do not use memcpy on physical addresses
fec: use dma_alloc_coherent for descriptor ring
fec: Fix KS8721BL_ICSR phy register offset
fec: replace flush_dcache_range with dma_sync_single
fec: Add support for Freescale MX27
FEC: Turn FEC driver into platform device driver
drivers/net/Kconfig | 6 +-
drivers/net/fec.c | 446 ++++++++++++++++++++++++++++-----------------------
drivers/net/fec.h | 11 +-
3 files changed, 260 insertions(+), 203 deletions(-)
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH] fec: remove unused #else branches 2009-01-29 9:03 FEC patches Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: remove empty functions Sascha Hauer 2009-01-30 0:04 ` FEC patches David Miller 1 sibling, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer The #else branches throughout this driver belong to a PowerPC 8xx for which this driver is not used. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 92 ----------------------------------------------------- 1 files changed, 0 insertions(+), 92 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 7e33c12..b754f60 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -72,8 +72,6 @@ static unsigned int fec_hw[] = { (MCF_MBAR+0x30000), #elif defined(CONFIG_M532x) (MCF_MBAR+0xfc030000), -#else - &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), #endif }; @@ -1760,96 +1758,6 @@ static void __inline__ fec_uncache(unsigned long addr) { } -/* ------------------------------------------------------------------------- */ - - -#else - -/* - * Code specific to the MPC860T setup. - */ -static void __inline__ fec_request_intrs(struct net_device *dev) -{ - volatile immap_t *immap; - - immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ - - if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) - panic("Could not allocate FEC IRQ!"); -} - -static void __inline__ fec_get_mac(struct net_device *dev) -{ - bd_t *bd; - - bd = (bd_t *)__res; - memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN); -} - -static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) -{ - extern uint _get_IMMR(void); - volatile immap_t *immap; - volatile fec_t *fecp; - - fecp = fep->hwp; - immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ - - /* Configure all of port D for MII. - */ - immap->im_ioport.iop_pdpar = 0x1fff; - - /* Bits moved from Rev. D onward. - */ - if ((_get_IMMR() & 0xffff) < 0x0501) - immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ - else - immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ - - /* Set MII speed to 2.5 MHz - */ - fecp->fec_mii_speed = fep->phy_speed = - ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e; -} - -static void __inline__ fec_enable_phy_intr(void) -{ - volatile fec_t *fecp; - - fecp = fep->hwp; - - /* Enable MII command finished interrupt - */ - fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; -} - -static void __inline__ fec_disable_phy_intr(void) -{ -} - -static void __inline__ fec_phy_ack_intr(void) -{ -} - -static void __inline__ fec_localhw_setup(void) -{ - volatile fec_t *fecp; - - fecp = fep->hwp; - fecp->fec_r_hash = PKT_MAXBUF_SIZE; - /* Enable big endian and don't care about SDMA FC. - */ - fecp->fec_fun_code = 0x78000000; -} - -static void __inline__ fec_uncache(unsigned long addr) -{ - pte_t *pte; - pte = va_to_pte(mem_addr); - pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(init_mm.mmap, mem_addr); -} - #endif /* ------------------------------------------------------------------------- */ -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: remove empty functions 2009-01-29 9:03 ` [PATCH] fec: remove unused #else branches Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: use linux/*.h instead of asm/*.h Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer There are some architecture specific functions which are all empty. Remove them. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 65 ----------------------------------------------------- 1 files changed, 0 insertions(+), 65 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index b754f60..f913c97 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1306,10 +1306,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { volatile unsigned long *icrp; @@ -1325,17 +1321,6 @@ static void __inline__ fec_phy_ack_intr(void) *icrp = 0x0d000000; } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 5272. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) @@ -1475,10 +1460,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { } @@ -1487,17 +1468,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 5272. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M520x) @@ -1596,10 +1566,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { } @@ -1608,14 +1574,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M532x) @@ -1735,10 +1693,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { } @@ -1747,17 +1701,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 532x. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - #endif /* ------------------------------------------------------------------------- */ @@ -2199,8 +2142,6 @@ int __init fec_enet_init(struct net_device *dev) cbd_base = (cbd_t *)mem_addr; /* XXX: missing check for allocation failure */ - fec_uncache(mem_addr); - /* Set receive and transmit descriptor base. */ fep->rx_bd_base = cbd_base; @@ -2221,8 +2162,6 @@ int __init fec_enet_init(struct net_device *dev) mem_addr = __get_free_page(GFP_KERNEL); /* XXX: missing check for allocation failure */ - fec_uncache(mem_addr); - /* Initialize the BD for every fragment in the page. */ for (j=0; j<FEC_ENET_RX_FRPPG; j++) { @@ -2338,7 +2277,6 @@ fec_restart(struct net_device *dev, int duplex) /* Clear any outstanding interrupt. */ fecp->fec_ievent = 0xffc00000; - fec_enable_phy_intr(); /* Set station address. */ @@ -2353,8 +2291,6 @@ fec_restart(struct net_device *dev, int duplex) */ fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fec_localhw_setup(); - /* Set receive and transmit descriptor base. */ fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); @@ -2460,7 +2396,6 @@ fec_stop(struct net_device *dev) /* Clear outstanding MII command interrupts. */ fecp->fec_ievent = FEC_ENET_MII; - fec_enable_phy_intr(); fecp->fec_imask = FEC_ENET_MII; fecp->fec_mii_speed = fep->phy_speed; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: use linux/*.h instead of asm/*.h 2009-01-29 9:03 ` [PATCH] fec: remove empty functions Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: do not use memcpy on physical addresses Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index f913c97..a44b4ee 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -36,15 +36,13 @@ #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/bitops.h> +#include <linux/io.h> +#include <linux/irq.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/pgtable.h> #include <asm/cacheflush.h> - #include <asm/coldfire.h> #include <asm/mcfsim.h> + #include "fec.h" #if defined(CONFIG_FEC2) -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: do not use memcpy on physical addresses 2009-01-29 9:03 ` [PATCH] fec: use linux/*.h instead of asm/*.h Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: use dma_alloc_coherent for descriptor ring Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index a44b4ee..1087c4d 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -341,7 +341,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) 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, skb->len); bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); } -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: use dma_alloc_coherent for descriptor ring 2009-01-29 9:03 ` [PATCH] fec: do not use memcpy on physical addresses Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: Fix KS8721BL_ICSR phy register offset Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 1087c4d..46a441a 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -186,6 +186,7 @@ struct fec_enet_private { /* CPM dual port RAM relative addresses. */ + dma_addr_t bd_dma; cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ cbd_t *tx_bd_base; cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ @@ -2107,7 +2108,8 @@ int __init fec_enet_init(struct net_device *dev) /* Allocate memory for buffer descriptors. */ - mem_addr = __get_free_page(GFP_KERNEL); + mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE, + &fep->bd_dma, GFP_KERNEL); if (mem_addr == 0) { printk("FEC: allocate descriptor memory failed?\n"); return -ENOMEM; @@ -2202,8 +2204,9 @@ int __init fec_enet_init(struct net_device *dev) /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); - fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + fecp->fec_r_des_start = fep->bd_dma; + fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) + * RX_RING_SIZE; /* Install our interrupt handlers. This varies depending on * the architecture. @@ -2291,8 +2294,9 @@ fec_restart(struct net_device *dev, int duplex) /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); - fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + fecp->fec_r_des_start = fep->bd_dma; + fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) + * RX_RING_SIZE; fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; fep->cur_rx = fep->rx_bd_base; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: Fix KS8721BL_ICSR phy register offset 2009-01-29 9:03 ` [PATCH] fec: use dma_alloc_coherent for descriptor ring Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: replace flush_dcache_range with dma_sync_single Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer According to the datasheet the ICSR register is at offset 27, not 22. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 46a441a..cab07ec 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1111,7 +1111,7 @@ static phy_info_t const phy_info_am79c874 = { /* register definitions for the 8721 */ #define MII_KS8721BL_RXERCR 21 -#define MII_KS8721BL_ICSR 22 +#define MII_KS8721BL_ICSR 27 #define MII_KS8721BL_PHYCR 31 static phy_cmd_t const phy_cmd_ks8721bl_config[] = { -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: replace flush_dcache_range with dma_sync_single 2009-01-29 9:03 ` [PATCH] fec: Fix KS8721BL_ICSR phy register offset Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: Add support for Freescale MX27 Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer flush_dcache_range is not portable across architectures. Use dma_sync_single instead. Also, the memory must be synchronised in the receive path aswell. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index cab07ec..a17dc6a 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -356,8 +356,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Push the data cache so the CPM does not get stale memory * data. */ - flush_dcache_range((unsigned long)skb->data, - (unsigned long)skb->data + skb->len); + dma_sync_single(NULL, bdp->cbd_bufaddr, + bdp->cbd_datlen, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. @@ -630,6 +630,9 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { dev->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); + dma_sync_single(NULL, (unsigned long)__pa(data), + pkt_len - 4, DMA_FROM_DEVICE); + /* This does 16 byte alignment, exactly what we need. * The packet length includes FCS, but we don't want to * include that when passing upstream as it messes up -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: Add support for Freescale MX27 2009-01-29 9:03 ` [PATCH] fec: replace flush_dcache_range with dma_sync_single Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 2009-01-29 9:03 ` [PATCH] FEC: Turn FEC driver into platform device driver Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/Kconfig | 6 +++--- drivers/net/fec.c | 15 +++++++++++++-- drivers/net/fec.h | 11 +++++++++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9fe8cb7..2d7cd61 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1828,11 +1828,11 @@ config 68360_ENET the Motorola 68360 processor. config FEC - bool "FEC ethernet controller (of ColdFire CPUs)" - depends on M523x || M527x || M5272 || M528x || M520x + bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" + depends on M523x || M527x || M5272 || M528x || M520x || MACH_MX27 help Say Y here if you want to use the built-in 10/100 Fast ethernet - controller on some Motorola ColdFire processors. + controller on some Motorola ColdFire and Freescale i.MX processors. config FEC2 bool "Second FEC ethernet controller (on some ColdFire CPUs)" diff --git a/drivers/net/fec.c b/drivers/net/fec.c index a17dc6a..7631062 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -38,10 +38,14 @@ #include <linux/bitops.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/clk.h> #include <asm/cacheflush.h> + +#ifndef CONFIG_ARCH_MXC #include <asm/coldfire.h> #include <asm/mcfsim.h> +#endif #include "fec.h" @@ -51,6 +55,13 @@ #define FEC_MAX_PORTS 1 #endif +#ifdef CONFIG_ARCH_MXC +#include <mach/hardware.h> +#define FEC_ALIGNMENT 0xf +#else +#define FEC_ALIGNMENT 0x3 +#endif + #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif @@ -158,7 +169,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_ARCH_MXC) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 @@ -339,7 +350,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ - if (bdp->cbd_bufaddr & 0x3) { + if (bdp->cbd_bufaddr & FEC_ALIGNMENT) { unsigned int index; index = bdp - fep->tx_bd_base; memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 292719d..76c64c9 100644 --- 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_ARCH_MXC) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models @@ -103,12 +103,19 @@ typedef struct fec { /* * Define the buffer descriptor structure. */ +#ifdef CONFIG_ARCH_MXC +typedef struct bufdesc { + unsigned short cbd_datlen; /* Data length */ + unsigned short cbd_sc; /* Control and status info */ + unsigned long cbd_bufaddr; /* Buffer address */ +} cbd_t; +#else typedef struct bufdesc { unsigned short cbd_sc; /* Control and status info */ unsigned short cbd_datlen; /* Data length */ unsigned long cbd_bufaddr; /* Buffer address */ } cbd_t; - +#endif /* * The following definitions courtesy of commproc.h, which where -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] FEC: Turn FEC driver into platform device driver 2009-01-29 9:03 ` [PATCH] fec: Add support for Freescale MX27 Sascha Hauer @ 2009-01-29 9:03 ` Sascha Hauer 0 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2009-01-29 9:03 UTC (permalink / raw) To: netdev; +Cc: David Miller, Greg Ungerer, Sascha Hauer This turns the fec driver into a platform device driver for new platforms. Old platforms are still supported through a FEC_LEGACY define till they are also ported. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Greg Ungerer <gerg@uclinux.org> --- drivers/net/fec.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 220 insertions(+), 29 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 7631062..ea23baa 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -39,6 +39,7 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/clk.h> +#include <linux/platform_device.h> #include <asm/cacheflush.h> @@ -49,12 +50,6 @@ #include "fec.h" -#if defined(CONFIG_FEC2) -#define FEC_MAX_PORTS 2 -#else -#define FEC_MAX_PORTS 1 -#endif - #ifdef CONFIG_ARCH_MXC #include <mach/hardware.h> #define FEC_ALIGNMENT 0xf @@ -62,13 +57,22 @@ #define FEC_ALIGNMENT 0x3 #endif +#if defined CONFIG_M5272 || defined CONFIG_M527x || defined CONFIG_M523x \ + || defined CONFIG_M528x || defined CONFIG_M532x || defined CONFIG_M520x +#define FEC_LEGACY +/* + * Define the fixed address of the FEC hardware. + */ #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif -/* - * Define the fixed address of the FEC hardware. - */ +#if defined(CONFIG_FEC2) +#define FEC_MAX_PORTS 2 +#else +#define FEC_MAX_PORTS 1 +#endif + static unsigned int fec_hw[] = { #if defined(CONFIG_M5272) (MCF_MBAR + 0x840), @@ -106,6 +110,8 @@ static unsigned char fec_mac_default[] = { #define FEC_FLASHMAC 0 #endif +#endif /* FEC_LEGACY */ + /* Forward declarations of some structures to support different PHYs */ @@ -189,6 +195,8 @@ struct fec_enet_private { struct net_device *netdev; + struct clk *clk; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; @@ -1919,7 +1927,9 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) printk("FEC: No PHY device found.\n"); /* Disable external MII interface */ fecp->fec_mii_speed = fep->phy_speed = 0; +#ifdef FREC_LEGACY fec_disable_phy_intr(); +#endif } } @@ -2101,12 +2111,12 @@ fec_set_mac_address(struct net_device *dev) } -/* Initialize the FEC Ethernet on 860T (or ColdFire 5272). - */ /* * XXX: We need to clean up on failure exits here. + * + * index is only used in legacy code */ -int __init fec_enet_init(struct net_device *dev) +int __init fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); unsigned long mem_addr; @@ -2114,11 +2124,6 @@ int __init fec_enet_init(struct net_device *dev) cbd_t *cbd_base; volatile fec_t *fecp; int i, j; - static int index = 0; - - /* Only allow us to be probed once. */ - if (index >= FEC_MAX_PORTS) - return -ENXIO; /* Allocate memory for buffer descriptors. */ @@ -2134,7 +2139,7 @@ int __init fec_enet_init(struct net_device *dev) /* Create an Ethernet device instance. */ - fecp = (volatile fec_t *) fec_hw[index]; + fecp = (volatile fec_t *)dev->base_addr; fep->index = index; fep->hwp = fecp; @@ -2145,16 +2150,24 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_ecntrl = 1; udelay(10); - /* Set the Ethernet address. If using multiple Enets on the 8xx, - * this needs some work to get unique addresses. - * - * This is our default MAC address unless the user changes - * it via eth_mac_addr (our dev->set_mac_addr handler). - */ + /* Set the Ethernet address */ +#ifdef FEC_LEGACY fec_get_mac(dev); +#else + { + unsigned long l; + l = fecp->fec_addr_low; + dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); + dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); + dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); + l = fecp->fec_addr_high; + dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); + } +#endif cbd_base = (cbd_t *)mem_addr; - /* XXX: missing check for allocation failure */ /* Set receive and transmit descriptor base. */ @@ -2222,10 +2235,12 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE; +#ifdef FEC_LEGACY /* Install our interrupt handlers. This varies depending on * the architecture. */ fec_request_intrs(dev); +#endif fecp->fec_grp_hash_table_high = 0; fecp->fec_grp_hash_table_low = 0; @@ -2237,8 +2252,6 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_hash_table_low = 0; #endif - dev->base_addr = (unsigned long)fecp; - /* The FEC Ethernet specific entries in the device structure. */ dev->open = fec_enet_open; dev->hard_start_xmit = fec_enet_start_xmit; @@ -2252,7 +2265,20 @@ int __init fec_enet_init(struct net_device *dev) mii_free = mii_cmds; /* setup MII interface */ +#ifdef FEC_LEGACY fec_set_mii(dev, fep); +#else + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; + fecp->fec_x_cntrl = 0x00; + + /* + * Set MII speed to 2.5 MHz + */ + fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) + / 2500000) / 2) & 0x3F) << 1; + fecp->fec_mii_speed = fep->phy_speed; + fec_restart(dev, 0); +#endif /* Clear and enable interrupts */ fecp->fec_ievent = 0xffc00000; @@ -2265,7 +2291,6 @@ int __init fec_enet_init(struct net_device *dev) fep->phy_addr = 0; mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); - index++; return 0; } @@ -2417,6 +2442,7 @@ fec_stop(struct net_device *dev) fecp->fec_mii_speed = fep->phy_speed; } +#ifdef FEC_LEGACY static int __init fec_enet_module_init(void) { struct net_device *dev; @@ -2428,7 +2454,8 @@ static int __init fec_enet_module_init(void) dev = alloc_etherdev(sizeof(struct fec_enet_private)); if (!dev) return -ENOMEM; - err = fec_enet_init(dev); + dev->base_addr = (unsigned long)fec_hw[i]; + err = fec_enet_init(dev, i); if (err) { free_netdev(dev); continue; @@ -2443,6 +2470,170 @@ static int __init fec_enet_module_init(void) } return 0; } +#else + +static int __devinit +fec_probe(struct platform_device *pdev) +{ + struct fec_enet_private *fep; + struct net_device *ndev; + int i, irq, ret = 0; + struct resource *r; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -ENXIO; + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) + return -EBUSY; + + /* Init network device */ + ndev = alloc_etherdev(sizeof(struct fec_enet_private)); + if (!ndev) + return -ENOMEM; + + SET_NETDEV_DEV(ndev, &pdev->dev); + + /* setup board info structure */ + fep = netdev_priv(ndev); + memset(fep, 0, sizeof(*fep)); + + ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); + + if (!ndev->base_addr) { + ret = -ENOMEM; + goto failed_ioremap; + } + + platform_set_drvdata(pdev, ndev); + + /* This device has up to three irqs on some platforms */ + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (i && irq < 0) + break; + ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); + if (ret) { + while (i >= 0) { + irq = platform_get_irq(pdev, i); + free_irq(irq, ndev); + i--; + } + goto failed_irq; + } + } + + fep->clk = clk_get(&pdev->dev, "fec_clk"); + if (IS_ERR(fep->clk)) { + ret = PTR_ERR(fep->clk); + goto failed_clk; + } + clk_enable(fep->clk); + + ret = fec_enet_init(ndev, 0); + if (ret) + goto failed_init; + + ret = register_netdev(ndev); + if (ret) + goto failed_register; + + return 0; + +failed_register: +failed_init: + clk_disable(fep->clk); + clk_put(fep->clk); +failed_clk: + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (irq > 0) + free_irq(irq, ndev); + } +failed_irq: + iounmap((void __iomem *)ndev->base_addr); +failed_ioremap: + free_netdev(ndev); + + return ret; +} + +static int __devexit +fec_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + fec_stop(ndev); + clk_disable(fep->clk); + clk_put(fep->clk); + iounmap((void __iomem *)ndev->base_addr); + unregister_netdev(ndev); + free_netdev(ndev); + return 0; +} + +static int +fec_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + struct fec_enet_private *fep; + + if (ndev) { + fep = netdev_priv(ndev); + if (netif_running(ndev)) { + netif_device_detach(ndev); + fec_stop(ndev); + } + } + return 0; +} + +static int +fec_resume(struct platform_device *dev) +{ + struct net_device *ndev = platform_get_drvdata(dev); + + if (ndev) { + if (netif_running(ndev)) { + fec_enet_init(ndev, 0); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct platform_driver fec_driver = { + .driver = { + .name = "fec", + .owner = THIS_MODULE, + }, + .probe = fec_probe, + .remove = __devexit_p(fec_drv_remove), + .suspend = fec_suspend, + .resume = fec_resume, +}; + +static int __init +fec_enet_module_init(void) +{ + printk(KERN_INFO "FEC Ethernet Driver\n"); + + return platform_driver_register(&fec_driver); +} + +static void __exit +fec_enet_cleanup(void) +{ + platform_driver_unregister(&fec_driver); +} + +module_exit(fec_enet_cleanup); + +#endif /* FEC_LEGACY */ module_init(fec_enet_module_init); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: FEC patches 2009-01-29 9:03 FEC patches Sascha Hauer 2009-01-29 9:03 ` [PATCH] fec: remove unused #else branches Sascha Hauer @ 2009-01-30 0:04 ` David Miller 1 sibling, 0 replies; 14+ messages in thread From: David Miller @ 2009-01-30 0:04 UTC (permalink / raw) To: s.hauer; +Cc: netdev, gerg From: Sascha Hauer <s.hauer@pengutronix.de> Date: Thu, 29 Jan 2009 10:03:02 +0100 > Please merge the following patches. The only change since I last sent > them is that I added CONFIG_M520x to the list of supported architectures > as Greg requested. I'll look these over and then queue them up for 2.6.30 Thanks! ^ permalink raw reply [flat|nested] 14+ messages in thread
* FEC Patches @ 2009-01-27 10:39 Sascha Hauer 2009-01-27 10:39 ` [PATCH] fec: remove unused #else branches Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:39 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo Hi all, hi Greg, Sorry guys, sending this again. Of course I'm not 'y', just playing git-send-email: Who should the emails appear to be from? [Sascha Hauer <s.hauer@pengutronix.de>] y[es] Emails will be sent from: y These patches are an updated version from the ones I posted some time ago. They give the FEC ethernet driver a facelift and turn it into a platform_device driver. The Coldfire cores are still supported through legacy ifdefs. The platform driver support has been tested on a Freescale i.MX27 SoC. Sascha ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH] fec: remove unused #else branches 2009-01-27 10:39 FEC Patches Sascha Hauer @ 2009-01-27 10:39 ` Sascha Hauer 2009-01-27 10:39 ` [PATCH] fec: remove empty functions Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:39 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer The #else branches throughout this driver belong to a PowerPC 8xx for which this driver is not used. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 92 ----------------------------------------------------- 1 files changed, 0 insertions(+), 92 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 7e33c12..b754f60 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -72,8 +72,6 @@ static unsigned int fec_hw[] = { (MCF_MBAR+0x30000), #elif defined(CONFIG_M532x) (MCF_MBAR+0xfc030000), -#else - &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), #endif }; @@ -1760,96 +1758,6 @@ static void __inline__ fec_uncache(unsigned long addr) { } -/* ------------------------------------------------------------------------- */ - - -#else - -/* - * Code specific to the MPC860T setup. - */ -static void __inline__ fec_request_intrs(struct net_device *dev) -{ - volatile immap_t *immap; - - immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ - - if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) - panic("Could not allocate FEC IRQ!"); -} - -static void __inline__ fec_get_mac(struct net_device *dev) -{ - bd_t *bd; - - bd = (bd_t *)__res; - memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN); -} - -static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) -{ - extern uint _get_IMMR(void); - volatile immap_t *immap; - volatile fec_t *fecp; - - fecp = fep->hwp; - immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ - - /* Configure all of port D for MII. - */ - immap->im_ioport.iop_pdpar = 0x1fff; - - /* Bits moved from Rev. D onward. - */ - if ((_get_IMMR() & 0xffff) < 0x0501) - immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ - else - immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ - - /* Set MII speed to 2.5 MHz - */ - fecp->fec_mii_speed = fep->phy_speed = - ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e; -} - -static void __inline__ fec_enable_phy_intr(void) -{ - volatile fec_t *fecp; - - fecp = fep->hwp; - - /* Enable MII command finished interrupt - */ - fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; -} - -static void __inline__ fec_disable_phy_intr(void) -{ -} - -static void __inline__ fec_phy_ack_intr(void) -{ -} - -static void __inline__ fec_localhw_setup(void) -{ - volatile fec_t *fecp; - - fecp = fep->hwp; - fecp->fec_r_hash = PKT_MAXBUF_SIZE; - /* Enable big endian and don't care about SDMA FC. - */ - fecp->fec_fun_code = 0x78000000; -} - -static void __inline__ fec_uncache(unsigned long addr) -{ - pte_t *pte; - pte = va_to_pte(mem_addr); - pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(init_mm.mmap, mem_addr); -} - #endif /* ------------------------------------------------------------------------- */ -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: remove empty functions 2009-01-27 10:39 ` [PATCH] fec: remove unused #else branches Sascha Hauer @ 2009-01-27 10:39 ` Sascha Hauer 2009-01-27 10:39 ` [PATCH] fec: use linux/*.h instead of asm/*.h Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:39 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer There are some architecture specific functions which are all empty. Remove them. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 65 ----------------------------------------------------- 1 files changed, 0 insertions(+), 65 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index b754f60..f913c97 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1306,10 +1306,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { volatile unsigned long *icrp; @@ -1325,17 +1321,6 @@ static void __inline__ fec_phy_ack_intr(void) *icrp = 0x0d000000; } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 5272. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) @@ -1475,10 +1460,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { } @@ -1487,17 +1468,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 5272. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M520x) @@ -1596,10 +1566,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { } @@ -1608,14 +1574,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M532x) @@ -1735,10 +1693,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) 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) { } @@ -1747,17 +1701,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 532x. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - #endif /* ------------------------------------------------------------------------- */ @@ -2199,8 +2142,6 @@ int __init fec_enet_init(struct net_device *dev) cbd_base = (cbd_t *)mem_addr; /* XXX: missing check for allocation failure */ - fec_uncache(mem_addr); - /* Set receive and transmit descriptor base. */ fep->rx_bd_base = cbd_base; @@ -2221,8 +2162,6 @@ int __init fec_enet_init(struct net_device *dev) mem_addr = __get_free_page(GFP_KERNEL); /* XXX: missing check for allocation failure */ - fec_uncache(mem_addr); - /* Initialize the BD for every fragment in the page. */ for (j=0; j<FEC_ENET_RX_FRPPG; j++) { @@ -2338,7 +2277,6 @@ fec_restart(struct net_device *dev, int duplex) /* Clear any outstanding interrupt. */ fecp->fec_ievent = 0xffc00000; - fec_enable_phy_intr(); /* Set station address. */ @@ -2353,8 +2291,6 @@ fec_restart(struct net_device *dev, int duplex) */ fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fec_localhw_setup(); - /* Set receive and transmit descriptor base. */ fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); @@ -2460,7 +2396,6 @@ fec_stop(struct net_device *dev) /* Clear outstanding MII command interrupts. */ fecp->fec_ievent = FEC_ENET_MII; - fec_enable_phy_intr(); fecp->fec_imask = FEC_ENET_MII; fecp->fec_mii_speed = fep->phy_speed; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: use linux/*.h instead of asm/*.h 2009-01-27 10:39 ` [PATCH] fec: remove empty functions Sascha Hauer @ 2009-01-27 10:39 ` Sascha Hauer 2009-01-27 10:39 ` [PATCH] fec: do not use memcpy on physical addresses Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:39 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index f913c97..a44b4ee 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -36,15 +36,13 @@ #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/bitops.h> +#include <linux/io.h> +#include <linux/irq.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/pgtable.h> #include <asm/cacheflush.h> - #include <asm/coldfire.h> #include <asm/mcfsim.h> + #include "fec.h" #if defined(CONFIG_FEC2) -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: do not use memcpy on physical addresses 2009-01-27 10:39 ` [PATCH] fec: use linux/*.h instead of asm/*.h Sascha Hauer @ 2009-01-27 10:39 ` Sascha Hauer 2009-01-27 10:40 ` [PATCH] fec: use dma_alloc_coherent for descriptor ring Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:39 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index a44b4ee..1087c4d 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -341,7 +341,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) 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, skb->len); bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); } -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: use dma_alloc_coherent for descriptor ring 2009-01-27 10:39 ` [PATCH] fec: do not use memcpy on physical addresses Sascha Hauer @ 2009-01-27 10:40 ` Sascha Hauer 2009-01-27 10:40 ` [PATCH] fec: Fix KS8721BL_ICSR phy register offset Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:40 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 1087c4d..d7ba07c 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -186,6 +186,7 @@ struct fec_enet_private { /* CPM dual port RAM relative addresses. */ + dma_addr_t bd_dma; cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ cbd_t *tx_bd_base; cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ @@ -2107,7 +2108,7 @@ int __init fec_enet_init(struct net_device *dev) /* Allocate memory for buffer descriptors. */ - mem_addr = __get_free_page(GFP_KERNEL); + mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, GFP_KERNEL); if (mem_addr == 0) { printk("FEC: allocate descriptor memory failed?\n"); return -ENOMEM; @@ -2202,8 +2203,8 @@ int __init fec_enet_init(struct net_device *dev) /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); - fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + fecp->fec_r_des_start = fep->bd_dma; + fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE; /* Install our interrupt handlers. This varies depending on * the architecture. @@ -2291,8 +2292,8 @@ fec_restart(struct net_device *dev, int duplex) /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); - fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + fecp->fec_r_des_start = fep->bd_dma; + fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE; fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; fep->cur_rx = fep->rx_bd_base; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: Fix KS8721BL_ICSR phy register offset 2009-01-27 10:40 ` [PATCH] fec: use dma_alloc_coherent for descriptor ring Sascha Hauer @ 2009-01-27 10:40 ` Sascha Hauer 2009-01-27 10:40 ` [PATCH] fec: replace flush_dcache_range with dma_sync_single Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:40 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer According to the datasheet the ICSR register is at offset 27, not 22. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index d7ba07c..f36ee43 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1111,7 +1111,7 @@ static phy_info_t const phy_info_am79c874 = { /* register definitions for the 8721 */ #define MII_KS8721BL_RXERCR 21 -#define MII_KS8721BL_ICSR 22 +#define MII_KS8721BL_ICSR 27 #define MII_KS8721BL_PHYCR 31 static phy_cmd_t const phy_cmd_ks8721bl_config[] = { -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: replace flush_dcache_range with dma_sync_single 2009-01-27 10:40 ` [PATCH] fec: Fix KS8721BL_ICSR phy register offset Sascha Hauer @ 2009-01-27 10:40 ` Sascha Hauer 2009-01-27 10:40 ` [PATCH] fec: Add support for Freescale MX27 Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:40 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer flush_dcache_range is not portable across architectures. Use dma_sync_single instead. Also, the memory must be synchronised in the receive path aswell. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index f36ee43..6a54d1f 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -356,8 +356,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Push the data cache so the CPM does not get stale memory * data. */ - flush_dcache_range((unsigned long)skb->data, - (unsigned long)skb->data + skb->len); + dma_sync_single(NULL, bdp->cbd_bufaddr, + bdp->cbd_datlen, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. @@ -630,6 +630,9 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { dev->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); + dma_sync_single(NULL, (unsigned long)__pa(data), + pkt_len - 4, DMA_FROM_DEVICE); + /* This does 16 byte alignment, exactly what we need. * The packet length includes FCS, but we don't want to * include that when passing upstream as it messes up -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] fec: Add support for Freescale MX27 2009-01-27 10:40 ` [PATCH] fec: replace flush_dcache_range with dma_sync_single Sascha Hauer @ 2009-01-27 10:40 ` Sascha Hauer 2009-01-27 10:40 ` [PATCH] FEC: Turn FEC driver into platform device driver Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:40 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/Kconfig | 6 +++--- drivers/net/fec.c | 15 +++++++++++++-- drivers/net/fec.h | 11 +++++++++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9fe8cb7..fcdab51 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1828,11 +1828,11 @@ config 68360_ENET the Motorola 68360 processor. config FEC - bool "FEC ethernet controller (of ColdFire CPUs)" - depends on M523x || M527x || M5272 || M528x || M520x + bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" + depends on M523x || M527x || M5272 || M528x || M520x || ARCH_MXC help Say Y here if you want to use the built-in 10/100 Fast ethernet - controller on some Motorola ColdFire processors. + controller on some Motorola ColdFire and Freescale i.MX processors. config FEC2 bool "Second FEC ethernet controller (on some ColdFire CPUs)" diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 6a54d1f..2c8783a 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -38,10 +38,14 @@ #include <linux/bitops.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/clk.h> #include <asm/cacheflush.h> + +#ifndef CONFIG_ARCH_MXC #include <asm/coldfire.h> #include <asm/mcfsim.h> +#endif #include "fec.h" @@ -51,6 +55,13 @@ #define FEC_MAX_PORTS 1 #endif +#ifdef CONFIG_ARCH_MXC +#include <mach/hardware.h> +#define FEC_ALIGNMENT 0xf +#else +#define FEC_ALIGNMENT 0x3 +#endif + #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif @@ -158,7 +169,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_ARCH_MXC) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 @@ -339,7 +350,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ - if (bdp->cbd_bufaddr & 0x3) { + if (bdp->cbd_bufaddr & FEC_ALIGNMENT) { unsigned int index; index = bdp - fep->tx_bd_base; memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 292719d..76c64c9 100644 --- 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_ARCH_MXC) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models @@ -103,12 +103,19 @@ typedef struct fec { /* * Define the buffer descriptor structure. */ +#ifdef CONFIG_ARCH_MXC +typedef struct bufdesc { + unsigned short cbd_datlen; /* Data length */ + unsigned short cbd_sc; /* Control and status info */ + unsigned long cbd_bufaddr; /* Buffer address */ +} cbd_t; +#else typedef struct bufdesc { unsigned short cbd_sc; /* Control and status info */ unsigned short cbd_datlen; /* Data length */ unsigned long cbd_bufaddr; /* Buffer address */ } cbd_t; - +#endif /* * The following definitions courtesy of commproc.h, which where -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] FEC: Turn FEC driver into platform device driver 2009-01-27 10:40 ` [PATCH] fec: Add support for Freescale MX27 Sascha Hauer @ 2009-01-27 10:40 ` Sascha Hauer 2009-01-28 7:36 ` Greg Ungerer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2009-01-27 10:40 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, frederic rodo, Sascha Hauer This turns the fec driver into a platform device driver for new platforms. Old platforms are still supported through a FEC_LEGACY define till they are also ported. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 220 insertions(+), 29 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 2c8783a..ed4825b 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -39,6 +39,7 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/clk.h> +#include <linux/platform_device.h> #include <asm/cacheflush.h> @@ -49,12 +50,6 @@ #include "fec.h" -#if defined(CONFIG_FEC2) -#define FEC_MAX_PORTS 2 -#else -#define FEC_MAX_PORTS 1 -#endif - #ifdef CONFIG_ARCH_MXC #include <mach/hardware.h> #define FEC_ALIGNMENT 0xf @@ -62,13 +57,22 @@ #define FEC_ALIGNMENT 0x3 #endif +#if defined CONFIG_M5272 || defined CONFIG_M527x || defined CONFIG_M523x \ + || defined CONFIG_M528x || defined CONFIG_M532x +#define FEC_LEGACY +/* + * Define the fixed address of the FEC hardware. + */ #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif -/* - * Define the fixed address of the FEC hardware. - */ +#if defined(CONFIG_FEC2) +#define FEC_MAX_PORTS 2 +#else +#define FEC_MAX_PORTS 1 +#endif + static unsigned int fec_hw[] = { #if defined(CONFIG_M5272) (MCF_MBAR + 0x840), @@ -106,6 +110,8 @@ static unsigned char fec_mac_default[] = { #define FEC_FLASHMAC 0 #endif +#endif /* FEC_LEGACY */ + /* Forward declarations of some structures to support different PHYs */ @@ -189,6 +195,8 @@ struct fec_enet_private { struct net_device *netdev; + struct clk *clk; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; @@ -1919,7 +1927,9 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) printk("FEC: No PHY device found.\n"); /* Disable external MII interface */ fecp->fec_mii_speed = fep->phy_speed = 0; +#ifdef FREC_LEGACY fec_disable_phy_intr(); +#endif } } @@ -2101,12 +2111,12 @@ fec_set_mac_address(struct net_device *dev) } -/* Initialize the FEC Ethernet on 860T (or ColdFire 5272). - */ /* * XXX: We need to clean up on failure exits here. + * + * index is only used in legacy code */ -int __init fec_enet_init(struct net_device *dev) +int __init fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); unsigned long mem_addr; @@ -2114,11 +2124,6 @@ int __init fec_enet_init(struct net_device *dev) cbd_t *cbd_base; volatile fec_t *fecp; int i, j; - static int index = 0; - - /* Only allow us to be probed once. */ - if (index >= FEC_MAX_PORTS) - return -ENXIO; /* Allocate memory for buffer descriptors. */ @@ -2133,7 +2138,7 @@ int __init fec_enet_init(struct net_device *dev) /* Create an Ethernet device instance. */ - fecp = (volatile fec_t *) fec_hw[index]; + fecp = (volatile fec_t *)dev->base_addr; fep->index = index; fep->hwp = fecp; @@ -2144,16 +2149,24 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_ecntrl = 1; udelay(10); - /* Set the Ethernet address. If using multiple Enets on the 8xx, - * this needs some work to get unique addresses. - * - * This is our default MAC address unless the user changes - * it via eth_mac_addr (our dev->set_mac_addr handler). - */ + /* Set the Ethernet address */ +#ifdef FEC_LEGACY fec_get_mac(dev); +#else + { + unsigned long l; + l = fecp->fec_addr_low; + dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); + dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); + dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); + l = fecp->fec_addr_high; + dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); + } +#endif cbd_base = (cbd_t *)mem_addr; - /* XXX: missing check for allocation failure */ /* Set receive and transmit descriptor base. */ @@ -2220,10 +2233,12 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_r_des_start = fep->bd_dma; fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE; +#ifdef FEC_LEGACY /* Install our interrupt handlers. This varies depending on * the architecture. */ fec_request_intrs(dev); +#endif fecp->fec_grp_hash_table_high = 0; fecp->fec_grp_hash_table_low = 0; @@ -2235,8 +2250,6 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_hash_table_low = 0; #endif - dev->base_addr = (unsigned long)fecp; - /* The FEC Ethernet specific entries in the device structure. */ dev->open = fec_enet_open; dev->hard_start_xmit = fec_enet_start_xmit; @@ -2250,7 +2263,20 @@ int __init fec_enet_init(struct net_device *dev) mii_free = mii_cmds; /* setup MII interface */ +#ifdef FEC_LEGACY fec_set_mii(dev, fep); +#else + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; + fecp->fec_x_cntrl = 0x00; + + /* + * Set MII speed to 2.5 MHz + */ + fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) + / 2500000) / 2) & 0x3F) << 1; + fecp->fec_mii_speed = fep->phy_speed; + fec_restart(dev, 0); +#endif /* Clear and enable interrupts */ fecp->fec_ievent = 0xffc00000; @@ -2263,7 +2289,6 @@ int __init fec_enet_init(struct net_device *dev) fep->phy_addr = 0; mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); - index++; return 0; } @@ -2414,6 +2439,7 @@ fec_stop(struct net_device *dev) fecp->fec_mii_speed = fep->phy_speed; } +#ifdef FEC_LEGACY static int __init fec_enet_module_init(void) { struct net_device *dev; @@ -2425,7 +2451,8 @@ static int __init fec_enet_module_init(void) dev = alloc_etherdev(sizeof(struct fec_enet_private)); if (!dev) return -ENOMEM; - err = fec_enet_init(dev); + dev->base_addr = (unsigned long)fec_hw[i]; + err = fec_enet_init(dev, i); if (err) { free_netdev(dev); continue; @@ -2440,6 +2467,170 @@ static int __init fec_enet_module_init(void) } return 0; } +#else + +static int __devinit +fec_probe(struct platform_device *pdev) +{ + struct fec_enet_private *fep; + struct net_device *ndev; + int i, irq, ret = 0; + struct resource *r; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -ENXIO; + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) + return -EBUSY; + + /* Init network device */ + ndev = alloc_etherdev(sizeof(struct fec_enet_private)); + if (!ndev) + return -ENOMEM; + + SET_NETDEV_DEV(ndev, &pdev->dev); + + /* setup board info structure */ + fep = netdev_priv(ndev); + memset(fep, 0, sizeof(*fep)); + + ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); + + if (!ndev->base_addr) { + ret = -ENOMEM; + goto failed_ioremap; + } + + platform_set_drvdata(pdev, ndev); + + /* This device has up to three irqs on some platforms */ + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (i && irq < 0) + break; + ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); + if (ret) { + while (i >= 0) { + irq = platform_get_irq(pdev, i); + free_irq(irq, ndev); + i--; + } + goto failed_irq; + } + } + + fep->clk = clk_get(&pdev->dev, "fec_clk"); + if (IS_ERR(fep->clk)) { + ret = PTR_ERR(fep->clk); + goto failed_clk; + } + clk_enable(fep->clk); + + ret = fec_enet_init(ndev, 0); + if (ret) + goto failed_init; + + ret = register_netdev(ndev); + if (ret) + goto failed_register; + + return 0; + +failed_register: +failed_init: + clk_disable(fep->clk); + clk_put(fep->clk); +failed_clk: + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (irq > 0) + free_irq(irq, ndev); + } +failed_irq: + iounmap((void __iomem *)ndev->base_addr); +failed_ioremap: + free_netdev(ndev); + + return ret; +} + +static int __devexit +fec_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + fec_stop(ndev); + clk_disable(fep->clk); + clk_put(fep->clk); + iounmap((void __iomem *)ndev->base_addr); + unregister_netdev(ndev); + free_netdev(ndev); + return 0; +} + +static int +fec_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + struct fec_enet_private *fep; + + if (ndev) { + fep = netdev_priv(ndev); + if (netif_running(ndev)) { + netif_device_detach(ndev); + fec_stop(ndev); + } + } + return 0; +} + +static int +fec_resume(struct platform_device *dev) +{ + struct net_device *ndev = platform_get_drvdata(dev); + + if (ndev) { + if (netif_running(ndev)) { + fec_enet_init(ndev, 0); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct platform_driver fec_driver = { + .driver = { + .name = "fec", + .owner = THIS_MODULE, + }, + .probe = fec_probe, + .remove = __devexit_p(fec_drv_remove), + .suspend = fec_suspend, + .resume = fec_resume, +}; + +static int __init +fec_enet_module_init(void) +{ + printk(KERN_INFO "FEC Ethernet Driver\n"); + + return platform_driver_register(&fec_driver); +} + +static void __exit +fec_enet_cleanup(void) +{ + platform_driver_unregister(&fec_driver); +} + +module_exit(fec_enet_cleanup); + +#endif /* FEC_LEGACY */ module_init(fec_enet_module_init); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] FEC: Turn FEC driver into platform device driver 2009-01-27 10:40 ` [PATCH] FEC: Turn FEC driver into platform device driver Sascha Hauer @ 2009-01-28 7:36 ` Greg Ungerer 0 siblings, 0 replies; 14+ messages in thread From: Greg Ungerer @ 2009-01-28 7:36 UTC (permalink / raw) To: Sascha Hauer; +Cc: netdev, frederic rodo Hi Sascha, Sascha Hauer wrote: > This turns the fec driver into a platform device driver for new > platforms. Old platforms are still supported through a FEC_LEGACY define > till they are also ported. > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > drivers/net/fec.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++------ > 1 files changed, 220 insertions(+), 29 deletions(-) > > diff --git a/drivers/net/fec.c b/drivers/net/fec.c > index 2c8783a..ed4825b 100644 > --- a/drivers/net/fec.c > +++ b/drivers/net/fec.c > @@ -39,6 +39,7 @@ > #include <linux/io.h> > #include <linux/irq.h> > #include <linux/clk.h> > +#include <linux/platform_device.h> > > #include <asm/cacheflush.h> > > @@ -49,12 +50,6 @@ > > #include "fec.h" > > -#if defined(CONFIG_FEC2) > -#define FEC_MAX_PORTS 2 > -#else > -#define FEC_MAX_PORTS 1 > -#endif > - > #ifdef CONFIG_ARCH_MXC > #include <mach/hardware.h> > #define FEC_ALIGNMENT 0xf > @@ -62,13 +57,22 @@ > #define FEC_ALIGNMENT 0x3 > #endif > > +#if defined CONFIG_M5272 || defined CONFIG_M527x || defined CONFIG_M523x \ > + || defined CONFIG_M528x || defined CONFIG_M532 This list needs to include a "defined CONFIG_M520x" as well. Aside from this it builds and runs fine on the ColdFire parts I tried it on. Regards Greg > +#define FEC_LEGACY > +/* > + * Define the fixed address of the FEC hardware. > + */ > #if defined(CONFIG_M5272) > #define HAVE_mii_link_interrupt > #endif > > -/* > - * Define the fixed address of the FEC hardware. > - */ > +#if defined(CONFIG_FEC2) > +#define FEC_MAX_PORTS 2 > +#else > +#define FEC_MAX_PORTS 1 > +#endif > + > static unsigned int fec_hw[] = { > #if defined(CONFIG_M5272) > (MCF_MBAR + 0x840), > @@ -106,6 +110,8 @@ static unsigned char fec_mac_default[] = { > #define FEC_FLASHMAC 0 > #endif > > +#endif /* FEC_LEGACY */ > + > /* Forward declarations of some structures to support different PHYs > */ > > @@ -189,6 +195,8 @@ struct fec_enet_private { > > struct net_device *netdev; > > + struct clk *clk; > + > /* The saved address of a sent-in-place packet/buffer, for skfree(). */ > unsigned char *tx_bounce[TX_RING_SIZE]; > struct sk_buff* tx_skbuff[TX_RING_SIZE]; > @@ -1919,7 +1927,9 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) > printk("FEC: No PHY device found.\n"); > /* Disable external MII interface */ > fecp->fec_mii_speed = fep->phy_speed = 0; > +#ifdef FREC_LEGACY > fec_disable_phy_intr(); > +#endif > } > } > > @@ -2101,12 +2111,12 @@ fec_set_mac_address(struct net_device *dev) > > } > > -/* Initialize the FEC Ethernet on 860T (or ColdFire 5272). > - */ > /* > * XXX: We need to clean up on failure exits here. > + * > + * index is only used in legacy code > */ > -int __init fec_enet_init(struct net_device *dev) > +int __init fec_enet_init(struct net_device *dev, int index) > { > struct fec_enet_private *fep = netdev_priv(dev); > unsigned long mem_addr; > @@ -2114,11 +2124,6 @@ int __init fec_enet_init(struct net_device *dev) > cbd_t *cbd_base; > volatile fec_t *fecp; > int i, j; > - static int index = 0; > - > - /* Only allow us to be probed once. */ > - if (index >= FEC_MAX_PORTS) > - return -ENXIO; > > /* Allocate memory for buffer descriptors. > */ > @@ -2133,7 +2138,7 @@ int __init fec_enet_init(struct net_device *dev) > > /* Create an Ethernet device instance. > */ > - fecp = (volatile fec_t *) fec_hw[index]; > + fecp = (volatile fec_t *)dev->base_addr; > > fep->index = index; > fep->hwp = fecp; > @@ -2144,16 +2149,24 @@ int __init fec_enet_init(struct net_device *dev) > fecp->fec_ecntrl = 1; > udelay(10); > > - /* Set the Ethernet address. If using multiple Enets on the 8xx, > - * this needs some work to get unique addresses. > - * > - * This is our default MAC address unless the user changes > - * it via eth_mac_addr (our dev->set_mac_addr handler). > - */ > + /* Set the Ethernet address */ > +#ifdef FEC_LEGACY > fec_get_mac(dev); > +#else > + { > + unsigned long l; > + l = fecp->fec_addr_low; > + dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); > + dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); > + dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); > + dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); > + l = fecp->fec_addr_high; > + dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); > + dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); > + } > +#endif > > cbd_base = (cbd_t *)mem_addr; > - /* XXX: missing check for allocation failure */ > > /* Set receive and transmit descriptor base. > */ > @@ -2220,10 +2233,12 @@ int __init fec_enet_init(struct net_device *dev) > fecp->fec_r_des_start = fep->bd_dma; > fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE; > > +#ifdef FEC_LEGACY > /* Install our interrupt handlers. This varies depending on > * the architecture. > */ > fec_request_intrs(dev); > +#endif > > fecp->fec_grp_hash_table_high = 0; > fecp->fec_grp_hash_table_low = 0; > @@ -2235,8 +2250,6 @@ int __init fec_enet_init(struct net_device *dev) > fecp->fec_hash_table_low = 0; > #endif > > - dev->base_addr = (unsigned long)fecp; > - > /* The FEC Ethernet specific entries in the device structure. */ > dev->open = fec_enet_open; > dev->hard_start_xmit = fec_enet_start_xmit; > @@ -2250,7 +2263,20 @@ int __init fec_enet_init(struct net_device *dev) > mii_free = mii_cmds; > > /* setup MII interface */ > +#ifdef FEC_LEGACY > fec_set_mii(dev, fep); > +#else > + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; > + fecp->fec_x_cntrl = 0x00; > + > + /* > + * Set MII speed to 2.5 MHz > + */ > + fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) > + / 2500000) / 2) & 0x3F) << 1; > + fecp->fec_mii_speed = fep->phy_speed; > + fec_restart(dev, 0); > +#endif > > /* Clear and enable interrupts */ > fecp->fec_ievent = 0xffc00000; > @@ -2263,7 +2289,6 @@ int __init fec_enet_init(struct net_device *dev) > fep->phy_addr = 0; > mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); > > - index++; > return 0; > } > > @@ -2414,6 +2439,7 @@ fec_stop(struct net_device *dev) > fecp->fec_mii_speed = fep->phy_speed; > } > > +#ifdef FEC_LEGACY > static int __init fec_enet_module_init(void) > { > struct net_device *dev; > @@ -2425,7 +2451,8 @@ static int __init fec_enet_module_init(void) > dev = alloc_etherdev(sizeof(struct fec_enet_private)); > if (!dev) > return -ENOMEM; > - err = fec_enet_init(dev); > + dev->base_addr = (unsigned long)fec_hw[i]; > + err = fec_enet_init(dev, i); > if (err) { > free_netdev(dev); > continue; > @@ -2440,6 +2467,170 @@ static int __init fec_enet_module_init(void) > } > return 0; > } > +#else > + > +static int __devinit > +fec_probe(struct platform_device *pdev) > +{ > + struct fec_enet_private *fep; > + struct net_device *ndev; > + int i, irq, ret = 0; > + struct resource *r; > + > + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!r) > + return -ENXIO; > + > + r = request_mem_region(r->start, resource_size(r), pdev->name); > + if (!r) > + return -EBUSY; > + > + /* Init network device */ > + ndev = alloc_etherdev(sizeof(struct fec_enet_private)); > + if (!ndev) > + return -ENOMEM; > + > + SET_NETDEV_DEV(ndev, &pdev->dev); > + > + /* setup board info structure */ > + fep = netdev_priv(ndev); > + memset(fep, 0, sizeof(*fep)); > + > + ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); > + > + if (!ndev->base_addr) { > + ret = -ENOMEM; > + goto failed_ioremap; > + } > + > + platform_set_drvdata(pdev, ndev); > + > + /* This device has up to three irqs on some platforms */ > + for (i = 0; i < 3; i++) { > + irq = platform_get_irq(pdev, i); > + if (i && irq < 0) > + break; > + ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); > + if (ret) { > + while (i >= 0) { > + irq = platform_get_irq(pdev, i); > + free_irq(irq, ndev); > + i--; > + } > + goto failed_irq; > + } > + } > + > + fep->clk = clk_get(&pdev->dev, "fec_clk"); > + if (IS_ERR(fep->clk)) { > + ret = PTR_ERR(fep->clk); > + goto failed_clk; > + } > + clk_enable(fep->clk); > + > + ret = fec_enet_init(ndev, 0); > + if (ret) > + goto failed_init; > + > + ret = register_netdev(ndev); > + if (ret) > + goto failed_register; > + > + return 0; > + > +failed_register: > +failed_init: > + clk_disable(fep->clk); > + clk_put(fep->clk); > +failed_clk: > + for (i = 0; i < 3; i++) { > + irq = platform_get_irq(pdev, i); > + if (irq > 0) > + free_irq(irq, ndev); > + } > +failed_irq: > + iounmap((void __iomem *)ndev->base_addr); > +failed_ioremap: > + free_netdev(ndev); > + > + return ret; > +} > + > +static int __devexit > +fec_drv_remove(struct platform_device *pdev) > +{ > + struct net_device *ndev = platform_get_drvdata(pdev); > + struct fec_enet_private *fep = netdev_priv(ndev); > + > + platform_set_drvdata(pdev, NULL); > + > + fec_stop(ndev); > + clk_disable(fep->clk); > + clk_put(fep->clk); > + iounmap((void __iomem *)ndev->base_addr); > + unregister_netdev(ndev); > + free_netdev(ndev); > + return 0; > +} > + > +static int > +fec_suspend(struct platform_device *dev, pm_message_t state) > +{ > + struct net_device *ndev = platform_get_drvdata(dev); > + struct fec_enet_private *fep; > + > + if (ndev) { > + fep = netdev_priv(ndev); > + if (netif_running(ndev)) { > + netif_device_detach(ndev); > + fec_stop(ndev); > + } > + } > + return 0; > +} > + > +static int > +fec_resume(struct platform_device *dev) > +{ > + struct net_device *ndev = platform_get_drvdata(dev); > + > + if (ndev) { > + if (netif_running(ndev)) { > + fec_enet_init(ndev, 0); > + netif_device_attach(ndev); > + } > + } > + return 0; > +} > + > +static struct platform_driver fec_driver = { > + .driver = { > + .name = "fec", > + .owner = THIS_MODULE, > + }, > + .probe = fec_probe, > + .remove = __devexit_p(fec_drv_remove), > + .suspend = fec_suspend, > + .resume = fec_resume, > +}; > + > +static int __init > +fec_enet_module_init(void) > +{ > + printk(KERN_INFO "FEC Ethernet Driver\n"); > + > + return platform_driver_register(&fec_driver); > +} > + > +static void __exit > +fec_enet_cleanup(void) > +{ > + platform_driver_unregister(&fec_driver); > +} > + > +module_exit(fec_enet_cleanup); > + > +#endif /* FEC_LEGACY */ > > module_init(fec_enet_module_init); > -- ------------------------------------------------------------------------ Greg Ungerer -- Principal Engineer EMAIL: gerg@snapgear.com SnapGear, a McAfee Company PHONE: +61 7 3435 2888 825 Stanley St, FAX: +61 7 3891 3630 Woolloongabba, QLD, 4102, Australia WEB: http://www.SnapGear.com ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <1233051848-5994-1-git-send-email-y>]
[parent not found: <1233051848-5994-2-git-send-email-y>]
[parent not found: <1233051848-5994-3-git-send-email-y>]
[parent not found: <1233051848-5994-4-git-send-email-y>]
[parent not found: <1233051848-5994-5-git-send-email-y>]
[parent not found: <1233051848-5994-6-git-send-email-y>]
[parent not found: <1233051848-5994-7-git-send-email-y>]
[parent not found: <1233051848-5994-8-git-send-email-y>]
[parent not found: <1233051848-5994-9-git-send-email-y>]
* [PATCH] FEC: Turn FEC driver into platform device driver [not found] ` <1233051848-5994-9-git-send-email-y> @ 2009-01-27 10:24 ` y 0 siblings, 0 replies; 14+ messages in thread From: y @ 2009-01-27 10:24 UTC (permalink / raw) To: netdev; +Cc: Greg Ungerer, Sascha Hauer From: Sascha Hauer <s.hauer@pengutronix.de> This turns the fec driver into a platform device driver for new platforms. Old platforms are still supported through a FEC_LEGACY define till they are also ported. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/net/fec.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 220 insertions(+), 29 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 2c8783a..ed4825b 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -39,6 +39,7 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/clk.h> +#include <linux/platform_device.h> #include <asm/cacheflush.h> @@ -49,12 +50,6 @@ #include "fec.h" -#if defined(CONFIG_FEC2) -#define FEC_MAX_PORTS 2 -#else -#define FEC_MAX_PORTS 1 -#endif - #ifdef CONFIG_ARCH_MXC #include <mach/hardware.h> #define FEC_ALIGNMENT 0xf @@ -62,13 +57,22 @@ #define FEC_ALIGNMENT 0x3 #endif +#if defined CONFIG_M5272 || defined CONFIG_M527x || defined CONFIG_M523x \ + || defined CONFIG_M528x || defined CONFIG_M532x +#define FEC_LEGACY +/* + * Define the fixed address of the FEC hardware. + */ #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif -/* - * Define the fixed address of the FEC hardware. - */ +#if defined(CONFIG_FEC2) +#define FEC_MAX_PORTS 2 +#else +#define FEC_MAX_PORTS 1 +#endif + static unsigned int fec_hw[] = { #if defined(CONFIG_M5272) (MCF_MBAR + 0x840), @@ -106,6 +110,8 @@ static unsigned char fec_mac_default[] = { #define FEC_FLASHMAC 0 #endif +#endif /* FEC_LEGACY */ + /* Forward declarations of some structures to support different PHYs */ @@ -189,6 +195,8 @@ struct fec_enet_private { struct net_device *netdev; + struct clk *clk; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; @@ -1919,7 +1927,9 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) printk("FEC: No PHY device found.\n"); /* Disable external MII interface */ fecp->fec_mii_speed = fep->phy_speed = 0; +#ifdef FREC_LEGACY fec_disable_phy_intr(); +#endif } } @@ -2101,12 +2111,12 @@ fec_set_mac_address(struct net_device *dev) } -/* Initialize the FEC Ethernet on 860T (or ColdFire 5272). - */ /* * XXX: We need to clean up on failure exits here. + * + * index is only used in legacy code */ -int __init fec_enet_init(struct net_device *dev) +int __init fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); unsigned long mem_addr; @@ -2114,11 +2124,6 @@ int __init fec_enet_init(struct net_device *dev) cbd_t *cbd_base; volatile fec_t *fecp; int i, j; - static int index = 0; - - /* Only allow us to be probed once. */ - if (index >= FEC_MAX_PORTS) - return -ENXIO; /* Allocate memory for buffer descriptors. */ @@ -2133,7 +2138,7 @@ int __init fec_enet_init(struct net_device *dev) /* Create an Ethernet device instance. */ - fecp = (volatile fec_t *) fec_hw[index]; + fecp = (volatile fec_t *)dev->base_addr; fep->index = index; fep->hwp = fecp; @@ -2144,16 +2149,24 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_ecntrl = 1; udelay(10); - /* Set the Ethernet address. If using multiple Enets on the 8xx, - * this needs some work to get unique addresses. - * - * This is our default MAC address unless the user changes - * it via eth_mac_addr (our dev->set_mac_addr handler). - */ + /* Set the Ethernet address */ +#ifdef FEC_LEGACY fec_get_mac(dev); +#else + { + unsigned long l; + l = fecp->fec_addr_low; + dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); + dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); + dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); + l = fecp->fec_addr_high; + dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); + } +#endif cbd_base = (cbd_t *)mem_addr; - /* XXX: missing check for allocation failure */ /* Set receive and transmit descriptor base. */ @@ -2220,10 +2233,12 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_r_des_start = fep->bd_dma; fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE; +#ifdef FEC_LEGACY /* Install our interrupt handlers. This varies depending on * the architecture. */ fec_request_intrs(dev); +#endif fecp->fec_grp_hash_table_high = 0; fecp->fec_grp_hash_table_low = 0; @@ -2235,8 +2250,6 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_hash_table_low = 0; #endif - dev->base_addr = (unsigned long)fecp; - /* The FEC Ethernet specific entries in the device structure. */ dev->open = fec_enet_open; dev->hard_start_xmit = fec_enet_start_xmit; @@ -2250,7 +2263,20 @@ int __init fec_enet_init(struct net_device *dev) mii_free = mii_cmds; /* setup MII interface */ +#ifdef FEC_LEGACY fec_set_mii(dev, fep); +#else + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; + fecp->fec_x_cntrl = 0x00; + + /* + * Set MII speed to 2.5 MHz + */ + fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) + / 2500000) / 2) & 0x3F) << 1; + fecp->fec_mii_speed = fep->phy_speed; + fec_restart(dev, 0); +#endif /* Clear and enable interrupts */ fecp->fec_ievent = 0xffc00000; @@ -2263,7 +2289,6 @@ int __init fec_enet_init(struct net_device *dev) fep->phy_addr = 0; mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); - index++; return 0; } @@ -2414,6 +2439,7 @@ fec_stop(struct net_device *dev) fecp->fec_mii_speed = fep->phy_speed; } +#ifdef FEC_LEGACY static int __init fec_enet_module_init(void) { struct net_device *dev; @@ -2425,7 +2451,8 @@ static int __init fec_enet_module_init(void) dev = alloc_etherdev(sizeof(struct fec_enet_private)); if (!dev) return -ENOMEM; - err = fec_enet_init(dev); + dev->base_addr = (unsigned long)fec_hw[i]; + err = fec_enet_init(dev, i); if (err) { free_netdev(dev); continue; @@ -2440,6 +2467,170 @@ static int __init fec_enet_module_init(void) } return 0; } +#else + +static int __devinit +fec_probe(struct platform_device *pdev) +{ + struct fec_enet_private *fep; + struct net_device *ndev; + int i, irq, ret = 0; + struct resource *r; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -ENXIO; + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) + return -EBUSY; + + /* Init network device */ + ndev = alloc_etherdev(sizeof(struct fec_enet_private)); + if (!ndev) + return -ENOMEM; + + SET_NETDEV_DEV(ndev, &pdev->dev); + + /* setup board info structure */ + fep = netdev_priv(ndev); + memset(fep, 0, sizeof(*fep)); + + ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); + + if (!ndev->base_addr) { + ret = -ENOMEM; + goto failed_ioremap; + } + + platform_set_drvdata(pdev, ndev); + + /* This device has up to three irqs on some platforms */ + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (i && irq < 0) + break; + ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); + if (ret) { + while (i >= 0) { + irq = platform_get_irq(pdev, i); + free_irq(irq, ndev); + i--; + } + goto failed_irq; + } + } + + fep->clk = clk_get(&pdev->dev, "fec_clk"); + if (IS_ERR(fep->clk)) { + ret = PTR_ERR(fep->clk); + goto failed_clk; + } + clk_enable(fep->clk); + + ret = fec_enet_init(ndev, 0); + if (ret) + goto failed_init; + + ret = register_netdev(ndev); + if (ret) + goto failed_register; + + return 0; + +failed_register: +failed_init: + clk_disable(fep->clk); + clk_put(fep->clk); +failed_clk: + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (irq > 0) + free_irq(irq, ndev); + } +failed_irq: + iounmap((void __iomem *)ndev->base_addr); +failed_ioremap: + free_netdev(ndev); + + return ret; +} + +static int __devexit +fec_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + fec_stop(ndev); + clk_disable(fep->clk); + clk_put(fep->clk); + iounmap((void __iomem *)ndev->base_addr); + unregister_netdev(ndev); + free_netdev(ndev); + return 0; +} + +static int +fec_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + struct fec_enet_private *fep; + + if (ndev) { + fep = netdev_priv(ndev); + if (netif_running(ndev)) { + netif_device_detach(ndev); + fec_stop(ndev); + } + } + return 0; +} + +static int +fec_resume(struct platform_device *dev) +{ + struct net_device *ndev = platform_get_drvdata(dev); + + if (ndev) { + if (netif_running(ndev)) { + fec_enet_init(ndev, 0); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct platform_driver fec_driver = { + .driver = { + .name = "fec", + .owner = THIS_MODULE, + }, + .probe = fec_probe, + .remove = __devexit_p(fec_drv_remove), + .suspend = fec_suspend, + .resume = fec_resume, +}; + +static int __init +fec_enet_module_init(void) +{ + printk(KERN_INFO "FEC Ethernet Driver\n"); + + return platform_driver_register(&fec_driver); +} + +static void __exit +fec_enet_cleanup(void) +{ + platform_driver_unregister(&fec_driver); +} + +module_exit(fec_enet_cleanup); + +#endif /* FEC_LEGACY */ module_init(fec_enet_module_init); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2009-01-30 0:04 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-29 9:03 FEC patches Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: remove unused #else branches Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: remove empty functions Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: use linux/*.h instead of asm/*.h Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: do not use memcpy on physical addresses Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: use dma_alloc_coherent for descriptor ring Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: Fix KS8721BL_ICSR phy register offset Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: replace flush_dcache_range with dma_sync_single Sascha Hauer
2009-01-29 9:03 ` [PATCH] fec: Add support for Freescale MX27 Sascha Hauer
2009-01-29 9:03 ` [PATCH] FEC: Turn FEC driver into platform device driver Sascha Hauer
2009-01-30 0:04 ` FEC patches David Miller
-- strict thread matches above, loose matches on Subject: below --
2009-01-27 10:39 FEC Patches Sascha Hauer
2009-01-27 10:39 ` [PATCH] fec: remove unused #else branches Sascha Hauer
2009-01-27 10:39 ` [PATCH] fec: remove empty functions Sascha Hauer
2009-01-27 10:39 ` [PATCH] fec: use linux/*.h instead of asm/*.h Sascha Hauer
2009-01-27 10:39 ` [PATCH] fec: do not use memcpy on physical addresses Sascha Hauer
2009-01-27 10:40 ` [PATCH] fec: use dma_alloc_coherent for descriptor ring Sascha Hauer
2009-01-27 10:40 ` [PATCH] fec: Fix KS8721BL_ICSR phy register offset Sascha Hauer
2009-01-27 10:40 ` [PATCH] fec: replace flush_dcache_range with dma_sync_single Sascha Hauer
2009-01-27 10:40 ` [PATCH] fec: Add support for Freescale MX27 Sascha Hauer
2009-01-27 10:40 ` [PATCH] FEC: Turn FEC driver into platform device driver Sascha Hauer
2009-01-28 7:36 ` Greg Ungerer
[not found] <1233051848-5994-1-git-send-email-y>
[not found] ` <1233051848-5994-2-git-send-email-y>
[not found] ` <1233051848-5994-3-git-send-email-y>
[not found] ` <1233051848-5994-4-git-send-email-y>
[not found] ` <1233051848-5994-5-git-send-email-y>
[not found] ` <1233051848-5994-6-git-send-email-y>
[not found] ` <1233051848-5994-7-git-send-email-y>
[not found] ` <1233051848-5994-8-git-send-email-y>
[not found] ` <1233051848-5994-9-git-send-email-y>
2009-01-27 10:24 ` y
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).