Signed-off-by: David Jander <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/Kconfig     |    2 +-
 drivers/net/fec.h                  |   43 ++++++++++++++++++++
 drivers/net/fs_enet/Kconfig        |   22 +++++++++-
 drivers/net/fs_enet/fs_enet-main.c |   76 ++++++++++++++++++++++++++++++------
 drivers/net/fs_enet/fs_enet.h      |   17 +++++---
 drivers/net/fs_enet/mac-fec.c      |   22 +++++++++-
 drivers/net/fs_enet/mii-fec.c      |   10 ++++-
 7 files changed, 167 insertions(+), 25 deletions(-)

diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 87454c5..a96937f 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -288,7 +288,7 @@ config CPM2
 
 config PPC_CPM_NEW_BINDING
        bool
-       depends on CPM1 || CPM2
+       depends on CPM1 || CPM2 || FS_ENET_MPC5121_FEC
        default y
 
 config AXON_RAM
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index 292719d..5c9fe34 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -59,6 +59,7 @@ typedef struct fec {
 } fec_t;
 
 #else
+#if !defined(CONFIG_FS_ENET_MPC5121_FEC)
 
 /*
  *     Define device register set address map.
@@ -97,6 +98,48 @@ typedef struct fec {
        unsigned long   fec_fifo_ram[112];      /* FIFO RAM buffer */
 } fec_t;
 
+#else /* CONFIG_FS_ENET_MPC5121_FEC */
+
+typedef struct fec {
+       u32 fec_reserved0;
+       u32 fec_ievent;         /* Interrupt event reg */
+       u32 fec_imask;          /* Interrupt mask reg */
+       u32 fec_reserved1;
+       u32 fec_r_des_active;   /* Receive descriptor reg */
+       u32 fec_x_des_active;   /* Transmit descriptor reg */
+       u32 fec_reserved2[3];
+       u32 fec_ecntrl;         /* Ethernet control reg */
+       u32 fec_reserved3[6];
+       u32 fec_mii_data;               /* MII manage frame reg */
+       u32 fec_mii_speed;              /* MII speed control reg */
+       u32 fec_reserved4[7];
+       u32 fec_mib_ctrlstat;   /* MIB control/status reg */
+       u32 fec_reserved5[7];
+       u32 fec_r_cntrl;                /* Receive control reg */
+       u32 fec_reserved6[15];
+       u32 fec_x_cntrl;                /* Transmit Control reg */
+       u32 fec_reserved7[7];
+       u32 fec_addr_low;               /* Low 32bits MAC address */
+       u32 fec_addr_high;              /* High 16bits MAC address */
+       u32 fec_opd;            /* Opcode + Pause duration */
+       u32 fec_reserved8[10];
+       u32 fec_hash_table_high;        /* High 32bits hash table */
+       u32 fec_hash_table_low; /* Low 32bits hash table */
+       u32 fec_grp_hash_table_high;/* High 32bits hash table */
+       u32 fec_grp_hash_table_low;     /* Low 32bits hash table */
+       u32 fec_reserved9[7];
+       u32 fec_x_wmrk;         /* FIFO transmit water mark */
+       u32 fec_reserved10;
+       u32 fec_r_bound;                /* FIFO receive bound reg */
+       u32 fec_r_fstart;               /* FIFO receive start reg */
+       u32 fec_reserved11[11];
+       u32 fec_r_des_start;    /* Receive descriptor ring */
+       u32 fec_x_des_start;    /* Transmit descriptor ring */
+       u32 fec_r_buff_size;    /* Maximum receive buff size */
+       u32 fec_dma_control;    /* DMA Endian and other ctrl */
+} fec_t;
+
+#endif /* CONFIG_FS_ENET_MPC5121_FEC */
 #endif /* CONFIG_M5272 */
 
 
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 562ea68..5e2520b 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,9 +1,23 @@
 config FS_ENET
        tristate "Freescale Ethernet Driver"
-       depends on CPM1 || CPM2
+       depends on CPM1 || CPM2 || FS_ENET_MPC5121_FEC
        select MII
        select PHYLIB
 
+config FS_ENET_MPC5121_FEC
+       bool "Freescale MPC512x FEC driver"
+       depends on PPC_MPC512x
+       select FS_ENET
+       select FS_ENET_HAS_FEC
+
+config FS_ENET_TX_ALIGN_WORKAROUND
+       bool "MPC5121 FEC driver TX alignment workaround"
+       depends on FS_ENET_MPC5121_FEC
+       help
+         Workaround for a problem with early Freescale MPC5121 chips.
+         If unsure say 'y'
+       default y
+
 config FS_ENET_HAS_SCC
        bool "Chip has an SCC usable for ethernet"
        depends on FS_ENET && (CPM1 || CPM2)
@@ -16,13 +30,15 @@ config FS_ENET_HAS_FCC
 
 config FS_ENET_HAS_FEC
        bool "Chip has an FEC usable for ethernet"
-       depends on FS_ENET && CPM1
+       depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
        select FS_ENET_MDIO_FEC
        default y
 
+
 config FS_ENET_MDIO_FEC
        tristate "MDIO driver for FEC"
-       depends on FS_ENET && CPM1
+       depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
+
 
 config FS_ENET_MDIO_FCC
        tristate "MDIO driver for FCC"
diff --git a/drivers/net/fs_enet/fs_enet-main.c 
b/drivers/net/fs_enet/fs_enet-main.c
index 31c9693..54f0079 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -592,6 +592,31 @@ void fs_cleanup_bds(struct net_device *dev)
 
 
/**********************************************************************************/
 
+#ifdef CONFIG_FS_ENET_TX_ALIGN_WORKAROUND
+static struct sk_buff *aligntxskb(struct net_device *dev, struct sk_buff *skb)
+{
+       struct sk_buff *skbn;
+       skbn = dev_alloc_skb(ENET_RX_FRSIZE+0x20);
+       if (skbn)
+               skb_align(skbn, 0x20);
+
+       if (!skbn) { 
+           printk(KERN_WARNING DRV_MODULE_NAME
+                   ": %s Memory squeeze, dropping tx packet.\n",
+                   dev->name);
+               dev_kfree_skb_any(skb);
+               return NULL;
+       }
+
+       skb_copy_from_linear_data(skb, skbn->data, skb->len);
+       skb_put(skbn, skb->len);
+       dev_kfree_skb_any(skb);
+       return skbn;
+}
+#else
+#define aligntxskb(skb) skb
+#endif
+
 static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
@@ -600,6 +625,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct 
net_device *dev)
        u16 sc;
        unsigned long flags;
 
+       skb = aligntxskb(dev, skb);
        spin_lock_irqsave(&fep->tx_lock, flags);
 
        /*
@@ -1370,10 +1396,17 @@ static struct of_device_id fs_enet_match[] = {
        },
 #endif
 #ifdef CONFIG_FS_ENET_HAS_FEC
+#ifndef CONFIG_FS_ENET_MPC5121_FEC
        {
                .compatible = "fsl,pq1-fec-enet",
                .data = (void *)&fs_fec_ops,
        },
+#else
+       {
+               .compatible = "fsl,mpc5121-fec",
+               .data = (void *)&fs_fec_ops,
+       },
+#endif
 #endif
        {}
 };
@@ -1431,15 +1464,38 @@ static int fs_enet_remove(struct device *dev)
        return fs_cleanup_instance(dev_get_drvdata(dev));
 }
 
+#ifdef CONFIG_PM
+static int fs_enet_suspend(struct device *dev, pm_message_t state)
+{
+       struct net_device *ndev = dev_get_drvdata(dev);
+
+       if (netif_running(ndev))
+               fs_enet_close(ndev);
+
+       return 0;
+}
+
+static int fs_enet_resume(struct device *dev)
+{
+       struct net_device *ndev = dev_get_drvdata(dev);
+
+       if (netif_running(ndev))
+               fs_enet_open(ndev);
+
+       return 0;
+}
+#else
+#define fs_enet_suspend        NULL
+#define fs_enet_resume NULL
+#endif
+
 static struct device_driver fs_enet_fec_driver = {
        .name           = "fsl-cpm-fec",
        .bus            = &platform_bus_type,
        .probe          = fs_enet_probe,
        .remove         = fs_enet_remove,
-#ifdef CONFIG_PM
-/*     .suspend        = fs_enet_suspend,      TODO */
-/*     .resume         = fs_enet_resume,       TODO */
-#endif
+       .suspend        = fs_enet_suspend,
+       .resume         = fs_enet_resume,
 };
 
 static struct device_driver fs_enet_scc_driver = {
@@ -1447,10 +1503,8 @@ static struct device_driver fs_enet_scc_driver = {
        .bus            = &platform_bus_type,
        .probe          = fs_enet_probe,
        .remove         = fs_enet_remove,
-#ifdef CONFIG_PM
-/*     .suspend        = fs_enet_suspend,      TODO */
-/*     .resume         = fs_enet_resume,       TODO */
-#endif
+       .suspend        = fs_enet_suspend,
+       .resume         = fs_enet_resume,
 };
 
 static struct device_driver fs_enet_fcc_driver = {
@@ -1458,10 +1512,8 @@ static struct device_driver fs_enet_fcc_driver = {
        .bus            = &platform_bus_type,
        .probe          = fs_enet_probe,
        .remove         = fs_enet_remove,
-#ifdef CONFIG_PM
-/*     .suspend        = fs_enet_suspend,      TODO */
-/*     .resume         = fs_enet_resume,       TODO */
-#endif
+       .suspend        = fs_enet_suspend,
+       .resume         = fs_enet_resume,
 };
 
 static int __init fs_init(void)
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index e05389c..ea3cf2f 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -10,10 +10,15 @@
 
 #include <linux/fs_enet_pd.h>
 #include <asm/fs_pd.h>
+#ifdef CONFIG_FS_ENET_MPC5121_FEC
+#include "../fec.h"
+#endif
 
 #ifdef CONFIG_CPM1
 #include <asm/cpm1.h>
+#endif
 
+#if defined(CONFIG_CPM1) || defined(CONFIG_FS_ENET_MPC5121_FEC)
 struct fec_info {
        fec_t __iomem *fecp;
        u32 mii_speed;
@@ -177,14 +182,14 @@ void fs_enet_platform_cleanup(void);
 #endif
 
 /* write */
-#define CBDW_SC(_cbd, _sc)             __cbd_out16(&(_cbd)->cbd_sc, (_sc))
-#define CBDW_DATLEN(_cbd, _datlen)     __cbd_out16(&(_cbd)->cbd_datlen, 
(_datlen))
-#define CBDW_BUFADDR(_cbd, _bufaddr)   __cbd_out32(&(_cbd)->cbd_bufaddr, 
(_bufaddr))
+#define CBDW_SC(_cbd, _sc)             __cbd_out16((volatile void __iomem 
*)&(_cbd)->cbd_sc, (_sc))
+#define CBDW_DATLEN(_cbd, _datlen)     __cbd_out16((volatile void __iomem 
*)&(_cbd)->cbd_datlen, (_datlen))
+#define CBDW_BUFADDR(_cbd, _bufaddr)   __cbd_out32((volatile void __iomem 
*)&(_cbd)->cbd_bufaddr, (_bufaddr))
 
 /* read */
-#define CBDR_SC(_cbd)                  __cbd_in16(&(_cbd)->cbd_sc)
-#define CBDR_DATLEN(_cbd)              __cbd_in16(&(_cbd)->cbd_datlen)
-#define CBDR_BUFADDR(_cbd)             __cbd_in32(&(_cbd)->cbd_bufaddr)
+#define CBDR_SC(_cbd)                  __cbd_in16((volatile void __iomem 
*)&(_cbd)->cbd_sc)
+#define CBDR_DATLEN(_cbd)              __cbd_in16((volatile void __iomem 
*)&(_cbd)->cbd_datlen)
+#define CBDR_BUFADDR(_cbd)             __cbd_in32((volatile void __iomem 
*)&(_cbd)->cbd_bufaddr)
 
 /* set bits */
 #define CBDS_SC(_cbd, _sc)             CBDW_SC(_cbd, CBDR_SC(_cbd) | (_sc))
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 8a311d1..ddbe548 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -42,6 +42,9 @@
 #include <asm/mpc8xx.h>
 #include <asm/cpm1.h>
 #endif
+#ifdef CONFIG_FS_ENET_MPC5121_FEC
+#include "../fec.h"
+#endif
 
 #ifdef CONFIG_PPC_CPM_NEW_BINDING
 #include <asm/of_device.h>
@@ -306,7 +309,9 @@ static void restart(struct net_device *dev)
         * Set maximum receive buffer size.
         */
        FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
+#ifndef CONFIG_FS_ENET_MPC5121_FEC
        FW(fecp, r_hash, PKT_MAXBUF_SIZE);
+#endif
 
        /* get physical address */
        rx_bd_base_phys = fep->ring_mem_addr;
@@ -320,10 +325,17 @@ static void restart(struct net_device *dev)
 
        fs_init_bds(dev);
 
+#ifndef CONFIG_FS_ENET_MPC5121_FEC
        /*
         * Enable big endian and don't care about SDMA FC.
         */
        FW(fecp, fun_code, 0x78000000);
+#else
+       /*
+        * Set DATA_BO and DESC_BO and leave the rest unchanged
+        */
+       FS(fecp, dma_control, 0xc0000000);
+#endif
 
        /*
         * Set MII speed.
@@ -334,11 +346,13 @@ static void restart(struct net_device *dev)
         * Clear any outstanding interrupt.
         */
        FW(fecp, ievent, 0xffc0);
+#ifndef CONFIG_FS_ENET_MPC5121_FEC
 #ifndef CONFIG_PPC_MERGE
        FW(fecp, ivec, (fep->interrupt / 2) << 29);
 #else
        FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
 #endif
+#endif
 
        /*
         * adjust to speed (only for DUET & RMII)
@@ -368,9 +382,13 @@ static void restart(struct net_device *dev)
                out_be32(&immap->im_cpm.cp_cptr, cptr);
        }
 #endif
-
-
+#ifdef CONFIG_FS_ENET_MPC5121_FEC
+       FW(fecp, r_cntrl, PKT_MAXBUF_SIZE<<16); /* max frame size */
+       FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+#else
        FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+#endif
+
        /*
         * adjust to duplex mode
         */
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index f0014cf..5d9b846 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -38,6 +38,7 @@
 
 #ifdef CONFIG_PPC_CPM_NEW_BINDING
 #include <asm/of_platform.h>
+#include <asm/time.h>
 #endif
 
 #include "fs_enet.h"
@@ -71,7 +72,7 @@ static int fs_mii_fec_init(struct fec_info* fec, struct 
fs_mii_fec_platform_info
 {
        struct resource *r;
        fec_t __iomem *fecp;
-       char* name = "fsl-cpm-fec";
+       char *name = "fsl-cpm-fec";
 
        /* we need fec in order to be useful */
        struct platform_device *fec_pdev =
@@ -261,9 +262,16 @@ static int fs_enet_mdio_remove(struct of_device *ofdev)
 }
 
 static struct of_device_id fs_enet_mdio_fec_match[] = {
+#ifdef CONFIG_FS_ENET_FEC
        {
                .compatible = "fsl,pq1-fec-mdio",
        },
+#endif
+#ifdef CONFIG_FS_ENET_MPC5121_FEC
+       {
+               .compatible = "fsl,mpc5121-fec-mdio",
+       },
+#endif
        {},
 };
 
-- 
1.5.4.3

_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Reply via email to