Commit 60b5adff authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents a9f4a700 038f0bab
Xilinx plb/axi GPIO controller
Dual channel GPIO controller with configurable number of pins
(from 1 to 32 per channel). Every pin can be configured as
input/output/tristate. Both channels share the same global IRQ but
local interrupts can be enabled on channel basis.
Required properties:
- compatible : Should be "xlnx,xps-gpio-1.00.a"
- reg : Address and length of the register set for the device
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
- gpio-controller : Marks the device node as a GPIO controller.
Optional properties:
- interrupts : Interrupt mapping for GPIO IRQ.
- interrupt-parent : Phandle for the interrupt controller that
services interrupts for this device.
- xlnx,all-inputs : if n-th bit is setup, GPIO-n is input
- xlnx,dout-default : if n-th bit is 1, GPIO-n default value is 1
- xlnx,gpio-width : gpio width
- xlnx,tri-default : if n-th bit is 1, GPIO-n is in tristate mode
- xlnx,is-dual : if 1, controller also uses the second channel
- xlnx,all-inputs-2 : as above but for the second channel
- xlnx,dout-default-2 : as above but the second channel
- xlnx,gpio2-width : as above but for the second channel
- xlnx,tri-default-2 : as above but for the second channel
Example:
gpio: gpio@40000000 {
#gpio-cells = <2>;
compatible = "xlnx,xps-gpio-1.00.a";
gpio-controller ;
interrupt-parent = <&microblaze_0_intc>;
interrupts = < 6 2 >;
reg = < 0x40000000 0x10000 >;
xlnx,all-inputs = <0x0>;
xlnx,all-inputs-2 = <0x0>;
xlnx,dout-default = <0x0>;
xlnx,dout-default-2 = <0x0>;
xlnx,gpio-width = <0x2>;
xlnx,gpio2-width = <0x2>;
xlnx,interrupt-present = <0x1>;
xlnx,is-dual = <0x1>;
xlnx,tri-default = <0xffffffff>;
xlnx,tri-default-2 = <0xffffffff>;
} ;
......@@ -3587,6 +3587,7 @@ GPIO SUBSYSTEM
M: Grant Likely <grant.likely@linaro.org>
M: Linus Walleij <linus.walleij@linaro.org>
S: Maintained
L: linux-gpio@vger.kernel.org
T: git git://git.secretlab.ca/git/linux-2.6.git
F: Documentation/gpio.txt
F: drivers/gpio/
......
......@@ -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"
......
......@@ -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().
......
......@@ -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;
......
......@@ -235,7 +235,7 @@ 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,
static int grgpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct grgpio_priv *priv = d->host_data;
......@@ -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;
......
......@@ -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);
......
/*
* 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;
......@@ -79,10 +78,8 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
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)
......@@ -320,54 +315,38 @@ 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)
{
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);
......@@ -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;
}
......
......@@ -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;
......
......@@ -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 >=
......
......@@ -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 = {
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -271,7 +271,7 @@ 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,
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;
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -279,7 +279,6 @@ static int vx855gpio_probe(struct platform_device *pdev)
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;
}
......
/*
* 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;
}
......
......@@ -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 @@ int gpiochip_add(struct gpio_chip *chip)
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",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment