* [PATCH 3/3] Add support to M54xx DMA FEC Driver
[not found] <1345551531-15348-1-git-send-email-stany.marcel@novasys-ingenierie.com>
@ 2012-08-21 12:18 ` Stany MARCEL
2012-08-23 10:47 ` [PATCH 1/3] Add support to broadcom 5222 PHY Geert Uytterhoeven
` (2 subsequent siblings)
3 siblings, 0 replies; 14+ messages in thread
From: Stany MARCEL @ 2012-08-21 12:18 UTC (permalink / raw)
To: linux-m68k; +Cc: geert, linux-kernel, Stany MARCEL
Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
---
This driver is an adaption of the one given by freescale for kernel 2.6.25.
Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
2 FEC configured with shared phy
drivers/net/ethernet/freescale/Kconfig | 27 +-
drivers/net/ethernet/freescale/Makefile | 1 +
drivers/net/ethernet/freescale/fec_m54xx.c | 1589 ++++++++++++++++++++++++++++
drivers/net/ethernet/freescale/fec_m54xx.h | 237 +++++
4 files changed, 1853 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/freescale/fec_m54xx.c
create mode 100644 drivers/net/ethernet/freescale/fec_m54xx.h
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index 3574e14..cef3c62 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -7,7 +7,8 @@ config NET_VENDOR_FREESCALE
default y
depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
M523x || M527x || M5272 || M528x || M520x || M532x || \
- ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM)
+ M54xx || ARCH_MXC || ARCH_MXS || \
+ (PPC_MPC52xx && PPC_BESTCOMM)
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -53,6 +54,30 @@ config FEC_MPC52xx_MDIO
If not sure, enable.
If compiled as module, it will be called fec_mpc52xx_phy.
+config FEC_M54xx
+ tristate "MCF547x/MCF548x Fast Ethernet Controller support"
+ depends on M54xx
+ select MCD_DMA
+ help
+ The MCF547x and MCF548x have a built-in Fast Ethernet Controller.
+ Saying Y here will include support for this device in the kernel.
+
+ To compile this driver as a module, choose M here: the module
+ will be called fecm.
+
+config FEC_M54xx_ENABLE_FEC2
+ bool "Enable the second FEC"
+ depends on FEC_M54xx
+ help
+ This enables the second FEC on the 547x/548x. If you want to use
+ it, say Y.
+
+config FEC_M54xx_SHARED_PHY
+ bool "Shared PHY interface(on some ColdFire designs)"
+ depends on FEC_M54xx_ENABLE_FEC2
+ help
+ Say Y here if both PHYs are controlled via a single channel.
+
source "drivers/net/ethernet/freescale/fs_enet/Kconfig"
config FSL_PQ_MDIO
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 1752488..64dba64 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
endif
+obj-$(CONFIG_FEC_M54xx) += fec_m54xx.o
obj-$(CONFIG_FS_ENET) += fs_enet/
obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
diff --git a/drivers/net/ethernet/freescale/fec_m54xx.c b/drivers/net/ethernet/freescale/fec_m54xx.c
new file mode 100644
index 0000000..dba1526
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fec_m54xx.c
@@ -0,0 +1,1589 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Author: Kurt Mahan, kmahan@freescale.com
+ *
+ * Copyright 2012 Stany MARCEL <smarcel@novasys-ingenierie.com> Linux
+ * 3.4 port
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/phy.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+#include <asm/dma.h>
+#include <asm/MCD_dma.h>
+#include <asm/m54xxsram.h>
+#include <asm/virtconvert.h>
+#include <asm/irq.h>
+
+#include "fec_m54xx.h"
+
+#ifdef CONFIG_FEC_M54xx_ENABLE_FEC2
+#define M54XX_FEC_MAX_PORTS 2
+#define M54XX_FEC2
+#else
+#define M54XX_FEC_MAX_PORTS 1
+#undef M54XX_FEC2
+#endif
+
+#define VERSION "0.20"
+MODULE_DESCRIPTION("DMA Fast Ethernet Controller driver ver " VERSION);
+
+/* fec private */
+struct m54xx_fec_priv {
+ struct net_device *netdev; /* owning net device */
+ void *txbuf[M54XX_FEC_TX_BUF_NUMBER]; /* tx buffer ptrs */
+ MCD_bufDescFec *txdesc; /* tx descriptor ptrs */
+ volatile unsigned int current_tx; /* current tx desc index */
+ volatile unsigned int next_tx; /* next tx desc index */
+ unsigned int current_rx; /* current rx desc index */
+ MCD_bufDescFec *rxdesc; /* rx descriptor ptrs */
+ struct sk_buff *askb_rx[M54XX_FEC_RX_BUF_NUMBER]; /* rx SKB ptrs */
+ unsigned int initiator_rx; /* rx dma initiator */
+ unsigned int initiator_tx; /* tx dma initiator */
+ int fec_rx_channel; /* rx dma channel */
+ int fec_tx_channel; /* tx dma channel */
+ int rx_requestor; /* rx dma requestor */
+ int tx_requestor; /* tx dma requestor */
+ void *interrupt_fec_rx_handler; /* dma rx handler */
+ void *interrupt_fec_tx_handler; /* dma tx handler */
+ unsigned char *mac_addr; /* private fec mac addr */
+ struct net_device_stats stat; /* stats ptr */
+ spinlock_t lock;
+ int rxflag;
+ struct tasklet_struct tasklet_reinit;
+ int index; /* fec hw number */
+ struct phy_device *phydev;
+ struct mii_bus *mdio_bus;
+ int duplex;
+ int link;
+ int speed;
+};
+
+struct net_device *m54xx_fec_dev[M54XX_FEC_MAX_PORTS];
+
+/* FEC functions */
+static int __init m54xx_fec_init(void);
+static struct net_device_stats *m54xx_fec_get_stat(struct net_device *dev);
+static int m54xx_fec_open(struct net_device *dev);
+static int m54xx_fec_close(struct net_device *nd);
+static int m54xx_fec_tx(struct sk_buff *skb, struct net_device *dev);
+static void m54xx_fec_set_multicast_list(struct net_device *nd);
+static int m54xx_fec_set_mac_address(struct net_device *dev, void *p);
+static void m54xx_fec_tx_timeout(struct net_device *dev);
+static void m54xx_fec_interrupt_fec_tx_handler(struct net_device *dev);
+static void m54xx_fec_interrupt_fec_rx_handler(struct net_device *dev);
+static irqreturn_t m54xx_fec_interrupt_handler(int irq, void *dev_id);
+static void m54xx_fec_interrupt_fec_tx_handler_fec0(void);
+static void m54xx_fec_interrupt_fec_rx_handler_fec0(void);
+static void m54xx_fec_interrupt_fec_reinit(unsigned long data);
+
+/* default fec0 address */
+unsigned char m54xx_fec_mac_addr_fec0[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x50 };
+
+#ifdef M54XX_FEC2
+/* default fec1 address */
+unsigned char m54xx_fec_mac_addr_fec1[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x51 };
+#endif
+
+extern unsigned char uboot_enet0[];
+extern unsigned char uboot_enet1[];
+
+#ifndef MODULE
+int m54xx_fec_str_to_mac(char *str_mac, unsigned char* addr);
+int __init m54xx_fec_mac_setup0(char *s);
+#endif
+
+
+#ifdef M54XX_FEC2
+void m54xx_fec_interrupt_fec_tx_handler_fec1(void);
+void m54xx_fec_interrupt_fec_rx_handler_fec1(void);
+#endif
+
+#ifndef MODULE
+int __init m54xx_fec_mac_setup1(char *s);
+#endif
+
+module_init(m54xx_fec_init);
+/* module_exit(m54xx_fec_cleanup); */
+
+__setup("mac0=", m54xx_fec_mac_setup0);
+
+#ifdef M54XX_FEC2
+__setup("mac1=", m54xx_fec_mac_setup1);
+#endif
+
+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
+ (VAL & 0xffff))
+
+
+static int m54xx_fec_mdio_read(struct mii_bus *bus,
+ int phy_id, int reg)
+{
+ int ret;
+#ifdef CONFIG_FEC_M54xx_SHARED_PHY
+ unsigned long base_addr = (unsigned long)M54XX_FEC_BASE_ADDR_FEC0;
+#else
+ struct net_device *dev = bus->priv;
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+#endif
+ int tries = 100;
+
+ /* Clear the MII interrupt bit */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_MII;
+
+ /* Write to the MII management frame register */
+ M54XX_FEC_MMFR(base_addr) = mk_mii_read(reg) | (phy_id << 23);
+
+ /* Wait for the reading */
+ while (!(M54XX_FEC_EIR(base_addr) & M54XX_FEC_EIR_MII)) {
+ udelay(10);
+
+ if (!tries) {
+ printk(KERN_ERR "%s timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ tries--;
+ }
+
+ /* Clear the MII interrupt bit */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_MII;
+ ret = M54XX_FEC_MMFR(base_addr) & 0x0000FFFF;
+ return ret;
+}
+
+static int m54xx_fec_mdio_write(struct mii_bus *bus,
+ int phy_id, int reg, u16 data)
+{
+ int ret;
+#ifdef CONFIG_FEC_M54xx_SHARED_PHY
+ unsigned long base_addr = (unsigned long)M54XX_FEC_BASE_ADDR_FEC0;
+#else
+ struct net_device *dev = bus->priv;
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+#endif
+ int tries = 100;
+
+ printk(KERN_ERR "%s base_addr %lx, phy_id %x, reg %x, data %x\n",
+ __func__, base_addr, phy_id, reg, data);
+ /* Clear the MII interrupt bit */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_MII;
+
+ /* Write to the MII management frame register */
+ M54XX_FEC_MMFR(base_addr) = mk_mii_write(reg, data) | (phy_id << 23);
+
+ /* Wait for the writing */
+ while (!(M54XX_FEC_EIR(base_addr) & M54XX_FEC_EIR_MII)) {
+ udelay(10);
+ if (!tries) {
+ printk(KERN_ERR "%s timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ tries--;
+ }
+ /* Clear the MII interrupt bit */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_MII;
+ ret = M54XX_FEC_MMFR(base_addr) & 0x0000FFFF;
+
+ return ret;
+}
+
+static void m54xx_fec_adjust_link(struct net_device *dev)
+{
+ struct m54xx_fec_priv *priv = netdev_priv(dev);
+ struct phy_device *phydev = priv->phydev;
+ int new_state = 0;
+
+ if (phydev->link != PHY_DOWN) {
+ if (phydev->duplex != priv->duplex) {
+ new_state = 1;
+ priv->duplex = phydev->duplex;
+ }
+
+ if (phydev->speed != priv->speed) {
+ new_state = 1;
+ priv->speed = phydev->speed;
+ }
+
+ if (priv->link == PHY_DOWN) {
+ new_state = 1;
+ priv->link = phydev->link;
+ }
+ } else if (priv->link) {
+ new_state = 1;
+ priv->link = PHY_DOWN;
+ priv->speed = 0;
+ priv->duplex = -1;
+ }
+
+ if (new_state)
+ phy_print_status(phydev);
+}
+
+static int m54xx_fec_init_phy(struct net_device *dev)
+{
+ struct m54xx_fec_priv *priv = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+ int i;
+ int startnode;
+
+#ifdef CONFIG_FEC_M54xx_SHARED_PHY
+ if (priv->index == 0)
+ startnode = 0;
+ else if (priv->index == 1) {
+ struct m54xx_fec_priv *priv0 = netdev_priv(m54xx_fec_dev[0]);
+ startnode = priv0->phydev->addr + 1;
+ } else
+ startnode = 0;
+#else
+ startnode = 0;
+#endif
+#ifdef M54XX_FEC_DEBUG
+ printk(KERN_ERR "%s priv->index %x, startnode %x\n",
+ __func__, priv->index, startnode);
+#endif
+ /* search for connect PHY device */
+ for (i = startnode; i < PHY_MAX_ADDR; i++) {
+ struct phy_device *const tmp_phydev =
+ priv->mdio_bus->phy_map[i];
+
+ if (!tmp_phydev) {
+#ifdef M54XX_FEC_DEBUG
+ printk(KERN_INFO "%s no PHY here at"
+ "mii_bus->phy_map[%d]\n",
+ __func__, i);
+#endif
+ continue; /* no PHY here... */
+ }
+ phydev = tmp_phydev;
+#ifdef M54XX_FEC_DEBUG
+ printk(KERN_INFO "%s find PHY here at"
+ "mii_bus->phy_map[%d]\n",
+ __func__, i);
+#endif
+ break; /* found it */
+ }
+
+ /* now we are supposed to have a proper phydev, to attach to... */
+ if (!phydev) {
+ printk(KERN_INFO "%s: Don't found any phy device at all\n",
+ dev->name);
+ return -ENODEV;
+ }
+
+ priv->link = 0;
+ priv->speed = 0;
+ priv->duplex = 0;
+#ifdef M54XX_FEC_DEBUG
+ printk(KERN_INFO "%s phydev_busid %s\n", __func__, dev_name(&phydev->dev));
+#endif
+
+ phydev = phy_connect(dev, dev_name(&phydev->dev),
+ &m54xx_fec_adjust_link,
+ 0,
+ PHY_INTERFACE_MODE_MII);
+
+ phydev->supported &= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_MII);
+ phydev->advertising = phydev->supported;
+
+
+
+ if (IS_ERR(phydev)) {
+ printk(KERN_ERR " %s phy_connect failed\n", __func__);
+ return PTR_ERR(phydev);
+ }
+
+ printk(KERN_INFO "M54xx FEC attached phy %i to driver %s %s\n",
+ phydev->addr,
+ phydev->drv->name,
+ dev_name(&phydev->dev));
+ priv->phydev = phydev;
+ return 0;
+}
+
+static int m54xx_fec_mdio_register(struct net_device *dev,
+ int slot)
+{
+ int err = 0;
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+
+ fp->mdio_bus = mdiobus_alloc();
+ if (!fp->mdio_bus) {
+ printk(KERN_ERR "ethernet mdiobus_alloc fail\n");
+ return -ENOMEM;
+ }
+
+ if (slot == 0) {
+ fp->mdio_bus->name = "Coldfire FEC MII 0 Bus";
+ strcpy(fp->mdio_bus->id, "0");
+ } else if (slot == 1) {
+ fp->mdio_bus->name = "Coldfire FEC MII 1 Bus";
+ strcpy(fp->mdio_bus->id, "1");
+ } else {
+ printk(KERN_ERR "Now coldfire can not"
+ "support more than 2 mii bus\n");
+ }
+
+ fp->mdio_bus->read = &m54xx_fec_mdio_read;
+ fp->mdio_bus->write = &m54xx_fec_mdio_write;
+ fp->mdio_bus->priv = dev;
+ err = mdiobus_register(fp->mdio_bus);
+ if (err) {
+ mdiobus_free(fp->mdio_bus);
+ printk(KERN_ERR "%s: ethernet mdiobus_register fail %d\n",
+ dev->name, err);
+ return -EIO;
+ }
+
+ printk(KERN_INFO "mdiobus_register %s ok\n",
+ fp->mdio_bus->name);
+ return err;
+}
+
+static const struct net_device_ops m547x_fec_netdev_ops = {
+ .ndo_open = m54xx_fec_open,
+ .ndo_stop = m54xx_fec_close,
+ .ndo_start_xmit = m54xx_fec_tx,
+ .ndo_set_rx_mode = m54xx_fec_set_multicast_list,
+ .ndo_set_mac_address = m54xx_fec_set_mac_address,
+ .ndo_tx_timeout = m54xx_fec_tx_timeout,
+ .ndo_get_stats = m54xx_fec_get_stat,
+};
+
+/**
+ * Initialize a FEC device
+ */
+int m54xx_fec_enet_init(struct net_device *dev, int slot)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ int i;
+
+ fp->index = slot;
+ fp->netdev = dev;
+ m54xx_fec_dev[slot] = dev;
+
+ if (slot == 0) {
+ /* disable fec0 */
+ M54XX_FEC_ECR(M54XX_FEC_BASE_ADDR_FEC0) = M54XX_FEC_ECR_DISABLE;
+
+ /* setup the interrupt handler */
+ dev->irq = 64 + M54XX_ISC_FEC0;
+
+ if (request_irq(dev->irq, m54xx_fec_interrupt_handler,
+ IRQF_DISABLED, "ColdFire FEC 0", dev)) {
+ dev->irq = 0;
+ printk(KERN_ERR "Cannot allocate FEC0 IRQ\n");
+ }
+
+ /* fec base address */
+ dev->base_addr = M54XX_FEC_BASE_ADDR_FEC0;
+
+ /* requestor numbers */
+ fp->rx_requestor = DMA_FEC0_RX;
+ fp->tx_requestor = DMA_FEC0_TX;
+
+ /* m54xx_fec0 handlers */
+ fp->interrupt_fec_rx_handler =
+ m54xx_fec_interrupt_fec_rx_handler_fec0;
+ fp->interrupt_fec_tx_handler =
+ m54xx_fec_interrupt_fec_tx_handler_fec0;
+
+ /* tx descriptors */
+ fp->txdesc = (void *)M54XX_FEC_TX_DESC_FEC0;
+
+ /* rx descriptors */
+ fp->rxdesc = (void *)M54XX_FEC_RX_DESC_FEC0;
+
+ /* mac addr
+ if (uboot_enet0[0] || uboot_enet0[1] || uboot_enet0[2] ||
+ uboot_enet0[3] || uboot_enet0[4] || uboot_enet0[5]) {
+ use uboot enet 0 addr
+ memcpy(m54xx_fec_mac_addr_fec0, uboot_enet0, 6);
+ }*/
+ m54xx_fec_mac_addr_fec0[0] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC0) >> 24) & 0xFF;
+ m54xx_fec_mac_addr_fec0[1] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC0) >> 16) & 0xFF;
+ m54xx_fec_mac_addr_fec0[2] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC0) >> 8) & 0xFF;
+ m54xx_fec_mac_addr_fec0[3] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC0)) & 0xFF;
+ m54xx_fec_mac_addr_fec0[4] =
+ (M54XX_FEC_PAUR(M54XX_FEC_BASE_ADDR_FEC0) >> 24) & 0xFF;
+ m54xx_fec_mac_addr_fec0[5] =
+ (M54XX_FEC_PAUR(M54XX_FEC_BASE_ADDR_FEC0) >> 16) & 0xFF;
+
+ fp->mac_addr = m54xx_fec_mac_addr_fec0;
+ } else {
+ /* disable fec1 */
+ M54XX_FEC_ECR(M54XX_FEC_BASE_ADDR_FEC1) = M54XX_FEC_ECR_DISABLE;
+#ifdef M54XX_FEC2
+ /* setup the interrupt handler */
+ dev->irq = 64 + M54XX_ISC_FEC1;
+
+ if (request_irq(dev->irq, m54xx_fec_interrupt_handler,
+ IRQF_DISABLED, "ColdFire FEC 1", dev)) {
+ dev->irq = 0;
+ printk(KERN_ERR "Cannot allocate FEC1 IRQ\n");
+ }
+
+ /* fec base address */
+ dev->base_addr = M54XX_FEC_BASE_ADDR_FEC1;
+
+ /* requestor numbers */
+ fp->rx_requestor = DMA_FEC1_RX;
+ fp->tx_requestor = DMA_FEC1_TX;
+
+ /* fec1 handlers */
+ fp->interrupt_fec_rx_handler =
+ m54xx_fec_interrupt_fec_rx_handler_fec1;
+ fp->interrupt_fec_tx_handler =
+ m54xx_fec_interrupt_fec_tx_handler_fec1;
+
+ /* tx descriptors */
+ fp->txdesc = (void *)M54XX_FEC_TX_DESC_FEC1;
+
+ /* rx descriptors */
+ fp->rxdesc = (void *)M54XX_FEC_RX_DESC_FEC1;
+
+ /* mac addr
+ if (uboot_enet1[0] || uboot_enet1[1] || uboot_enet1[2] ||
+ uboot_enet1[3] || uboot_enet1[4] || uboot_enet1[5]) {
+ use uboot enet 1 addr
+ memcpy(m54xx_fec_mac_addr_fec1, uboot_enet1, 6);
+ }*/
+ m54xx_fec_mac_addr_fec1[0] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC1) >> 24) & 0xFF;
+ m54xx_fec_mac_addr_fec1[1] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC1) >> 16) & 0xFF;
+ m54xx_fec_mac_addr_fec1[2] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC1) >> 8) & 0xFF;
+ m54xx_fec_mac_addr_fec1[3] =
+ (M54XX_FEC_PALR(M54XX_FEC_BASE_ADDR_FEC1)) & 0xFF;
+ m54xx_fec_mac_addr_fec1[4] =
+ (M54XX_FEC_PAUR(M54XX_FEC_BASE_ADDR_FEC1) >> 24) & 0xFF;
+ m54xx_fec_mac_addr_fec1[5] =
+ (M54XX_FEC_PAUR(M54XX_FEC_BASE_ADDR_FEC1) >> 16) & 0xFF;
+
+ fp->mac_addr = m54xx_fec_mac_addr_fec1;
+#endif
+ }
+
+ /* clear MIB */
+ memset((void *) (dev->base_addr + 0x200), 0, M54XX_FEC_MIB_LEN);
+
+ /* clear the statistics structure */
+ memset((void *) &(fp->stat), 0,
+ sizeof(struct net_device_stats));
+
+ /* grab the FEC initiators */
+ dma_set_initiator(fp->tx_requestor);
+ fp->initiator_tx = dma_get_initiator(fp->tx_requestor);
+ dma_set_initiator(fp->rx_requestor);
+ fp->initiator_rx = dma_get_initiator(fp->rx_requestor);
+
+ /* reset the DMA channels */
+ fp->fec_rx_channel = -1;
+ fp->fec_tx_channel = -1;
+
+ for (i = 0; i < M54XX_FEC_RX_BUF_NUMBER; i++)
+ fp->askb_rx[i] = NULL;
+
+ /* initialize the pointers to the socket buffers */
+ for (i = 0; i < M54XX_FEC_TX_BUF_NUMBER; i++)
+ fp->txbuf[i] = NULL;
+
+ ether_setup(dev);
+
+
+ dev->netdev_ops = &m547x_fec_netdev_ops;
+ dev->watchdog_timeo = M54XX_FEC_TX_TIMEOUT * HZ;
+
+ memcpy(dev->dev_addr, fp->mac_addr, ETH_ALEN);
+
+ spin_lock_init(&fp->lock);
+
+ /* Initialize FEC/I2C/IRQ Pin Assignment Register*/
+ M54XX_FEC_GPIO_PAR_FECI2CIRQ &= 0xF;
+ M54XX_FEC_GPIO_PAR_FECI2CIRQ |= M54XX_FEC_FECI2CIRQ;
+
+ return 0;
+}
+
+
+/**
+ * Module Initialization
+ */
+int __init m54xx_fec_init(void)
+{
+ struct net_device *dev;
+ int i;
+ int err;
+ struct m54xx_fec_priv *fep;
+
+ printk(KERN_INFO "M54xx FEC ENET (DMA) Version %s\n", VERSION);
+ if (M54XX_FEC_MAX_PORTS > 1)
+ {
+ printk(KERN_INFO "M54xx FEC %d ports\n", M54XX_FEC_MAX_PORTS);
+#ifdef CONFIG_FEC_M54xx_SHARED_PHY
+ printk(KERN_INFO "M54xx FEC Shared PHY\n");
+#endif
+ }
+ else
+ {
+ printk(KERN_INFO "M54xx FEC 1 port\n");
+ }
+
+ for (i = 0; i < M54XX_FEC_MAX_PORTS; i++) {
+ dev = alloc_etherdev(sizeof(struct m54xx_fec_priv));
+ if (!dev)
+ return -ENOMEM;
+ err = m54xx_fec_enet_init(dev, i);
+ if (err) {
+ free_netdev(dev);
+ continue;
+ }
+
+ fep = netdev_priv(dev);
+ M54XX_FEC_MSCR(dev->base_addr) = M54XX_FEC_MII_SPEED;
+#ifdef CONFIG_FEC_M54xx_SHARED_PHY
+ if (i == 0)
+ err = m54xx_fec_mdio_register(dev, i);
+ else {
+ struct m54xx_fec_priv *priv0 = netdev_priv(m54xx_fec_dev[0]);
+ fep->mdio_bus = priv0->mdio_bus;
+ printk(KERN_INFO "FEC%d SHARED the %s ok\n",
+ i, fep->mdio_bus->name);
+ }
+#else
+ err = m54xx_fec_mdio_register(dev, i);
+#endif
+ if (err) {
+ printk(KERN_ERR "%s: ethernet fec_mdio_register\n",
+ dev->name);
+ free_netdev(dev);
+ return -ENOMEM;
+ }
+
+ if (register_netdev(dev) != 0) {
+ free_netdev(dev);
+ return -EIO;
+ }
+
+ printk(KERN_INFO "%s: ethernet %pM\n",
+ dev->name, dev->dev_addr);
+ }
+ return 0;
+}
+
+/**
+ * Stop a device
+ */
+void m54xx_fec_stop(struct net_device *dev)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+
+ dma_remove_initiator(fp->initiator_tx);
+ dma_remove_initiator(fp->initiator_rx);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+}
+
+/**
+ * m54xx_fec_open
+ *
+ * @brief This function performs the initialization of
+ * of FEC and corresponding KS8721 transiver
+ *
+ * RETURNS: If no error occurs, this function returns zero.
+ */
+int m54xx_fec_open(struct net_device *dev)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+ int fduplex;
+ int i;
+ int channel;
+ int error_code = -EBUSY;
+
+ fp->link = 0;
+ fp->duplex = 0;
+ fp->speed = 0;
+ m54xx_fec_init_phy(dev);
+ phy_start(fp->phydev);
+
+ /* Receive the DMA channels */
+ channel = dma_set_channel_fec(fp->rx_requestor);
+
+ if (channel == -1) {
+ printk(KERN_ERR "M54xx FEC DMA RX channel cannot be reserved\n");
+ goto ERRORS;
+ }
+
+ fp->fec_rx_channel = channel;
+
+ dma_connect(channel, (int) fp->interrupt_fec_rx_handler);
+
+ channel = dma_set_channel_fec(fp->tx_requestor);
+
+ if (channel == -1) {
+ printk(KERN_ERR "M54xx FEC DMA RX channel cannot be reserved\n");
+ goto ERRORS;
+ }
+
+ fp->fec_tx_channel = channel;
+
+ dma_connect(channel, (int) fp->interrupt_fec_tx_handler);
+
+ /* init tasklet for controller reinitialization */
+ tasklet_init(&fp->tasklet_reinit,
+ m54xx_fec_interrupt_fec_reinit, (unsigned long) dev);
+
+ /* Reset FIFOs */
+ M54XX_FEC_FECFRST(base_addr) |= M54XX_FEC_SW_RST | M54XX_FEC_RST_CTL;
+ M54XX_FEC_FECFRST(base_addr) &= ~M54XX_FEC_SW_RST;
+
+ /* Reset and disable FEC */
+ M54XX_FEC_ECR(base_addr) = M54XX_FEC_ECR_RESET;
+
+ udelay(10);
+
+ /* Clear all events */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_CLEAR;
+
+ /* Reset FIFO status */
+ M54XX_FEC_FECTFSR(base_addr) = M54XX_FEC_FECTFSR_MSK;
+ M54XX_FEC_FECRFSR(base_addr) = M54XX_FEC_FECRFSR_MSK;
+
+ /* Set the default address */
+ M54XX_FEC_PALR(base_addr) = (fp->mac_addr[0] << 24) |
+ (fp->mac_addr[1] << 16) |
+ (fp->mac_addr[2] << 8) |
+ fp->mac_addr[3];
+ M54XX_FEC_PAUR(base_addr) = (fp->mac_addr[4] << 24) |
+ (fp->mac_addr[5] << 16) | 0x8808;
+
+ /* Reset the group address descriptor */
+ M54XX_FEC_GALR(base_addr) = 0x00000000;
+ M54XX_FEC_GAUR(base_addr) = 0x00000000;
+
+ /* Reset the individual address descriptor */
+ M54XX_FEC_IALR(base_addr) = 0x00000000;
+ M54XX_FEC_IAUR(base_addr) = 0x00000000;
+
+ /* Set the receive control register */
+ M54XX_FEC_RCR(base_addr) = M54XX_FEC_RCR_MAX_FRM_SIZE | M54XX_FEC_RCR_MII;
+
+ /* Set the receive FIFO control register */
+ /*M54XX_FEC_FECRFCR(base_addr) =
+ * M54XX_FEC_FECRFCR_FRM | M54XX_FEC_FECRFCR_GR | M54XX_FEC_FECRFCR_MSK;*/
+ M54XX_FEC_FECRFCR(base_addr) = M54XX_FEC_FECRFCR_FRM | M54XX_FEC_FECRFCR_GR
+ | (M54XX_FEC_FECRFCR_MSK
+ /* disable all but ...*/
+ & ~M54XX_FEC_FECRFCR_FAE
+ /* enable frame accept error*/
+ & ~M54XX_FEC_FECRFCR_RXW
+ /* enable receive wait condition*/
+ /*& ~M54XX_FEC_FECRFCR_UF*/
+ /* enable FIFO underflow*/
+ );
+
+ /* Set the receive FIFO alarm register */
+ M54XX_FEC_FECRFAR(base_addr) = M54XX_FEC_FECRFAR_ALARM;
+
+ /* Set the transmit FIFO control register */
+ /*M54XX_FEC_FECTFCR(base_addr) =
+ M54XX_FEC_FECTFCR_FRM | M54XX_FEC_FECTFCR_GR | M54XX_FEC_FECTFCR_MSK;*/
+ M54XX_FEC_FECTFCR(base_addr) = M54XX_FEC_FECTFCR_FRM | M54XX_FEC_FECTFCR_GR
+ | (M54XX_FEC_FECTFCR_MSK
+ /* disable all but ... */
+ & ~M54XX_FEC_FECTFCR_FAE
+ /* enable frame accept error */
+ /* & ~M54XX_FEC_FECTFCR_TXW */
+ /*enable transmit wait condition*/
+ /*& ~M54XX_FEC_FECTFCR_UF*/
+ /*enable FIFO underflow*/
+ & ~M54XX_FEC_FECTFCR_OF);
+ /* enable FIFO overflow */
+
+ /* Set the transmit FIFO alarm register */
+ M54XX_FEC_FECTFAR(base_addr) = M54XX_FEC_FECTFAR_ALARM;
+
+ /* Set the Tx FIFO watermark */
+ M54XX_FEC_FECTFWR(base_addr) = M54XX_FEC_FECTFWR_XWMRK;
+
+ /* Enable the transmitter to append the CRC */
+ M54XX_FEC_CTCWR(base_addr) = M54XX_FEC_CTCWR_TFCW_CRC;
+
+ /* Enable the ethernet interrupts */
+ /*M54XX_FEC_EIMR(base_addr) = M54XX_FEC_EIMR_MASK;*/
+ M54XX_FEC_EIMR(base_addr) = M54XX_FEC_EIMR_DISABLE
+ | M54XX_FEC_EIR_LC
+ | M54XX_FEC_EIR_RL
+ | M54XX_FEC_EIR_HBERR
+ | M54XX_FEC_EIR_XFUN
+ | M54XX_FEC_EIR_XFERR
+ | M54XX_FEC_EIR_RFERR;
+
+#if 0
+ error_code = init_transceiver(base_addr, &fduplex);
+ if (error_code != 0) {
+ printk(KERN_ERR "Initialization of the "
+ "transceiver is failed\n");
+ goto ERRORS;
+ }
+#else
+ fduplex = 1;
+#endif
+ if (fduplex)
+ /* Enable the full duplex mode */
+ M54XX_FEC_TCR(base_addr) = M54XX_FEC_TCR_FDEN | M54XX_FEC_TCR_HBC;
+ else
+ /* Disable reception of frames while transmitting */
+ M54XX_FEC_RCR(base_addr) |= M54XX_FEC_RCR_DRT;
+
+ /* Enable MIB */
+ M54XX_FEC_MIBC(base_addr) = M54XX_FEC_MIBC_ENABLE;
+
+ /* Enable M54XX_FEC */
+ M54XX_FEC_ECR(base_addr) |= M54XX_FEC_ECR_ETHEREN;
+ M54XX_FEC_MSCR(dev->base_addr) = M54XX_FEC_MII_SPEED;
+ /* Initialize tx descriptors and start DMA for the transmission */
+ for (i = 0; i < M54XX_FEC_TX_BUF_NUMBER; i++)
+ fp->txdesc[i].statCtrl = MCD_FEC_INTERRUPT;
+
+ fp->txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
+
+ fp->current_tx = fp->next_tx = 0;
+
+ MCD_startDma(fp->fec_tx_channel, (char *) fp->txdesc, 0,
+ (unsigned char *) &(M54XX_FEC_FECTFDR(base_addr)), 0,
+ M54XX_FEC_MAX_FRM_SIZE, 0, fp->initiator_tx,
+ M54XX_FEC_TX_DMA_PRI, MCD_FECTX_DMA | MCD_INTERRUPT,
+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
+
+ /* Initialize rx descriptors and start DMA for the reception */
+ for (i = 0; i < M54XX_FEC_RX_BUF_NUMBER; i++) {
+ fp->askb_rx[i] = alloc_skb(M54XX_FEC_MAXBUF_SIZE + 16, GFP_DMA);
+ if (!fp->askb_rx[i]) {
+ fp->rxdesc[i].dataPointer = 0;
+ fp->rxdesc[i].statCtrl = 0;
+ fp->rxdesc[i].length = 0;
+ } else {
+ skb_reserve(fp->askb_rx[i], 16);
+ fp->askb_rx[i]->dev = dev;
+ fp->rxdesc[i].dataPointer =
+ (unsigned int)virt_to_phys(fp->askb_rx[i]->tail);
+ fp->rxdesc[i].statCtrl =
+ MCD_FEC_BUF_READY | MCD_FEC_INTERRUPT;
+ fp->rxdesc[i].length = M54XX_FEC_MAXBUF_SIZE;
+ }
+ }
+
+ fp->rxdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
+ fp->current_rx = 0;
+
+ MCD_startDma(fp->fec_rx_channel, (char *) fp->rxdesc, 0,
+ (unsigned char *) &(M54XX_FEC_FECRFDR(base_addr)), 0,
+ M54XX_FEC_MAX_FRM_SIZE, 0, fp->initiator_rx,
+ M54XX_FEC_RX_DMA_PRI, MCD_FECRX_DMA | MCD_INTERRUPT,
+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
+
+ netif_start_queue(dev);
+ return 0;
+
+ERRORS:
+
+ /* Remove the channels and return with the error code */
+ if (fp->fec_rx_channel != -1) {
+ dma_disconnect(fp->fec_rx_channel);
+ dma_remove_channel_by_number(fp->fec_rx_channel);
+ fp->fec_rx_channel = -1;
+ }
+
+ if (fp->fec_tx_channel != -1) {
+ dma_disconnect(fp->fec_tx_channel);
+ dma_remove_channel_by_number(fp->fec_tx_channel);
+ fp->fec_tx_channel = -1;
+ }
+
+ return error_code;
+}
+
+/**
+ * m54xx_fec_close
+ *
+ * @brief This function performs the graceful stop of the
+ * transmission and disables FEC
+ *
+ * RETURNS: This function always returns zero.
+ */
+int m54xx_fec_close(struct net_device *dev)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+ unsigned long time;
+ int i;
+
+ netif_stop_queue(dev);
+ phy_disconnect(fp->phydev);
+ phy_stop(fp->phydev);
+ /* Perform the graceful stop */
+ M54XX_FEC_TCR(base_addr) |= M54XX_FEC_TCR_GTS;
+
+ time = jiffies;
+
+ /* Wait for the graceful stop */
+ while (!(M54XX_FEC_EIR(base_addr) & M54XX_FEC_EIR_GRA) && jiffies - time <
+ (M54XX_FEC_GR_TIMEOUT * HZ))
+ schedule();
+
+ /* Disable M54XX_FEC */
+ M54XX_FEC_ECR(base_addr) = M54XX_FEC_ECR_DISABLE;
+
+ /* Reset the DMA channels */
+ spin_lock_irq(&fp->lock);
+ MCD_killDma(fp->fec_tx_channel);
+ spin_unlock_irq(&fp->lock);
+ dma_remove_channel_by_number(fp->fec_tx_channel);
+ dma_disconnect(fp->fec_tx_channel);
+ fp->fec_tx_channel = -1;
+
+ for (i = 0; i < M54XX_FEC_TX_BUF_NUMBER; i++) {
+ if (fp->txbuf[i]) {
+ kfree(fp->txbuf[i]);
+ fp->txbuf[i] = NULL;
+ }
+ }
+
+ spin_lock_irq(&fp->lock);
+ MCD_killDma(fp->fec_rx_channel);
+ spin_unlock_irq(&fp->lock);
+
+ dma_remove_channel_by_number(fp->fec_rx_channel);
+ dma_disconnect(fp->fec_rx_channel);
+ fp->fec_rx_channel = -1;
+
+ for (i = 0; i < M54XX_FEC_RX_BUF_NUMBER; i++) {
+ if (fp->askb_rx[i]) {
+ kfree_skb(fp->askb_rx[i]);
+ fp->askb_rx[i] = NULL;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * +m54xx_fec_get_stat
+ *
+ * RETURNS: This function returns the statistical information.
+ */
+struct net_device_stats *m54xx_fec_get_stat(struct net_device *dev)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ unsigned long base_addr = dev->base_addr;
+
+ /* Receive the statistical information */
+ fp->stat.rx_packets = M54XX_FECSTAT_RMON_R_PACKETS(base_addr);
+ fp->stat.tx_packets = M54XX_FECSTAT_RMON_T_PACKETS(base_addr);
+ fp->stat.rx_bytes = M54XX_FECSTAT_RMON_R_OCTETS(base_addr);
+ fp->stat.tx_bytes = M54XX_FECSTAT_RMON_T_OCTETS(base_addr);
+
+ fp->stat.multicast = M54XX_FECSTAT_RMON_R_MC_PKT(base_addr);
+ fp->stat.collisions = M54XX_FECSTAT_RMON_T_COL(base_addr);
+
+ fp->stat.rx_length_errors =
+ M54XX_FECSTAT_RMON_R_UNDERSIZE(base_addr) +
+ M54XX_FECSTAT_RMON_R_OVERSIZE(base_addr) +
+ M54XX_FECSTAT_RMON_R_FRAG(base_addr) +
+ M54XX_FECSTAT_RMON_R_JAB(base_addr);
+ fp->stat.rx_crc_errors = M54XX_FECSTAT_IEEE_R_CRC(base_addr);
+ fp->stat.rx_frame_errors = M54XX_FECSTAT_IEEE_R_ALIGN(base_addr);
+ fp->stat.rx_over_errors = M54XX_FECSTAT_IEEE_R_MACERR(base_addr);
+
+ fp->stat.tx_carrier_errors = M54XX_FECSTAT_IEEE_T_CSERR(base_addr);
+ fp->stat.tx_fifo_errors = M54XX_FECSTAT_IEEE_T_MACERR(base_addr);
+ fp->stat.tx_window_errors = M54XX_FECSTAT_IEEE_T_LCOL(base_addr);
+
+ /* I hope that one frame doesn't have more than one error */
+ fp->stat.rx_errors = fp->stat.rx_length_errors +
+ fp->stat.rx_crc_errors +
+ fp->stat.rx_frame_errors +
+ fp->stat.rx_over_errors +
+ fp->stat.rx_dropped;
+ fp->stat.tx_errors = fp->stat.tx_carrier_errors +
+ fp->stat.tx_fifo_errors +
+ fp->stat.tx_window_errors +
+ fp->stat.tx_aborted_errors +
+ fp->stat.tx_heartbeat_errors +
+ fp->stat.tx_dropped;
+
+ return &fp->stat;
+}
+
+/**
+ * m54xx_fec_set_multicast_list
+ *
+ * @brief This function sets the frame filtering parameters
+ */
+void m54xx_fec_set_multicast_list(struct net_device *dev)
+{
+ unsigned int crc, data;
+ int i, j;
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+
+ if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI) {
+ /* Allow all incoming frames */
+ M54XX_FEC_GALR(base_addr) = 0xFFFFFFFF;
+ M54XX_FEC_GAUR(base_addr) = 0xFFFFFFFF;
+ return ;
+ }
+
+ /* Reset the group address register */
+ M54XX_FEC_GALR(base_addr) = 0x00000000;
+ M54XX_FEC_GAUR(base_addr) = 0x00000000;
+
+ if (!netdev_mc_empty(dev)) {
+ struct netdev_hw_addr *ha;
+
+ netdev_for_each_mc_addr(ha, dev) {
+ /* Processing must be only for the group addresses */
+ if (!(ha->addr[0] & 1))
+ continue;
+
+ /* Calculate crc value for the current address */
+ crc = 0xFFFFFFFF;
+ for (i = 0; i < 6; i++) {
+ for (j = 0, data = ha->addr[i];
+ j < 8; j++, data >>= 1) {
+ if ((crc ^ data) & 1)
+ crc = (crc >> 1) ^ M54XX_FEC_CRCPOL;
+ else
+ crc >>= 1;
+ }
+ }
+
+ /* Add this value */
+ crc >>= 26;
+ crc &= 0x3F;
+ if (crc > 31)
+ M54XX_FEC_GAUR(base_addr) |= 0x1 << (crc - 32);
+ else
+ M54XX_FEC_GALR(base_addr) |= 0x1 << crc;
+ }
+ }
+}
+
+/**
+ * m54xx_fec_set_mac_address
+ *
+ * @brief This function sets the MAC address
+ */
+int m54xx_fec_set_mac_address(struct net_device *dev, void *p)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+ struct sockaddr *addr = p;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ /* Copy a new address to the device structure */
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ /* Copy a new address to the private structure */
+ memcpy(fp->mac_addr, addr->sa_data, 6);
+
+ /* Set the address to the registers */
+ M54XX_FEC_PALR(base_addr) = (fp->mac_addr[0] << 24) |
+ (fp->mac_addr[1] << 16) |
+ (fp->mac_addr[2] << 8) |
+ fp->mac_addr[3];
+ M54XX_FEC_PAUR(base_addr) = (fp->mac_addr[4] << 24) |
+ (fp->mac_addr[5] << 16) |
+ 0x8808;
+
+ return 0;
+}
+
+/**
+ * m54xx_fec_tx
+ *
+ * @brief This function starts transmission of the frame using DMA
+ *
+ * RETURNS: This function always returns zero.
+ */
+int m54xx_fec_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ void *data, *data_aligned;
+ int offset;
+
+ data = kmalloc(skb->len + 15, GFP_DMA | GFP_ATOMIC);
+
+ if (!data) {
+ fp->stat.tx_dropped++;
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ offset = (((unsigned long)virt_to_phys(data) + 15) & 0xFFFFFFF0) -
+ (unsigned long)virt_to_phys(data);
+ data_aligned = (void *)((unsigned long)data + offset);
+ memcpy(data_aligned, skb->data, skb->len);
+
+ /* flush data cache before initializing
+ * the descriptor and starting DMA */
+
+ spin_lock_irq(&fp->lock);
+
+ /* Initialize the descriptor */
+ fp->txbuf[fp->next_tx] = data;
+ fp->txdesc[fp->next_tx].dataPointer
+ = (unsigned int) virt_to_phys(data_aligned);
+ fp->txdesc[fp->next_tx].length = skb->len;
+ fp->txdesc[fp->next_tx].statCtrl
+ |= (MCD_FEC_END_FRAME | MCD_FEC_BUF_READY);
+ fp->next_tx = (fp->next_tx + 1) & M54XX_FEC_TX_INDEX_MASK;
+
+ if (fp->txbuf[fp->current_tx]
+ && fp->current_tx == fp->next_tx)
+ netif_stop_queue(dev);
+
+ spin_unlock_irq(&fp->lock);
+
+ /* Tell the DMA to continue the transmission */
+ MCD_continDma(fp->fec_tx_channel);
+
+ dev_kfree_skb(skb);
+
+ dev->trans_start = jiffies;
+
+ return 0;
+}
+
+/**
+ * m54xx_fec_tx_timeout
+ *
+ * @brief If the interrupt processing of received frames was lost
+ * and DMA stopped the reception, this function clears
+ * the transmission descriptors and starts DMA
+ *
+ */
+void m54xx_fec_tx_timeout(struct net_device *dev)
+{
+ int i;
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+
+ spin_lock_irq(&fp->lock);
+ MCD_killDma(fp->fec_tx_channel);
+ for (i = 0; i < M54XX_FEC_TX_BUF_NUMBER; i++) {
+ if (fp->txbuf[i]) {
+ kfree(fp->txbuf[i]);
+ fp->txbuf[i] = NULL;
+ }
+ fp->txdesc[i].statCtrl = MCD_FEC_INTERRUPT;
+ }
+ fp->txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
+
+ fp->current_tx = fp->next_tx = 0;
+
+ /* Reset FIFOs */
+ M54XX_FEC_FECFRST(base_addr) |= M54XX_FEC_SW_RST;
+ M54XX_FEC_FECFRST(base_addr) &= ~M54XX_FEC_SW_RST;
+
+ /* Reset and disable M54XX_FEC */
+ /* M54XX_FEC_ECR(base_addr) = M54XX_FEC_ECR_RESET; */
+
+ /* Enable M54XX_FEC */
+ M54XX_FEC_ECR(base_addr) |= M54XX_FEC_ECR_ETHEREN;
+
+ MCD_startDma(fp->fec_tx_channel, (char *) fp->txdesc, 0,
+ (unsigned char *) &(M54XX_FEC_FECTFDR(base_addr)), 0,
+ M54XX_FEC_MAX_FRM_SIZE, 0, fp->initiator_tx,
+ M54XX_FEC_TX_DMA_PRI, MCD_FECTX_DMA | MCD_INTERRUPT,
+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
+
+ spin_unlock_irq(&fp->lock);
+
+ netif_wake_queue(dev);
+
+}
+
+/**
+ * m54xx_fec_interrupt_tx_handler
+ *
+ * @brief This function is called when the data
+ * transmission from the buffer to the FEC is completed.
+ *
+ */
+void m54xx_fec_interrupt_fec_tx_handler(struct net_device *dev)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+
+ /* Release the socket buffer */
+ if (fp->txbuf[fp->current_tx]) {
+ kfree(fp->txbuf[fp->current_tx]);
+ fp->txbuf[fp->current_tx] = NULL;
+ }
+ fp->current_tx =
+ (fp->current_tx + 1) & M54XX_FEC_TX_INDEX_MASK;
+
+ if (MCD_dmaStatus(fp->fec_tx_channel) == MCD_DONE) {
+ for (; fp->current_tx != fp->next_tx;
+ fp->current_tx =
+ (fp->current_tx + 1)
+ & M54XX_FEC_TX_INDEX_MASK) {
+ if (fp->txbuf[fp->current_tx]) {
+ kfree(fp->txbuf[
+ fp->current_tx]);
+ fp->txbuf[fp->current_tx]
+ = NULL;
+ }
+ }
+ }
+
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+}
+
+/**
+ * m54xx_fec_interrupt_rx_handler
+ *
+ * @brief This function is called when the data
+ * reception from the FEC to the reception buffer is completed.
+ *
+ */
+void m54xx_fec_interrupt_fec_rx_handler(struct net_device *dev)
+{
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ struct sk_buff *skb;
+ int i;
+
+ fp->rxflag = 1;
+ /* Some buffers can be missed */
+ if (!(fp->rxdesc[fp->current_rx].statCtrl
+ & MCD_FEC_END_FRAME)) {
+ /* Find a valid index */
+ for (i = 0; ((i < M54XX_FEC_RX_BUF_NUMBER) &&
+ !(fp->rxdesc[
+ fp->current_rx].statCtrl
+ & MCD_FEC_END_FRAME)); i++,
+ (fp->current_rx =
+ (fp->current_rx + 1)
+ & M54XX_FEC_RX_INDEX_MASK))
+ /* NOP */;
+
+ if (i == M54XX_FEC_RX_BUF_NUMBER) {
+ /* There are no data to process */
+ /* Tell the DMA to continue the reception */
+ MCD_continDma(fp->fec_rx_channel);
+
+ fp->rxflag = 0;
+
+ return;
+ }
+ }
+
+ for (; fp->rxdesc[fp->current_rx].statCtrl
+ & MCD_FEC_END_FRAME;
+ fp->current_rx = (fp->current_rx + 1)
+ & M54XX_FEC_RX_INDEX_MASK) {
+ if ((fp->rxdesc[fp->current_rx].length
+ <= M54XX_FEC_MAXBUF_SIZE) &&
+ (fp->rxdesc[fp->current_rx].length
+ > 4)) {
+ /* --tym-- */
+ skb = fp->askb_rx[fp->current_rx];
+ if (!skb)
+ fp->stat.rx_dropped++;
+ else {
+ /*
+ * flush data cache before initializing
+ * the descriptor and starting DMA
+ */
+ skb_put(skb,
+ (fp->rxdesc[
+ fp->current_rx].length - 4));
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ }
+ fp->rxdesc[fp->current_rx].statCtrl &=
+ ~MCD_FEC_END_FRAME;
+ /* allocate new skbuff */
+ fp->askb_rx[fp->current_rx] =
+ alloc_skb(M54XX_FEC_MAXBUF_SIZE + 16,
+ /*GFP_ATOMIC |*/ GFP_DMA);
+ if (!fp->askb_rx[fp->current_rx]) {
+ fp->rxdesc[
+ fp->current_rx].dataPointer
+ = 0;
+ fp->rxdesc[
+ fp->current_rx].length = 0;
+ fp->stat.rx_dropped++;
+ } else {
+ skb_reserve(
+ fp->askb_rx[fp->current_rx], 16);
+ fp->askb_rx[fp->current_rx]->dev = dev;
+
+ /*
+ * flush data cache before initializing
+ * the descriptor and starting DMA
+ */
+
+ fp->rxdesc[
+ fp->current_rx].dataPointer =
+ (unsigned int) virt_to_phys(
+ fp->askb_rx[
+ fp->current_rx]->tail);
+ fp->rxdesc[
+ fp->current_rx].length =
+ M54XX_FEC_MAXBUF_SIZE;
+ fp->rxdesc[
+ fp->current_rx].statCtrl |=
+ MCD_FEC_BUF_READY;
+
+ /*
+ * flush data cache before initializing
+ * the descriptor and starting DMA
+ */
+ }
+ }
+
+ }
+
+ /* Tell the DMA to continue the reception */
+ MCD_continDma(fp->fec_rx_channel);
+
+ fp->rxflag = 0;
+}
+
+/**
+ * m54xx_fec_interrupt_handler
+ *
+ * @brief This function is called when some special errors occur
+ *
+ */
+irqreturn_t m54xx_fec_interrupt_handler(int irq, void *dev_id)
+{
+
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+ unsigned long events;
+
+ /* Read and clear the events */
+ events = M54XX_FEC_EIR(base_addr) & M54XX_FEC_EIMR(base_addr);
+
+ if (events & M54XX_FEC_EIR_HBERR) {
+ fp->stat.tx_heartbeat_errors++;
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_HBERR;
+ }
+
+ /* receive/transmit FIFO error */
+ if (((events & M54XX_FEC_EIR_RFERR) != 0)
+ || ((events & M54XX_FEC_EIR_XFERR) != 0)) {
+ /* kill DMA receive channel */
+ MCD_killDma(fp->fec_rx_channel);
+
+ /* kill running transmission by DMA */
+ MCD_killDma(fp->fec_tx_channel);
+
+ /* Reset FIFOs */
+ M54XX_FEC_FECFRST(base_addr) |= M54XX_FEC_SW_RST;
+ M54XX_FEC_FECFRST(base_addr) &= ~M54XX_FEC_SW_RST;
+
+ /* reset receive FIFO status register */
+ M54XX_FEC_FECRFSR(base_addr) = M54XX_FEC_FECRFSR_FAE |
+ M54XX_FEC_FECRFSR_RXW |
+ M54XX_FEC_FECRFSR_UF;
+
+ /* reset transmit FIFO status register */
+ M54XX_FEC_FECTFSR(base_addr) = M54XX_FEC_FECTFSR_FAE |
+ M54XX_FEC_FECTFSR_TXW |
+ M54XX_FEC_FECTFSR_UF |
+ M54XX_FEC_FECTFSR_OF;
+
+ /* reset RFERR and XFERR event */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_RFERR | M54XX_FEC_EIR_XFERR;
+
+ /* stop queue */
+ netif_stop_queue(dev);
+
+ /* execute reinitialization as tasklet */
+ tasklet_schedule(&fp->tasklet_reinit);
+
+ fp->stat.rx_dropped++;
+ }
+
+ /* transmit FIFO underrun */
+ if ((events & M54XX_FEC_EIR_XFUN) != 0) {
+ /* reset XFUN event */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_XFUN;
+ fp->stat.tx_aborted_errors++;
+ }
+
+ /* late collision */
+ if ((events & M54XX_FEC_EIR_LC) != 0) {
+ /* reset LC event */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_LC;
+ fp->stat.tx_aborted_errors++;
+ }
+
+ /* collision retry limit */
+ if ((events & M54XX_FEC_EIR_RL) != 0) {
+ /* reset RL event */
+ M54XX_FEC_EIR(base_addr) = M54XX_FEC_EIR_RL;
+ fp->stat.tx_aborted_errors++;
+ }
+ return 0;
+}
+
+/**
+ * m54xx_fec_interrupt_reinit
+ *
+ * @brief This function is called from interrupt handler
+ * when controller must be reinitialized.
+ *
+ */
+void m54xx_fec_interrupt_fec_reinit(unsigned long data)
+{
+ int i;
+ struct net_device *dev = (struct net_device *)data;
+ struct m54xx_fec_priv *fp = netdev_priv(dev);
+ unsigned long base_addr = (unsigned long) dev->base_addr;
+
+ /* Initialize reception descriptors and start DMA for the reception */
+ for (i = 0; i < M54XX_FEC_RX_BUF_NUMBER; i++) {
+ if (!fp->askb_rx[i]) {
+ fp->askb_rx[i] = alloc_skb(M54XX_FEC_MAXBUF_SIZE + 16,
+ GFP_ATOMIC | GFP_DMA);
+ if (!fp->askb_rx[i]) {
+ fp->rxdesc[i].dataPointer = 0;
+ fp->rxdesc[i].statCtrl = 0;
+ fp->rxdesc[i].length = 0;
+ continue;
+ }
+ fp->askb_rx[i]->dev = dev;
+ skb_reserve(fp->askb_rx[i], 16);
+ }
+ fp->rxdesc[i].dataPointer =
+ (unsigned int) virt_to_phys(fp->askb_rx[i]->tail);
+ fp->rxdesc[i].statCtrl =
+ MCD_FEC_BUF_READY | MCD_FEC_INTERRUPT;
+ fp->rxdesc[i].length = M54XX_FEC_MAXBUF_SIZE;
+ }
+
+ fp->rxdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
+ fp->current_rx = 0;
+
+ /* restart frame transmission */
+ for (i = 0; i < M54XX_FEC_TX_BUF_NUMBER; i++) {
+ if (fp->txbuf[i]) {
+ kfree(fp->txbuf[i]);
+ fp->txbuf[i] = NULL;
+ fp->stat.tx_dropped++;
+ }
+ fp->txdesc[i].statCtrl = MCD_FEC_INTERRUPT;
+ }
+ fp->txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
+ fp->current_tx = fp->next_tx = 0;
+
+ /* flush entire data cache before restarting the DMA */
+
+ /* restart DMA from beginning */
+ MCD_startDma(fp->fec_rx_channel,
+ (char *) fp->rxdesc, 0,
+ (unsigned char *) &(M54XX_FEC_FECRFDR(base_addr)), 0,
+ M54XX_FEC_MAX_FRM_SIZE, 0, fp->initiator_rx,
+ M54XX_FEC_RX_DMA_PRI, MCD_FECRX_DMA | MCD_INTERRUPT,
+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
+
+ MCD_startDma(fp->fec_tx_channel, (char *) fp->txdesc, 0,
+ (unsigned char *) &(M54XX_FEC_FECTFDR(base_addr)), 0,
+ M54XX_FEC_MAX_FRM_SIZE, 0, fp->initiator_tx,
+ M54XX_FEC_TX_DMA_PRI, MCD_FECTX_DMA | MCD_INTERRUPT,
+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
+
+ /* Enable M54XX_FEC */
+ M54XX_FEC_ECR(base_addr) |= M54XX_FEC_ECR_ETHEREN;
+
+ netif_wake_queue(dev);
+}
+
+/**
+ * m54xx_fec_interrupt_tx_handler_fec0
+ *
+ * @brief This is the DMA interrupt handler using for FEC0
+ * transmission.
+ *
+ */
+void m54xx_fec_interrupt_fec_tx_handler_fec0(void)
+{
+ m54xx_fec_interrupt_fec_tx_handler(m54xx_fec_dev[0]);
+}
+
+#ifdef M54XX_FEC2
+/**
+ * m54xx_fec_interrupt_tx_handler_fec1
+ *
+ * @brief This is the DMA interrupt handler using for the FEC1
+ * transmission.
+ *
+ */
+void m54xx_fec_interrupt_fec_tx_handler_fec1(void)
+{
+ m54xx_fec_interrupt_fec_tx_handler(m54xx_fec_dev[1]);
+}
+#endif
+
+/**
+ * m54xx_fec_interrupt_rx_handler_fec0
+ *
+ * @brief This is the DMA interrupt handler using for the FEC0
+ * reception.
+ *
+ */
+void m54xx_fec_interrupt_fec_rx_handler_fec0(void)
+{
+ m54xx_fec_interrupt_fec_rx_handler(m54xx_fec_dev[0]);
+}
+
+#ifdef M54XX_FEC2
+/**
+ * m54xx_fec_interrupt_rx_handler_fec1
+ *
+ * @brief This is the DMA interrupt handler using for the FEC1
+ * reception.
+ *
+ */
+void m54xx_fec_interrupt_fec_rx_handler_fec1(void)
+{
+ m54xx_fec_interrupt_fec_rx_handler(m54xx_fec_dev[1]);
+}
+
+#endif
+
+#ifndef MODULE
+/**
+ * m54xx_fec_mac_setup0
+ *
+ * @brief This function sets the MAC address of FEC0 from command line
+ *
+ */
+int __init m54xx_fec_mac_setup0(char *s)
+{
+ if (!s || !*s)
+ return 1;
+
+ if (m54xx_fec_str_to_mac(s, m54xx_fec_mac_addr_fec0))
+ printk(KERN_ERR "The MAC address of FEC0 "
+ "cannot be set from command line");
+ return 1;
+}
+
+#ifdef M54XX_FEC2
+
+/**
+ * m54xx_fec_mac_setup1
+ *
+ * @brief This function sets the MAC address of FEC1 from command line
+ *
+ */
+int __init m54xx_fec_mac_setup1(char *s)
+{
+ if (!s || !*s)
+ return 1;
+
+ if (m54xx_fec_str_to_mac(s, m54xx_fec_mac_addr_fec1))
+ printk(KERN_ERR "The MAC address of FEC1 "
+ "cannot be set from command line\n");
+ return 1;
+}
+#endif
+
+/**
+ * m54xx_fec_str_to_mac
+ *
+ * @brief This function interprets the character string into MAC addr
+ *
+ */
+int m54xx_fec_str_to_mac(char *str_mac, unsigned char* addr)
+{
+ unsigned long val;
+ char c;
+ unsigned long octet[6], *octetptr = octet;
+ int i;
+
+again:
+ val = 0;
+ while ((c = *str_mac) != '\0') {
+ if ((c >= '0') && (c <= '9')) {
+ val = (val * 16) + (c - '0');
+ str_mac++;
+ continue;
+ } else if (((c >= 'a') && (c <= 'f'))
+ || ((c >= 'A') && (c <= 'F'))) {
+ val = (val << 4) +
+ (c + 10 -
+ (((c >= 'a') && (c <= 'f')) ? 'a' : 'A'));
+ str_mac++;
+ continue;
+ }
+ break;
+ }
+ if (*str_mac == ':') {
+ *octetptr++ = val, str_mac++;
+ if (octetptr >= octet + 6)
+ return 1;
+ goto again;
+ }
+
+ /* Check for trailing characters */
+ if (*str_mac && !(*str_mac == ' '))
+ return 1;
+
+ *octetptr++ = val;
+
+ if ((octetptr - octet) == 6) {
+ for (i = 0; i <= 6; i++)
+ addr[i] = octet[i];
+ } else
+ return 1;
+
+ return 0;
+}
+#endif
diff --git a/drivers/net/ethernet/freescale/fec_m54xx.h b/drivers/net/ethernet/freescale/fec_m54xx.h
new file mode 100644
index 0000000..8a1455f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fec_m54xx.h
@@ -0,0 +1,237 @@
+#ifndef _FEC_M54XX_H_
+#define _FEC_M54XX_H_
+
+#define M54XX_FEC_BASE_ADDR_FEC0 ((unsigned int)MCF_MBAR + 0x9000)
+#define M54XX_FEC_BASE_ADDR_FEC1 ((unsigned int)MCF_MBAR + 0x9800)
+
+#define M54XX_ISC_FEC1 (38)
+#define M54XX_ISC_FEC0 (39)
+
+#define M54XX_FEC_FECI2CIRQ (0xFFC0)
+#define M54XX_FEC_GPIO_PAR_FECI2CIRQ \
+ (*(volatile unsigned short *)((unsigned int)MCF_MBAR + 0xA44))
+
+#define M54XX_FEC_ECR_DISABLE (0x00000000)
+
+#define M54XX_FEC_ECR(x) \
+ (*(volatile unsigned int *)(x + 0x024))
+#define M54XX_FEC_EIR(x) \
+ (*(volatile unsigned int *)(x + 0x004))
+#define M54XX_FEC_PALR(x) \
+ (*(volatile unsigned int *)(x + 0x0E4))
+#define M54XX_FEC_PAUR(x) \
+ (*(volatile unsigned int *)(x + 0x0E8))
+#define M54XX_FEC_IALR(x) \
+ (*(volatile unsigned int *)(x + 0x11C))
+#define M54XX_FEC_IAUR(x) \
+ (*(volatile unsigned int *)(x + 0x118))
+#define M54XX_FEC_GALR(x) \
+ (*(volatile unsigned int *)(x + 0x124))
+#define M54XX_FEC_GAUR(x) \
+ (*(volatile unsigned int *)(x + 0x120))
+#define M54XX_FEC_RCR(x) \
+ (*(volatile unsigned int *)(x + 0x084))
+#define M54XX_FEC_FECRFCR(x) \
+ (*(volatile unsigned int *)(x + 0x18C))
+#define M54XX_FEC_FECRFAR(x) \
+ (*(volatile unsigned int *)(x + 0x198))
+#define M54XX_FEC_FECTFCR(x) \
+ (*(volatile unsigned int *)(x + 0x1AC))
+#define M54XX_FEC_FECTFAR(x) \
+ (*(volatile unsigned int *)(x + 0x1B8))
+#define M54XX_FEC_FECTFWR(x) \
+ (*(volatile unsigned int *)(x + 0x144))
+#define M54XX_FEC_CTCWR(x) \
+ (*(volatile unsigned int *)(x + 0x1C8))
+#define M54XX_FEC_EIMR(x) \
+ (*(volatile unsigned int *)(x + 0x008))
+#define M54XX_FEC_TCR(x) \
+ (*(volatile unsigned int *)(x + 0x0C4))
+#define M54XX_FEC_MIBC(x) \
+ (*(volatile unsigned int *)(x + 0x064))
+#define M54XX_FEC_MSCR(x) \
+ (*(volatile unsigned int *)(x + 0x044))
+#define M54XX_FEC_FECTFDR(x) \
+ (*(volatile unsigned int *)(x + 0x1A4))
+#define M54XX_FEC_FECRFDR(x) \
+ (*(volatile unsigned int *)(x + 0x184))
+#define M54XX_FEC_FECTFSR(x) \
+ (*(volatile unsigned int *)(x + 0x1A8))
+#define M54XX_FEC_FECRFSR(x) \
+ (*(volatile unsigned int *)(x + 0x188))
+#define M54XX_FECSTAT_RMON_R_PACKETS(x) \
+ (*(volatile unsigned int *)(x + 0x284))
+#define M54XX_FECSTAT_RMON_T_PACKETS(x) \
+ (*(volatile unsigned int *)(x + 0x204))
+#define M54XX_FECSTAT_RMON_R_OCTETS(x) \
+ (*(volatile unsigned int *)(x + 0x2C4))
+#define M54XX_FECSTAT_RMON_T_OCTETS(x) \
+ (*(volatile unsigned int *)(x + 0x244))
+#define M54XX_FECSTAT_RMON_R_UNDERSIZE(x) \
+ (*(volatile unsigned int *)(x + 0x294))
+#define M54XX_FECSTAT_RMON_R_OVERSIZE(x) \
+ (*(volatile unsigned int *)(x + 0x298))
+#define M54XX_FECSTAT_RMON_R_FRAG(x) \
+ (*(volatile unsigned int *)(x + 0x29C))
+#define M54XX_FECSTAT_RMON_R_JAB(x) \
+ (*(volatile unsigned int *)(x + 0x2A0))
+#define M54XX_FECSTAT_RMON_R_MC_PKT(x) \
+ (*(volatile unsigned int *)(x + 0x28C))
+#define M54XX_FECSTAT_RMON_T_COL(x) \
+ (*(volatile unsigned int *)(x + 0x224))
+#define M54XX_FECSTAT_IEEE_R_ALIGN(x) \
+ (*(volatile unsigned int *)(x + 0x2D4))
+#define M54XX_FECSTAT_IEEE_R_CRC(x) \
+ (*(volatile unsigned int *)(x + 0x2D0))
+#define M54XX_FECSTAT_IEEE_R_MACERR(x) \
+ (*(volatile unsigned int *)(x + 0x2D8))
+#define M54XX_FECSTAT_IEEE_T_CSERR(x) \
+ (*(volatile unsigned int *)(x + 0x268))
+#define M54XX_FECSTAT_IEEE_T_MACERR(x) \
+ (*(volatile unsigned int *)(x + 0x264))
+#define M54XX_FECSTAT_IEEE_T_LCOL(x) \
+ (*(volatile unsigned int *)(x + 0x25C))
+#define M54XX_FECSTAT_IEEE_R_OCTETS_OK(x) \
+ (*(volatile unsigned int *)(x + 0x2E0))
+#define M54XX_FECSTAT_IEEE_T_OCTETS_OK(x) \
+ (*(volatile unsigned int *)(x + 0x274))
+#define M54XX_FECSTAT_IEEE_R_DROP(x) \
+ (*(volatile unsigned int *)(x + 0x2C8))
+#define M54XX_FECSTAT_IEEE_T_DROP(x) \
+ (*(volatile unsigned int *)(x + 0x248))
+#define M54XX_FECSTAT_IEEE_R_FRAME_OK(x) \
+ (*(volatile unsigned int *)(x + 0x2CC))
+#define M54XX_FECSTAT_IEEE_T_FRAME_OK(x) \
+ (*(volatile unsigned int *)(x + 0x24C))
+#define M54XX_FEC_MMFR(x) \
+ (*(volatile unsigned int *)(x + 0x040))
+#define M54XX_FEC_FECFRST(x) \
+ (*(volatile unsigned int *)(x + 0x1C4))
+
+#define M54XX_FEC_MAX_FRM_SIZE (1518)
+#define M54XX_FEC_MAXBUF_SIZE (1520)
+
+/* Register values */
+#define M54XX_FEC_ECR_RESET (0x00000001)
+#define M54XX_FEC_EIR_CLEAR (0xFFFFFFFF)
+#define M54XX_FEC_EIR_RL (0x00100000)
+#define M54XX_FEC_EIR_HBERR (0x80000000)
+#define M54XX_FEC_EIR_BABR (0x40000000)
+/* babbling receive error */
+#define M54XX_FEC_EIR_BABT (0x20000000)
+/* babbling transmit error */
+#define M54XX_FEC_EIR_TXF (0x08000000)
+/* transmit frame interrupt */
+#define M54XX_FEC_EIR_MII (0x00800000)
+/* MII interrupt */
+#define M54XX_FEC_EIR_LC (0x00200000)
+/* late collision */
+#define M54XX_FEC_EIR_XFUN (0x00080000)
+/* transmit FIFO underrun */
+#define M54XX_FEC_EIR_XFERR (0x00040000)
+/* transmit FIFO error */
+#define M54XX_FEC_EIR_RFERR (0x00020000)
+/* receive FIFO error */
+#define M54XX_FEC_RCR_MAX_FRM_SIZE (M54XX_FEC_MAX_FRM_SIZE << 16)
+#define M54XX_FEC_RCR_MII (0x00000004)
+#define M54XX_FEC_FECRFCR_FAE (0x00400000)
+/* frame accept error */
+#define M54XX_FEC_FECRFCR_RXW (0x00200000)
+/* receive wait condition */
+#define M54XX_FEC_FECRFCR_UF (0x00100000)
+/* receive FIFO underflow */
+#define M54XX_FEC_FECRFCR_FRM (0x08000000)
+#define M54XX_FEC_FECRFCR_GR (0x7 << 24)
+
+#define M54XX_FEC_EIMR_DISABLE (0x00000000)
+
+#define M54XX_FEC_FECRFAR_ALARM (0x300)
+#define M54XX_FEC_FECTFCR_FRM (0x08000000)
+#define M54XX_FEC_FECTFCR_GR (0x7 << 24)
+#define M54XX_FEC_FECTFCR_FAE (0x00400000)
+/* frame accept error */
+#define M54XX_FEC_FECTFCR_TXW (0x00040000)
+/* transmit wait condition */
+#define M54XX_FEC_FECTFCR_UF (0x00100000)
+/* transmit FIFO underflow */
+#define M54XX_FEC_FECTFCR_OF (0x00080000)
+/* transmit FIFO overflow */
+
+#define M54XX_FEC_FECTFAR_ALARM (0x100)
+#define M54XX_FEC_FECTFWR_XWMRK (0x00000000)
+
+#define M54XX_FEC_FECTFSR_MSK (0xC0B00000)
+#define M54XX_FEC_FECTFSR_TXW (0x40000000)
+/* transmit wait condition */
+#define M54XX_FEC_FECTFSR_FAE (0x00800000)
+/* frame accept error */
+#define M54XX_FEC_FECTFSR_UF (0x00200000)
+/* transmit FIFO underflow */
+#define M54XX_FEC_FECTFSR_OF (0x00100000)
+/* transmit FIFO overflow */
+
+#define M54XX_FEC_FECRFSR_MSK (0x80F00000)
+#define M54XX_FEC_FECRFSR_FAE (0x00800000)
+/* frame accept error */
+#define M54XX_FEC_FECRFSR_RXW (0x00400000)
+/* receive wait condition */
+#define M54XX_FEC_FECRFSR_UF (0x00200000)
+/* receive FIFO underflow */
+
+#define M54XX_FEC_CTCWR_TFCW_CRC (0x03000000)
+#define M54XX_FEC_TCR_FDEN (0x00000004)
+#define M54XX_FEC_TCR_HBC (0x00000002)
+#define M54XX_FEC_RCR_DRT (0x00000002)
+#define M54XX_FEC_EIMR_MASK (M54XX_FEC_EIR_RL | M54XX_FEC_EIR_HBERR)
+#define M54XX_FEC_ECR_ETHEREN (0x00000002)
+#define M54XX_FEC_FECTFCR_MSK (0x00FC0000)
+#define M54XX_FEC_FECRFCR_MSK (0x00F80000)
+#define M54XX_FEC_EIR_GRA (0x10000000)
+#define M54XX_FEC_TCR_GTS (0x00000001)
+#define M54XX_FEC_MIBC_ENABLE (0x00000000)
+#define M54XX_FEC_MIB_LEN (228)
+#define M54XX_FEC_PHY_ADDR (0x01)
+
+#define M54XX_FEC_RX_DMA_PRI (6)
+#define M54XX_FEC_TX_DMA_PRI (6)
+
+#define M54XX_FEC_TX_BUF_NUMBER (8)
+#define M54XX_FEC_RX_BUF_NUMBER (64)
+
+#define M54XX_FEC_TX_INDEX_MASK (0x7)
+#define M54XX_FEC_RX_INDEX_MASK (0x3f)
+
+#define M54XX_FEC_RX_DESC_FEC0 SYS_SRAM_FEC_START
+#define M54XX_FEC_TX_DESC_FEC0 \
+ (M54XX_FEC_RX_DESC_FEC0 + M54XX_FEC_RX_BUF_NUMBER * sizeof(MCD_bufDescFec))
+
+#define M54XX_FEC_RX_DESC_FEC1 \
+ (SYS_SRAM_FEC_START + SYS_SRAM_FEC_SIZE/2)
+#define M54XX_FEC_TX_DESC_FEC1 \
+ (M54XX_FEC_RX_DESC_FEC1 + M54XX_FEC_RX_BUF_NUMBER * sizeof(MCD_bufDescFec))
+
+#define M54XX_FEC_EIR_MII (0x00800000)
+#define M54XX_FEC_MMFR_READ (0x60020000)
+#define M54XX_FEC_MMFR_WRITE (0x50020000)
+
+#define M54XX_FEC_FLAGS_RX (0x00000001)
+
+#define M54XX_FEC_CRCPOL (0xEDB88320)
+
+#define M54XX_FEC_MII_TIMEOUT (2)
+#define M54XX_FEC_GR_TIMEOUT (1)
+#define M54XX_FEC_TX_TIMEOUT (1)
+#define M54XX_FEC_RX_TIMEOUT (1)
+
+#define M54XX_FEC_SW_RST 0x2000000
+#define M54XX_FEC_RST_CTL 0x1000000
+
+int m54xx_fec_read_mii(unsigned int base_addr, unsigned int pa, unsigned int ra,
+ unsigned int *data);
+int m54xx_fec_write_mii(unsigned int base_addr, unsigned int pa, unsigned int ra,
+ unsigned int data);
+
+#define M54XX_FEC_MII_SPEED \
+ ((MCF_CLK / 2) / ((2500000 / 2) * 2))
+
+#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] Add support to broadcom 5222 PHY
[not found] <1345551531-15348-1-git-send-email-stany.marcel@novasys-ingenierie.com>
2012-08-21 12:18 ` [PATCH 3/3] Add support to M54xx DMA FEC Driver Stany MARCEL
@ 2012-08-23 10:47 ` Geert Uytterhoeven
[not found] ` <CAMuHMdUo5UPLtUhf6_GafMj_kEnM25k+XYszdwsGwkGyCUC6zw@mail.gmail.com>
[not found] ` <1345551531-15348-3-git-send-email-stany.marcel@novasys-ingenierie.com>
3 siblings, 0 replies; 14+ messages in thread
From: Geert Uytterhoeven @ 2012-08-23 10:47 UTC (permalink / raw)
To: Stany MARCEL; +Cc: linux-m68k, linux-kernel
On Tue, Aug 21, 2012 at 2:18 PM, Stany MARCEL
<stany.marcel@novasys-ingenierie.com> wrote:
> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
> ---
>
> This driver is an adaption of the one given by freescale for kernel 2.6.25.
>
> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
> 2 FEC configured with shared phy
>
> drivers/net/phy/Kconfig | 7 +-
> drivers/net/phy/Makefile | 1 +
> drivers/net/phy/broadcom522x.c | 171 ++++++++++++++++++++++++++++++++++++++++
This patch and "[PATCH 3/3] Add support to M54xx DMA FEC Driver" need to go
through the netdev tree, or collect acks there.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] Add support to broadcom 5222 PHY
[not found] ` <CAMuHMdUo5UPLtUhf6_GafMj_kEnM25k+XYszdwsGwkGyCUC6zw@mail.gmail.com>
@ 2012-08-23 12:34 ` Greg Ungerer
2012-08-23 15:25 ` Stany MARCEL
2012-08-23 15:21 ` Stany MARCEL
[not found] ` <CA+mBkFXnOB9hPoJVf6c92UuemqtLJwc2KW-G-ja6cG8VqLPZdw@mail.gmail.com>
2 siblings, 1 reply; 14+ messages in thread
From: Greg Ungerer @ 2012-08-23 12:34 UTC (permalink / raw)
To: Stany MARCEL; +Cc: Geert Uytterhoeven, linux-m68k, linux-kernel
Hi Stany,
On 08/23/2012 08:47 PM, Geert Uytterhoeven wrote:
> On Tue, Aug 21, 2012 at 2:18 PM, Stany MARCEL
> <stany.marcel@novasys-ingenierie.com> wrote:
>> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
>> ---
>>
>> This driver is an adaption of the one given by freescale for kernel 2.6.25.
>>
>> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
>> 2 FEC configured with shared phy
>>
>> drivers/net/phy/Kconfig | 7 +-
>> drivers/net/phy/Makefile | 1 +
>> drivers/net/phy/broadcom522x.c | 171 ++++++++++++++++++++++++++++++++++++++++
>
> This patch and "[PATCH 3/3] Add support to M54xx DMA FEC Driver" need to go
> through the netdev tree, or collect acks there.
And patch 2/3 never made it to the linux-m68k list. Though I can see
that it made it onto the linux-kernel list.
I would suggest running them through checkpatch, there is a number of
formating and the like issues that need cleaning up.
Also you will want to break up patch 2. It is a bit large to be reviewed
the way it is.
Regards
Greg
> Gr{oetje,eeting}s,
>
> Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
> -- Linus Torvalds
> --
> To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg@snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close, FAX: +61 7 3891 3630
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] Add support to broadcom 5222 PHY
[not found] ` <CAMuHMdUo5UPLtUhf6_GafMj_kEnM25k+XYszdwsGwkGyCUC6zw@mail.gmail.com>
2012-08-23 12:34 ` Greg Ungerer
@ 2012-08-23 15:21 ` Stany MARCEL
[not found] ` <CA+mBkFXnOB9hPoJVf6c92UuemqtLJwc2KW-G-ja6cG8VqLPZdw@mail.gmail.com>
2 siblings, 0 replies; 14+ messages in thread
From: Stany MARCEL @ 2012-08-23 15:21 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linux-m68k, linux-kernel
On Thu, Aug 23, 2012 at 12:47 PM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Tue, Aug 21, 2012 at 2:18 PM, Stany MARCEL
> <stany.marcel@novasys-ingenierie.com> wrote:
>> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
>> ---
>>
>> This driver is an adaption of the one given by freescale for kernel 2.6.25.
>>
>> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
>> 2 FEC configured with shared phy
>>
>> drivers/net/phy/Kconfig | 7 +-
>> drivers/net/phy/Makefile | 1 +
>> drivers/net/phy/broadcom522x.c | 171 ++++++++++++++++++++++++++++++++++++++++
>
> This patch and "[PATCH 3/3] Add support to M54xx DMA FEC Driver" need to go
> through the netdev tree, or collect acks there.
>
> Gr{oetje,eeting}s,
>
> Geert
>
Hello Geert,
Please, what is the good process to follow as patch 3 depends on patch 1 ?
Submit 1 to m68k tree and wait for it to be pulled on mainline then
push 3 to netdev tree ?
Regards,
Stany
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] Add support to broadcom 5222 PHY
2012-08-23 12:34 ` Greg Ungerer
@ 2012-08-23 15:25 ` Stany MARCEL
0 siblings, 0 replies; 14+ messages in thread
From: Stany MARCEL @ 2012-08-23 15:25 UTC (permalink / raw)
To: Greg Ungerer; +Cc: Geert Uytterhoeven, linux-m68k, linux-kernel
On Thu, Aug 23, 2012 at 2:34 PM, Greg Ungerer <gerg@snapgear.com> wrote:
> Hi Stany,
>
>
> On 08/23/2012 08:47 PM, Geert Uytterhoeven wrote:
>>
>> On Tue, Aug 21, 2012 at 2:18 PM, Stany MARCEL
>> <stany.marcel@novasys-ingenierie.com> wrote:
>>>
>>> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
>>> ---
>>>
>>> This driver is an adaption of the one given by freescale for kernel
>>> 2.6.25.
>>>
>>> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
>>> 2 FEC configured with shared phy
>>>
>>> drivers/net/phy/Kconfig | 7 +-
>>> drivers/net/phy/Makefile | 1 +
>>> drivers/net/phy/broadcom522x.c | 171
>>> ++++++++++++++++++++++++++++++++++++++++
>>
>>
>> This patch and "[PATCH 3/3] Add support to M54xx DMA FEC Driver" need to
>> go
>> through the netdev tree, or collect acks there.
>
>
> And patch 2/3 never made it to the linux-m68k list. Though I can see
> that it made it onto the linux-kernel list.
>
> I would suggest running them through checkpatch, there is a number of
> formating and the like issues that need cleaning up.
>
> Also you will want to break up patch 2. It is a bit large to be reviewed
> the way it is.
>
> Regards
> Greg
Hi Greg
I will rework my patches and resend them.
Regards,
Stany
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] Add support to broadcom 5222 PHY
[not found] ` <CA+mBkFXnOB9hPoJVf6c92UuemqtLJwc2KW-G-ja6cG8VqLPZdw@mail.gmail.com>
@ 2012-08-23 15:37 ` Geert Uytterhoeven
2012-08-23 16:02 ` Philippe De Muyter
1 sibling, 0 replies; 14+ messages in thread
From: Geert Uytterhoeven @ 2012-08-23 15:37 UTC (permalink / raw)
To: Stany MARCEL; +Cc: linux-m68k, linux-kernel
Hi Stany,
On Thu, Aug 23, 2012 at 5:21 PM, Stany MARCEL
<stany.marcel@novasys-ingenierie.com> wrote:
> On Thu, Aug 23, 2012 at 12:47 PM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
>> On Tue, Aug 21, 2012 at 2:18 PM, Stany MARCEL
>> <stany.marcel@novasys-ingenierie.com> wrote:
>>> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
>>> ---
>>>
>>> This driver is an adaption of the one given by freescale for kernel 2.6.25.
>>>
>>> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
>>> 2 FEC configured with shared phy
>>>
>>> drivers/net/phy/Kconfig | 7 +-
>>> drivers/net/phy/Makefile | 1 +
>>> drivers/net/phy/broadcom522x.c | 171 ++++++++++++++++++++++++++++++++++++++++
>>
>> This patch and "[PATCH 3/3] Add support to M54xx DMA FEC Driver" need to go
>> through the netdev tree, or collect acks there.
>
> Please, what is the good process to follow as patch 3 depends on patch 1 ?
>
> Submit 1 to m68k tree and wait for it to be pulled on mainline then
> push 3 to netdev tree ?
Just make sure to add netdev@vger.kernel.org to the CC list, and mention in the
introductory email that you want to collect acks from the netdev maintainer
for patches 1 and 3. After that all 3 patches can go via Greg's m68knommu
tree (for Coldfire).
Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] Add support to broadcom 5222 PHY
[not found] ` <CA+mBkFXnOB9hPoJVf6c92UuemqtLJwc2KW-G-ja6cG8VqLPZdw@mail.gmail.com>
2012-08-23 15:37 ` Geert Uytterhoeven
@ 2012-08-23 16:02 ` Philippe De Muyter
2012-08-23 22:01 ` Stany MARCEL
1 sibling, 1 reply; 14+ messages in thread
From: Philippe De Muyter @ 2012-08-23 16:02 UTC (permalink / raw)
To: Stany MARCEL; +Cc: Geert Uytterhoeven, linux-m68k, linux-kernel
On Thu, Aug 23, 2012 at 05:21:23PM +0200, Stany MARCEL wrote:
> On Thu, Aug 23, 2012 at 12:47 PM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
> > On Tue, Aug 21, 2012 at 2:18 PM, Stany MARCEL
> > <stany.marcel@novasys-ingenierie.com> wrote:
> >> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
> >> ---
> >>
> >> This driver is an adaption of the one given by freescale for kernel 2.6.25.
> >>
> >> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
> >> 2 FEC configured with shared phy
> >>
> >> drivers/net/phy/Kconfig | 7 +-
> >> drivers/net/phy/Makefile | 1 +
> >> drivers/net/phy/broadcom522x.c | 171 ++++++++++++++++++++++++++++++++++++++++
> >
> > This patch and "[PATCH 3/3] Add support to M54xx DMA FEC Driver" need to go
> > through the netdev tree, or collect acks there.
> >
> > Gr{oetje,eeting}s,
> >
> > Geert
> >
>
> Hello Geert,
>
> Please, what is the good process to follow as patch 3 depends on patch 1 ?
Actually, IMHO patch 3 does not depend on patch 1, and I even think that
patch 1 is not needed, except to get a message with "BCM5222" instead
of "Generic PHY" in the kernel log.
AFAIK the phy interface is standardized.
Philippe
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] Add support to broadcom 5222 PHY
2012-08-23 16:02 ` Philippe De Muyter
@ 2012-08-23 22:01 ` Stany MARCEL
0 siblings, 0 replies; 14+ messages in thread
From: Stany MARCEL @ 2012-08-23 22:01 UTC (permalink / raw)
To: Philippe De Muyter; +Cc: Geert Uytterhoeven, linux-m68k, linux-kernel
On Thu, Aug 23, 2012 at 6:02 PM, Philippe De Muyter <phdm@macqel.be> wrote:
> On Thu, Aug 23, 2012 at 05:21:23PM +0200, Stany MARCEL wrote:
>> On Thu, Aug 23, 2012 at 12:47 PM, Geert Uytterhoeven
>> <geert@linux-m68k.org> wrote:
>> > On Tue, Aug 21, 2012 at 2:18 PM, Stany MARCEL
>> > <stany.marcel@novasys-ingenierie.com> wrote:
>> >> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
>> >> ---
>> >>
>> >> This driver is an adaption of the one given by freescale for kernel 2.6.25.
>> >>
>> >> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
>> >> 2 FEC configured with shared phy
>> >>
>> >> drivers/net/phy/Kconfig | 7 +-
>> >> drivers/net/phy/Makefile | 1 +
>> >> drivers/net/phy/broadcom522x.c | 171 ++++++++++++++++++++++++++++++++++++++++
>> >
>> > This patch and "[PATCH 3/3] Add support to M54xx DMA FEC Driver" need to go
>> > through the netdev tree, or collect acks there.
>> >
>> > Gr{oetje,eeting}s,
>> >
>> > Geert
>> >
>>
>> Hello Geert,
>>
>> Please, what is the good process to follow as patch 3 depends on patch 1 ?
>
> Actually, IMHO patch 3 does not depend on patch 1, and I even think that
> patch 1 is not needed, except to get a message with "BCM5222" instead
> of "Generic PHY" in the kernel log.
>
> AFAIK the phy interface is standardized.
>
> Philippe
I meant patch 3 depends on patch 2 (multi channel dma api)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] Add support to M54xx DMA FEC Driver
[not found] ` <1345551531-15348-3-git-send-email-stany.marcel@novasys-ingenierie.com>
@ 2012-08-28 5:51 ` Greg Ungerer
2012-09-05 9:14 ` Philippe De Muyter
0 siblings, 1 reply; 14+ messages in thread
From: Greg Ungerer @ 2012-08-28 5:51 UTC (permalink / raw)
To: Stany MARCEL; +Cc: linux-m68k, geert, linux-kernel
Hi Stany,
I haven't looked over it in detail, but a few little things anyway.
On 21/08/12 22:18, Stany MARCEL wrote:
> Signed-off-by: Stany MARCEL <stany.marcel@novasys-ingenierie.com>
> ---
>
> This driver is an adaption of the one given by freescale for kernel 2.6.25.
>
> Tested with kernel 3.4.8 with arch/m68k backported from linux-m68k head
> 2 FEC configured with shared phy
I would put your signed-off-by line here (with the --- separator).
I would like to see the above text in the commit message.
> drivers/net/ethernet/freescale/Kconfig | 27 +-
> drivers/net/ethernet/freescale/Makefile | 1 +
> drivers/net/ethernet/freescale/fec_m54xx.c | 1589 ++++++++++++++++++++++++++++
> drivers/net/ethernet/freescale/fec_m54xx.h | 237 +++++
> 4 files changed, 1853 insertions(+), 1 deletion(-)
> create mode 100644 drivers/net/ethernet/freescale/fec_m54xx.c
> create mode 100644 drivers/net/ethernet/freescale/fec_m54xx.h
>
> diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
> index 3574e14..cef3c62 100644
> --- a/drivers/net/ethernet/freescale/Kconfig
> +++ b/drivers/net/ethernet/freescale/Kconfig
> @@ -7,7 +7,8 @@ config NET_VENDOR_FREESCALE
> default y
> depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
> M523x || M527x || M5272 || M528x || M520x || M532x || \
> - ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM)
> + M54xx || ARCH_MXC || ARCH_MXS || \
> + (PPC_MPC52xx && PPC_BESTCOMM)
> ---help---
> If you have a network (Ethernet) card belonging to this class, say Y
> and read the Ethernet-HOWTO, available from
> @@ -53,6 +54,30 @@ config FEC_MPC52xx_MDIO
> If not sure, enable.
> If compiled as module, it will be called fec_mpc52xx_phy.
>
> +config FEC_M54xx
> + tristate "MCF547x/MCF548x Fast Ethernet Controller support"
> + depends on M54xx
> + select MCD_DMA
This should select PHYLIB too, since this driver needs it.
> + help
> + The MCF547x and MCF548x have a built-in Fast Ethernet Controller.
> + Saying Y here will include support for this device in the kernel.
> +
> + To compile this driver as a module, choose M here: the module
> + will be called fecm.
> +
> +config FEC_M54xx_ENABLE_FEC2
> + bool "Enable the second FEC"
> + depends on FEC_M54xx
> + help
> + This enables the second FEC on the 547x/548x. If you want to use
> + it, say Y.
We used to have this on the older FEC driver, but it is all removed
now. I don't think we want this as a config option.
Regards
Greg
> +config FEC_M54xx_SHARED_PHY
> + bool "Shared PHY interface(on some ColdFire designs)"
> + depends on FEC_M54xx_ENABLE_FEC2
> + help
> + Say Y here if both PHYs are controlled via a single channel.
> +
> source "drivers/net/ethernet/freescale/fs_enet/Kconfig"
>
> config FSL_PQ_MDIO
> diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
> index 1752488..64dba64 100644
> --- a/drivers/net/ethernet/freescale/Makefile
> +++ b/drivers/net/ethernet/freescale/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
> ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
> obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
> endif
> +obj-$(CONFIG_FEC_M54xx) += fec_m54xx.o
> obj-$(CONFIG_FS_ENET) += fs_enet/
> obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
> obj-$(CONFIG_GIANFAR) += gianfar_driver.o
--
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg@snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close FAX: +61 7 3217 5323
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] Add support to M54xx DMA FEC Driver
2012-08-28 5:51 ` [PATCH 3/3] Add support to M54xx DMA FEC Driver Greg Ungerer
@ 2012-09-05 9:14 ` Philippe De Muyter
2012-09-05 10:48 ` RE : " Stany MARCEL
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Philippe De Muyter @ 2012-09-05 9:14 UTC (permalink / raw)
To: Greg Ungerer; +Cc: Stany MARCEL, linux-m68k, geert, linux-kernel
Hi Stany & Greg
Seeing that I was not the only one wanting to have the m54xx fec dma
driver merged in, and hoping to compare Stany's version to mine,
I have rebased (step by step) my patch from v2.38 to v3.6rc2.
The driver still works and perhaps even better due to some fixes
in other m68k area.
Unfortunately I have not being able to compare it yet fully with Stany's
version because Stany's patch 2/2 did not apply (using `git am') to v3.5
or v3.6rc2.
I have checked my patch using a recent version of checkpatch.pl (not the
v3.5 version, because v3.5 version of checkpatch.pl fails with :
Nested quantifiers in regex; marked by <-- HERE in m/(\((?:[^\(\)]++ <-- HERE |(
?-1))*\))/ at scripts/checkpatch.pl line 340.))
and I am now at :
464 WARNING: line over 80 characters
90 WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
Many "volatile" warnings are about such definitions :
#define FEC_FECFRST(x) (*(volatile unsigned int *)(x + 0x1C4))
which are afterwards used with
+ FEC_FECFRST(base_addr) |= FEC_SW_RST;
+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
+ FEC_FECFRST(base_addr) |= FEC_SW_RST;
+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
+ FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
Any advice about those ones ?
while many "80 characters" ones are about :
#4014: FILE: arch/m68k/platform/coldfire/MCD_tasks.c:2406:
+ 0x6000000b, /* 0098(:1560): DRD2A: EU0=0 EU1=0 EU2=0 EU3=11 EXT ini
t=0 WS=0 RS=0 */
I would like to keep those lines intact because the comment seems to actually
be the assembler source of the hex value at left, which seems to be a
microcode, and it makes sense to me to keep that on one line. What do
you think about that ?
I did not include the current status of the patch because of its size
(I did not separate the dma part of the ethernet driver part because
the dma part is useless without the ethernet driver, and linking the
ethernet driver cannot succeed without the dma part), but if you ask,
I'll send it privately.
Best regards
Philippe
--
Philippe De Muyter +32 2 6101532 Macq SA rue de l'Aeronef 2 B-1140 Bruxelles
^ permalink raw reply [flat|nested] 14+ messages in thread
* RE : [PATCH 3/3] Add support to M54xx DMA FEC Driver
2012-09-05 9:14 ` Philippe De Muyter
@ 2012-09-05 10:48 ` Stany MARCEL
2012-09-05 11:25 ` Geert Uytterhoeven
2012-09-05 13:50 ` Greg Ungerer
2 siblings, 0 replies; 14+ messages in thread
From: Stany MARCEL @ 2012-09-05 10:48 UTC (permalink / raw)
To: Philippe De Muyter, Greg Ungerer; +Cc: linux-m68k, geert, linux-kernel
Hi,
I made a lot of cleanup in my patches, I hope to have some time next week to run my ethernet tests on my board test bench.
If no regressions are identified I'll resubmit my patch.
Regards,
Stany
-------- Message d'origine--------
De: Philippe De Muyter [mailto:phdm@macqel.be]
Date: mer. 05/09/2012 11:14
À: Greg Ungerer
Cc: Stany MARCEL; linux-m68k@lists.linux-m68k.org; geert@linux-m68k.org; linux-kernel@vger.kernel.org
Objet : Re: [PATCH 3/3] Add support to M54xx DMA FEC Driver
Hi Stany & Greg
Seeing that I was not the only one wanting to have the m54xx fec dma
driver merged in, and hoping to compare Stany's version to mine,
I have rebased (step by step) my patch from v2.38 to v3.6rc2.
The driver still works and perhaps even better due to some fixes
in other m68k area.
Unfortunately I have not being able to compare it yet fully with Stany's
version because Stany's patch 2/2 did not apply (using `git am') to v3.5
or v3.6rc2.
I have checked my patch using a recent version of checkpatch.pl (not the
v3.5 version, because v3.5 version of checkpatch.pl fails with :
Nested quantifiers in regex; marked by <-- HERE in m/(\((?:[^\(\)]++ <-- HERE |(
?-1))*\))/ at scripts/checkpatch.pl line 340.))
and I am now at :
464 WARNING: line over 80 characters
90 WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
Many "volatile" warnings are about such definitions :
#define FEC_FECFRST(x) (*(volatile unsigned int *)(x + 0x1C4))
which are afterwards used with
+ FEC_FECFRST(base_addr) |= FEC_SW_RST;
+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
+ FEC_FECFRST(base_addr) |= FEC_SW_RST;
+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
+ FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
Any advice about those ones ?
while many "80 characters" ones are about :
#4014: FILE: arch/m68k/platform/coldfire/MCD_tasks.c:2406:
+ 0x6000000b, /* 0098(:1560): DRD2A: EU0=0 EU1=0 EU2=0 EU3=11 EXT ini
t=0 WS=0 RS=0 */
I would like to keep those lines intact because the comment seems to actually
be the assembler source of the hex value at left, which seems to be a
microcode, and it makes sense to me to keep that on one line. What do
you think about that ?
I did not include the current status of the patch because of its size
(I did not separate the dma part of the ethernet driver part because
the dma part is useless without the ethernet driver, and linking the
ethernet driver cannot succeed without the dma part), but if you ask,
I'll send it privately.
Best regards
Philippe
--
Philippe De Muyter +32 2 6101532 Macq SA rue de l'Aeronef 2 B-1140 Bruxelles
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] Add support to M54xx DMA FEC Driver
2012-09-05 9:14 ` Philippe De Muyter
2012-09-05 10:48 ` RE : " Stany MARCEL
@ 2012-09-05 11:25 ` Geert Uytterhoeven
2012-09-05 13:50 ` Greg Ungerer
2 siblings, 0 replies; 14+ messages in thread
From: Geert Uytterhoeven @ 2012-09-05 11:25 UTC (permalink / raw)
To: Philippe De Muyter; +Cc: Greg Ungerer, Stany MARCEL, linux-m68k, linux-kernel
On Wed, Sep 5, 2012 at 11:14 AM, Philippe De Muyter <phdm@macqel.be> wrote:
> and I am now at :
> 464 WARNING: line over 80 characters
> 90 WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
>
> Many "volatile" warnings are about such definitions :
>
> #define FEC_FECFRST(x) (*(volatile unsigned int *)(x + 0x1C4))
> which are afterwards used with
>
> + FEC_FECFRST(base_addr) |= FEC_SW_RST;
> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
> + FEC_FECFRST(base_addr) |= FEC_SW_RST;
> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
> + FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
>
> Any advice about those ones ?
>
> while many "80 characters" ones are about :
> #4014: FILE: arch/m68k/platform/coldfire/MCD_tasks.c:2406:
> + 0x6000000b, /* 0098(:1560): DRD2A: EU0=0 EU1=0 EU2=0 EU3=11 EXT ini
> t=0 WS=0 RS=0 */
>
> I would like to keep those lines intact because the comment seems to actually
> be the assembler source of the hex value at left, which seems to be a
> microcode, and it makes sense to me to keep that on one line. What do
> you think about that ?
Just ignore these 2 warnings (for this particular case).
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] Add support to M54xx DMA FEC Driver
2012-09-05 9:14 ` Philippe De Muyter
2012-09-05 10:48 ` RE : " Stany MARCEL
2012-09-05 11:25 ` Geert Uytterhoeven
@ 2012-09-05 13:50 ` Greg Ungerer
2012-09-05 22:48 ` Greg Ungerer
2 siblings, 1 reply; 14+ messages in thread
From: Greg Ungerer @ 2012-09-05 13:50 UTC (permalink / raw)
To: Philippe De Muyter; +Cc: Stany MARCEL, linux-m68k, geert
Hi Philippe,
On 09/05/2012 07:14 PM, Philippe De Muyter wrote:
> Seeing that I was not the only one wanting to have the m54xx fec dma
> driver merged in, and hoping to compare Stany's version to mine,
> I have rebased (step by step) my patch from v2.38 to v3.6rc2.
> The driver still works and perhaps even better due to some fixes
> in other m68k area.
>
> Unfortunately I have not being able to compare it yet fully with Stany's
> version because Stany's patch 2/2 did not apply (using `git am') to v3.5
> or v3.6rc2.
>
> I have checked my patch using a recent version of checkpatch.pl (not the
> v3.5 version, because v3.5 version of checkpatch.pl fails with :
> Nested quantifiers in regex; marked by <-- HERE in m/(\((?:[^\(\)]++ <-- HERE |(
> ?-1))*\))/ at scripts/checkpatch.pl line 340.))
>
> and I am now at :
> 464 WARNING: line over 80 characters
> 90 WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
>
> Many "volatile" warnings are about such definitions :
>
> #define FEC_FECFRST(x) (*(volatile unsigned int *)(x + 0x1C4))
> which are afterwards used with
>
> + FEC_FECFRST(base_addr) |= FEC_SW_RST;
> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
> + FEC_FECFRST(base_addr) |= FEC_SW_RST;
> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
> + FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
>
> Any advice about those ones ?
I am glad you brought this one up :-)
I really don't like the macro use for register access like this.
What I much prefer is use of the standard read/write functions for this.
So we have sane definitions for register offsets, eg:
#define FEC_FECFRST 0x1c4
And then use becomes something like:
frst = __raw_readl(base_addr + FEC_FECFRST);
__raw_writel(frst | FEC_SW_RST, base_addr + FEC_FECFRST);
__raw_writel(frst & ~FEC_SW_RST, base_addr + FEC_FECFRST);
...
Obviously you need to be careful of requirement to re-read the
register, I just assumed it wasn't required for this example.
And we can possibly optimize the address, but you get the idea.
The keeps all the use of volatile hidden away like we want.
> while many "80 characters" ones are about :
> #4014: FILE: arch/m68k/platform/coldfire/MCD_tasks.c:2406:
> + 0x6000000b, /* 0098(:1560): DRD2A: EU0=0 EU1=0 EU2=0 EU3=11 EXT ini
> t=0 WS=0 RS=0 */
>
> I would like to keep those lines intact because the comment seems to actually
> be the assembler source of the hex value at left, which seems to be a
> microcode, and it makes sense to me to keep that on one line. What do
> you think about that ?
Like Geert said, it is ok to exceed 80 chars for good reason, and I
think this is a good reason. The other most common one is to not break
up strings - you want them to be easily grepable.
> I did not include the current status of the patch because of its size
> (I did not separate the dma part of the ethernet driver part because
> the dma part is useless without the ethernet driver, and linking the
> ethernet driver cannot succeed without the dma part), but if you ask,
> I'll send it privately.
I understand that it all fits logically together. It is just really
hard for a reviewer to go through a huge single patch. Anything you
can do to break up into smaller pieces will make it much easier to
check over.
If you can send header files first, as separate patches, then C files,
maybe one patch each, and finally the Kconfig and Makefile changes last.
Just a suggestion though. This way you never break the build, even if
the files themselves are not used/built until after the last patch is
applied.
Regards
Greg
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg@snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close, FAX: +61 7 3891 3630
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] Add support to M54xx DMA FEC Driver
2012-09-05 13:50 ` Greg Ungerer
@ 2012-09-05 22:48 ` Greg Ungerer
0 siblings, 0 replies; 14+ messages in thread
From: Greg Ungerer @ 2012-09-05 22:48 UTC (permalink / raw)
To: Philippe De Muyter; +Cc: Stany MARCEL, linux-m68k, geert
On 09/05/2012 11:50 PM, Greg Ungerer wrote:
[snip]
>> I have checked my patch using a recent version of checkpatch.pl (not the
>> v3.5 version, because v3.5 version of checkpatch.pl fails with :
>> Nested quantifiers in regex; marked by <-- HERE in m/(\((?:[^\(\)]++
>> <-- HERE |(
>> ?-1))*\))/ at scripts/checkpatch.pl line 340.))
>>
>> and I am now at :
>> 464 WARNING: line over 80 characters
>> 90 WARNING: Use of volatile is usually wrong: see
>> Documentation/volatile-considered-harmful.txt
>>
>> Many "volatile" warnings are about such definitions :
>>
>> #define FEC_FECFRST(x) (*(volatile unsigned int *)(x +
>> 0x1C4))
>> which are afterwards used with
>>
>> + FEC_FECFRST(base_addr) |= FEC_SW_RST;
>> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
>> + FEC_FECFRST(base_addr) |= FEC_SW_RST;
>> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
>> + FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
>> + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
>>
>> Any advice about those ones ?
>
> I am glad you brought this one up :-)
> I really don't like the macro use for register access like this.
> What I much prefer is use of the standard read/write functions for this.
>
> So we have sane definitions for register offsets, eg:
>
> #define FEC_FECFRST 0x1c4
>
> And then use becomes something like:
>
> frst = __raw_readl(base_addr + FEC_FECFRST);
> __raw_writel(frst | FEC_SW_RST, base_addr + FEC_FECFRST);
> __raw_writel(frst & ~FEC_SW_RST, base_addr + FEC_FECFRST);
> ...
>
> Obviously you need to be careful of requirement to re-read the
> register, I just assumed it wasn't required for this example.
> And we can possibly optimize the address, but you get the idea.
>
> The keeps all the use of volatile hidden away like we want.
I should have been a little more careful here. The use of the
normal versions of the memory access functions is preferred.
So readl() instead of __raw_readl(), etc. Certainly within drivers
we should be using the standard readl/writel/... varients.
There are some situations on some platforms in m68k arch where you
may need to use one of the other variations.
Regards
Greg
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg@snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close, FAX: +61 7 3891 3630
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2012-09-05 22:48 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1345551531-15348-1-git-send-email-stany.marcel@novasys-ingenierie.com>
2012-08-21 12:18 ` [PATCH 3/3] Add support to M54xx DMA FEC Driver Stany MARCEL
2012-08-23 10:47 ` [PATCH 1/3] Add support to broadcom 5222 PHY Geert Uytterhoeven
[not found] ` <CAMuHMdUo5UPLtUhf6_GafMj_kEnM25k+XYszdwsGwkGyCUC6zw@mail.gmail.com>
2012-08-23 12:34 ` Greg Ungerer
2012-08-23 15:25 ` Stany MARCEL
2012-08-23 15:21 ` Stany MARCEL
[not found] ` <CA+mBkFXnOB9hPoJVf6c92UuemqtLJwc2KW-G-ja6cG8VqLPZdw@mail.gmail.com>
2012-08-23 15:37 ` Geert Uytterhoeven
2012-08-23 16:02 ` Philippe De Muyter
2012-08-23 22:01 ` Stany MARCEL
[not found] ` <1345551531-15348-3-git-send-email-stany.marcel@novasys-ingenierie.com>
2012-08-28 5:51 ` [PATCH 3/3] Add support to M54xx DMA FEC Driver Greg Ungerer
2012-09-05 9:14 ` Philippe De Muyter
2012-09-05 10:48 ` RE : " Stany MARCEL
2012-09-05 11:25 ` Geert Uytterhoeven
2012-09-05 13:50 ` Greg Ungerer
2012-09-05 22:48 ` Greg Ungerer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox