smc911x: introduce platform data flags
authorMagnus Damm <magnus.damm@gmail.com>
Mon, 9 Jun 2008 23:33:55 +0000 (16:33 -0700)
committerJeff Garzik <jgarzik@redhat.com>
Thu, 12 Jun 2008 01:58:11 +0000 (21:58 -0400)
This patch adds a new header file for platform data information
together with code that adds run time bus width and irq flag support.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/net/smc911x.c
drivers/net/smc911x.h
include/linux/smc911x.h [new file with mode: 0644]

index 2ca4db85f93872827711f960164cb49d51250edb..fc605f276c0051aea2b29e746483f5cfd1404cdf 100644 (file)
@@ -1819,6 +1819,7 @@ static int __init smc911x_probe(struct net_device *dev)
        int i, retval;
        unsigned int val, chip_id, revision;
        const char *version_string;
+       unsigned long irq_flags;
 
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
 
@@ -1985,9 +1986,15 @@ static int __init smc911x_probe(struct net_device *dev)
        lp->ctl_rfduplx = 1;
        lp->ctl_rspeed = 100;
 
+#ifdef SMC_DYNAMIC_BUS_CONFIG
+       irq_flags = lp->cfg.irq_flags;
+#else
+       irq_flags = IRQF_SHARED | SMC_IRQ_SENSE;
+#endif
+
        /* Grab the IRQ */
        retval = request_irq(dev->irq, &smc911x_interrupt,
-                       IRQF_SHARED | SMC_IRQ_SENSE, dev->name, dev);
+                            irq_flags, dev->name, dev);
        if (retval)
                goto err_out;
 
@@ -2057,6 +2064,7 @@ err_out:
  */
 static int smc911x_drv_probe(struct platform_device *pdev)
 {
+       struct smc91x_platdata *pd = pdev->dev.platform_data;
        struct net_device *ndev;
        struct resource *res;
        struct smc911x_local *lp;
@@ -2090,6 +2098,13 @@ static int smc911x_drv_probe(struct platform_device *pdev)
        ndev->irq = platform_get_irq(pdev, 0);
        lp = netdev_priv(ndev);
        lp->netdev = ndev;
+#ifdef SMC_DYNAMIC_BUS_CONFIG
+       if (!pd) {
+               ret = -EINVAL;
+               goto release_both;
+       }
+       memcpy(&lp->cfg, pd, sizeof(lp->cfg));
+#endif
 
        addr = ioremap(res->start, SMC911X_IO_EXTENT);
        if (!addr) {
index 271a3e8cf683426a2bda0869a974732949024050..266232271a72879467afab4579f9dcad68ad3071 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef _SMC911X_H_
 #define _SMC911X_H_
 
+#include <linux/smc911x.h>
 /*
  * Use the DMA feature on PXA chips
  */
   #define SMC_USE_16BIT                0
   #define SMC_USE_32BIT                1
   #define SMC_IRQ_SENSE                IRQF_TRIGGER_LOW
+#else
+/*
+ * Default configuration
+ */
+
+#define SMC_DYNAMIC_BUS_CONFIG
 #endif
 
 /* store this information for the driver.. */
@@ -92,12 +99,84 @@ struct smc911x_local {
        struct device *dev;
 #endif
        void __iomem *base;
+#ifdef SMC_DYNAMIC_BUS_CONFIG
+       struct smc911x_platdata cfg;
+#endif
 };
 
 /*
  * Define the bus width specific IO macros
  */
 
+#ifdef SMC_DYNAMIC_BUS_CONFIG
+static inline unsigned int SMC_inl(struct smc911x_local *lp, int reg)
+{
+       void __iomem *ioaddr = lp->base + reg;
+
+       if (lp->cfg.flags & SMC911X_USE_32BIT)
+               return readl(ioaddr);
+
+       if (lp->cfg.flags & SMC911X_USE_16BIT)
+               return readw(ioaddr) | (readw(ioaddr + 2) << 16);
+
+       BUG();
+}
+
+static inline void SMC_outl(unsigned int value, struct smc911x_local *lp,
+                           int reg)
+{
+       void __iomem *ioaddr = lp->base + reg;
+
+       if (lp->cfg.flags & SMC911X_USE_32BIT) {
+               writel(value, ioaddr);
+               return;
+       }
+
+       if (lp->cfg.flags & SMC911X_USE_16BIT) {
+               writew(value & 0xffff, ioaddr);
+               writew(value >> 16, ioaddr + 2);
+               return;
+       }
+
+       BUG();
+}
+
+static inline void SMC_insl(struct smc911x_local *lp, int reg,
+                             void *addr, unsigned int count)
+{
+       void __iomem *ioaddr = lp->base + reg;
+
+       if (lp->cfg.flags & SMC911X_USE_32BIT) {
+               readsl(ioaddr, addr, count);
+               return;
+       }
+
+       if (lp->cfg.flags & SMC911X_USE_16BIT) {
+               readsw(ioaddr, addr, count * 2);
+               return;
+       }
+
+       BUG();
+}
+
+static inline void SMC_outsl(struct smc911x_local *lp, int reg,
+                            void *addr, unsigned int count)
+{
+       void __iomem *ioaddr = lp->base + reg;
+
+       if (lp->cfg.flags & SMC911X_USE_32BIT) {
+               writesl(ioaddr, addr, count);
+               return;
+       }
+
+       if (lp->cfg.flags & SMC911X_USE_16BIT) {
+               writesw(ioaddr, addr, count * 2);
+               return;
+       }
+
+       BUG();
+}
+#else
 #if    SMC_USE_16BIT
 #define SMC_inl(lp, r)          ((readw((lp)->base + (r)) & 0xFFFF) + (readw((lp)->base + (r) + 2) << 16))
 #define SMC_outl(v, lp, r)                      \
@@ -115,6 +194,8 @@ struct smc911x_local {
 #define SMC_outsl(lp, r, p, l)  writesl((int*)((lp)->base + (r)), p, l)
 
 #endif /* SMC_USE_16BIT */
+#endif /* SMC_DYNAMIC_BUS_CONFIG */
+
 
 #ifdef SMC_USE_PXA_DMA
 #define SMC_USE_DMA
diff --git a/include/linux/smc911x.h b/include/linux/smc911x.h
new file mode 100644 (file)
index 0000000..b58f54c
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __SMC911X_H__
+#define __SMC911X_H__
+
+#define SMC911X_USE_16BIT (1 << 0)
+#define SMC911X_USE_32BIT (1 << 1)
+
+struct smc911x_platdata {
+       unsigned long flags;
+       unsigned long irq_flags; /* IRQF_... */
+};
+
+#endif /* __SMC911X_H__ */