Commit ea97caee authored by David S. Miller's avatar David S. Miller

Merge branch 'gianfar'

Claudiu Manoil says:

====================
gianfar: ARM port driver updates (1/2)

This is the first round of driver portability fixes and clean-up
with the main purpose to make gianfar portable on ARM, for the ARM
based SoC that integrates the eTSEC ethernet controller - "ls1021a".
The patches primarily address compile time errors, when compiling
gianfar on ARM.  They replace PPC specific functions and macros
with architecture independent ones, solve arch specific header
inclusions, guard code that relates to PPC only, and even address
some simple endianess issues (see MAC address setup patch).
The patches addressing the bulk of remaining endianess issues,
like handling DMA fields (BD and FCB), will follow with the second
round.
====================
Reviewed-by: default avatarKim Phillips <kim.phillips@freescale.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 59f35b81 d55398ba
...@@ -28,7 +28,9 @@ ...@@ -28,7 +28,9 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#if IS_ENABLED(CONFIG_UCC_GETH)
#include <asm/ucc.h> /* for ucc_set_qe_mux_mii_mng() */ #include <asm/ucc.h> /* for ucc_set_qe_mux_mii_mng() */
#endif
#include "gianfar.h" #include "gianfar.h"
...@@ -102,19 +104,22 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ...@@ -102,19 +104,22 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
{ {
struct fsl_pq_mdio_priv *priv = bus->priv; struct fsl_pq_mdio_priv *priv = bus->priv;
struct fsl_pq_mii __iomem *regs = priv->regs; struct fsl_pq_mii __iomem *regs = priv->regs;
u32 status; unsigned int timeout;
/* Set the PHY address and the register address we want to write */ /* Set the PHY address and the register address we want to write */
out_be32(&regs->miimadd, (mii_id << 8) | regnum); iowrite32be((mii_id << 8) | regnum, &regs->miimadd);
/* Write out the value we want */ /* Write out the value we want */
out_be32(&regs->miimcon, value); iowrite32be(value, &regs->miimcon);
/* Wait for the transaction to finish */ /* Wait for the transaction to finish */
status = spin_event_timeout(!(in_be32(&regs->miimind) & MIIMIND_BUSY), timeout = MII_TIMEOUT;
MII_TIMEOUT, 0); while ((ioread32be(&regs->miimind) & MIIMIND_BUSY) && timeout) {
cpu_relax();
timeout--;
}
return status ? 0 : -ETIMEDOUT; return timeout ? 0 : -ETIMEDOUT;
} }
/* /*
...@@ -131,25 +136,29 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ...@@ -131,25 +136,29 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{ {
struct fsl_pq_mdio_priv *priv = bus->priv; struct fsl_pq_mdio_priv *priv = bus->priv;
struct fsl_pq_mii __iomem *regs = priv->regs; struct fsl_pq_mii __iomem *regs = priv->regs;
u32 status; unsigned int timeout;
u16 value; u16 value;
/* Set the PHY address and the register address we want to read */ /* Set the PHY address and the register address we want to read */
out_be32(&regs->miimadd, (mii_id << 8) | regnum); iowrite32be((mii_id << 8) | regnum, &regs->miimadd);
/* Clear miimcom, and then initiate a read */ /* Clear miimcom, and then initiate a read */
out_be32(&regs->miimcom, 0); iowrite32be(0, &regs->miimcom);
out_be32(&regs->miimcom, MII_READ_COMMAND); iowrite32be(MII_READ_COMMAND, &regs->miimcom);
/* Wait for the transaction to finish, normally less than 100us */ /* Wait for the transaction to finish, normally less than 100us */
status = spin_event_timeout(!(in_be32(&regs->miimind) & timeout = MII_TIMEOUT;
(MIIMIND_NOTVALID | MIIMIND_BUSY)), while ((ioread32be(&regs->miimind) &
MII_TIMEOUT, 0); (MIIMIND_NOTVALID | MIIMIND_BUSY)) && timeout) {
if (!status) cpu_relax();
timeout--;
}
if (!timeout)
return -ETIMEDOUT; return -ETIMEDOUT;
/* Grab the value of the register from miimstat */ /* Grab the value of the register from miimstat */
value = in_be32(&regs->miimstat); value = ioread32be(&regs->miimstat);
dev_dbg(&bus->dev, "read %04x from address %x/%x\n", value, mii_id, regnum); dev_dbg(&bus->dev, "read %04x from address %x/%x\n", value, mii_id, regnum);
return value; return value;
...@@ -160,23 +169,26 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus) ...@@ -160,23 +169,26 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
{ {
struct fsl_pq_mdio_priv *priv = bus->priv; struct fsl_pq_mdio_priv *priv = bus->priv;
struct fsl_pq_mii __iomem *regs = priv->regs; struct fsl_pq_mii __iomem *regs = priv->regs;
u32 status; unsigned int timeout;
mutex_lock(&bus->mdio_lock); mutex_lock(&bus->mdio_lock);
/* Reset the management interface */ /* Reset the management interface */
out_be32(&regs->miimcfg, MIIMCFG_RESET); iowrite32be(MIIMCFG_RESET, &regs->miimcfg);
/* Setup the MII Mgmt clock speed */ /* Setup the MII Mgmt clock speed */
out_be32(&regs->miimcfg, MIIMCFG_INIT_VALUE); iowrite32be(MIIMCFG_INIT_VALUE, &regs->miimcfg);
/* Wait until the bus is free */ /* Wait until the bus is free */
status = spin_event_timeout(!(in_be32(&regs->miimind) & MIIMIND_BUSY), timeout = MII_TIMEOUT;
MII_TIMEOUT, 0); while ((ioread32be(&regs->miimind) & MIIMIND_BUSY) && timeout) {
cpu_relax();
timeout--;
}
mutex_unlock(&bus->mdio_lock); mutex_unlock(&bus->mdio_lock);
if (!status) { if (!timeout) {
dev_err(&bus->dev, "timeout waiting for MII bus\n"); dev_err(&bus->dev, "timeout waiting for MII bus\n");
return -EBUSY; return -EBUSY;
} }
...@@ -433,7 +445,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) ...@@ -433,7 +445,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
tbipa = data->get_tbipa(priv->map); tbipa = data->get_tbipa(priv->map);
out_be32(tbipa, be32_to_cpup(prop)); iowrite32be(be32_to_cpup(prop), tbipa);
} }
} }
......
...@@ -88,8 +88,10 @@ ...@@ -88,8 +88,10 @@
#include <linux/net_tstamp.h> #include <linux/net_tstamp.h>
#include <asm/io.h> #include <asm/io.h>
#ifdef CONFIG_PPC
#include <asm/reg.h> #include <asm/reg.h>
#include <asm/mpc85xx.h> #include <asm/mpc85xx.h>
#endif
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -100,6 +102,8 @@ ...@@ -100,6 +102,8 @@
#include <linux/phy_fixed.h> #include <linux/phy_fixed.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include "gianfar.h" #include "gianfar.h"
...@@ -161,7 +165,7 @@ static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, ...@@ -161,7 +165,7 @@ static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1) if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1)
lstatus |= BD_LFLAG(RXBD_WRAP); lstatus |= BD_LFLAG(RXBD_WRAP);
eieio(); gfar_wmb();
bdp->lstatus = lstatus; bdp->lstatus = lstatus;
} }
...@@ -1061,6 +1065,7 @@ static void gfar_init_filer_table(struct gfar_private *priv) ...@@ -1061,6 +1065,7 @@ static void gfar_init_filer_table(struct gfar_private *priv)
} }
} }
#ifdef CONFIG_PPC
static void __gfar_detect_errata_83xx(struct gfar_private *priv) static void __gfar_detect_errata_83xx(struct gfar_private *priv)
{ {
unsigned int pvr = mfspr(SPRN_PVR); unsigned int pvr = mfspr(SPRN_PVR);
...@@ -1093,6 +1098,7 @@ static void __gfar_detect_errata_85xx(struct gfar_private *priv) ...@@ -1093,6 +1098,7 @@ static void __gfar_detect_errata_85xx(struct gfar_private *priv)
((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20))) ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20)))
priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */ priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */
} }
#endif
static void gfar_detect_errata(struct gfar_private *priv) static void gfar_detect_errata(struct gfar_private *priv)
{ {
...@@ -1101,10 +1107,12 @@ static void gfar_detect_errata(struct gfar_private *priv) ...@@ -1101,10 +1107,12 @@ static void gfar_detect_errata(struct gfar_private *priv)
/* no plans to fix */ /* no plans to fix */
priv->errata |= GFAR_ERRATA_A002; priv->errata |= GFAR_ERRATA_A002;
#ifdef CONFIG_PPC
if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2)) if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2))
__gfar_detect_errata_85xx(priv); __gfar_detect_errata_85xx(priv);
else /* non-mpc85xx parts, i.e. e300 core based */ else /* non-mpc85xx parts, i.e. e300 core based */
__gfar_detect_errata_83xx(priv); __gfar_detect_errata_83xx(priv);
#endif
if (priv->errata) if (priv->errata)
dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
...@@ -1754,26 +1762,32 @@ static void gfar_halt_nodisable(struct gfar_private *priv) ...@@ -1754,26 +1762,32 @@ static void gfar_halt_nodisable(struct gfar_private *priv)
{ {
struct gfar __iomem *regs = priv->gfargrp[0].regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval; u32 tempval;
unsigned int timeout;
int stopped;
gfar_ints_disable(priv); gfar_ints_disable(priv);
if (gfar_is_dma_stopped(priv))
return;
/* Stop the DMA, and wait for it to stop */ /* Stop the DMA, and wait for it to stop */
tempval = gfar_read(&regs->dmactrl); tempval = gfar_read(&regs->dmactrl);
if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
(DMACTRL_GRS | DMACTRL_GTS)) {
int ret;
tempval |= (DMACTRL_GRS | DMACTRL_GTS); tempval |= (DMACTRL_GRS | DMACTRL_GTS);
gfar_write(&regs->dmactrl, tempval); gfar_write(&regs->dmactrl, tempval);
do { retry:
ret = spin_event_timeout(((gfar_read(&regs->ievent) & timeout = 1000;
(IEVENT_GRSC | IEVENT_GTSC)) == while (!(stopped = gfar_is_dma_stopped(priv)) && timeout) {
(IEVENT_GRSC | IEVENT_GTSC)), 1000000, 0); cpu_relax();
if (!ret && !(gfar_read(&regs->ievent) & IEVENT_GRSC)) timeout--;
ret = __gfar_is_rx_idle(priv);
} while (!ret);
} }
if (!timeout)
stopped = gfar_is_dma_stopped(priv);
if (!stopped && !gfar_is_rx_dma_stopped(priv) &&
!__gfar_is_rx_idle(priv))
goto retry;
} }
/* Halt the receive and transmit queues */ /* Halt the receive and transmit queues */
...@@ -2357,18 +2371,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2357,18 +2371,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/ */
spin_lock_irqsave(&tx_queue->txlock, flags); spin_lock_irqsave(&tx_queue->txlock, flags);
/* The powerpc-specific eieio() is used, as wmb() has too strong gfar_wmb();
* semantics (it requires synchronization between cacheable and
* uncacheable mappings, which eieio doesn't provide and which we
* don't need), thus requiring a more expensive sync instruction. At
* some point, the set of architecture-independent barrier functions
* should be expanded to include weaker barriers.
*/
eieio();
txbdp_start->lstatus = lstatus; txbdp_start->lstatus = lstatus;
eieio(); /* force lstatus write before tx_skbuff */ gfar_wmb(); /* force lstatus write before tx_skbuff */
tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb; tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb;
...@@ -3240,22 +3247,21 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, ...@@ -3240,22 +3247,21 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num,
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
int idx;
char tmpbuf[ETH_ALEN];
u32 tempval; u32 tempval;
u32 __iomem *macptr = &regs->macstnaddr1; u32 __iomem *macptr = &regs->macstnaddr1;
macptr += num*2; macptr += num*2;
/* Now copy it into the mac registers backwards, cuz /* For a station address of 0x12345678ABCD in transmission
* little endian is silly * order (BE), MACnADDR1 is set to 0xCDAB7856 and
* MACnADDR2 is set to 0x34120000.
*/ */
for (idx = 0; idx < ETH_ALEN; idx++) tempval = (addr[5] << 24) | (addr[4] << 16) |
tmpbuf[ETH_ALEN - 1 - idx] = addr[idx]; (addr[3] << 8) | addr[2];
gfar_write(macptr, *((u32 *) (tmpbuf))); gfar_write(macptr, tempval);
tempval = *((u32 *) (tmpbuf + 4)); tempval = (addr[1] << 24) | (addr[0] << 16);
gfar_write(macptr+1, tempval); gfar_write(macptr+1, tempval);
} }
......
...@@ -1226,6 +1226,37 @@ static inline void gfar_write_isrg(struct gfar_private *priv) ...@@ -1226,6 +1226,37 @@ static inline void gfar_write_isrg(struct gfar_private *priv)
} }
} }
static inline int gfar_is_dma_stopped(struct gfar_private *priv)
{
struct gfar __iomem *regs = priv->gfargrp[0].regs;
return ((gfar_read(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) ==
(IEVENT_GRSC | IEVENT_GTSC));
}
static inline int gfar_is_rx_dma_stopped(struct gfar_private *priv)
{
struct gfar __iomem *regs = priv->gfargrp[0].regs;
return gfar_read(&regs->ievent) & IEVENT_GRSC;
}
static inline void gfar_wmb(void)
{
#if defined(CONFIG_PPC)
/* The powerpc-specific eieio() is used, as wmb() has too strong
* semantics (it requires synchronization between cacheable and
* uncacheable mappings, which eieio() doesn't provide and which we
* don't need), thus requiring a more expensive sync instruction. At
* some point, the set of architecture-independent barrier functions
* should be expanded to include weaker barriers.
*/
eieio();
#else
wmb(); /* order write acesses for BD (or FCB) fields */
#endif
}
irqreturn_t gfar_receive(int irq, void *dev_id); irqreturn_t gfar_receive(int irq, void *dev_id);
int startup_gfar(struct net_device *dev); int startup_gfar(struct net_device *dev);
void stop_gfar(struct net_device *dev); void stop_gfar(struct net_device *dev);
......
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