From patchwork Wed Jan 14 16:09:13 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sascha Hauer X-Patchwork-Id: 18459 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id DC8F5DE148 for ; Thu, 15 Jan 2009 03:10:54 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757801AbZANQKu (ORCPT ); Wed, 14 Jan 2009 11:10:50 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757721AbZANQKu (ORCPT ); Wed, 14 Jan 2009 11:10:50 -0500 Received: from metis.ext.pengutronix.de ([92.198.50.35]:33893 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754934AbZANQKs (ORCPT ); Wed, 14 Jan 2009 11:10:48 -0500 Received: from octopus.hi.pengutronix.de ([2001:6f8:1178:2:215:17ff:fe12:23b0]) by metis.ext.pengutronix.de with esmtp (Exim 4.63) (envelope-from ) id 1LN8Iv-0003A0-6p; Wed, 14 Jan 2009 17:09:17 +0100 Received: from sha by octopus.hi.pengutronix.de with local (Exim 4.69) (envelope-from ) id 1LN8Is-0007mJ-40; Wed, 14 Jan 2009 17:09:14 +0100 From: Sascha Hauer To: netdev@vger.kernel.org Cc: Sebastian Siewior , Greg Ungerer , Sascha Hauer Subject: [PATCH] fec: Add mx2 support (WIP) Date: Wed, 14 Jan 2009 17:09:13 +0100 Message-Id: <1231949353-29630-7-git-send-email-s.hauer@pengutronix.de> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1231949353-29630-6-git-send-email-s.hauer@pengutronix.de> References: <1231949353-29630-1-git-send-email-s.hauer@pengutronix.de> <1231949353-29630-2-git-send-email-s.hauer@pengutronix.de> <1231949353-29630-3-git-send-email-s.hauer@pengutronix.de> <1231949353-29630-4-git-send-email-s.hauer@pengutronix.de> <1231949353-29630-5-git-send-email-s.hauer@pengutronix.de> <1231949353-29630-6-git-send-email-s.hauer@pengutronix.de> X-SA-Exim-Connect-IP: 2001:6f8:1178:2:215:17ff:fe12:23b0 X-SA-Exim-Mail-From: sha@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Signed-off-by: Sascha Hauer --- drivers/net/Kconfig | 2 +- drivers/net/fec.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++-- drivers/net/fec.h | 11 ++++- 3 files changed, 127 insertions(+), 7 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9fe8cb7..5333e65 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1829,7 +1829,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 || ARCH_MX2 help Say Y here if you want to use the built-in 10/100 Fast ethernet controller on some Motorola ColdFire processors. diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 81c8e11..a3e5b63 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -38,10 +38,14 @@ #include #include #include +#include #include + +#ifndef CONFIG_ARCH_MX2 #include #include +#endif #include "fec.h" @@ -51,6 +55,13 @@ #define FEC_MAX_PORTS 1 #endif +#ifdef CONFIG_ARCH_MX2 +#include +#define FEC_ALIGNMENT 0xf +#else +#define FEC_ALIGNMENT 0x3 +#endif + #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif @@ -70,6 +81,8 @@ static unsigned int fec_hw[] = { (MCF_MBAR+0x30000), #elif defined(CONFIG_M532x) (MCF_MBAR+0xfc030000), +#elif defined(CONFIG_ARCH_MX2) + (unsigned int)IO_ADDRESS(FEC_BASE_ADDR), #endif }; @@ -156,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_MX2) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 @@ -337,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); @@ -354,8 +367,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. @@ -628,6 +641,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 @@ -1109,7 +1125,14 @@ static phy_info_t const phy_info_am79c874 = { /* register definitions for the 8721 */ #define MII_KS8721BL_RXERCR 21 +#ifdef CONFIG_ARCH_MX2 + /* FIXME: is this a bug or board specific? + * 27 was found somewhere in the Freescale code + */ +#define MII_KS8721BL_ICSR 27 +#else #define MII_KS8721BL_ICSR 22 +#endif #define MII_KS8721BL_PHYCR 31 static phy_cmd_t const phy_cmd_ks8721bl_config[] = { @@ -1698,6 +1721,95 @@ static void __inline__ fec_phy_ack_intr(void) { } +#elif defined(CONFIG_ARCH_MX2) + +/* + * do some initializtion based architecture of this chip + */ +static void inline fec_arch_init(void) +{ + struct clk *clk; + clk = clk_get(NULL, "fec_clk"); + clk_enable(clk); + clk_put(clk); + return; +} + +/* + * Code specific to Freescale i.MXC + */ +static void inline fec_request_intrs(struct net_device *dev) +{ + /* Setup interrupt handlers. */ + if (request_irq(MXC_INT_FEC, fec_enet_interrupt, 0, "fec", dev) != 0) + panic("FEC: Could not allocate FEC IRQ(%d)!\n", MXC_INT_FEC); +} + +static void inline fec_set_mii(struct net_device *dev, + struct fec_enet_private *fep) +{ + u32 rate; + struct clk *clk; + 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 + */ + clk = clk_get(NULL, "fec_clk"); + rate = clk_get_rate(clk); + clk_put(clk); + + fep->phy_speed = ((((rate / 2 + 4999999) / 2500000) / 2) & 0x3F) << 1; + 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]; + int i; + unsigned long l; + unsigned char mac_preinitialized = 0; + fecp = fep->hwp; + + /* check if mac address was already initialized by firmware */ + l = fecp->fec_addr_low; + tmpaddr[0] = (unsigned char)((l & 0xFF000000) >> 24); + tmpaddr[1] = (unsigned char)((l & 0x00FF0000) >> 16); + tmpaddr[2] = (unsigned char)((l & 0x0000FF00) >> 8); + tmpaddr[3] = (unsigned char)((l & 0x000000FF) >> 0); + l = fecp->fec_addr_high; + tmpaddr[4] = (unsigned char)((l & 0xFF000000) >> 24); + tmpaddr[5] = (unsigned char)((l & 0x00FF0000) >> 16); + + for (i = 0; i < ETH_ALEN; i++) + mac_preinitialized |= tmpaddr[i]; + + if (mac_preinitialized) { + iap = &tmpaddr[0]; + memcpy(dev->dev_addr, iap, ETH_ALEN); + } +} + +static void inline fec_disable_phy_intr(void) +{ +} + +static void inline fec_phy_ack_intr(void) +{ +} + +static void inline fec_localhw_setup(void) +{ +} + +/* ------------------------------------------------------------------------- */ + #endif /* ------------------------------------------------------------------------- */ @@ -2404,6 +2516,7 @@ static int __init fec_enet_module_init(void) int i, err; printk("FEC ENET Version 0.2\n"); + fec_arch_init(); for (i = 0; (i < FEC_MAX_PORTS); i++) { dev = alloc_etherdev(sizeof(struct fec_enet_private)); diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 292719d..ca36ea0 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_MX2) /* * 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