Merge branch 'devicetree/merge' of git://git.secretlab.ca/git/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Oct 2011 14:29:40 +0000 (07:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Oct 2011 14:29:40 +0000 (07:29 -0700)
* 'devicetree/merge' of git://git.secretlab.ca/git/linux-2.6:
  ARM: mark empty gpio.h files empty
  gpio: Fix ARM versatile-express build failure
  of: include errno.h

48 files changed:
arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
arch/h8300/include/asm/gpio-internal.h [moved from arch/h8300/include/asm/gpio.h with 100% similarity]
arch/h8300/platform/h8300h/irq.c
arch/h8300/platform/h8s/irq.c
drivers/gpio/Kconfig
drivers/gpio/gpio-langwell.c
drivers/gpio/gpio-ml-ioh.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpio-nomadik.c
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-pl061.c
drivers/spi/spi-altera.c
drivers/spi/spi-ath79.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bfin-sport.c
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-mid.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-ep93xx.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-imx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mpc52xx-psc.c
drivers/spi/spi-mpc52xx.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-pl022.c
drivers/spi/spi-ppc4xx.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh-sci.c
drivers/spi/spi-sh.c
drivers/spi/spi-stmp.c
drivers/spi/spi-tegra.c
drivers/spi/spi-ti-ssp.c
drivers/spi/spi-xilinx.c
drivers/tty/serial/of_serial.c
include/asm-generic/gpio.h
include/linux/amba/pl061.h
include/linux/gpio.h
include/linux/platform_device.h
kernel/irq/generic-chip.c

index 3ba4d8f..9605bf2 100644 (file)
@@ -67,6 +67,9 @@ extern int nmk_gpio_get_mode(int gpio);
 extern void nmk_gpio_wakeups_suspend(void);
 extern void nmk_gpio_wakeups_resume(void);
 
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
 extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
 
 /*
index e977345..bc4f51b 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
 #include <asm/regs306x.h>
 
 const int __initdata h8300_saved_vectors[] = {
index 8182f04..7b5f29f 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
 #include <asm/regs267x.h>
 
 /* saved vector list */
index 4caa3d3..cb0bd07 100644 (file)
@@ -397,6 +397,7 @@ config GPIO_LANGWELL
 config GPIO_PCH
        tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
        depends on PCI && X86
+       select GENERIC_IRQ_CHIP
        help
          This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
          which is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -411,6 +412,7 @@ config GPIO_PCH
 config GPIO_ML_IOH
        tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
        depends on PCI
+       select GENERIC_IRQ_CHIP
        help
          ML7213 is companion chip for Intel Atom E6xx series.
          This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output
index d2eb57c..00692e8 100644 (file)
@@ -59,6 +59,7 @@ enum GPIO_REG {
        GRER,           /* rising edge detect */
        GFER,           /* falling edge detect */
        GEDR,           /* edge detect result */
+       GAFR,           /* alt function */
 };
 
 struct lnw_gpio {
@@ -81,6 +82,31 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
        return ptr;
 }
 
+static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
+                                  enum GPIO_REG reg_type)
+{
+       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+       unsigned nreg = chip->ngpio / 32;
+       u8 reg = offset / 16;
+       void __iomem *ptr;
+
+       ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
+       return ptr;
+}
+
+static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
+       u32 value = readl(gafr);
+       int shift = (offset % 16) << 1, af = (value >> shift) & 3;
+
+       if (af) {
+               value &= ~(3 << shift);
+               writel(value, gafr);
+       }
+       return 0;
+}
+
 static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        void __iomem *gplr = gpio_reg(chip, offset, GPLR);
@@ -321,6 +347,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
        lnw->reg_base = base;
        lnw->irq_base = irq_base;
        lnw->chip.label = dev_name(&pdev->dev);
+       lnw->chip.request = lnw_gpio_request;
        lnw->chip.direction_input = lnw_gpio_direction_input;
        lnw->chip.direction_output = lnw_gpio_direction_output;
        lnw->chip.get = lnw_gpio_get;
index a9016f5..3aa6bee 100644 (file)
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#define IOH_EDGE_FALLING       0
+#define IOH_EDGE_RISING                BIT(0)
+#define IOH_LEVEL_L            BIT(1)
+#define IOH_LEVEL_H            (BIT(0) | BIT(1))
+#define IOH_EDGE_BOTH          BIT(2)
+#define IOH_IM_MASK            (BIT(0) | BIT(1) | BIT(2))
+
+#define IOH_IRQ_BASE           0
 
 #define PCI_VENDOR_ID_ROHM             0x10DB
 
@@ -46,12 +57,22 @@ struct ioh_regs {
 
 /**
  * struct ioh_gpio_reg_data - The register store data.
+ * @ien_reg    To store contents of interrupt enable register.
+ * @imask_reg: To store contents of interrupt mask regist
  * @po_reg:    To store contents of PO register.
  * @pm_reg:    To store contents of PM register.
+ * @im0_reg:   To store contents of interrupt mode regist0
+ * @im1_reg:   To store contents of interrupt mode regist1
+ * @use_sel_reg: To store contents of GPIO_USE_SEL0~3
  */
 struct ioh_gpio_reg_data {
+       u32 ien_reg;
+       u32 imask_reg;
        u32 po_reg;
        u32 pm_reg;
+       u32 im0_reg;
+       u32 im1_reg;
+       u32 use_sel_reg;
 };
 
 /**
@@ -62,7 +83,11 @@ struct ioh_gpio_reg_data {
  * @gpio:                      Data for GPIO infrastructure.
  * @ioh_gpio_reg:              Memory mapped Register data is saved here
  *                             when suspend.
+ * @gpio_use_sel:              Save GPIO_USE_SEL1~4 register for PM
  * @ch:                                Indicate GPIO channel
+ * @irq_base:          Save base of IRQ number for interrupt
+ * @spinlock:          Used for register access protection in
+ *                             interrupt context ioh_irq_type and PM;
  */
 struct ioh_gpio {
        void __iomem *base;
@@ -70,8 +95,11 @@ struct ioh_gpio {
        struct device *dev;
        struct gpio_chip gpio;
        struct ioh_gpio_reg_data ioh_gpio_reg;
+       u32 gpio_use_sel;
        struct mutex lock;
        int ch;
+       int irq_base;
+       spinlock_t spinlock;
 };
 
 static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
@@ -145,8 +173,25 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
  */
 static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
 {
-       chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
-       chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
+       int i;
+
+       for (i = 0; i < 8; i ++, chip++) {
+               chip->ioh_gpio_reg.po_reg =
+                                       ioread32(&chip->reg->regs[chip->ch].po);
+               chip->ioh_gpio_reg.pm_reg =
+                                       ioread32(&chip->reg->regs[chip->ch].pm);
+               chip->ioh_gpio_reg.ien_reg =
+                                      ioread32(&chip->reg->regs[chip->ch].ien);
+               chip->ioh_gpio_reg.imask_reg =
+                                    ioread32(&chip->reg->regs[chip->ch].imask);
+               chip->ioh_gpio_reg.im0_reg =
+                                     ioread32(&chip->reg->regs[chip->ch].im_0);
+               chip->ioh_gpio_reg.im1_reg =
+                                     ioread32(&chip->reg->regs[chip->ch].im_1);
+               if (i < 4)
+                       chip->ioh_gpio_reg.use_sel_reg =
+                                          ioread32(&chip->reg->ioh_sel_reg[i]);
+       }
 }
 
 /*
@@ -154,13 +199,34 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
  */
 static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
 {
-       /* to store contents of PO register */
-       iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
-       /* to store contents of PM register */
-       iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
+       int i;
+
+       for (i = 0; i < 8; i ++, chip++) {
+               iowrite32(chip->ioh_gpio_reg.po_reg,
+                         &chip->reg->regs[chip->ch].po);
+               iowrite32(chip->ioh_gpio_reg.pm_reg,
+                         &chip->reg->regs[chip->ch].pm);
+               iowrite32(chip->ioh_gpio_reg.ien_reg,
+                         &chip->reg->regs[chip->ch].ien);
+               iowrite32(chip->ioh_gpio_reg.imask_reg,
+                         &chip->reg->regs[chip->ch].imask);
+               iowrite32(chip->ioh_gpio_reg.im0_reg,
+                         &chip->reg->regs[chip->ch].im_0);
+               iowrite32(chip->ioh_gpio_reg.im1_reg,
+                         &chip->reg->regs[chip->ch].im_1);
+               if (i < 4)
+                       iowrite32(chip->ioh_gpio_reg.use_sel_reg,
+                                 &chip->reg->ioh_sel_reg[i]);
+       }
 }
 #endif
 
+static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+       return chip->irq_base + offset;
+}
+
 static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
 {
        struct gpio_chip *gpio = &chip->gpio;
@@ -175,16 +241,148 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
        gpio->base = -1;
        gpio->ngpio = num_port;
        gpio->can_sleep = 0;
+       gpio->to_irq = ioh_gpio_to_irq;
+}
+
+static int ioh_irq_type(struct irq_data *d, unsigned int type)
+{
+       u32 im;
+       u32 *im_reg;
+       u32 ien;
+       u32 im_pos;
+       int ch;
+       unsigned long flags;
+       u32 val;
+       int irq = d->irq;
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct ioh_gpio *chip = gc->private;
+
+       ch = irq - chip->irq_base;
+       if (irq <= chip->irq_base + 7) {
+               im_reg = &chip->reg->regs[chip->ch].im_0;
+               im_pos = ch;
+       } else {
+               im_reg = &chip->reg->regs[chip->ch].im_1;
+               im_pos = ch - 8;
+       }
+       dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
+               __func__, irq, type, ch, im_pos, type);
+
+       spin_lock_irqsave(&chip->spinlock, flags);
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+               val = IOH_EDGE_RISING;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               val = IOH_EDGE_FALLING;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               val = IOH_EDGE_BOTH;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               val = IOH_LEVEL_H;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               val = IOH_LEVEL_L;
+               break;
+       case IRQ_TYPE_PROBE:
+               goto end;
+       default:
+               dev_warn(chip->dev, "%s: unknown type(%dd)",
+                       __func__, type);
+               goto end;
+       }
+
+       /* Set interrupt mode */
+       im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4));
+       iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+       /* iclr */
+       iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr);
+
+       /* IMASKCLR */
+       iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr);
+
+       /* Enable interrupt */
+       ien = ioread32(&chip->reg->regs[chip->ch].ien);
+       iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
+end:
+       spin_unlock_irqrestore(&chip->spinlock, flags);
+
+       return 0;
+}
+
+static void ioh_irq_unmask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct ioh_gpio *chip = gc->private;
+
+       iowrite32(1 << (d->irq - chip->irq_base),
+                 &chip->reg->regs[chip->ch].imaskclr);
+}
+
+static void ioh_irq_mask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct ioh_gpio *chip = gc->private;
+
+       iowrite32(1 << (d->irq - chip->irq_base),
+                 &chip->reg->regs[chip->ch].imask);
+}
+
+static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
+{
+       struct ioh_gpio *chip = dev_id;
+       u32 reg_val;
+       int i, j;
+       int ret = IRQ_NONE;
+
+       for (i = 0; i < 8; i++) {
+               reg_val = ioread32(&chip->reg->regs[i].istatus);
+               for (j = 0; j < num_ports[i]; j++) {
+                       if (reg_val & BIT(j)) {
+                               dev_dbg(chip->dev,
+                                       "%s:[%d]:irq=%d status=0x%x\n",
+                                       __func__, j, irq, reg_val);
+                               iowrite32(BIT(j),
+                                         &chip->reg->regs[chip->ch].iclr);
+                               generic_handle_irq(chip->irq_base + j);
+                               ret = IRQ_HANDLED;
+                       }
+               }
+       }
+       return ret;
+}
+
+static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+                               unsigned int irq_start, unsigned int num)
+{
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+
+       gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base,
+                                   handle_simple_irq);
+       gc->private = chip;
+       ct = gc->chip_types;
+
+       ct->chip.irq_mask = ioh_irq_mask;
+       ct->chip.irq_unmask = ioh_irq_unmask;
+       ct->chip.irq_set_type = ioh_irq_type;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
 static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
                                    const struct pci_device_id *id)
 {
        int ret;
-       int i;
+       int i, j;
        struct ioh_gpio *chip;
        void __iomem *base;
        void __iomem *chip_save;
+       int irq_base;
 
        ret = pci_enable_device(pdev);
        if (ret) {
@@ -228,10 +426,41 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
        }
 
        chip = chip_save;
+       for (j = 0; j < 8; j++, chip++) {
+               irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
+                                          NUMA_NO_NODE);
+               if (irq_base < 0) {
+                       dev_warn(&pdev->dev,
+                               "ml_ioh_gpio: Failed to get IRQ base num\n");
+                       chip->irq_base = -1;
+                       goto err_irq_alloc_descs;
+               }
+               chip->irq_base = irq_base;
+               ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
+       }
+
+       chip = chip_save;
+       ret = request_irq(pdev->irq, ioh_gpio_handler,
+                            IRQF_SHARED, KBUILD_MODNAME, chip);
+       if (ret != 0) {
+               dev_err(&pdev->dev,
+                       "%s request_irq failed\n", __func__);
+               goto err_request_irq;
+       }
+
        pci_set_drvdata(pdev, chip);
 
        return 0;
 
+err_request_irq:
+       chip = chip_save;
+err_irq_alloc_descs:
+       while (--j >= 0) {
+               chip--;
+               irq_free_descs(chip->irq_base, num_ports[j]);
+       }
+
+       chip = chip_save;
 err_gpiochip_add:
        while (--i >= 0) {
                chip--;
@@ -264,7 +493,11 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
        void __iomem *chip_save;
 
        chip_save = chip;
+
+       free_irq(pdev->irq, chip);
+
        for (i = 0; i < 8; i++, chip++) {
+               irq_free_descs(chip->irq_base, num_ports[i]);
                err = gpiochip_remove(&chip->gpio);
                if (err)
                        dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -282,9 +515,11 @@ static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        s32 ret;
        struct ioh_gpio *chip = pci_get_drvdata(pdev);
+       unsigned long flags;
 
+       spin_lock_irqsave(&chip->spinlock, flags);
        ioh_gpio_save_reg_conf(chip);
-       ioh_gpio_restore_reg_conf(chip);
+       spin_unlock_irqrestore(&chip->spinlock, flags);
 
        ret = pci_save_state(pdev);
        if (ret) {
@@ -304,6 +539,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
 {
        s32 ret;
        struct ioh_gpio *chip = pci_get_drvdata(pdev);
+       unsigned long flags;
 
        ret = pci_enable_wake(pdev, PCI_D0, 0);
 
@@ -315,9 +551,11 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
        }
        pci_restore_state(pdev);
 
+       spin_lock_irqsave(&chip->spinlock, flags);
        iowrite32(0x01, &chip->reg->srst);
        iowrite32(0x00, &chip->reg->srst);
        ioh_gpio_restore_reg_conf(chip);
+       spin_unlock_irqrestore(&chip->spinlock, flags);
 
        return 0;
 }
index 4340aca..82f7b65 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <asm-generic/bug.h>
+#include <asm/mach/irq.h>
 
 enum mxc_gpio_hwtype {
        IMX1_GPIO,      /* runs on i.mx1 */
@@ -232,10 +233,15 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        u32 irq_stat;
        struct mxc_gpio_port *port = irq_get_handler_data(irq);
+       struct irq_chip *chip = irq_get_chip(irq);
+
+       chained_irq_enter(chip, desc);
 
        irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
 
        mxc_gpio_irq_handler(port, irq_stat);
+
+       chained_irq_exit(chip, desc);
 }
 
 /* MX2 has one interrupt *for all* gpio ports */
index 740caed..1ebedfb 100644 (file)
@@ -59,7 +59,6 @@ struct nmk_gpio_chip {
        u32 rwimsc;
        u32 fwimsc;
        u32 slpm;
-       u32 enabled;
        u32 pull_up;
 };
 
@@ -277,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
                if (!chip)
                        break;
 
+               clk_enable(chip->clk);
+
                slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
                writel(temp, chip->addr + NMK_GPIO_SLPC);
        }
@@ -293,6 +294,8 @@ static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
                        break;
 
                writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+
+               clk_disable(chip->clk);
        }
 }
 
@@ -337,10 +340,12 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
                        break;
                }
 
+               clk_enable(nmk_chip->clk);
                spin_lock(&nmk_chip->lock);
                __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
                                 cfgs[i], sleep, glitch ? slpm : NULL);
                spin_unlock(&nmk_chip->lock);
+               clk_disable(nmk_chip->clk);
        }
 
        if (glitch)
@@ -425,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
        if (!nmk_chip)
                return -EINVAL;
 
+       clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
@@ -432,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
 
        spin_unlock(&nmk_chip->lock);
        spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+       clk_disable(nmk_chip->clk);
 
        return 0;
 }
@@ -458,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
        if (!nmk_chip)
                return -EINVAL;
 
+       clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_chip->lock, flags);
        __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
+       clk_disable(nmk_chip->clk);
 
        return 0;
 }
@@ -484,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
        if (!nmk_chip)
                return -EINVAL;
 
+       clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_chip->lock, flags);
        __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
+       clk_disable(nmk_chip->clk);
 
        return 0;
 }
@@ -503,9 +514,13 @@ int nmk_gpio_get_mode(int gpio)
 
        bit = 1 << (gpio - nmk_chip->chip.base);
 
+       clk_enable(nmk_chip->clk);
+
        afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
        bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
 
+       clk_disable(nmk_chip->clk);
+
        return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
 }
 EXPORT_SYMBOL(nmk_gpio_get_mode);
@@ -526,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_data *d)
        nmk_chip = irq_data_get_irq_chip_data(d);
        if (!nmk_chip)
                return;
+
+       clk_enable(nmk_chip->clk);
        writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
+       clk_disable(nmk_chip->clk);
 }
 
 enum nmk_gpio_irq_type {
@@ -587,11 +605,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
        if (!nmk_chip)
                return -EINVAL;
 
-       if (enable)
-               nmk_chip->enabled |= bitmask;
-       else
-               nmk_chip->enabled &= ~bitmask;
-
+       clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
@@ -602,6 +616,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
 
        spin_unlock(&nmk_chip->lock);
        spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+       clk_disable(nmk_chip->clk);
 
        return 0;
 }
@@ -629,10 +644,11 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
                return -EINVAL;
        bitmask = nmk_gpio_get_bitmask(gpio);
 
+       clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
-       if (!(nmk_chip->enabled & bitmask))
+       if (irqd_irq_disabled(d))
                __nmk_gpio_set_wake(nmk_chip, gpio, on);
 
        if (on)
@@ -642,13 +658,15 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 
        spin_unlock(&nmk_chip->lock);
        spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+       clk_disable(nmk_chip->clk);
 
        return 0;
 }
 
 static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-       bool enabled, wake = irqd_is_wakeup_set(d);
+       bool enabled = !irqd_irq_disabled(d);
+       bool wake = irqd_is_wakeup_set(d);
        int gpio;
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
@@ -665,8 +683,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        if (type & IRQ_TYPE_LEVEL_LOW)
                return -EINVAL;
 
-       enabled = nmk_chip->enabled & bitmask;
-
+       clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_chip->lock, flags);
 
        if (enabled)
@@ -690,10 +707,28 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
                __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
 
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
+       clk_disable(nmk_chip->clk);
 
        return 0;
 }
 
+static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
+{
+       struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+       clk_enable(nmk_chip->clk);
+       nmk_gpio_irq_unmask(d);
+       return 0;
+}
+
+static void nmk_gpio_irq_shutdown(struct irq_data *d)
+{
+       struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+       nmk_gpio_irq_mask(d);
+       clk_disable(nmk_chip->clk);
+}
+
 static struct irq_chip nmk_gpio_irq_chip = {
        .name           = "Nomadik-GPIO",
        .irq_ack        = nmk_gpio_irq_ack,
@@ -701,6 +736,8 @@ static struct irq_chip nmk_gpio_irq_chip = {
        .irq_unmask     = nmk_gpio_irq_unmask,
        .irq_set_type   = nmk_gpio_irq_set_type,
        .irq_set_wake   = nmk_gpio_irq_set_wake,
+       .irq_startup    = nmk_gpio_irq_startup,
+       .irq_shutdown   = nmk_gpio_irq_shutdown,
 };
 
 static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
@@ -727,7 +764,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
 static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
-       u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
+       u32 status;
+
+       clk_enable(nmk_chip->clk);
+       status = readl(nmk_chip->addr + NMK_GPIO_IS);
+       clk_disable(nmk_chip->clk);
 
        __nmk_gpio_irq_handler(irq, desc, status);
 }
@@ -773,7 +814,12 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
+       clk_enable(nmk_chip->clk);
+
        writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+
+       clk_disable(nmk_chip->clk);
+
        return 0;
 }
 
@@ -782,8 +828,15 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
        u32 bit = 1 << offset;
+       int value;
+
+       clk_enable(nmk_chip->clk);
 
-       return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+       value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+
+       clk_disable(nmk_chip->clk);
+
+       return value;
 }
 
 static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
@@ -792,7 +845,11 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
+       clk_enable(nmk_chip->clk);
+
        __nmk_gpio_set_output(nmk_chip, offset, val);
+
+       clk_disable(nmk_chip->clk);
 }
 
 static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@@ -801,8 +858,12 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
+       clk_enable(nmk_chip->clk);
+
        __nmk_gpio_make_output(nmk_chip, offset, val);
 
+       clk_disable(nmk_chip->clk);
+
        return 0;
 }
 
@@ -833,6 +894,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                [NMK_GPIO_ALT_C]        = "altC",
        };
 
+       clk_enable(nmk_chip->clk);
+
        for (i = 0; i < chip->ngpio; i++, gpio++) {
                const char *label = gpiochip_is_requested(chip, i);
                bool pull;
@@ -877,6 +940,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 
                seq_printf(s, "\n");
        }
+
+       clk_disable(nmk_chip->clk);
 }
 
 #else
@@ -894,6 +959,34 @@ static struct gpio_chip nmk_gpio_template = {
        .can_sleep              = 0,
 };
 
+void nmk_gpio_clocks_enable(void)
+{
+       int i;
+
+       for (i = 0; i < NUM_BANKS; i++) {
+               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+               if (!chip)
+                       continue;
+
+               clk_enable(chip->clk);
+       }
+}
+
+void nmk_gpio_clocks_disable(void)
+{
+       int i;
+
+       for (i = 0; i < NUM_BANKS; i++) {
+               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+               if (!chip)
+                       continue;
+
+               clk_disable(chip->clk);
+       }
+}
+
 /*
  * Called from the suspend/resume path to only keep the real wakeup interrupts
  * (those that have had set_irq_wake() called on them) as wakeup interrupts,
@@ -913,6 +1006,8 @@ void nmk_gpio_wakeups_suspend(void)
                if (!chip)
                        break;
 
+               clk_enable(chip->clk);
+
                chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
                chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
 
@@ -927,6 +1022,8 @@ void nmk_gpio_wakeups_suspend(void)
                        /* 0 -> wakeup enable */
                        writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
                }
+
+               clk_disable(chip->clk);
        }
 }
 
@@ -940,11 +1037,15 @@ void nmk_gpio_wakeups_resume(void)
                if (!chip)
                        break;
 
+               clk_enable(chip->clk);
+
                writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
                writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
 
                if (chip->sleepmode)
                        writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
+
+               clk_disable(chip->clk);
        }
 }
 
@@ -1011,8 +1112,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
                goto out_release;
        }
 
-       clk_enable(clk);
-
        nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
        if (!nmk_chip) {
                ret = -ENOMEM;
index 36919e7..1e8a4a5 100644 (file)
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 
-#define PCH_GPIO_ALL_PINS      0xfff /* Mask for GPIO pins 0 to 11 */
-#define GPIO_NUM_PINS  12      /* Specifies number of GPIO PINS GPIO0-GPIO11 */
+#define PCH_EDGE_FALLING       0
+#define PCH_EDGE_RISING                BIT(0)
+#define PCH_LEVEL_L            BIT(1)
+#define PCH_LEVEL_H            (BIT(0) | BIT(1))
+#define PCH_EDGE_BOTH          BIT(2)
+#define PCH_IM_MASK            (BIT(0) | BIT(1) | BIT(2))
+
+#define PCH_IRQ_BASE           24
 
 struct pch_regs {
        u32     ien;
@@ -33,18 +41,43 @@ struct pch_regs {
        u32     pm;
        u32     im0;
        u32     im1;
-       u32     reserved[4];
+       u32     reserved[3];
+       u32     gpio_use_sel;
        u32     reset;
 };
 
+enum pch_type_t {
+       INTEL_EG20T_PCH,
+       OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */
+       OKISEMI_ML7223n_IOH  /* OKISEMI ML7223 IOH PCIe Bus-n */
+};
+
+/* Specifies number of GPIO PINS */
+static int gpio_pins[] = {
+       [INTEL_EG20T_PCH] = 12,
+       [OKISEMI_ML7223m_IOH] = 8,
+       [OKISEMI_ML7223n_IOH] = 8,
+};
+
 /**
  * struct pch_gpio_reg_data - The register store data.
+ * @ien_reg:   To store contents of IEN register.
+ * @imask_reg: To store contents of IMASK register.
  * @po_reg:    To store contents of PO register.
  * @pm_reg:    To store contents of PM register.
+ * @im0_reg:   To store contents of IM0 register.
+ * @im1_reg:   To store contents of IM1 register.
+ * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register.
+ *                    (Only ML7223 Bus-n)
  */
 struct pch_gpio_reg_data {
+       u32 ien_reg;
+       u32 imask_reg;
        u32 po_reg;
        u32 pm_reg;
+       u32 im0_reg;
+       u32 im1_reg;
+       u32 gpio_use_sel_reg;
 };
 
 /**
@@ -55,6 +88,12 @@ struct pch_gpio_reg_data {
  * @gpio:                      Data for GPIO infrastructure.
  * @pch_gpio_reg:              Memory mapped Register data is saved here
  *                             when suspend.
+ * @lock:                      Used for register access protection
+ * @irq_base:          Save base of IRQ number for interrupt
+ * @ioh:               IOH ID
+ * @spinlock:          Used for register access protection in
+ *                             interrupt context pch_irq_mask,
+ *                             pch_irq_unmask and pch_irq_type;
  */
 struct pch_gpio {
        void __iomem *base;
@@ -63,6 +102,9 @@ struct pch_gpio {
        struct gpio_chip gpio;
        struct pch_gpio_reg_data pch_gpio_reg;
        struct mutex lock;
+       int irq_base;
+       enum pch_type_t ioh;
+       spinlock_t spinlock;
 };
 
 static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
@@ -96,7 +138,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
        u32 reg_val;
 
        mutex_lock(&chip->lock);
-       pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
+       pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
        pm |= (1 << nr);
        iowrite32(pm, &chip->reg->pm);
 
@@ -118,7 +160,7 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
        u32 pm;
 
        mutex_lock(&chip->lock);
-       pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
+       pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
        pm &= ~(1 << nr);
        iowrite32(pm, &chip->reg->pm);
        mutex_unlock(&chip->lock);
@@ -131,8 +173,16 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
  */
 static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
 {
+       chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
+       chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
        chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
        chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
+       chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
+       if (chip->ioh == INTEL_EG20T_PCH)
+               chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
+       if (chip->ioh == OKISEMI_ML7223n_IOH)
+               chip->pch_gpio_reg.gpio_use_sel_reg =\
+                                           ioread32(&chip->reg->gpio_use_sel);
 }
 
 /*
@@ -140,10 +190,24 @@ static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
  */
 static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
 {
+       iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
+       iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
        /* to store contents of PO register */
        iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
        /* to store contents of PM register */
        iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
+       iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
+       if (chip->ioh == INTEL_EG20T_PCH)
+               iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
+       if (chip->ioh == OKISEMI_ML7223n_IOH)
+               iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg,
+                         &chip->reg->gpio_use_sel);
+}
+
+static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+       return chip->irq_base + offset;
 }
 
 static void pch_gpio_setup(struct pch_gpio *chip)
@@ -158,8 +222,132 @@ static void pch_gpio_setup(struct pch_gpio *chip)
        gpio->set = pch_gpio_set;
        gpio->dbg_show = NULL;
        gpio->base = -1;
-       gpio->ngpio = GPIO_NUM_PINS;
+       gpio->ngpio = gpio_pins[chip->ioh];
        gpio->can_sleep = 0;
+       gpio->to_irq = pch_gpio_to_irq;
+}
+
+static int pch_irq_type(struct irq_data *d, unsigned int type)
+{
+       u32 im;
+       u32 *im_reg;
+       u32 ien;
+       u32 im_pos;
+       int ch;
+       unsigned long flags;
+       u32 val;
+       int irq = d->irq;
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct pch_gpio *chip = gc->private;
+
+       ch = irq - chip->irq_base;
+       if (irq <= chip->irq_base + 7) {
+               im_reg = &chip->reg->im0;
+               im_pos = ch;
+       } else {
+               im_reg = &chip->reg->im1;
+               im_pos = ch - 8;
+       }
+       dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n",
+               __func__, irq, type, ch, im_pos);
+
+       spin_lock_irqsave(&chip->spinlock, flags);
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+               val = PCH_EDGE_RISING;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               val = PCH_EDGE_FALLING;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               val = PCH_EDGE_BOTH;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               val = PCH_LEVEL_H;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               val = PCH_LEVEL_L;
+               break;
+       case IRQ_TYPE_PROBE:
+               goto end;
+       default:
+               dev_warn(chip->dev, "%s: unknown type(%dd)",
+                       __func__, type);
+               goto end;
+       }
+
+       /* Set interrupt mode */
+       im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
+       iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+       /* iclr */
+       iowrite32(BIT(ch), &chip->reg->iclr);
+
+       /* IMASKCLR */
+       iowrite32(BIT(ch), &chip->reg->imaskclr);
+
+       /* Enable interrupt */
+       ien = ioread32(&chip->reg->ien);
+       iowrite32(ien | BIT(ch), &chip->reg->ien);
+end:
+       spin_unlock_irqrestore(&chip->spinlock, flags);
+
+       return 0;
+}
+
+static void pch_irq_unmask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct pch_gpio *chip = gc->private;
+
+       iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr);
+}
+
+static void pch_irq_mask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct pch_gpio *chip = gc->private;
+
+       iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
+}
+
+static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
+{
+       struct pch_gpio *chip = dev_id;
+       u32 reg_val = ioread32(&chip->reg->istatus);
+       int i;
+       int ret = IRQ_NONE;
+
+       for (i = 0; i < gpio_pins[chip->ioh]; i++) {
+               if (reg_val & BIT(i)) {
+                       dev_dbg(chip->dev, "%s:[%d]:irq=%d  status=0x%x\n",
+                               __func__, i, irq, reg_val);
+                       iowrite32(BIT(i), &chip->reg->iclr);
+                       generic_handle_irq(chip->irq_base + i);
+                       ret = IRQ_HANDLED;
+               }
+       }
+       return ret;
+}
+
+static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+                               unsigned int irq_start, unsigned int num)
+{
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+
+       gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base,
+                                   handle_simple_irq);
+       gc->private = chip;
+       ct = gc->chip_types;
+
+       ct->chip.irq_mask = pch_irq_mask;
+       ct->chip.irq_unmask = pch_irq_unmask;
+       ct->chip.irq_set_type = pch_irq_type;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
 static int __devinit pch_gpio_probe(struct pci_dev *pdev,
@@ -167,6 +355,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
 {
        s32 ret;
        struct pch_gpio *chip;
+       int irq_base;
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
@@ -192,6 +381,13 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
                goto err_iomap;
        }
 
+       if (pdev->device == 0x8803)
+               chip->ioh = INTEL_EG20T_PCH;
+       else if (pdev->device == 0x8014)
+               chip->ioh = OKISEMI_ML7223m_IOH;
+       else if (pdev->device == 0x8043)
+               chip->ioh = OKISEMI_ML7223n_IOH;
+
        chip->reg = chip->base;
        pci_set_drvdata(pdev, chip);
        mutex_init(&chip->lock);
@@ -202,8 +398,36 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
                goto err_gpiochip_add;
        }
 
+       irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
+       if (irq_base < 0) {
+               dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
+               chip->irq_base = -1;
+               goto end;
+       }
+       chip->irq_base = irq_base;
+
+       ret = request_irq(pdev->irq, pch_gpio_handler,
+                            IRQF_SHARED, KBUILD_MODNAME, chip);
+       if (ret != 0) {
+               dev_err(&pdev->dev,
+                       "%s request_irq failed\n", __func__);
+               goto err_request_irq;
+       }
+
+       pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
+
+       /* Initialize interrupt ien register */
+       iowrite32(0, &chip->reg->ien);
+end:
        return 0;
 
+err_request_irq:
+       irq_free_descs(irq_base, gpio_pins[chip->ioh]);
+
+       ret = gpiochip_remove(&chip->gpio);
+       if (ret)
+               dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+
 err_gpiochip_add:
        pci_iounmap(pdev, chip->base);
 
@@ -224,6 +448,12 @@ static void __devexit pch_gpio_remove(struct pci_dev *pdev)
        int err;
        struct pch_gpio *chip = pci_get_drvdata(pdev);
 
+       if (chip->irq_base != -1) {
+               free_irq(pdev->irq, chip);
+
+               irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
+       }
+
        err = gpiochip_remove(&chip->gpio);
        if (err)
                dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -239,9 +469,11 @@ static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        s32 ret;
        struct pch_gpio *chip = pci_get_drvdata(pdev);
+       unsigned long flags;
 
+       spin_lock_irqsave(&chip->spinlock, flags);
        pch_gpio_save_reg_conf(chip);
-       pch_gpio_restore_reg_conf(chip);
+       spin_unlock_irqrestore(&chip->spinlock, flags);
 
        ret = pci_save_state(pdev);
        if (ret) {
@@ -261,6 +493,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
 {
        s32 ret;
        struct pch_gpio *chip = pci_get_drvdata(pdev);
+       unsigned long flags;
 
        ret = pci_enable_wake(pdev, PCI_D0, 0);
 
@@ -272,9 +505,11 @@ static int pch_gpio_resume(struct pci_dev *pdev)
        }
        pci_restore_state(pdev);
 
+       spin_lock_irqsave(&chip->spinlock, flags);
        iowrite32(0x01, &chip->reg->reset);
        iowrite32(0x00, &chip->reg->reset);
        pch_gpio_restore_reg_conf(chip);
+       spin_unlock_irqrestore(&chip->spinlock, flags);
 
        return 0;
 }
@@ -287,6 +522,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
 static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
        { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
index 2c5a18f..093c90b 100644 (file)
@@ -118,7 +118,7 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
 {
        struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
 
-       if (chip->irq_base == (unsigned) -1)
+       if (chip->irq_base == NO_IRQ)
                return -EINVAL;
 
        return chip->irq_base + offset;
@@ -246,6 +246,18 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
        if (chip == NULL)
                return -ENOMEM;
 
+       pdata = dev->dev.platform_data;
+       if (pdata) {
+               chip->gc.base = pdata->gpio_base;
+               chip->irq_base = pdata->irq_base;
+       } else if (dev->dev.of_node) {
+               chip->gc.base = -1;
+               chip->irq_base = NO_IRQ;
+       } else {
+               ret = -ENODEV;
+               goto free_mem;
+       }
+
        if (!request_mem_region(dev->res.start,
                                resource_size(&dev->res), "pl061")) {
                ret = -EBUSY;
@@ -267,14 +279,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
        chip->gc.get = pl061_get_value;
        chip->gc.set = pl061_set_value;
        chip->gc.to_irq = pl061_to_irq;
-       chip->gc.base = pdata->gpio_base;
        chip->gc.ngpio = PL061_GPIO_NR;
        chip->gc.label = dev_name(&dev->dev);
        chip->gc.dev = &dev->dev;
        chip->gc.owner = THIS_MODULE;
 
-       chip->irq_base = pdata->irq_base;
-
        ret = gpiochip_add(&chip->gc);
        if (ret)
                goto iounmap;
@@ -283,7 +292,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
         * irq_chip support
         */
 
-       if (chip->irq_base == (unsigned) -1)
+       if (chip->irq_base == NO_IRQ)
                return 0;
 
        writeb(0, chip->base + GPIOIE); /* disable irqs */
@@ -307,11 +316,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
        list_add(&chip->list, chip_list);
 
        for (i = 0; i < PL061_GPIO_NR; i++) {
-               if (pdata->directions & (1 << i))
-                       pl061_direction_output(&chip->gc, i,
-                                       pdata->values & (1 << i));
-               else
-                       pl061_direction_input(&chip->gc, i);
+               if (pdata) {
+                       if (pdata->directions & (1 << i))
+                               pl061_direction_output(&chip->gc, i,
+                                               pdata->values & (1 << i));
+                       else
+                               pl061_direction_input(&chip->gc, i);
+               }
 
                irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
                                         handle_simple_irq);
index 4813a63..881c196 100644 (file)
@@ -320,18 +320,7 @@ static struct platform_driver altera_spi_driver = {
                .of_match_table = altera_spi_match,
        },
 };
-
-static int __init altera_spi_init(void)
-{
-       return platform_driver_register(&altera_spi_driver);
-}
-module_init(altera_spi_init);
-
-static void __exit altera_spi_exit(void)
-{
-       platform_driver_unregister(&altera_spi_driver);
-}
-module_exit(altera_spi_exit);
+module_platform_driver(altera_spi_driver);
 
 MODULE_DESCRIPTION("Altera SPI driver");
 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
index 03019bf..024b48a 100644 (file)
@@ -273,18 +273,7 @@ static struct platform_driver ath79_spi_driver = {
                .owner  = THIS_MODULE,
        },
 };
-
-static __init int ath79_spi_init(void)
-{
-       return platform_driver_register(&ath79_spi_driver);
-}
-module_init(ath79_spi_init);
-
-static __exit void ath79_spi_exit(void)
-{
-       platform_driver_unregister(&ath79_spi_driver);
-}
-module_exit(ath79_spi_exit);
+module_platform_driver(ath79_spi_driver);
 
 MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X");
 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
index d3bff42..79665e2 100644 (file)
@@ -1074,18 +1074,7 @@ static struct platform_driver atmel_spi_driver = {
        .resume         = atmel_spi_resume,
        .remove         = __exit_p(atmel_spi_remove),
 };
-
-static int __init atmel_spi_init(void)
-{
-       return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
-}
-module_init(atmel_spi_init);
-
-static void __exit atmel_spi_exit(void)
-{
-       platform_driver_unregister(&atmel_spi_driver);
-}
-module_exit(atmel_spi_exit);
+module_platform_driver(atmel_spi_driver);
 
 MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
 MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
index e557ff6..248a2cc 100644 (file)
@@ -938,15 +938,4 @@ static struct platform_driver bfin_sport_spi_driver = {
        .suspend = bfin_sport_spi_suspend,
        .resume  = bfin_sport_spi_resume,
 };
-
-static int __init bfin_sport_spi_init(void)
-{
-       return platform_driver_register(&bfin_sport_spi_driver);
-}
-module_init(bfin_sport_spi_init);
-
-static void __exit bfin_sport_spi_exit(void)
-{
-       platform_driver_unregister(&bfin_sport_spi_driver);
-}
-module_exit(bfin_sport_spi_exit);
+module_platform_driver(bfin_sport_spi_driver);
index b8d25f2..3b83ff8 100644 (file)
@@ -1098,7 +1098,7 @@ static int bfin_spi_setup(struct spi_device *spi)
 
        if (chip->pio_interrupt && !drv_data->irq_requested) {
                ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
-                       IRQF_DISABLED, "BFIN_SPI", drv_data);
+                       0, "BFIN_SPI", drv_data);
                if (ret) {
                        dev_err(&spi->dev, "Unable to register spi IRQ\n");
                        goto error;
index ae2cd1c..6eee64a 100644 (file)
@@ -487,7 +487,7 @@ static int __devinit mcfqspi_probe(struct platform_device *pdev)
                goto fail2;
        }
 
-       status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, IRQF_DISABLED,
+       status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0,
                             pdev->name, mcfqspi);
        if (status) {
                dev_dbg(&pdev->dev, "request_irq failed\n");
@@ -621,20 +621,10 @@ static struct platform_driver mcfqspi_driver = {
        .driver.name    = DRIVER_NAME,
        .driver.owner   = THIS_MODULE,
        .driver.pm      = MCFQSPI_DEV_PM_OPS,
+       .probe          = mcfqspi_probe,
        .remove         = __devexit_p(mcfqspi_remove),
 };
-
-static int __init mcfqspi_init(void)
-{
-       return platform_driver_probe(&mcfqspi_driver, mcfqspi_probe);
-}
-module_init(mcfqspi_init);
-
-static void __exit mcfqspi_exit(void)
-{
-       platform_driver_unregister(&mcfqspi_driver);
-}
-module_exit(mcfqspi_exit);
+module_platform_driver(mcfqspi_driver);
 
 MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
 MODULE_DESCRIPTION("Coldfire QSPI Controller Driver");
index 1f0ed80..31bfba8 100644 (file)
@@ -799,7 +799,7 @@ rx_dma_failed:
  * It will invoke spi_bitbang_start to create work queue so that client driver
  * can register transfer method to work queue.
  */
-static int davinci_spi_probe(struct platform_device *pdev)
+static int __devinit davinci_spi_probe(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct davinci_spi *dspi;
@@ -984,7 +984,7 @@ err:
  * It will also call spi_bitbang_stop to destroy the work queue which was
  * created by spi_bitbang_start.
  */
-static int __exit davinci_spi_remove(struct platform_device *pdev)
+static int __devexit davinci_spi_remove(struct platform_device *pdev)
 {
        struct davinci_spi *dspi;
        struct spi_master *master;
@@ -1011,20 +1011,10 @@ static struct platform_driver davinci_spi_driver = {
                .name = "spi_davinci",
                .owner = THIS_MODULE,
        },
-       .remove = __exit_p(davinci_spi_remove),
+       .probe = davinci_spi_probe,
+       .remove = __devexit_p(davinci_spi_remove),
 };
-
-static int __init davinci_spi_init(void)
-{
-       return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe);
-}
-module_init(davinci_spi_init);
-
-static void __exit davinci_spi_exit(void)
-{
-       platform_driver_unregister(&davinci_spi_driver);
-}
-module_exit(davinci_spi_exit);
+module_platform_driver(davinci_spi_driver);
 
 MODULE_DESCRIPTION("TI DaVinci SPI Master Controller Driver");
 MODULE_LICENSE("GPL");
index 130e555..e743a45 100644 (file)
@@ -116,13 +116,13 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        /* 1. setup DMA related registers */
        if (cs_change) {
                spi_enable_chip(dws, 0);
-               dw_writew(dws, dmardlr, 0xf);
-               dw_writew(dws, dmatdlr, 0x10);
+               dw_writew(dws, DW_SPI_DMARDLR, 0xf);
+               dw_writew(dws, DW_SPI_DMATDLR, 0x10);
                if (dws->tx_dma)
                        dma_ctrl |= 0x2;
                if (dws->rx_dma)
                        dma_ctrl |= 0x1;
-               dw_writew(dws, dmacr, dma_ctrl);
+               dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
                spi_enable_chip(dws, 1);
        }
 
@@ -200,7 +200,8 @@ static struct dw_spi_dma_ops mid_dma_ops = {
 
 int dw_spi_mid_init(struct dw_spi *dws)
 {
-       u32 *clk_reg, clk_cdiv;
+       void __iomem *clk_reg;
+       u32 clk_cdiv;
 
        clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
        if (!clk_reg)
index 34eb665..fac399c 100644 (file)
@@ -127,24 +127,14 @@ static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver dw_spi_mmio_driver = {
+       .probe          = dw_spi_mmio_probe,
        .remove         = __devexit_p(dw_spi_mmio_remove),
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
        },
 };
-
-static int __init dw_spi_mmio_init(void)
-{
-       return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe);
-}
-module_init(dw_spi_mmio_init);
-
-static void __exit dw_spi_mmio_exit(void)
-{
-       platform_driver_unregister(&dw_spi_mmio_driver);
-}
-module_exit(dw_spi_mmio_exit);
+module_platform_driver(dw_spi_mmio_driver);
 
 MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
 MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
index 857cd30..296d94f 100644 (file)
@@ -88,35 +88,35 @@ static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
                        "=================================\n");
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "CTRL0: \t\t0x%08x\n", dw_readl(dws, ctrl0));
+                       "CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "CTRL1: \t\t0x%08x\n", dw_readl(dws, ctrl1));
+                       "CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "SSIENR: \t0x%08x\n", dw_readl(dws, ssienr));
+                       "SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "SER: \t\t0x%08x\n", dw_readl(dws, ser));
+                       "SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "BAUDR: \t\t0x%08x\n", dw_readl(dws, baudr));
+                       "BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "TXFTLR: \t0x%08x\n", dw_readl(dws, txfltr));
+                       "TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "RXFTLR: \t0x%08x\n", dw_readl(dws, rxfltr));
+                       "RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "TXFLR: \t\t0x%08x\n", dw_readl(dws, txflr));
+                       "TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "RXFLR: \t\t0x%08x\n", dw_readl(dws, rxflr));
+                       "RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "SR: \t\t0x%08x\n", dw_readl(dws, sr));
+                       "SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "IMR: \t\t0x%08x\n", dw_readl(dws, imr));
+                       "IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "ISR: \t\t0x%08x\n", dw_readl(dws, isr));
+                       "ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "DMACR: \t\t0x%08x\n", dw_readl(dws, dmacr));
+                       "DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "DMATDLR: \t0x%08x\n", dw_readl(dws, dmatdlr));
+                       "DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-                       "DMARDLR: \t0x%08x\n", dw_readl(dws, dmardlr));
+                       "DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR));
        len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
                        "=================================\n");
 
@@ -166,7 +166,7 @@ static inline u32 tx_max(struct dw_spi *dws)
        u32 tx_left, tx_room, rxtx_gap;
 
        tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
-       tx_room = dws->fifo_len - dw_readw(dws, txflr);
+       tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR);
 
        /*
         * Another concern is about the tx/rx mismatch, we
@@ -187,7 +187,7 @@ static inline u32 rx_max(struct dw_spi *dws)
 {
        u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
 
-       return min(rx_left, (u32)dw_readw(dws, rxflr));
+       return min(rx_left, (u32)dw_readw(dws, DW_SPI_RXFLR));
 }
 
 static void dw_writer(struct dw_spi *dws)
@@ -203,7 +203,7 @@ static void dw_writer(struct dw_spi *dws)
                        else
                                txw = *(u16 *)(dws->tx);
                }
-               dw_writew(dws, dr, txw);
+               dw_writew(dws, DW_SPI_DR, txw);
                dws->tx += dws->n_bytes;
        }
 }
@@ -214,7 +214,7 @@ static void dw_reader(struct dw_spi *dws)
        u16 rxw;
 
        while (max--) {
-               rxw = dw_readw(dws, dr);
+               rxw = dw_readw(dws, DW_SPI_DR);
                /* Care rx only if the transfer's original "rx" is not null */
                if (dws->rx_end - dws->len) {
                        if (dws->n_bytes == 1)
@@ -322,13 +322,13 @@ EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
-       u16 irq_status = dw_readw(dws, isr);
+       u16 irq_status = dw_readw(dws, DW_SPI_ISR);
 
        /* Error handling */
        if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
-               dw_readw(dws, txoicr);
-               dw_readw(dws, rxoicr);
-               dw_readw(dws, rxuicr);
+               dw_readw(dws, DW_SPI_TXOICR);
+               dw_readw(dws, DW_SPI_RXOICR);
+               dw_readw(dws, DW_SPI_RXUICR);
                int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun");
                return IRQ_HANDLED;
        }
@@ -352,7 +352,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 {
        struct dw_spi *dws = dev_id;
-       u16 irq_status = dw_readw(dws, isr) & 0x3f;
+       u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f;
 
        if (!irq_status)
                return IRQ_NONE;
@@ -520,11 +520,11 @@ static void pump_transfers(unsigned long data)
         *      2. clk_div is changed
         *      3. control value changes
         */
-       if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div || imask) {
+       if (dw_readw(dws, DW_SPI_CTRL0) != cr0 || cs_change || clk_div || imask) {
                spi_enable_chip(dws, 0);
 
-               if (dw_readw(dws, ctrl0) != cr0)
-                       dw_writew(dws, ctrl0, cr0);
+               if (dw_readw(dws, DW_SPI_CTRL0) != cr0)
+                       dw_writew(dws, DW_SPI_CTRL0, cr0);
 
                spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
                spi_chip_sel(dws, spi->chip_select);
@@ -534,7 +534,7 @@ static void pump_transfers(unsigned long data)
                if (imask)
                        spi_umask_intr(dws, imask);
                if (txint_level)
-                       dw_writew(dws, txfltr, txint_level);
+                       dw_writew(dws, DW_SPI_TXFLTR, txint_level);
 
                spi_enable_chip(dws, 1);
                if (cs_change)
@@ -790,13 +790,13 @@ static void spi_hw_init(struct dw_spi *dws)
        if (!dws->fifo_len) {
                u32 fifo;
                for (fifo = 2; fifo <= 257; fifo++) {
-                       dw_writew(dws, txfltr, fifo);
-                       if (fifo != dw_readw(dws, txfltr))
+                       dw_writew(dws, DW_SPI_TXFLTR, fifo);
+                       if (fifo != dw_readw(dws, DW_SPI_TXFLTR))
                                break;
                }
 
                dws->fifo_len = (fifo == 257) ? 0 : fifo;
-               dw_writew(dws, txfltr, 0);
+               dw_writew(dws, DW_SPI_TXFLTR, 0);
        }
 }
 
index 8b7b07b..9c57c07 100644 (file)
@@ -4,6 +4,33 @@
 #include <linux/io.h>
 #include <linux/scatterlist.h>
 
+/* Register offsets */
+#define DW_SPI_CTRL0                   0x00
+#define DW_SPI_CTRL1                   0x04
+#define DW_SPI_SSIENR                  0x08
+#define DW_SPI_MWCR                    0x0c
+#define DW_SPI_SER                     0x10
+#define DW_SPI_BAUDR                   0x14
+#define DW_SPI_TXFLTR                  0x18
+#define DW_SPI_RXFLTR                  0x1c
+#define DW_SPI_TXFLR                   0x20
+#define DW_SPI_RXFLR                   0x24
+#define DW_SPI_SR                      0x28
+#define DW_SPI_IMR                     0x2c
+#define DW_SPI_ISR                     0x30
+#define DW_SPI_RISR                    0x34
+#define DW_SPI_TXOICR                  0x38
+#define DW_SPI_RXOICR                  0x3c
+#define DW_SPI_RXUICR                  0x40
+#define DW_SPI_MSTICR                  0x44
+#define DW_SPI_ICR                     0x48
+#define DW_SPI_DMACR                   0x4c
+#define DW_SPI_DMATDLR                 0x50
+#define DW_SPI_DMARDLR                 0x54
+#define DW_SPI_IDR                     0x58
+#define DW_SPI_VERSION                 0x5c
+#define DW_SPI_DR                      0x60
+
 /* Bit fields in CTRLR0 */
 #define SPI_DFS_OFFSET                 0
 
@@ -55,35 +82,6 @@ enum dw_ssi_type {
        SSI_NS_MICROWIRE,
 };
 
-struct dw_spi_reg {
-       u32     ctrl0;
-       u32     ctrl1;
-       u32     ssienr;
-       u32     mwcr;
-       u32     ser;
-       u32     baudr;
-       u32     txfltr;
-       u32     rxfltr;
-       u32     txflr;
-       u32     rxflr;
-       u32     sr;
-       u32     imr;
-       u32     isr;
-       u32     risr;
-       u32     txoicr;
-       u32     rxoicr;
-       u32     rxuicr;
-       u32     msticr;
-       u32     icr;
-       u32     dmacr;
-       u32     dmatdlr;
-       u32     dmardlr;
-       u32     idr;
-       u32     version;
-       u32     dr;             /* Currently oper as 32 bits,
-                               though only low 16 bits matters */
-} __packed;
-
 struct dw_spi;
 struct dw_spi_dma_ops {
        int (*dma_init)(struct dw_spi *dws);
@@ -161,23 +159,34 @@ struct dw_spi {
 #endif
 };
 
-#define dw_readl(dw, name) \
-       __raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writel(dw, name, val) \
-       __raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_readw(dw, name) \
-       __raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writew(dw, name, val) \
-       __raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
+static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
+{
+       return __raw_readl(dws->regs + offset);
+}
+
+static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
+{
+       __raw_writel(val, dws->regs + offset);
+}
+
+static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
+{
+       return __raw_readw(dws->regs + offset);
+}
+
+static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
+{
+       __raw_writew(val, dws->regs + offset);
+}
 
 static inline void spi_enable_chip(struct dw_spi *dws, int enable)
 {
-       dw_writel(dws, ssienr, (enable ? 1 : 0));
+       dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
 }
 
 static inline void spi_set_clk(struct dw_spi *dws, u16 div)
 {
-       dw_writel(dws, baudr, div);
+       dw_writel(dws, DW_SPI_BAUDR, div);
 }
 
 static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
@@ -188,7 +197,7 @@ static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
        if (dws->cs_control)
                dws->cs_control(1);
 
-       dw_writel(dws, ser, 1 << cs);
+       dw_writel(dws, DW_SPI_SER, 1 << cs);
 }
 
 /* Disable IRQ bits */
@@ -196,8 +205,8 @@ static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
 {
        u32 new_mask;
 
-       new_mask = dw_readl(dws, imr) & ~mask;
-       dw_writel(dws, imr, new_mask);
+       new_mask = dw_readl(dws, DW_SPI_IMR) & ~mask;
+       dw_writel(dws, DW_SPI_IMR, new_mask);
 }
 
 /* Enable IRQ bits */
@@ -205,8 +214,8 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
 {
        u32 new_mask;
 
-       new_mask = dw_readl(dws, imr) | mask;
-       dw_writel(dws, imr, new_mask);
+       new_mask = dw_readl(dws, DW_SPI_IMR) | mask;
+       dw_writel(dws, DW_SPI_IMR, new_mask);
 }
 
 /*
index 1cf6454..0a282e5 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/dmaengine.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/sched.h>
@@ -1025,7 +1026,7 @@ static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
                free_page((unsigned long)espi->zeropage);
 }
 
-static int __init ep93xx_spi_probe(struct platform_device *pdev)
+static int __devinit ep93xx_spi_probe(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct ep93xx_spi_info *info;
@@ -1150,7 +1151,7 @@ fail_release_master:
        return error;
 }
 
-static int __exit ep93xx_spi_remove(struct platform_device *pdev)
+static int __devexit ep93xx_spi_remove(struct platform_device *pdev)
 {
        struct spi_master *master = platform_get_drvdata(pdev);
        struct ep93xx_spi *espi = spi_master_get_devdata(master);
@@ -1196,20 +1197,10 @@ static struct platform_driver ep93xx_spi_driver = {
                .name   = "ep93xx-spi",
                .owner  = THIS_MODULE,
        },
-       .remove         = __exit_p(ep93xx_spi_remove),
+       .probe          = ep93xx_spi_probe,
+       .remove         = __devexit_p(ep93xx_spi_remove),
 };
-
-static int __init ep93xx_spi_init(void)
-{
-       return platform_driver_probe(&ep93xx_spi_driver, ep93xx_spi_probe);
-}
-module_init(ep93xx_spi_init);
-
-static void __exit ep93xx_spi_exit(void)
-{
-       platform_driver_unregister(&ep93xx_spi_driver);
-}
-module_exit(ep93xx_spi_exit);
+module_platform_driver(ep93xx_spi_driver);
 
 MODULE_DESCRIPTION("EP93xx SPI Controller driver");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
index 54e499d..d770f03 100644 (file)
@@ -744,18 +744,7 @@ static struct platform_driver fsl_espi_driver = {
        .probe          = of_fsl_espi_probe,
        .remove         = __devexit_p(of_fsl_espi_remove),
 };
-
-static int __init fsl_espi_init(void)
-{
-       return platform_driver_register(&fsl_espi_driver);
-}
-module_init(fsl_espi_init);
-
-static void __exit fsl_espi_exit(void)
-{
-       platform_driver_unregister(&fsl_espi_driver);
-}
-module_exit(fsl_espi_exit);
+module_platform_driver(fsl_espi_driver);
 
 MODULE_AUTHOR("Mingkai Hu");
 MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
index 0e88ab7..635ff08 100644 (file)
@@ -311,7 +311,7 @@ done:
        return value;
 }
 
-static int __init spi_gpio_probe(struct platform_device *pdev)
+static int __devinit spi_gpio_probe(struct platform_device *pdev)
 {
        int                             status;
        struct spi_master               *master;
@@ -379,7 +379,7 @@ gpio_free:
        return status;
 }
 
-static int __exit spi_gpio_remove(struct platform_device *pdev)
+static int __devexit spi_gpio_remove(struct platform_device *pdev)
 {
        struct spi_gpio                 *spi_gpio;
        struct spi_gpio_platform_data   *pdata;
@@ -408,21 +408,10 @@ MODULE_ALIAS("platform:" DRIVER_NAME);
 static struct platform_driver spi_gpio_driver = {
        .driver.name    = DRIVER_NAME,
        .driver.owner   = THIS_MODULE,
-       .remove         = __exit_p(spi_gpio_remove),
+       .probe          = spi_gpio_probe,
+       .remove         = __devexit_p(spi_gpio_remove),
 };
-
-static int __init spi_gpio_init(void)
-{
-       return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
-}
-module_init(spi_gpio_init);
-
-static void __exit spi_gpio_exit(void)
-{
-       platform_driver_unregister(&spi_gpio_driver);
-}
-module_exit(spi_gpio_exit);
-
+module_platform_driver(spi_gpio_driver);
 
 MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
 MODULE_AUTHOR("David Brownell");
index fa594d6..c6e697f 100644 (file)
@@ -929,19 +929,7 @@ static struct platform_driver spi_imx_driver = {
        .probe = spi_imx_probe,
        .remove = __devexit_p(spi_imx_remove),
 };
-
-static int __init spi_imx_init(void)
-{
-       return platform_driver_register(&spi_imx_driver);
-}
-
-static void __exit spi_imx_exit(void)
-{
-       platform_driver_unregister(&spi_imx_driver);
-}
-
-module_init(spi_imx_init);
-module_exit(spi_imx_exit);
+module_platform_driver(spi_imx_driver);
 
 MODULE_DESCRIPTION("SPI Master Controller driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
index 6a5b423..4c63f77 100644 (file)
@@ -559,18 +559,7 @@ static struct platform_driver mpc512x_psc_spi_of_driver = {
                .of_match_table = mpc512x_psc_spi_of_match,
        },
 };
-
-static int __init mpc512x_psc_spi_init(void)
-{
-       return platform_driver_register(&mpc512x_psc_spi_of_driver);
-}
-module_init(mpc512x_psc_spi_init);
-
-static void __exit mpc512x_psc_spi_exit(void)
-{
-       platform_driver_unregister(&mpc512x_psc_spi_of_driver);
-}
-module_exit(mpc512x_psc_spi_exit);
+module_platform_driver(mpc512x_psc_spi_of_driver);
 
 MODULE_AUTHOR("John Rigby");
 MODULE_DESCRIPTION("MPC512x PSC SPI Driver");
index e30baf0..6604715 100644 (file)
@@ -511,18 +511,7 @@ static struct platform_driver mpc52xx_psc_spi_of_driver = {
                .of_match_table = mpc52xx_psc_spi_of_match,
        },
 };
-
-static int __init mpc52xx_psc_spi_init(void)
-{
-       return platform_driver_register(&mpc52xx_psc_spi_of_driver);
-}
-module_init(mpc52xx_psc_spi_init);
-
-static void __exit mpc52xx_psc_spi_exit(void)
-{
-       platform_driver_unregister(&mpc52xx_psc_spi_of_driver);
-}
-module_exit(mpc52xx_psc_spi_exit);
+module_platform_driver(mpc52xx_psc_spi_of_driver);
 
 MODULE_AUTHOR("Dragos Carp");
 MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
index 015a974..57633d9 100644 (file)
@@ -564,16 +564,4 @@ static struct platform_driver mpc52xx_spi_of_driver = {
        .probe = mpc52xx_spi_probe,
        .remove = __devexit_p(mpc52xx_spi_remove),
 };
-
-static int __init mpc52xx_spi_init(void)
-{
-       return platform_driver_register(&mpc52xx_spi_of_driver);
-}
-module_init(mpc52xx_spi_init);
-
-static void __exit mpc52xx_spi_exit(void)
-{
-       platform_driver_unregister(&mpc52xx_spi_of_driver);
-}
-module_exit(mpc52xx_spi_exit);
-
+module_platform_driver(mpc52xx_spi_of_driver);
index c0a6ce8..e763254 100644 (file)
@@ -484,19 +484,7 @@ static struct platform_driver nuc900_spi_driver = {
                .owner  = THIS_MODULE,
        },
 };
-
-static int __init nuc900_spi_init(void)
-{
-       return platform_driver_register(&nuc900_spi_driver);
-}
-
-static void __exit nuc900_spi_exit(void)
-{
-       platform_driver_unregister(&nuc900_spi_driver);
-}
-
-module_init(nuc900_spi_init);
-module_exit(nuc900_spi_exit);
+module_platform_driver(nuc900_spi_driver);
 
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("nuc900 spi driver!");
index f1bde66..897274e 100644 (file)
@@ -406,18 +406,7 @@ static struct platform_driver tiny_spi_driver = {
                .of_match_table = tiny_spi_match,
        },
 };
-
-static int __init tiny_spi_init(void)
-{
-       return platform_driver_register(&tiny_spi_driver);
-}
-module_init(tiny_spi_init);
-
-static void __exit tiny_spi_exit(void)
-{
-       platform_driver_unregister(&tiny_spi_driver);
-}
-module_exit(tiny_spi_exit);
+module_platform_driver(tiny_spi_driver);
 
 MODULE_DESCRIPTION("OpenCores tiny SPI driver");
 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
index fde3a2d..322be7a 100644 (file)
@@ -1116,15 +1116,16 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
                status = -ENODEV;
                goto err1;
        }
+
+       r->start += pdata->regs_offset;
+       r->end += pdata->regs_offset;
+       mcspi->phys = r->start;
        if (!request_mem_region(r->start, resource_size(r),
                                dev_name(&pdev->dev))) {
                status = -EBUSY;
                goto err1;
        }
 
-       r->start += pdata->regs_offset;
-       r->end += pdata->regs_offset;
-       mcspi->phys = r->start;
        mcspi->base = ioremap(r->start, resource_size(r));
        if (!mcspi->base) {
                dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
index 1ab2fa0..f103e47 100644 (file)
 #define SSP_CR0_MASK_CSS_ST    (0x1FUL << 16)
 #define SSP_CR0_MASK_FRF_ST    (0x3UL << 21)
 
-
 /*
  * SSP Control Register 0  - SSP_CR1
  */
 
 #define SPI_POLLING_TIMEOUT 1000
 
-
 /*
  * The type of reading going on on this chip
  */
@@ -749,7 +747,6 @@ static void readwriter(struct pl022 *pl022)
         */
 }
 
-
 /**
  * next_transfer - Move to the Next transfer in the current spi message
  * @pl022: SSP driver private data structure
@@ -1016,14 +1013,14 @@ static int configure_dma(struct pl022 *pl022)
        dmaengine_slave_config(txchan, &tx_conf);
 
        /* Create sglists for the transfers */
-       pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
+       pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
        dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
 
-       ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL);
+       ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC);
        if (ret)
                goto err_alloc_rx_sg;
 
-       ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL);
+       ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_ATOMIC);
        if (ret)
                goto err_alloc_tx_sg;
 
@@ -1531,8 +1528,7 @@ static void pump_messages(struct work_struct *work)
        /* Initial message state */
        pl022->cur_msg->state = STATE_START;
        pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next,
-                                           struct spi_transfer,
-                                           transfer_list);
+                                           struct spi_transfer, transfer_list);
 
        /* Setup the SPI using the per chip configuration */
        pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
@@ -1551,7 +1547,6 @@ static void pump_messages(struct work_struct *work)
                do_interrupt_dma_transfer(pl022);
 }
 
-
 static int __init init_queue(struct pl022 *pl022)
 {
        INIT_LIST_HEAD(&pl022->queue);
@@ -1560,8 +1555,8 @@ static int __init init_queue(struct pl022 *pl022)
        pl022->running = false;
        pl022->busy = false;
 
-       tasklet_init(&pl022->pump_transfers,
-                       pump_transfers, (unsigned long)pl022);
+       tasklet_init(&pl022->pump_transfers, pump_transfers,
+                       (unsigned long)pl022);
 
        INIT_WORK(&pl022->pump_messages, pump_messages);
        pl022->workqueue = create_singlethread_workqueue(
@@ -1572,7 +1567,6 @@ static int __init init_queue(struct pl022 *pl022)
        return 0;
 }
 
-
 static int start_queue(struct pl022 *pl022)
 {
        unsigned long flags;
@@ -1595,7 +1589,6 @@ static int start_queue(struct pl022 *pl022)
        return 0;
 }
 
-
 static int stop_queue(struct pl022 *pl022)
 {
        unsigned long flags;
@@ -1791,71 +1784,70 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
        return 0;
 }
 
-static int calculate_effective_freq(struct pl022 *pl022,
-                                   int freq,
-                                   struct ssp_clock_params *clk_freq)
+static inline u32 spi_rate(u32 rate, u16 cpsdvsr, u16 scr)
+{
+       return rate / (cpsdvsr * (1 + scr));
+}
+
+static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
+                                   ssp_clock_params * clk_freq)
 {
        /* Lets calculate the frequency parameters */
-       u16 cpsdvsr = 2;
-       u16 scr = 0;
-       bool freq_found = false;
-       u32 rate;
-       u32 max_tclk;
-       u32 min_tclk;
+       u16 cpsdvsr = CPSDVR_MIN, scr = SCR_MIN;
+       u32 rate, max_tclk, min_tclk, best_freq = 0, best_cpsdvsr = 0,
+               best_scr = 0, tmp, found = 0;
 
        rate = clk_get_rate(pl022->clk);
        /* cpsdvscr = 2 & scr 0 */
-       max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN)));
+       max_tclk = spi_rate(rate, CPSDVR_MIN, SCR_MIN);
        /* cpsdvsr = 254 & scr = 255 */
-       min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX)));
-
-       if ((freq <= max_tclk) && (freq >= min_tclk)) {
-               while (cpsdvsr <= CPSDVR_MAX && !freq_found) {
-                       while (scr <= SCR_MAX && !freq_found) {
-                               if ((rate /
-                                    (cpsdvsr * (1 + scr))) > freq)
-                                       scr += 1;
-                               else {
-                                       /*
-                                        * This bool is made true when
-                                        * effective frequency >=
-                                        * target frequency is found
-                                        */
-                                       freq_found = true;
-                                       if ((rate /
-                                            (cpsdvsr * (1 + scr))) != freq) {
-                                               if (scr == SCR_MIN) {
-                                                       cpsdvsr -= 2;
-                                                       scr = SCR_MAX;
-                                               } else
-                                                       scr -= 1;
-                                       }
-                               }
-                       }
-                       if (!freq_found) {
-                               cpsdvsr += 2;
-                               scr = SCR_MIN;
-                       }
-               }
-               if (cpsdvsr != 0) {
-                       dev_dbg(&pl022->adev->dev,
-                               "SSP Effective Frequency is %u\n",
-                               (rate / (cpsdvsr * (1 + scr))));
-                       clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF);
-                       clk_freq->scr = (u8) (scr & 0xFF);
-                       dev_dbg(&pl022->adev->dev,
-                               "SSP cpsdvsr = %d, scr = %d\n",
-                               clk_freq->cpsdvsr, clk_freq->scr);
-               }
-       } else {
+       min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
+
+       if (!((freq <= max_tclk) && (freq >= min_tclk))) {
                dev_err(&pl022->adev->dev,
                        "controller data is incorrect: out of range frequency");
                return -EINVAL;
        }
+
+       /*
+        * best_freq will give closest possible available rate (<= requested
+        * freq) for all values of scr & cpsdvsr.
+        */
+       while ((cpsdvsr <= CPSDVR_MAX) && !found) {
+               while (scr <= SCR_MAX) {
+                       tmp = spi_rate(rate, cpsdvsr, scr);
+
+                       if (tmp > freq)
+                               scr++;
+                       /*
+                        * If found exact value, update and break.
+                        * If found more closer value, update and continue.
+                        */
+                       else if ((tmp == freq) || (tmp > best_freq)) {
+                               best_freq = tmp;
+                               best_cpsdvsr = cpsdvsr;
+                               best_scr = scr;
+
+                               if (tmp == freq)
+                                       break;
+                       }
+                       scr++;
+               }
+               cpsdvsr += 2;
+               scr = SCR_MIN;
+       }
+
+       clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
+       clk_freq->scr = (u8) (best_scr & 0xFF);
+       dev_dbg(&pl022->adev->dev,
+               "SSP Target Frequency is: %u, Effective Frequency is %u\n",
+               freq, best_freq);
+       dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
+               clk_freq->cpsdvsr, clk_freq->scr);
+
        return 0;
 }
 
-
 /*
  * A piece of default chip info unless the platform
  * supplies it.
@@ -1873,7 +1865,6 @@ static const struct pl022_config_chip pl022_default_chip_info = {
        .cs_control = null_cs_control,
 };
 
-
 /**
  * pl022_setup - setup function registered to SPI master framework
  * @spi: spi device which is requesting setup
@@ -1950,7 +1941,6 @@ static int pl022_setup(struct spi_device *spi)
                goto err_config_params;
        }
 
-
        status = verify_controller_parameters(pl022, chip_info);
        if (status) {
                dev_err(&spi->dev, "controller data is incorrect");
@@ -2090,7 +2080,8 @@ static int pl022_setup(struct spi_device *spi)
        }
        SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
        SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
-       SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
+       SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD,
+               3);
 
        /* Save controller_state */
        spi_set_ctldata(spi, chip);
@@ -2116,7 +2107,6 @@ static void pl022_cleanup(struct spi_device *spi)
        kfree(chip);
 }
 
-
 static int __devinit
 pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
@@ -2242,7 +2232,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
  err_start_queue:
  err_init_queue:
        destroy_queue(pl022);
-       pl022_dma_remove(pl022);
+       if (platform_info->enable_dma)
+               pl022_dma_remove(pl022);
+
        free_irq(adev->irq[0], pl022);
  err_no_irq:
        clk_unprepare(pl022->clk);
@@ -2277,7 +2269,9 @@ pl022_remove(struct amba_device *adev)
        if (destroy_queue(pl022) != 0)
                dev_err(&adev->dev, "queue remove failed\n");
        load_ssp_default_config(pl022);
-       pl022_dma_remove(pl022);
+       if (pl022->master_info->enable_dma)
+               pl022_dma_remove(pl022);
+
        free_irq(adev->irq[0], pl022);
        clk_disable(pl022->clk);
        clk_unprepare(pl022->clk);
@@ -2364,7 +2358,6 @@ static struct vendor_data vendor_arm = {
        .loopback = true,
 };
 
-
 static struct vendor_data vendor_st = {
        .fifodepth = 32,
        .max_bpw = 32,
@@ -2419,9 +2412,9 @@ static struct amba_id pl022_ids[] = {
                 * and 32 locations deep TX/RX FIFO but no extended
                 * CR0/CR1 register
                 */
-               .id     = 0x00080023,
-               .mask   = 0xffffffff,
-               .data   = &vendor_st_pl023,
+               .id     = 0x00080023,
+               .mask   = 0xffffffff,
+               .data   = &vendor_st_pl023,
        },
        {
                .id     = 0x10080023,
@@ -2441,19 +2434,16 @@ static struct amba_driver pl022_driver = {
        .remove         = __devexit_p(pl022_remove),
 };
 
-
 static int __init pl022_init(void)
 {
        return amba_driver_register(&pl022_driver);
 }
-
 subsys_initcall(pl022_init);
 
 static void __exit pl022_exit(void)
 {
        amba_driver_unregister(&pl022_driver);
 }
-
 module_exit(pl022_exit);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
index b267fd9..98ec532 100644 (file)
@@ -514,7 +514,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op)
        /* Request IRQ */
        hw->irqnum = irq_of_parse_and_map(np, 0);
        ret = request_irq(hw->irqnum, spi_ppc4xx_int,
-                         IRQF_DISABLED, "spi_ppc4xx_of", (void *)hw);
+                         0, "spi_ppc4xx_of", (void *)hw);
        if (ret) {
                dev_err(dev, "unable to allocate interrupt\n");
                goto free_gpios;
@@ -594,18 +594,7 @@ static struct platform_driver spi_ppc4xx_of_driver = {
                .of_match_table = spi_ppc4xx_of_match,
        },
 };
-
-static int __init spi_ppc4xx_init(void)
-{
-       return platform_driver_register(&spi_ppc4xx_of_driver);
-}
-module_init(spi_ppc4xx_init);
-
-static void __exit spi_ppc4xx_exit(void)
-{
-       platform_driver_unregister(&spi_ppc4xx_of_driver);
-}
-module_exit(spi_ppc4xx_exit);
+module_platform_driver(spi_ppc4xx_of_driver);
 
 MODULE_AUTHOR("Gary Jennejohn & Stefan Roese");
 MODULE_DESCRIPTION("Simple PPC4xx SPI Driver");
index 1996ac5..b857a3e 100644 (file)
@@ -505,7 +505,7 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
        }
 }
 
-static int __init s3c24xx_spi_probe(struct platform_device *pdev)
+static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)
 {
        struct s3c2410_spi_info *pdata;
        struct s3c24xx_spi *hw;
@@ -661,7 +661,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __exit s3c24xx_spi_remove(struct platform_device *dev)
+static int __devexit s3c24xx_spi_remove(struct platform_device *dev)
 {
        struct s3c24xx_spi *hw = platform_get_drvdata(dev);
 
@@ -719,26 +719,15 @@ static const struct dev_pm_ops s3c24xx_spi_pmops = {
 
 MODULE_ALIAS("platform:s3c2410-spi");
 static struct platform_driver s3c24xx_spi_driver = {
-       .remove         = __exit_p(s3c24xx_spi_remove),
+       .probe          = s3c24xx_spi_probe,
+       .remove         = __devexit_p(s3c24xx_spi_remove),
        .driver         = {
                .name   = "s3c2410-spi",
                .owner  = THIS_MODULE,
                .pm     = S3C24XX_SPI_PMOPS,
        },
 };
-
-static int __init s3c24xx_spi_init(void)
-{
-        return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);
-}
-
-static void __exit s3c24xx_spi_exit(void)
-{
-        platform_driver_unregister(&s3c24xx_spi_driver);
-}
-
-module_init(s3c24xx_spi_init);
-module_exit(s3c24xx_spi_exit);
+module_platform_driver(s3c24xx_spi_driver);
 
 MODULE_DESCRIPTION("S3C24XX SPI Driver");
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
index e00d94b..0f4834a 100644 (file)
@@ -635,7 +635,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
                goto err2;
        }
 
-       ret = request_irq(i, sh_msiof_spi_irq, IRQF_DISABLED,
+       ret = request_irq(i, sh_msiof_spi_irq, 0,
                          dev_name(&pdev->dev), p);
        if (ret) {
                dev_err(&pdev->dev, "unable to request irq\n");
@@ -730,18 +730,7 @@ static struct platform_driver sh_msiof_spi_drv = {
                .pm             = &sh_msiof_spi_dev_pm_ops,
        },
 };
-
-static int __init sh_msiof_spi_init(void)
-{
-       return platform_driver_register(&sh_msiof_spi_drv);
-}
-module_init(sh_msiof_spi_init);
-
-static void __exit sh_msiof_spi_exit(void)
-{
-       platform_driver_unregister(&sh_msiof_spi_drv);
-}
-module_exit(sh_msiof_spi_exit);
+module_platform_driver(sh_msiof_spi_drv);
 
 MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver");
 MODULE_AUTHOR("Magnus Damm");
index e7779c0..8844bc3 100644 (file)
@@ -186,18 +186,7 @@ static struct platform_driver sh_sci_spi_drv = {
                .owner  = THIS_MODULE,
        },
 };
-
-static int __init sh_sci_spi_init(void)
-{
-       return platform_driver_register(&sh_sci_spi_drv);
-}
-module_init(sh_sci_spi_init);
-
-static void __exit sh_sci_spi_exit(void)
-{
-       platform_driver_unregister(&sh_sci_spi_drv);
-}
-module_exit(sh_sci_spi_exit);
+module_platform_driver(sh_sci_spi_drv);
 
 MODULE_DESCRIPTION("SH SCI SPI Driver");
 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
index 9eedd71..70c8af9 100644 (file)
@@ -484,7 +484,7 @@ static int __devinit spi_sh_probe(struct platform_device *pdev)
                goto error2;
        }
 
-       ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss);
+       ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);
        if (ret < 0) {
                dev_err(&pdev->dev, "request_irq error\n");
                goto error3;
@@ -524,18 +524,7 @@ static struct platform_driver spi_sh_driver = {
                .owner = THIS_MODULE,
        },
 };
-
-static int __init spi_sh_init(void)
-{
-       return platform_driver_register(&spi_sh_driver);
-}
-module_init(spi_sh_init);
-
-static void __exit spi_sh_exit(void)
-{
-       platform_driver_unregister(&spi_sh_driver);
-}
-module_exit(spi_sh_exit);
+module_platform_driver(spi_sh_driver);
 
 MODULE_DESCRIPTION("SH SPI bus driver");
 MODULE_LICENSE("GPL");
index fadff76..58e3852 100644 (file)
@@ -659,19 +659,8 @@ static struct platform_driver stmp_spi_driver = {
        .suspend = stmp_spi_suspend,
        .resume  = stmp_spi_resume,
 };
+module_platform_driver(stmp_spi_driver);
 
-static int __init stmp_spi_init(void)
-{
-       return platform_driver_register(&stmp_spi_driver);
-}
-
-static void __exit stmp_spi_exit(void)
-{
-       platform_driver_unregister(&stmp_spi_driver);
-}
-
-module_init(stmp_spi_init);
-module_exit(stmp_spi_exit);
 module_param(pio, int, S_IRUGO);
 module_param(clock, int, S_IRUGO);
 MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
index a5a6302..ae6d78a 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -464,7 +465,7 @@ static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
        return 0;
 }
 
-static int __init spi_tegra_probe(struct platform_device *pdev)
+static int __devinit spi_tegra_probe(struct platform_device *pdev)
 {
        struct spi_master       *master;
        struct spi_tegra_data   *tspi;
@@ -612,19 +613,9 @@ static struct platform_driver spi_tegra_driver = {
                .owner =        THIS_MODULE,
                .of_match_table = spi_tegra_of_match_table,
        },
+       .probe =        spi_tegra_probe,
        .remove =       __devexit_p(spi_tegra_remove),
 };
-
-static int __init spi_tegra_init(void)
-{
-       return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe);
-}
-module_init(spi_tegra_init);
-
-static void __exit spi_tegra_exit(void)
-{
-       platform_driver_unregister(&spi_tegra_driver);
-}
-module_exit(spi_tegra_exit);
+module_platform_driver(spi_tegra_driver);
 
 MODULE_LICENSE("GPL");
index ee22795..7963c60 100644 (file)
@@ -383,18 +383,7 @@ static struct platform_driver ti_ssp_spi_driver = {
                .owner  = THIS_MODULE,
        },
 };
-
-static int __init ti_ssp_spi_init(void)
-{
-       return platform_driver_register(&ti_ssp_spi_driver);
-}
-module_init(ti_ssp_spi_init);
-
-static void __exit ti_ssp_spi_exit(void)
-{
-       platform_driver_unregister(&ti_ssp_spi_driver);
-}
-module_exit(ti_ssp_spi_exit);
+module_platform_driver(ti_ssp_spi_driver);
 
 MODULE_DESCRIPTION("SSP SPI Master");
 MODULE_AUTHOR("Cyril Chemparathy");
index 4d2c75d..4c5a663 100644 (file)
@@ -538,18 +538,7 @@ static struct platform_driver xilinx_spi_driver = {
                .of_match_table = xilinx_spi_of_match,
        },
 };
-
-static int __init xilinx_spi_pltfm_init(void)
-{
-       return platform_driver_register(&xilinx_spi_driver);
-}
-module_init(xilinx_spi_pltfm_init);
-
-static void __exit xilinx_spi_pltfm_exit(void)
-{
-       platform_driver_unregister(&xilinx_spi_driver);
-}
-module_exit(xilinx_spi_pltfm_exit);
+module_platform_driver(xilinx_spi_driver);
 
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
 MODULE_DESCRIPTION("Xilinx SPI driver");
index e58cece..e8c9cee 100644 (file)
@@ -200,17 +200,7 @@ static struct platform_driver of_platform_serial_driver = {
        .remove = of_platform_serial_remove,
 };
 
-static int __init of_platform_serial_init(void)
-{
-       return platform_driver_register(&of_platform_serial_driver);
-}
-module_init(of_platform_serial_init);
-
-static void __exit of_platform_serial_exit(void)
-{
-       return platform_driver_unregister(&of_platform_serial_driver);
-};
-module_exit(of_platform_serial_exit);
+module_platform_driver(of_platform_serial_driver);
 
 MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
 MODULE_LICENSE("GPL");
index d494001..8c86210 100644 (file)
@@ -41,6 +41,7 @@ static inline bool gpio_is_valid(int number)
 }
 
 struct device;
+struct gpio;
 struct seq_file;
 struct module;
 struct device_node;
@@ -170,18 +171,6 @@ extern int __gpio_cansleep(unsigned gpio);
 
 extern int __gpio_to_irq(unsigned gpio);
 
-/**
- * struct gpio - a structure describing a GPIO with configuration
- * @gpio:      the GPIO number
- * @flags:     GPIO configuration as specified by GPIOF_*
- * @label:     a literal description string of this GPIO
- */
-struct gpio {
-       unsigned        gpio;
-       unsigned long   flags;
-       const char      *label;
-};
-
 extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
 extern int gpio_request_array(const struct gpio *array, size_t num);
 extern void gpio_free_array(const struct gpio *array, size_t num);
@@ -220,13 +209,13 @@ static inline int gpio_cansleep(unsigned gpio)
 static inline int gpio_get_value_cansleep(unsigned gpio)
 {
        might_sleep();
-       return gpio_get_value(gpio);
+       return __gpio_get_value(gpio);
 }
 
 static inline void gpio_set_value_cansleep(unsigned gpio, int value)
 {
        might_sleep();
-       gpio_set_value(gpio, value);
+       __gpio_set_value(gpio, value);
 }
 
 #endif /* !CONFIG_GPIOLIB */
index 5ddd9ad..2412af9 100644 (file)
@@ -7,8 +7,7 @@ struct pl061_platform_data {
        unsigned        gpio_base;
 
        /* number of the first IRQ.
-        * If the IRQ functionality in not desired this must be set to
-        * (unsigned) -1.
+        * If the IRQ functionality in not desired this must be set to NO_IRQ.
         */
        unsigned        irq_base;
 
index 17b5a0d..38ac48b 100644 (file)
 #define GPIOF_OUT_INIT_LOW     (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
 #define GPIOF_OUT_INIT_HIGH    (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
 
+/**
+ * struct gpio - a structure describing a GPIO with configuration
+ * @gpio:      the GPIO number
+ * @flags:     GPIO configuration as specified by GPIOF_*
+ * @label:     a literal description string of this GPIO
+ */
+struct gpio {
+       unsigned        gpio;
+       unsigned long   flags;
+       const char      *label;
+};
+
 #ifdef CONFIG_GENERIC_GPIO
 #include <asm/gpio.h>
 
 #include <linux/errno.h>
 
 struct device;
-struct gpio;
 struct gpio_chip;
 
-/*
- * Some platforms don't support the GPIO programming interface.
- *
- * In case some driver uses it anyway (it should normally have
- * depended on GENERIC_GPIO), these routines help the compiler
- * optimize out much GPIO-related code ... or trigger a runtime
- * warning when something is wrongly called.
- */
-
 static inline bool gpio_is_valid(int number)
 {
        return false;
index 651a066..2a23f7d 100644 (file)
@@ -190,6 +190,23 @@ static inline void platform_set_drvdata(struct platform_device *pdev, void *data
        dev_set_drvdata(&pdev->dev, data);
 }
 
+/* module_platform_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit.  This eliminates a lot of
+ * boilerplate.  Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_platform_driver(__platform_driver) \
+static int __init __platform_driver##_init(void) \
+{ \
+       return platform_driver_register(&(__platform_driver)); \
+} \
+module_init(__platform_driver##_init); \
+static void __exit __platform_driver##_exit(void) \
+{ \
+       platform_driver_unregister(&(__platform_driver)); \
+} \
+module_exit(__platform_driver##_exit);
+
 extern struct platform_device *platform_create_bundle(struct platform_driver *driver,
                                        int (*probe)(struct platform_device *),
                                        struct resource *res, unsigned int n_res,
index e38544d..6cb7613 100644 (file)
@@ -211,6 +211,7 @@ irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base,
        }
        return gc;
 }
+EXPORT_SYMBOL_GPL(irq_alloc_generic_chip);
 
 /*
  * Separate lockdep class for interrupt chip which can nest irq_desc
@@ -258,6 +259,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
        }
        gc->irq_cnt = i - gc->irq_base;
 }
+EXPORT_SYMBOL_GPL(irq_setup_generic_chip);
 
 /**
  * irq_setup_alt_chip - Switch to alternative chip
@@ -281,6 +283,7 @@ int irq_setup_alt_chip(struct irq_data *d, unsigned int type)
        }
        return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(irq_setup_alt_chip);
 
 /**
  * irq_remove_generic_chip - Remove a chip
@@ -311,6 +314,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
                irq_modify_status(i, clr, set);
        }
 }
+EXPORT_SYMBOL_GPL(irq_remove_generic_chip);
 
 #ifdef CONFIG_PM
 static int irq_gc_suspend(void)