summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 11:39:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 11:39:44 -0700
commit60b5adffb4f3e4b4c1978959f24e8e531b2ef3cb (patch)
tree998e8d9a01b8367097de46dce9d102593b97cc9a /drivers/gpio
parenta9f4a7005fb1a0f6142cbb689e734621c61574d5 (diff)
parent038f0babc98a16211959010d7cd48b4a14f108cc (diff)
downloadop-kernel-dev-60b5adffb4f3e4b4c1978959f24e8e531b2ef3cb.zip
op-kernel-dev-60b5adffb4f3e4b4c1978959f24e8e531b2ef3cb.tar.gz
Merge tag 'gpio-for-v3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "Here is a batch of GPIO changes for v3.11. I have agreed with Grant to take care of the pull requests for this development cycle. No special things are happening in the GPIO tree this time (nice with some calm) and I have been extra careful to do regression builds and it's well boiled in -next. GPIO changes for the v3.11 development cycle: - Incremental development for the Langwell (Atom SoC), Xilinx, ICH and RCAR drivers. - Cleanups from Jingoo Han, Axel Lin, Wei Jongjun, Wolfram Sang, Tushar Behera, Sachin Kamat and Yijing Wang" * tag 'gpio-for-v3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (35 commits) Gpio/trivial: replace numeric with standard PM state macros gpiolib: remove warnning of allocations with IRQs disabled gpio: grgpio: Staticize local symbols gpio-langwell: remove Withney point support gpio: ich: add GPO_BLINK support gpio-sta2x11: Convert to use devm_ioremap_resource gpio_msm: Convert to use devm_ioremap_resource gpio-rcar: Use OUTDT when reading GPIOs configured as output gpio-sta2x11: Fix potential NULL pointer dereference gpio/omap: omap_gpio_init_context stub must be inline gpio: msm-v1: Remove errant __devinit to fix compile gpio: devres: make comments proper GPIO: xilinx: Enable driver for Xilinx zynq DT: Add documentation for gpio-xilinx GPIO: xilinx: Use BIT macro GPIO: xilinx: Use __raw_readl/__raw_writel IO functions GPIO: xilinx: Add support for dual channel GPIO: xilinx: Simplify driver probe function gpio: sx150x: convert to use devm_* functions MAINTAINERS: add linux-gpio mailing list ...
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/devres.c14
-rw-r--r--drivers/gpio/gpio-bt8xx.c2
-rw-r--r--drivers/gpio/gpio-grgpio.c6
-rw-r--r--drivers/gpio/gpio-ich.c8
-rw-r--r--drivers/gpio/gpio-langwell.c164
-rw-r--r--drivers/gpio/gpio-lynxpoint.c1
-rw-r--r--drivers/gpio/gpio-ml-ioh.c1
-rw-r--r--drivers/gpio/gpio-msm-v1.c12
-rw-r--r--drivers/gpio/gpio-omap.c2
-rw-r--r--drivers/gpio/gpio-rcar.c9
-rw-r--r--drivers/gpio/gpio-rdc321x.c7
-rw-r--r--drivers/gpio/gpio-sta2x11.c6
-rw-r--r--drivers/gpio/gpio-stmpe.c7
-rw-r--r--drivers/gpio/gpio-sx150x.c18
-rw-r--r--drivers/gpio/gpio-tc3589x.c1
-rw-r--r--drivers/gpio/gpio-timberdale.c2
-rw-r--r--drivers/gpio/gpio-vx855.c2
-rw-r--r--drivers/gpio/gpio-xilinx.c144
-rw-r--r--drivers/gpio/gpiolib.c8
20 files changed, 198 insertions, 220 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 9462437..b2450ba 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -244,7 +244,7 @@ config GPIO_TS5500
config GPIO_XILINX
bool "Xilinx GPIO support"
- depends on PPC_OF || MICROBLAZE
+ depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
help
Say yes here to support the Xilinx FPGA GPIO device
@@ -340,7 +340,7 @@ config GPIO_MAX7300
depends on I2C
select GPIO_MAX730X
help
- GPIO driver for Maxim MAX7301 I2C-based GPIO expander.
+ GPIO driver for Maxim MAX7300 I2C-based GPIO expander.
config GPIO_MAX732X
tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 1077754..3e7812f 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -34,10 +34,10 @@ static int devm_gpio_match(struct device *dev, void *res, void *data)
}
/**
- * devm_gpio_request - request a gpio for a managed device
- * @dev: device to request the gpio for
- * @gpio: gpio to allocate
- * @label: the name of the requested gpio
+ * devm_gpio_request - request a GPIO for a managed device
+ * @dev: device to request the GPIO for
+ * @gpio: GPIO to allocate
+ * @label: the name of the requested GPIO
*
* Except for the extra @dev argument, this function takes the
* same arguments and performs the same function as
@@ -101,9 +101,9 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio,
EXPORT_SYMBOL(devm_gpio_request_one);
/**
- * devm_gpio_free - free an interrupt
- * @dev: device to free gpio for
- * @gpio: gpio to free
+ * devm_gpio_free - free a GPIO
+ * @dev: device to free GPIO for
+ * @gpio: GPIO to free
*
* Except for the extra @dev argument, this function takes the
* same arguments and performs the same function as gpio_free().
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c
index 7d9d7cb..8369e71 100644
--- a/drivers/gpio/gpio-bt8xx.c
+++ b/drivers/gpio/gpio-bt8xx.c
@@ -286,7 +286,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev)
unsigned long flags;
int err;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
err = pci_enable_device(pdev);
if (err)
return err;
diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
index 8e08b86..84d2478 100644
--- a/drivers/gpio/gpio-grgpio.c
+++ b/drivers/gpio/gpio-grgpio.c
@@ -235,8 +235,8 @@ static irqreturn_t grgpio_irq_handler(int irq, void *dev)
* This function will be called as a consequence of the call to
* irq_create_mapping in grgpio_to_irq
*/
-int grgpio_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
+static int grgpio_irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
{
struct grgpio_priv *priv = d->host_data;
struct grgpio_lirq *lirq;
@@ -291,7 +291,7 @@ int grgpio_irq_map(struct irq_domain *d, unsigned int irq,
return ret;
}
-void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq)
+static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq)
{
struct grgpio_priv *priv = d->host_data;
int index;
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index e16d932..2729e3d 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -41,12 +41,14 @@ enum GPIO_REG {
GPIO_USE_SEL = 0,
GPIO_IO_SEL,
GPIO_LVL,
+ GPO_BLINK
};
-static const u8 ichx_regs[3][3] = {
+static const u8 ichx_regs[4][3] = {
{0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */
{0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */
{0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */
+ {0x18, 0x18, 0x18}, /* BLINK offset */
};
static const u8 ichx_reglen[3] = {
@@ -148,6 +150,10 @@ static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
int val)
{
+ /* Disable blink hardware which is available for GPIOs from 0 to 31. */
+ if (nr < 32)
+ ichx_write_bit(GPO_BLINK, nr, 0, 0);
+
/* Set GPIO output value. */
ichx_write_bit(GPIO_LVL, nr, val, 0);
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
index 62ef10a..f4b7245 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -1,7 +1,7 @@
/*
* Moorestown platform Langwell chip GPIO driver
*
- * Copyright (c) 2008 - 2009, Intel Corporation.
+ * Copyright (c) 2008, 2009, 2013, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,7 +20,6 @@
/* Supports:
* Moorestown platform Langwell chip.
* Medfield platform Penwell chip.
- * Whitney point.
*/
#include <linux/module.h>
@@ -65,7 +64,7 @@ enum GPIO_REG {
struct lnw_gpio {
struct gpio_chip chip;
- void *reg_base;
+ void __iomem *reg_base;
spinlock_t lock;
struct pci_dev *pdev;
struct irq_domain *domain;
@@ -74,15 +73,13 @@ struct lnw_gpio {
#define to_lnw_priv(chip) container_of(chip, struct lnw_gpio, chip)
static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
- enum GPIO_REG reg_type)
+ enum GPIO_REG reg_type)
{
struct lnw_gpio *lnw = to_lnw_priv(chip);
unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 32;
- void __iomem *ptr;
- ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
- return ptr;
+ return lnw->reg_base + reg_type * nreg * 4 + reg * 4;
}
static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
@@ -91,10 +88,8 @@ static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
struct lnw_gpio *lnw = to_lnw_priv(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;
+ return lnw->reg_base + reg_type * nreg * 4 + reg * 4;
}
static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -318,56 +313,40 @@ static const struct dev_pm_ops lnw_gpio_pm_ops = {
};
static int lnw_gpio_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+ const struct pci_device_id *id)
{
- void *base;
- resource_size_t start, len;
+ void __iomem *base;
struct lnw_gpio *lnw;
u32 gpio_base;
u32 irq_base;
int retval;
int ngpio = id->driver_data;
- retval = pci_enable_device(pdev);
+ retval = pcim_enable_device(pdev);
if (retval)
return retval;
- retval = pci_request_regions(pdev, "langwell_gpio");
+ retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
if (retval) {
- dev_err(&pdev->dev, "error requesting resources\n");
- goto err_pci_req_region;
- }
- /* get the gpio_base from bar1 */
- start = pci_resource_start(pdev, 1);
- len = pci_resource_len(pdev, 1);
- base = ioremap_nocache(start, len);
- if (!base) {
- dev_err(&pdev->dev, "error mapping bar1\n");
- retval = -EFAULT;
- goto err_ioremap;
+ dev_err(&pdev->dev, "I/O memory mapping error\n");
+ return retval;
}
- irq_base = *(u32 *)base;
- gpio_base = *((u32 *)base + 1);
+
+ base = pcim_iomap_table(pdev)[1];
+
+ irq_base = readl(base);
+ gpio_base = readl(sizeof(u32) + base);
+
/* release the IO mapping, since we already get the info from bar1 */
- iounmap(base);
- /* get the register base from bar0 */
- start = pci_resource_start(pdev, 0);
- len = pci_resource_len(pdev, 0);
- base = devm_ioremap_nocache(&pdev->dev, start, len);
- if (!base) {
- dev_err(&pdev->dev, "error mapping bar0\n");
- retval = -EFAULT;
- goto err_ioremap;
- }
+ pcim_iounmap_regions(pdev, 1 << 1);
lnw = devm_kzalloc(&pdev->dev, sizeof(*lnw), GFP_KERNEL);
if (!lnw) {
- dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
- retval = -ENOMEM;
- goto err_ioremap;
+ dev_err(&pdev->dev, "can't allocate chip data\n");
+ return -ENOMEM;
}
- lnw->reg_base = base;
+ lnw->reg_base = pcim_iomap_table(pdev)[0];
lnw->chip.label = dev_name(&pdev->dev);
lnw->chip.request = lnw_gpio_request;
lnw->chip.direction_input = lnw_gpio_direction_input;
@@ -380,18 +359,18 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
lnw->chip.can_sleep = 0;
lnw->pdev = pdev;
+ spin_lock_init(&lnw->lock);
+
lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base,
&lnw_gpio_irq_ops, lnw);
- if (!lnw->domain) {
- retval = -ENOMEM;
- goto err_ioremap;
- }
+ if (!lnw->domain)
+ return -ENOMEM;
pci_set_drvdata(pdev, lnw);
retval = gpiochip_add(&lnw->chip);
if (retval) {
- dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
- goto err_ioremap;
+ dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
+ return retval;
}
lnw_irq_init_hw(lnw);
@@ -399,18 +378,10 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
irq_set_handler_data(pdev->irq, lnw);
irq_set_chained_handler(pdev->irq, lnw_irq_handler);
- spin_lock_init(&lnw->lock);
-
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
return 0;
-
-err_ioremap:
- pci_release_regions(pdev);
-err_pci_req_region:
- pci_disable_device(pdev);
- return retval;
}
static struct pci_driver lnw_gpio_driver = {
@@ -422,88 +393,9 @@ static struct pci_driver lnw_gpio_driver = {
},
};
-
-static int wp_gpio_probe(struct platform_device *pdev)
-{
- struct lnw_gpio *lnw;
- struct gpio_chip *gc;
- struct resource *rc;
- int retval = 0;
-
- rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!rc)
- return -EINVAL;
-
- lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
- if (!lnw) {
- dev_err(&pdev->dev,
- "can't allocate whitneypoint_gpio chip data\n");
- return -ENOMEM;
- }
- lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc));
- if (lnw->reg_base == NULL) {
- retval = -EINVAL;
- goto err_kmalloc;
- }
- spin_lock_init(&lnw->lock);
- gc = &lnw->chip;
- gc->label = dev_name(&pdev->dev);
- gc->owner = THIS_MODULE;
- gc->direction_input = lnw_gpio_direction_input;
- gc->direction_output = lnw_gpio_direction_output;
- gc->get = lnw_gpio_get;
- gc->set = lnw_gpio_set;
- gc->to_irq = NULL;
- gc->base = 0;
- gc->ngpio = 64;
- gc->can_sleep = 0;
- retval = gpiochip_add(gc);
- if (retval) {
- dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n",
- retval);
- goto err_ioremap;
- }
- platform_set_drvdata(pdev, lnw);
- return 0;
-err_ioremap:
- iounmap(lnw->reg_base);
-err_kmalloc:
- kfree(lnw);
- return retval;
-}
-
-static int wp_gpio_remove(struct platform_device *pdev)
-{
- struct lnw_gpio *lnw = platform_get_drvdata(pdev);
- int err;
- err = gpiochip_remove(&lnw->chip);
- if (err)
- dev_err(&pdev->dev, "failed to remove gpio_chip.\n");
- iounmap(lnw->reg_base);
- kfree(lnw);
- platform_set_drvdata(pdev, NULL);
- return 0;
-}
-
-static struct platform_driver wp_gpio_driver = {
- .probe = wp_gpio_probe,
- .remove = wp_gpio_remove,
- .driver = {
- .name = "wp_gpio",
- .owner = THIS_MODULE,
- },
-};
-
static int __init lnw_gpio_init(void)
{
- int ret;
- ret = pci_register_driver(&lnw_gpio_driver);
- if (ret < 0)
- return ret;
- ret = platform_driver_register(&wp_gpio_driver);
- if (ret < 0)
- pci_unregister_driver(&lnw_gpio_driver);
- return ret;
+ return pci_register_driver(&lnw_gpio_driver);
}
device_initcall(lnw_gpio_init);
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index 86c17de..761c470 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -447,7 +447,6 @@ static int lp_gpio_remove(struct platform_device *pdev)
err = gpiochip_remove(&lg->chip);
if (err)
dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
- platform_set_drvdata(pdev, NULL);
return 0;
}
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 0966f26..6da6d76 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -465,6 +465,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
dev_warn(&pdev->dev,
"ml_ioh_gpio: Failed to get IRQ base num\n");
chip->irq_base = -1;
+ ret = irq_base;
goto err_irq_alloc_descs;
}
chip->irq_base = irq_base;
diff --git a/drivers/gpio/gpio-msm-v1.c b/drivers/gpio/gpio-msm-v1.c
index fb2cc90..e3ceaac 100644
--- a/drivers/gpio/gpio-msm-v1.c
+++ b/drivers/gpio/gpio-msm-v1.c
@@ -652,14 +652,14 @@ static int gpio_msm_v1_probe(struct platform_device *pdev)
return irq2;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base1 = devm_request_and_ioremap(&pdev->dev, res);
- if (!base1)
- return -EADDRNOTAVAIL;
+ base1 = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base1))
+ return PTR_ERR(base1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- base2 = devm_request_and_ioremap(&pdev->dev, res);
- if (!base2)
- return -EADDRNOTAVAIL;
+ base2 = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base2))
+ return PTR_ERR(base2);
for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
if (i - FIRST_GPIO_IRQ >=
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 4a43036..dfeb3a3 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1482,7 +1482,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
#else
#define omap_gpio_runtime_suspend NULL
#define omap_gpio_runtime_resume NULL
-static void omap_gpio_init_context(struct gpio_bank *p) {}
+static inline void omap_gpio_init_context(struct gpio_bank *p) {}
#endif
static const struct dev_pm_ops gpio_pm_ops = {
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 6ec82f7..e8198dd 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -232,7 +232,14 @@ static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset)
static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
{
- return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) & BIT(offset));
+ u32 bit = BIT(offset);
+
+ /* testing on r8a7790 shows that INDT does not show correct pin state
+ * when configured as output, so use OUTDT in case of output pins */
+ if (gpio_rcar_read(gpio_to_priv(chip), INOUTSEL) & bit)
+ return (int)(gpio_rcar_read(gpio_to_priv(chip), OUTDT) & bit);
+ else
+ return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) & bit);
}
static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value)
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index 1bf55f6..368c3c0 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -187,20 +187,18 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
rdc321x_gpio_dev->reg1_data_base,
&rdc321x_gpio_dev->data_reg[0]);
if (err)
- goto out_drvdata;
+ goto out_free;
err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
rdc321x_gpio_dev->reg2_data_base,
&rdc321x_gpio_dev->data_reg[1]);
if (err)
- goto out_drvdata;
+ goto out_free;
dev_info(&pdev->dev, "registering %d GPIOs\n",
rdc321x_gpio_dev->chip.ngpio);
return gpiochip_add(&rdc321x_gpio_dev->chip);
-out_drvdata:
- platform_set_drvdata(pdev, NULL);
out_free:
kfree(rdc321x_gpio_dev);
return err;
@@ -216,7 +214,6 @@ static int rdc321x_gpio_remove(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to unregister chip\n");
kfree(rdc321x_gpio_dev);
- platform_set_drvdata(pdev, NULL);
return ret;
}
diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c
index 5585425..f43ab6a 100644
--- a/drivers/gpio/gpio-sta2x11.c
+++ b/drivers/gpio/gpio-sta2x11.c
@@ -371,8 +371,12 @@ static int gsta_probe(struct platform_device *dev)
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
chip = devm_kzalloc(&dev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
chip->dev = &dev->dev;
- chip->reg_base = devm_request_and_ioremap(&dev->dev, res);
+ chip->reg_base = devm_ioremap_resource(&dev->dev, res);
+ if (IS_ERR(chip->reg_base))
+ return PTR_ERR(chip->reg_base);
for (i = 0; i < GSTA_NR_BLOCKS; i++) {
chip->regs[i] = chip->reg_base + i * 4096;
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 3ce5bc3..b33bad1 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -271,8 +271,8 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hwirq)
+static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hwirq)
{
struct stmpe_gpio *stmpe_gpio = d->host_data;
@@ -292,7 +292,7 @@ int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
return 0;
}
-void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
+static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
{
#ifdef CONFIG_ARM
set_irq_flags(virq, 0);
@@ -431,7 +431,6 @@ static int stmpe_gpio_remove(struct platform_device *pdev)
if (irq >= 0)
free_irq(irq, stmpe_gpio);
- platform_set_drvdata(pdev, NULL);
kfree(stmpe_gpio);
return 0;
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index 796b6c4..f371732 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -548,7 +548,8 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip,
#endif
}
- err = request_threaded_irq(irq_summary,
+ err = devm_request_threaded_irq(&chip->client->dev,
+ irq_summary,
NULL,
sx150x_irq_thread_fn,
IRQF_SHARED | IRQF_TRIGGER_FALLING,
@@ -567,8 +568,6 @@ static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
unsigned n;
unsigned irq;
- free_irq(chip->irq_summary, chip);
-
for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
irq = chip->irq_base + n;
irq_set_chip_and_handler(irq, NULL, NULL);
@@ -591,18 +590,19 @@ static int sx150x_probe(struct i2c_client *client,
if (!i2c_check_functionality(client->adapter, i2c_funcs))
return -ENOSYS;
- chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL);
+ chip = devm_kzalloc(&client->dev,
+ sizeof(struct sx150x_chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
sx150x_init_chip(chip, client, id->driver_data, pdata);
rc = sx150x_init_hw(chip, pdata);
if (rc < 0)
- goto probe_fail_pre_gpiochip_add;
+ return rc;
rc = gpiochip_add(&chip->gpio_chip);
- if (rc < 0)
- goto probe_fail_pre_gpiochip_add;
+ if (rc)
+ return rc;
if (pdata->irq_summary >= 0) {
rc = sx150x_install_irq_chip(chip,
@@ -617,8 +617,6 @@ static int sx150x_probe(struct i2c_client *client,
return 0;
probe_fail_post_gpiochip_add:
WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
-probe_fail_pre_gpiochip_add:
- kfree(chip);
return rc;
}
@@ -635,8 +633,6 @@ static int sx150x_remove(struct i2c_client *client)
if (chip->irq_summary >= 0)
sx150x_remove_irq_chip(chip);
- kfree(chip);
-
return 0;
}
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index d34d80d..4a5de27 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -407,7 +407,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
free_irq(irq, tc3589x_gpio);
- platform_set_drvdata(pdev, NULL);
kfree(tc3589x_gpio);
return 0;
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index 4377405..4c65f88 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -342,8 +342,6 @@ static int timbgpio_remove(struct platform_device *pdev)
release_mem_region(iomem->start, resource_size(iomem));
kfree(tgpio);
- platform_set_drvdata(pdev, NULL);
-
return 0;
}
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
index 2b7252c..cddfa22 100644
--- a/drivers/gpio/gpio-vx855.c
+++ b/drivers/gpio/gpio-vx855.c
@@ -279,7 +279,6 @@ out_release:
release_region(res_gpi->start, resource_size(res_gpi));
if (vg->gpo_reserved)
release_region(res_gpi->start, resource_size(res_gpo));
- platform_set_drvdata(pdev, NULL);
kfree(vg);
return ret;
}
@@ -301,7 +300,6 @@ static int vx855gpio_remove(struct platform_device *pdev)
release_region(res->start, resource_size(res));
}
- platform_set_drvdata(pdev, NULL);
kfree(vg);
return 0;
}
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 9ae7aa8..792a05a 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -1,7 +1,7 @@
/*
- * Xilinx gpio driver
+ * Xilinx gpio driver for xps/axi_gpio IP.
*
- * Copyright 2008 Xilinx, Inc.
+ * Copyright 2008 - 2013 Xilinx, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -12,6 +12,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -26,11 +27,31 @@
#define XGPIO_DATA_OFFSET (0x0) /* Data register */
#define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */
+#define XGPIO_CHANNEL_OFFSET 0x8
+
+/* Read/Write access to the GPIO registers */
+#ifdef CONFIG_ARCH_ZYNQ
+# define xgpio_readreg(offset) readl(offset)
+# define xgpio_writereg(offset, val) writel(val, offset)
+#else
+# define xgpio_readreg(offset) __raw_readl(offset)
+# define xgpio_writereg(offset, val) __raw_writel(val, offset)
+#endif
+
+/**
+ * struct xgpio_instance - Stores information about GPIO device
+ * struct of_mm_gpio_chip mmchip: OF GPIO chip for memory mapped banks
+ * gpio_state: GPIO state shadow register
+ * gpio_dir: GPIO direction shadow register
+ * offset: GPIO channel offset
+ * gpio_lock: Lock used for synchronization
+ */
struct xgpio_instance {
struct of_mm_gpio_chip mmchip;
- u32 gpio_state; /* GPIO state shadow register */
- u32 gpio_dir; /* GPIO direction shadow register */
- spinlock_t gpio_lock; /* Lock used for synchronization */
+ u32 gpio_state;
+ u32 gpio_dir;
+ u32 offset;
+ spinlock_t gpio_lock;
};
/**
@@ -44,8 +65,12 @@ struct xgpio_instance {
static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct xgpio_instance *chip =
+ container_of(mm_gc, struct xgpio_instance, mmchip);
- return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1;
+ void __iomem *regs = mm_gc->regs + chip->offset;
+
+ return !!(xgpio_readreg(regs + XGPIO_DATA_OFFSET) & BIT(gpio));
}
/**
@@ -63,15 +88,18 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip);
+ void __iomem *regs = mm_gc->regs;
spin_lock_irqsave(&chip->gpio_lock, flags);
/* Write to GPIO signal and set its direction to output */
if (val)
- chip->gpio_state |= 1 << gpio;
+ chip->gpio_state |= BIT(gpio);
else
- chip->gpio_state &= ~(1 << gpio);
- out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+ chip->gpio_state &= ~BIT(gpio);
+
+ xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET,
+ chip->gpio_state);
spin_unlock_irqrestore(&chip->gpio_lock, flags);
}
@@ -91,12 +119,13 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip);
+ void __iomem *regs = mm_gc->regs;
spin_lock_irqsave(&chip->gpio_lock, flags);
/* Set the GPIO bit in shadow register and set direction as input */
- chip->gpio_dir |= (1 << gpio);
- out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+ chip->gpio_dir |= BIT(gpio);
+ xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir);
spin_unlock_irqrestore(&chip->gpio_lock, flags);
@@ -119,19 +148,21 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip);
+ void __iomem *regs = mm_gc->regs;
spin_lock_irqsave(&chip->gpio_lock, flags);
/* Write state of GPIO signal */
if (val)
- chip->gpio_state |= 1 << gpio;
+ chip->gpio_state |= BIT(gpio);
else
- chip->gpio_state &= ~(1 << gpio);
- out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+ chip->gpio_state &= ~BIT(gpio);
+ xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET,
+ chip->gpio_state);
/* Clear the GPIO bit in shadow register and set direction as output */
- chip->gpio_dir &= (~(1 << gpio));
- out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+ chip->gpio_dir &= ~BIT(gpio);
+ xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir);
spin_unlock_irqrestore(&chip->gpio_lock, flags);
@@ -147,8 +178,10 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip);
- out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
- out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+ xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_DATA_OFFSET,
+ chip->gpio_state);
+ xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_TRI_OFFSET,
+ chip->gpio_dir);
}
/**
@@ -170,24 +203,20 @@ static int xgpio_of_probe(struct device_node *np)
return -ENOMEM;
/* Update GPIO state shadow register with default value */
- tree_info = of_get_property(np, "xlnx,dout-default", NULL);
- if (tree_info)
- chip->gpio_state = be32_to_cpup(tree_info);
+ of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state);
+
+ /* By default, all pins are inputs */
+ chip->gpio_dir = 0xFFFFFFFF;
/* Update GPIO direction shadow register with default value */
- chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
- tree_info = of_get_property(np, "xlnx,tri-default", NULL);
- if (tree_info)
- chip->gpio_dir = be32_to_cpup(tree_info);
+ of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir);
+
+ /* By default assume full GPIO controller */
+ chip->mmchip.gc.ngpio = 32;
/* Check device node and parent device node for device width */
- chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
- tree_info = of_get_property(np, "xlnx,gpio-width", NULL);
- if (!tree_info)
- tree_info = of_get_property(np->parent,
- "xlnx,gpio-width", NULL);
- if (tree_info)
- chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
+ of_property_read_u32(np, "xlnx,gpio-width",
+ (u32 *)&chip->mmchip.gc.ngpio);
spin_lock_init(&chip->gpio_lock);
@@ -206,6 +235,57 @@ static int xgpio_of_probe(struct device_node *np)
np->full_name, status);
return status;
}
+
+ pr_info("XGpio: %s: registered, base is %d\n", np->full_name,
+ chip->mmchip.gc.base);
+
+ tree_info = of_get_property(np, "xlnx,is-dual", NULL);
+ if (tree_info && be32_to_cpup(tree_info)) {
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ /* Add dual channel offset */
+ chip->offset = XGPIO_CHANNEL_OFFSET;
+
+ /* Update GPIO state shadow register with default value */
+ of_property_read_u32(np, "xlnx,dout-default-2",
+ &chip->gpio_state);
+
+ /* By default, all pins are inputs */
+ chip->gpio_dir = 0xFFFFFFFF;
+
+ /* Update GPIO direction shadow register with default value */
+ of_property_read_u32(np, "xlnx,tri-default-2", &chip->gpio_dir);
+
+ /* By default assume full GPIO controller */
+ chip->mmchip.gc.ngpio = 32;
+
+ /* Check device node and parent device node for device width */
+ of_property_read_u32(np, "xlnx,gpio2-width",
+ (u32 *)&chip->mmchip.gc.ngpio);
+
+ spin_lock_init(&chip->gpio_lock);
+
+ chip->mmchip.gc.direction_input = xgpio_dir_in;
+ chip->mmchip.gc.direction_output = xgpio_dir_out;
+ chip->mmchip.gc.get = xgpio_get;
+ chip->mmchip.gc.set = xgpio_set;
+
+ chip->mmchip.save_regs = xgpio_save_regs;
+
+ /* Call the OF gpio helper to setup and register the GPIO dev */
+ status = of_mm_gpiochip_add(np, &chip->mmchip);
+ if (status) {
+ kfree(chip);
+ pr_err("%s: error in probe function with status %d\n",
+ np->full_name, status);
+ return status;
+ }
+ pr_info("XGpio: %s: dual channel registered, base is %d\n",
+ np->full_name, chip->mmchip.gc.base);
+ }
+
return 0;
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index c2534d6..ff0fd65 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1214,15 +1214,14 @@ int gpiochip_add(struct gpio_chip *chip)
}
}
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
#ifdef CONFIG_PINCTRL
INIT_LIST_HEAD(&chip->pin_ranges);
#endif
of_gpiochip_add(chip);
-unlock:
- spin_unlock_irqrestore(&gpio_lock, flags);
-
if (status)
goto fail;
@@ -1235,6 +1234,9 @@ unlock:
chip->label ? : "generic");
return 0;
+
+unlock:
+ spin_unlock_irqrestore(&gpio_lock, flags);
fail:
/* failures here can mean systems won't boot... */
pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",
OpenPOWER on IntegriCloud