Commit 60ab4361 authored by Anatolij Gustschin's avatar Anatolij Gustschin Committed by David S. Miller

fs_enet: Add support for MPC512x to fs_enet driver

Extend the fs_enet driver to support MPC512x FEC.
Enable it with CONFIG_FS_ENET_MPC5121_FEC option.
Signed-off-by: default avatarJohn Rigby <jcrigby@gmail.com>
Signed-off-by: default avatarPiotr Ziecik <kosmo@semihalf.com>
Signed-off-by: default avatarWolfgang Denk <wd@denx.de>
Signed-off-by: default avatarAnatolij Gustschin <agust@denx.de>
Acked-by: default avatarGrant Likely <grant.likely@secretlab.ca>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fcb6a1c8
config FS_ENET config FS_ENET
tristate "Freescale Ethernet Driver" tristate "Freescale Ethernet Driver"
depends on CPM1 || CPM2 depends on CPM1 || CPM2 || PPC_MPC512x
select MII select MII
select PHYLIB select PHYLIB
config FS_ENET_MPC5121_FEC
def_bool y if (FS_ENET && PPC_MPC512x)
select FS_ENET_HAS_FEC
config FS_ENET_HAS_SCC config FS_ENET_HAS_SCC
bool "Chip has an SCC usable for ethernet" bool "Chip has an SCC usable for ethernet"
depends on FS_ENET && (CPM1 || CPM2) depends on FS_ENET && (CPM1 || CPM2)
...@@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC ...@@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC
config FS_ENET_HAS_FEC config FS_ENET_HAS_FEC
bool "Chip has an FEC usable for ethernet" 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 select FS_ENET_MDIO_FEC
default y default y
config FS_ENET_MDIO_FEC config FS_ENET_MDIO_FEC
tristate "MDIO driver for 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 config FS_ENET_MDIO_FCC
tristate "MDIO driver for FCC" tristate "MDIO driver for FCC"
......
...@@ -1094,10 +1094,17 @@ static struct of_device_id fs_enet_match[] = { ...@@ -1094,10 +1094,17 @@ static struct of_device_id fs_enet_match[] = {
}, },
#endif #endif
#ifdef CONFIG_FS_ENET_HAS_FEC #ifdef CONFIG_FS_ENET_HAS_FEC
#ifdef CONFIG_FS_ENET_MPC5121_FEC
{
.compatible = "fsl,mpc5121-fec",
.data = (void *)&fs_fec_ops,
},
#else
{ {
.compatible = "fsl,pq1-fec-enet", .compatible = "fsl,pq1-fec-enet",
.data = (void *)&fs_fec_ops, .data = (void *)&fs_fec_ops,
}, },
#endif
#endif #endif
{} {}
}; };
......
...@@ -13,9 +13,56 @@ ...@@ -13,9 +13,56 @@
#ifdef CONFIG_CPM1 #ifdef CONFIG_CPM1
#include <asm/cpm1.h> #include <asm/cpm1.h>
#endif
#if defined(CONFIG_FS_ENET_HAS_FEC)
#include <asm/cpm.h>
#if defined(CONFIG_FS_ENET_MPC5121_FEC)
/* MPC5121 FEC has different register layout */
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_reserved12[26];
u32 fec_dma_control; /* DMA Endian and other ctrl */
};
#endif
struct fec_info { struct fec_info {
fec_t __iomem *fecp; struct fec __iomem *fecp;
u32 mii_speed; u32 mii_speed;
}; };
#endif #endif
......
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
*/ */
#define FEC_RESET_DELAY 50 #define FEC_RESET_DELAY 50
static int whack_reset(fec_t __iomem *fecp) static int whack_reset(struct fec __iomem *fecp)
{ {
int i; int i;
...@@ -168,7 +168,7 @@ static void cleanup_data(struct net_device *dev) ...@@ -168,7 +168,7 @@ static void cleanup_data(struct net_device *dev)
static void set_promiscuous_mode(struct net_device *dev) static void set_promiscuous_mode(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
FS(fecp, r_cntrl, FEC_RCNTRL_PROM); FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
} }
...@@ -216,7 +216,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac) ...@@ -216,7 +216,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
static void set_multicast_finish(struct net_device *dev) static void set_multicast_finish(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
/* if all multi or too many multicasts; just enable all */ /* if all multi or too many multicasts; just enable all */
if ((dev->flags & IFF_ALLMULTI) != 0 || if ((dev->flags & IFF_ALLMULTI) != 0 ||
...@@ -246,7 +246,7 @@ static void set_multicast_list(struct net_device *dev) ...@@ -246,7 +246,7 @@ static void set_multicast_list(struct net_device *dev)
static void restart(struct net_device *dev) static void restart(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
const struct fs_platform_info *fpi = fep->fpi; const struct fs_platform_info *fpi = fep->fpi;
dma_addr_t rx_bd_base_phys, tx_bd_base_phys; dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
int r; int r;
...@@ -280,7 +280,11 @@ static void restart(struct net_device *dev) ...@@ -280,7 +280,11 @@ static void restart(struct net_device *dev)
* Set maximum receive buffer size. * Set maximum receive buffer size.
*/ */
FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
#ifdef CONFIG_FS_ENET_MPC5121_FEC
FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16);
#else
FW(fecp, r_hash, PKT_MAXBUF_SIZE); FW(fecp, r_hash, PKT_MAXBUF_SIZE);
#endif
/* get physical address */ /* get physical address */
rx_bd_base_phys = fep->ring_mem_addr; rx_bd_base_phys = fep->ring_mem_addr;
...@@ -297,7 +301,11 @@ static void restart(struct net_device *dev) ...@@ -297,7 +301,11 @@ static void restart(struct net_device *dev)
/* /*
* Enable big endian and don't care about SDMA FC. * Enable big endian and don't care about SDMA FC.
*/ */
#ifdef CONFIG_FS_ENET_MPC5121_FEC
FS(fecp, dma_control, 0xC0000000);
#else
FW(fecp, fun_code, 0x78000000); FW(fecp, fun_code, 0x78000000);
#endif
/* /*
* Set MII speed. * Set MII speed.
...@@ -308,9 +316,17 @@ static void restart(struct net_device *dev) ...@@ -308,9 +316,17 @@ static void restart(struct net_device *dev)
* Clear any outstanding interrupt. * Clear any outstanding interrupt.
*/ */
FW(fecp, ievent, 0xffc0); FW(fecp, ievent, 0xffc0);
#ifndef CONFIG_FS_ENET_MPC5121_FEC
FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
#else
/*
* Only set MII mode - do not touch maximum frame length
* configured before.
*/
FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
#endif
/* /*
* adjust to duplex mode * adjust to duplex mode
*/ */
...@@ -339,7 +355,7 @@ static void stop(struct net_device *dev) ...@@ -339,7 +355,7 @@ static void stop(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi; const struct fs_platform_info *fpi = fep->fpi;
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
struct fec_info* feci= fep->phydev->bus->priv; struct fec_info* feci= fep->phydev->bus->priv;
...@@ -375,7 +391,7 @@ static void stop(struct net_device *dev) ...@@ -375,7 +391,7 @@ static void stop(struct net_device *dev)
static void napi_clear_rx_event(struct net_device *dev) static void napi_clear_rx_event(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK); FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);
} }
...@@ -383,7 +399,7 @@ static void napi_clear_rx_event(struct net_device *dev) ...@@ -383,7 +399,7 @@ static void napi_clear_rx_event(struct net_device *dev)
static void napi_enable_rx(struct net_device *dev) static void napi_enable_rx(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK); FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
} }
...@@ -391,7 +407,7 @@ static void napi_enable_rx(struct net_device *dev) ...@@ -391,7 +407,7 @@ static void napi_enable_rx(struct net_device *dev)
static void napi_disable_rx(struct net_device *dev) static void napi_disable_rx(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
} }
...@@ -399,7 +415,7 @@ static void napi_disable_rx(struct net_device *dev) ...@@ -399,7 +415,7 @@ static void napi_disable_rx(struct net_device *dev)
static void rx_bd_done(struct net_device *dev) static void rx_bd_done(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
FW(fecp, r_des_active, 0x01000000); FW(fecp, r_des_active, 0x01000000);
} }
...@@ -407,7 +423,7 @@ static void rx_bd_done(struct net_device *dev) ...@@ -407,7 +423,7 @@ static void rx_bd_done(struct net_device *dev)
static void tx_kickstart(struct net_device *dev) static void tx_kickstart(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
FW(fecp, x_des_active, 0x01000000); FW(fecp, x_des_active, 0x01000000);
} }
...@@ -415,7 +431,7 @@ static void tx_kickstart(struct net_device *dev) ...@@ -415,7 +431,7 @@ static void tx_kickstart(struct net_device *dev)
static u32 get_int_events(struct net_device *dev) static u32 get_int_events(struct net_device *dev)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
return FR(fecp, ievent) & FR(fecp, imask); return FR(fecp, ievent) & FR(fecp, imask);
} }
...@@ -423,7 +439,7 @@ static u32 get_int_events(struct net_device *dev) ...@@ -423,7 +439,7 @@ static u32 get_int_events(struct net_device *dev)
static void clear_int_events(struct net_device *dev, u32 int_events) static void clear_int_events(struct net_device *dev, u32 int_events)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
fec_t __iomem *fecp = fep->fec.fecp; struct fec __iomem *fecp = fep->fec.fecp;
FW(fecp, ievent, int_events); FW(fecp, ievent, int_events);
} }
...@@ -439,17 +455,17 @@ static int get_regs(struct net_device *dev, void *p, int *sizep) ...@@ -439,17 +455,17 @@ static int get_regs(struct net_device *dev, void *p, int *sizep)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = netdev_priv(dev);
if (*sizep < sizeof(fec_t)) if (*sizep < sizeof(struct fec))
return -EINVAL; return -EINVAL;
memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t)); memcpy_fromio(p, fep->fec.fecp, sizeof(struct fec));
return 0; return 0;
} }
static int get_regs_len(struct net_device *dev) static int get_regs_len(struct net_device *dev)
{ {
return sizeof(fec_t); return sizeof(struct fec);
} }
static void tx_restart(struct net_device *dev) static void tx_restart(struct net_device *dev)
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
{ {
struct fec_info* fec = bus->priv; struct fec_info* fec = bus->priv;
fec_t __iomem *fecp = fec->fecp; struct fec __iomem *fecp = fec->fecp;
int i, ret = -1; int i, ret = -1;
BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
...@@ -75,7 +75,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) ...@@ -75,7 +75,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
{ {
struct fec_info* fec = bus->priv; struct fec_info* fec = bus->priv;
fec_t __iomem *fecp = fec->fecp; struct fec __iomem *fecp = fec->fecp;
int i; int i;
/* this must never happen */ /* this must never happen */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment