Commit dff8360a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO changes from Linus Walleij:
 "So this is the LW GPIO patch stack for v3.7:
   - refactoring from Thierry Redding at Arnd Bergmann's request to use
     the seq_file iterator interface in gpiolib.
   - A new driver for Avionic Design's N-bit GPIO expander.
   - Two instances of mutexes replaced by spinlocks from Axel Lin to
     code that is supposed to be fastpath compliant.
   - IRQ demuxer and gpio_to_irq() support for pcf857x by Kuninori
     Morimoto.
   - Dynamic GPIO numbers, device tree support, daisy chaining and some
     other fixes for the 74x164 driver by Maxime Ripard.
   - IRQ domain and device tree support for the tc3589x driver by Lee
     Jones.
   - Some conversion to use managed resources devm_* code.
   - Some instances of clk_prepare() or clk_prepare_enable() added to
     support the new, stricter common clock framework.
   - Some for_each_set_bit() simplifications.
   - Then a lot of fixes as we fixed up all of the above tripping over
     our own shoelaces and that kind of thing."

* tag 'gpio-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (34 commits)
  gpio: pcf857x: select IRQ_DOMAIN
  gpio: Document device_node's det_debounce
  gpio-lpc32xx: Add GPI_28
  gpio: adnp: dt: Reference generic interrupt binding
  gpio: Add Avionic Design N-bit GPIO expander support
  gpio: pxa: using for_each_set_bit to simplify the code
  gpio_msm: using for_each_set_bit to simplify the code
  gpio: Enable the tc3298x GPIO expander driver for Device Tree
  gpio: Provide the tc3589x GPIO expander driver with an IRQ domain
  ARM: shmobile: kzm9g: use gpio-keys instead of gpio-keys-polled
  gpio: pcf857x: fixup smatch WARNING
  gpio: 74x164: Add support for the daisy-chaining
  gpio: 74x164: dts: Add documentation for the dt binding
  dt: Fix incorrect reference in gpio-led documentation
  gpio: 74x164: Add device tree support
  gpio: 74x164: Use dynamic gpio number assignment if no pdata is present
  gpio: 74x164: Use devm_kzalloc
  gpio: 74x164: Use module_spi_driver boiler plate function
  gpio: sx150x: Use irq_data_get_irq_chip_data() at appropriate places
  gpio: em: Use irq_data_get_irq_chip_data() at appropriate places
  ...
parents 916082b0 901acf5b
* Generic 8-bits shift register GPIO driver
Required properties:
- compatible : Should be "fairchild,74hc595"
- reg : chip select number
- gpio-controller : Marks the device node as a gpio controller.
- #gpio-cells : Should be two. The first cell is the pin number and
the second cell is used to specify the gpio polarity:
0 = active high
1 = active low
- registers-number: Number of daisy-chained shift registers
Example:
gpio5: gpio5@0 {
compatible = "fairchild,74hc595";
reg = <0>;
gpio-controller;
#gpio-cells = <2>;
registers-number = <4>;
spi-max-frequency = <100000>;
};
Avionic Design N-bit GPIO expander bindings
Required properties:
- compatible: should be "ad,gpio-adnp"
- reg: The I2C slave address for this device.
- interrupt-parent: phandle of the parent interrupt controller.
- interrupts: Interrupt specifier for the controllers interrupt.
- #gpio-cells: Should be 2. The first cell is the GPIO number and the
second cell is used to specify optional parameters:
- bit 0: polarity (0: normal, 1: inverted)
- gpio-controller: Marks the device as a GPIO controller
- nr-gpios: The number of pins supported by the controller.
The GPIO expander can optionally be used as an interrupt controller, in
which case it uses the default two cell specifier as described in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
Example:
gpioext: gpio-controller@41 {
compatible = "ad,gpio-adnp";
reg = <0x41>;
interrupt-parent = <&gpio>;
interrupts = <160 1>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
nr-gpios = <64>;
};
...@@ -8,7 +8,7 @@ node's name represents the name of the corresponding LED. ...@@ -8,7 +8,7 @@ node's name represents the name of the corresponding LED.
LED sub-node properties: LED sub-node properties:
- gpios : Should specify the LED's GPIO, see "gpios property" in - gpios : Should specify the LED's GPIO, see "gpios property" in
Documentation/devicetree/gpio.txt. Active low LEDs should be Documentation/devicetree/bindings/gpio/gpio.txt. Active low LEDs should be
indicated using flags in the GPIO specifier. indicated using flags in the GPIO specifier.
- label : (optional) The label for this LED. If omitted, the label is - label : (optional) The label for this LED. If omitted, the label is
taken from the node name (excluding the unit address). taken from the node name (excluding the unit address).
......
...@@ -23,7 +23,6 @@ CONFIG_MODULE_UNLOAD=y ...@@ -23,7 +23,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set # CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_SHMOBILE=y CONFIG_ARCH_SHMOBILE=y
CONFIG_KEYBOARD_GPIO_POLLED=y
CONFIG_ARCH_SH73A0=y CONFIG_ARCH_SH73A0=y
CONFIG_MACH_KZM9G=y CONFIG_MACH_KZM9G=y
CONFIG_MEMORY_START=0x41000000 CONFIG_MEMORY_START=0x41000000
...@@ -71,6 +70,7 @@ CONFIG_INPUT_SPARSEKMAP=y ...@@ -71,6 +70,7 @@ CONFIG_INPUT_SPARSEKMAP=y
# CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set # CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ST1232=y CONFIG_TOUCHSCREEN_ST1232=y
......
...@@ -482,12 +482,10 @@ static struct gpio_keys_button gpio_buttons[] = { ...@@ -482,12 +482,10 @@ static struct gpio_keys_button gpio_buttons[] = {
static struct gpio_keys_platform_data gpio_key_info = { static struct gpio_keys_platform_data gpio_key_info = {
.buttons = gpio_buttons, .buttons = gpio_buttons,
.nbuttons = ARRAY_SIZE(gpio_buttons), .nbuttons = ARRAY_SIZE(gpio_buttons),
.poll_interval = 250, /* poling at this point */
}; };
static struct platform_device gpio_keys_device = { static struct platform_device gpio_keys_device = {
/* gpio-pcf857x.c driver doesn't support gpio_to_irq() */ .name = "gpio-keys",
.name = "gpio-keys-polled",
.dev = { .dev = {
.platform_data = &gpio_key_info, .platform_data = &gpio_key_info,
}, },
...@@ -550,6 +548,7 @@ static struct platform_device fsi_ak4648_device = { ...@@ -550,6 +548,7 @@ static struct platform_device fsi_ak4648_device = {
/* I2C */ /* I2C */
static struct pcf857x_platform_data pcf8575_pdata = { static struct pcf857x_platform_data pcf8575_pdata = {
.gpio_base = GPIO_PCF8575_BASE, .gpio_base = GPIO_PCF8575_BASE,
.irq = intcs_evt2irq(0x3260), /* IRQ19 */
}; };
static struct i2c_board_info i2c0_devices[] = { static struct i2c_board_info i2c0_devices[] = {
......
...@@ -82,7 +82,7 @@ config GPIO_GENERIC ...@@ -82,7 +82,7 @@ config GPIO_GENERIC
config GPIO_DA9052 config GPIO_DA9052
tristate "Dialog DA9052 GPIO" tristate "Dialog DA9052 GPIO"
depends on PMIC_DA9052 && BROKEN depends on PMIC_DA9052
help help
Say yes here to enable the GPIO driver for the DA9052 chip. Say yes here to enable the GPIO driver for the DA9052 chip.
...@@ -330,6 +330,7 @@ config GPIO_PCA953X_IRQ ...@@ -330,6 +330,7 @@ config GPIO_PCA953X_IRQ
config GPIO_PCF857X config GPIO_PCF857X
tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
depends on I2C depends on I2C
select IRQ_DOMAIN
help help
Say yes here to provide access to most "quasi-bidirectional" I2C Say yes here to provide access to most "quasi-bidirectional" I2C
GPIO expanders used for additional digital outputs or inputs. GPIO expanders used for additional digital outputs or inputs.
...@@ -450,6 +451,17 @@ config GPIO_ADP5588_IRQ ...@@ -450,6 +451,17 @@ config GPIO_ADP5588_IRQ
Say yes here to enable the adp5588 to be used as an interrupt Say yes here to enable the adp5588 to be used as an interrupt
controller. It requires the driver to be built in the kernel. controller. It requires the driver to be built in the kernel.
config GPIO_ADNP
tristate "Avionic Design N-bit GPIO expander"
depends on I2C && OF
help
This option enables support for N GPIOs found on Avionic Design
I2C GPIO expanders. The register space will be extended by powers
of two, so the controller will need to accomodate for that. For
example: if a controller provides 48 pins, 6 registers will be
enough to represent all pins, but the driver will assume a
register layout for 64 pins (8 registers).
comment "PCI GPIO expanders:" comment "PCI GPIO expanders:"
config GPIO_CS5535 config GPIO_CS5535
......
...@@ -10,6 +10,7 @@ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o ...@@ -10,6 +10,7 @@ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
......
...@@ -14,14 +14,18 @@ ...@@ -14,14 +14,18 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/74x164.h> #include <linux/spi/74x164.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#define GEN_74X164_NUMBER_GPIOS 8
struct gen_74x164_chip { struct gen_74x164_chip {
struct spi_device *spi; struct spi_device *spi;
u8 *buffer;
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
struct mutex lock; struct mutex lock;
u8 port_config; u32 registers;
}; };
static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
...@@ -31,17 +35,47 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) ...@@ -31,17 +35,47 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
static int __gen_74x164_write_config(struct gen_74x164_chip *chip) static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
{ {
return spi_write(chip->spi, struct spi_message message;
&chip->port_config, sizeof(chip->port_config)); struct spi_transfer *msg_buf;
int i, ret = 0;
msg_buf = kzalloc(chip->registers * sizeof(struct spi_transfer),
GFP_KERNEL);
if (!msg_buf)
return -ENOMEM;
spi_message_init(&message);
/*
* Since the registers are chained, every byte sent will make
* the previous byte shift to the next register in the
* chain. Thus, the first byte send will end up in the last
* register at the end of the transfer. So, to have a logical
* numbering, send the bytes in reverse order so that the last
* byte of the buffer will end up in the last register.
*/
for (i = chip->registers - 1; i >= 0; i--) {
msg_buf[i].tx_buf = chip->buffer +i;
msg_buf[i].len = sizeof(u8);
spi_message_add_tail(msg_buf + i, &message);
}
ret = spi_sync(chip->spi, &message);
kfree(msg_buf);
return ret;
} }
static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
{ {
struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
u8 bank = offset / 8;
u8 pin = offset % 8;
int ret; int ret;
mutex_lock(&chip->lock); mutex_lock(&chip->lock);
ret = (chip->port_config >> offset) & 0x1; ret = (chip->buffer[bank] >> pin) & 0x1;
mutex_unlock(&chip->lock); mutex_unlock(&chip->lock);
return ret; return ret;
...@@ -51,12 +85,14 @@ static void gen_74x164_set_value(struct gpio_chip *gc, ...@@ -51,12 +85,14 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
unsigned offset, int val) unsigned offset, int val)
{ {
struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
u8 bank = offset / 8;
u8 pin = offset % 8;
mutex_lock(&chip->lock); mutex_lock(&chip->lock);
if (val) if (val)
chip->port_config |= (1 << offset); chip->buffer[bank] |= (1 << pin);
else else
chip->port_config &= ~(1 << offset); chip->buffer[bank] &= ~(1 << pin);
__gen_74x164_write_config(chip); __gen_74x164_write_config(chip);
mutex_unlock(&chip->lock); mutex_unlock(&chip->lock);
...@@ -75,9 +111,8 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) ...@@ -75,9 +111,8 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
struct gen_74x164_chip_platform_data *pdata; struct gen_74x164_chip_platform_data *pdata;
int ret; int ret;
pdata = spi->dev.platform_data; if (!spi->dev.of_node) {
if (!pdata || !pdata->base) { dev_err(&spi->dev, "No device tree data available.\n");
dev_dbg(&spi->dev, "incorrect or missing platform data\n");
return -EINVAL; return -EINVAL;
} }
...@@ -90,10 +125,16 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) ...@@ -90,10 +125,16 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
if (ret < 0) if (ret < 0)
return ret; return ret;
chip = kzalloc(sizeof(*chip), GFP_KERNEL); chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
pdata = spi->dev.platform_data;
if (pdata && pdata->base)
chip->gpio_chip.base = pdata->base;
else
chip->gpio_chip.base = -1;
mutex_init(&chip->lock); mutex_init(&chip->lock);
dev_set_drvdata(&spi->dev, chip); dev_set_drvdata(&spi->dev, chip);
...@@ -104,8 +145,20 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) ...@@ -104,8 +145,20 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.direction_output = gen_74x164_direction_output;
chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.get = gen_74x164_get_value;
chip->gpio_chip.set = gen_74x164_set_value; chip->gpio_chip.set = gen_74x164_set_value;
chip->gpio_chip.base = pdata->base;
chip->gpio_chip.ngpio = 8; if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) {
dev_err(&spi->dev, "Missing registers-number property in the DT.\n");
ret = -EINVAL;
goto exit_destroy;
}
chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
if (!chip->buffer) {
ret = -ENOMEM;
goto exit_destroy;
}
chip->gpio_chip.can_sleep = 1; chip->gpio_chip.can_sleep = 1;
chip->gpio_chip.dev = &spi->dev; chip->gpio_chip.dev = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE; chip->gpio_chip.owner = THIS_MODULE;
...@@ -125,7 +178,6 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) ...@@ -125,7 +178,6 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
exit_destroy: exit_destroy:
dev_set_drvdata(&spi->dev, NULL); dev_set_drvdata(&spi->dev, NULL);
mutex_destroy(&chip->lock); mutex_destroy(&chip->lock);
kfree(chip);
return ret; return ret;
} }
...@@ -141,36 +193,31 @@ static int __devexit gen_74x164_remove(struct spi_device *spi) ...@@ -141,36 +193,31 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
dev_set_drvdata(&spi->dev, NULL); dev_set_drvdata(&spi->dev, NULL);
ret = gpiochip_remove(&chip->gpio_chip); ret = gpiochip_remove(&chip->gpio_chip);
if (!ret) { if (!ret)
mutex_destroy(&chip->lock); mutex_destroy(&chip->lock);
kfree(chip); else
} else
dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
ret); ret);
return ret; return ret;
} }
static const struct of_device_id gen_74x164_dt_ids[] = {
{ .compatible = "fairchild,74hc595" },
{},
};
MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);
static struct spi_driver gen_74x164_driver = { static struct spi_driver gen_74x164_driver = {
.driver = { .driver = {
.name = "74x164", .name = "74x164",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(gen_74x164_dt_ids),
}, },
.probe = gen_74x164_probe, .probe = gen_74x164_probe,
.remove = __devexit_p(gen_74x164_remove), .remove = __devexit_p(gen_74x164_remove),
}; };
module_spi_driver(gen_74x164_driver);
static int __init gen_74x164_init(void)
{
return spi_register_driver(&gen_74x164_driver);
}
subsys_initcall(gen_74x164_init);
static void __exit gen_74x164_exit(void)
{
spi_unregister_driver(&gen_74x164_driver);
}
module_exit(gen_74x164_exit);
MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>"); MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
......
This diff is collapsed.
...@@ -483,19 +483,7 @@ static struct i2c_driver adp5588_gpio_driver = { ...@@ -483,19 +483,7 @@ static struct i2c_driver adp5588_gpio_driver = {
.id_table = adp5588_gpio_id, .id_table = adp5588_gpio_id,
}; };
static int __init adp5588_gpio_init(void) module_i2c_driver(adp5588_gpio_driver);
{
return i2c_add_driver(&adp5588_gpio_driver);
}
module_init(adp5588_gpio_init);
static void __exit adp5588_gpio_exit(void)
{
i2c_del_driver(&adp5588_gpio_driver);
}
module_exit(adp5588_gpio_exit);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("GPIO ADP5588 Driver"); MODULE_DESCRIPTION("GPIO ADP5588 Driver");
......
...@@ -310,7 +310,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev) ...@@ -310,7 +310,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev)
#define bt8xxgpio_resume NULL #define bt8xxgpio_resume NULL
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
static struct pci_device_id bt8xxgpio_pci_tbl[] = { static DEFINE_PCI_DEVICE_TABLE(bt8xxgpio_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) }, { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) }, { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) }, { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
......
...@@ -207,7 +207,7 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev) ...@@ -207,7 +207,7 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev)
struct da9052_pdata *pdata; struct da9052_pdata *pdata;
int ret; int ret;
gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (gpio == NULL) if (gpio == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -221,28 +221,19 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev) ...@@ -221,28 +221,19 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev)
ret = gpiochip_add(&gpio->gp); ret = gpiochip_add(&gpio->gp);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
goto err_mem; return ret;
} }
platform_set_drvdata(pdev, gpio); platform_set_drvdata(pdev, gpio);
return 0; return 0;
err_mem:
kfree(gpio);
return ret;
} }
static int __devexit da9052_gpio_remove(struct platform_device *pdev) static int __devexit da9052_gpio_remove(struct platform_device *pdev)
{ {
struct da9052_gpio *gpio = platform_get_drvdata(pdev); struct da9052_gpio *gpio = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&gpio->gp);
if (ret == 0)
kfree(gpio);
return ret; return gpiochip_remove(&gpio->gp);
} }
static struct platform_driver da9052_gpio_driver = { static struct platform_driver da9052_gpio_driver = {
......
...@@ -366,7 +366,7 @@ static int __init davinci_gpio_irq_setup(void) ...@@ -366,7 +366,7 @@ static int __init davinci_gpio_irq_setup(void)
PTR_ERR(clk)); PTR_ERR(clk));
return PTR_ERR(clk); return PTR_ERR(clk);
} }
clk_enable(clk); clk_prepare_enable(clk);
/* Arrange gpio_to_irq() support, handling either direct IRQs or /* Arrange gpio_to_irq() support, handling either direct IRQs or
* banked IRQs. Having GPIOs in the first GPIO bank use direct * banked IRQs. Having GPIOs in the first GPIO bank use direct
......
...@@ -85,22 +85,16 @@ static inline void em_gio_write(struct em_gio_priv *p, int offs, ...@@ -85,22 +85,16 @@ static inline void em_gio_write(struct em_gio_priv *p, int offs,
iowrite32(value, p->base1 + (offs - GIO_IDT0)); iowrite32(value, p->base1 + (offs - GIO_IDT0));
} }
static inline struct em_gio_priv *irq_to_priv(struct irq_data *d)
{
struct irq_chip *chip = irq_data_get_irq_chip(d);
return container_of(chip, struct em_gio_priv, irq_chip);
}
static void em_gio_irq_disable(struct irq_data *d) static void em_gio_irq_disable(struct irq_data *d)
{ {
struct em_gio_priv *p = irq_to_priv(d); struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d))); em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d)));
} }
static void em_gio_irq_enable(struct irq_data *d) static void em_gio_irq_enable(struct irq_data *d)
{ {
struct em_gio_priv *p = irq_to_priv(d); struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d))); em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));
} }
...@@ -118,7 +112,7 @@ static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { ...@@ -118,7 +112,7 @@ static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
static int em_gio_irq_set_type(struct irq_data *d, unsigned int type) static int em_gio_irq_set_type(struct irq_data *d, unsigned int type)
{ {
unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK]; unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK];
struct em_gio_priv *p = irq_to_priv(d); struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
unsigned int reg, offset, shift; unsigned int reg, offset, shift;
unsigned long flags; unsigned long flags;
unsigned long tmp; unsigned long tmp;
......
...@@ -113,7 +113,8 @@ static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = { ...@@ -113,7 +113,8 @@ static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
NULL, NULL, NULL, "gpi15", NULL, NULL, NULL, "gpi15",
"gpi16", "gpi17", "gpi18", "gpi19", "gpi16", "gpi17", "gpi18", "gpi19",
"gpi20", "gpi21", "gpi22", "gpi23", "gpi20", "gpi21", "gpi22", "gpi23",
"gpi24", "gpi25", "gpi26", "gpi27" "gpi24", "gpi25", "gpi26", "gpi27",
"gpi28"
}; };
static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = { static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
......
...@@ -91,10 +91,9 @@ static int mc9s08dz60_direction_output(struct gpio_chip *gc, ...@@ -91,10 +91,9 @@ static int mc9s08dz60_direction_output(struct gpio_chip *gc,
static int mc9s08dz60_probe(struct i2c_client *client, static int mc9s08dz60_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
int ret = 0;
struct mc9s08dz60 *mc9s; struct mc9s08dz60 *mc9s;
mc9s = kzalloc(sizeof(*mc9s), GFP_KERNEL); mc9s = devm_kzalloc(&client->dev, sizeof(*mc9s), GFP_KERNEL);
if (!mc9s) if (!mc9s)
return -ENOMEM; return -ENOMEM;
...@@ -110,30 +109,16 @@ static int mc9s08dz60_probe(struct i2c_client *client, ...@@ -110,30 +109,16 @@ static int mc9s08dz60_probe(struct i2c_client *client,
mc9s->client = client; mc9s->client = client;
i2c_set_clientdata(client, mc9s); i2c_set_clientdata(client, mc9s);
ret = gpiochip_add(&mc9s->chip); return gpiochip_add(&mc9s->chip);
if (ret)
goto error;
return 0;
error:
kfree(mc9s);
return ret;
} }
static int mc9s08dz60_remove(struct i2c_client *client) static int mc9s08dz60_remove(struct i2c_client *client)
{ {
struct mc9s08dz60 *mc9s; struct mc9s08dz60 *mc9s;
int ret;
mc9s = i2c_get_clientdata(client); mc9s = i2c_get_clientdata(client);
ret = gpiochip_remove(&mc9s->chip); return gpiochip_remove(&mc9s->chip);
if (!ret)
kfree(mc9s);
return ret;
} }
static const struct i2c_device_id mc9s08dz60_id[] = { static const struct i2c_device_id mc9s08dz60_id[] = {
......
...@@ -87,8 +87,7 @@ struct ioh_gpio_reg_data { ...@@ -87,8 +87,7 @@ struct ioh_gpio_reg_data {
* @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM * @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM
* @ch: Indicate GPIO channel * @ch: Indicate GPIO channel
* @irq_base: Save base of IRQ number for interrupt * @irq_base: Save base of IRQ number for interrupt
* @spinlock: Used for register access protection in * @spinlock: Used for register access protection
* interrupt context ioh_irq_type and PM;
*/ */
struct ioh_gpio { struct ioh_gpio {
void __iomem *base; void __iomem *base;
...@@ -97,7 +96,6 @@ struct ioh_gpio { ...@@ -97,7 +96,6 @@ struct ioh_gpio {
struct gpio_chip gpio; struct gpio_chip gpio;
struct ioh_gpio_reg_data ioh_gpio_reg; struct ioh_gpio_reg_data ioh_gpio_reg;
u32 gpio_use_sel; u32 gpio_use_sel;
struct mutex lock;
int ch; int ch;
int irq_base; int irq_base;
spinlock_t spinlock; spinlock_t spinlock;
...@@ -109,8 +107,9 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) ...@@ -109,8 +107,9 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
{ {
u32 reg_val; u32 reg_val;
struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
unsigned long flags;
mutex_lock(&chip->lock); spin_lock_irqsave(&chip->spinlock, flags);
reg_val = ioread32(&chip->reg->regs[chip->ch].po); reg_val = ioread32(&chip->reg->regs[chip->ch].po);
if (val) if (val)
reg_val |= (1 << nr); reg_val |= (1 << nr);
...@@ -118,7 +117,7 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) ...@@ -118,7 +117,7 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
reg_val &= ~(1 << nr); reg_val &= ~(1 << nr);
iowrite32(reg_val, &chip->reg->regs[chip->ch].po); iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
mutex_unlock(&chip->lock); spin_unlock_irqrestore(&chip->spinlock, flags);
} }
static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr) static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
...@@ -134,8 +133,9 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, ...@@ -134,8 +133,9 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
u32 pm; u32 pm;
u32 reg_val; u32 reg_val;
unsigned long flags;
mutex_lock(&chip->lock); spin_lock_irqsave(&chip->spinlock, flags);
pm = ioread32(&chip->reg->regs[chip->ch].pm) & pm = ioread32(&chip->reg->regs[chip->ch].pm) &
((1 << num_ports[chip->ch]) - 1); ((1 << num_ports[chip->ch]) - 1);
pm |= (1 << nr); pm |= (1 << nr);
...@@ -148,7 +148,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, ...@@ -148,7 +148,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
reg_val &= ~(1 << nr); reg_val &= ~(1 << nr);
iowrite32(reg_val, &chip->reg->regs[chip->ch].po); iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
mutex_unlock(&chip->lock); spin_unlock_irqrestore(&chip->spinlock, flags);
return 0; return 0;
} }
...@@ -157,13 +157,14 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) ...@@ -157,13 +157,14 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
{ {
struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
u32 pm; u32 pm;
unsigned long flags;
mutex_lock(&chip->lock); spin_lock_irqsave(&chip->spinlock, flags);
pm = ioread32(&chip->reg->regs[chip->ch].pm) & pm = ioread32(&chip->reg->regs[chip->ch].pm) &
((1 << num_ports[chip->ch]) - 1); ((1 << num_ports[chip->ch]) - 1);
pm &= ~(1 << nr); pm &= ~(1 << nr);
iowrite32(pm, &chip->reg->regs[chip->ch].pm); iowrite32(pm, &chip->reg->regs[chip->ch].pm);
mutex_unlock(&chip->lock); spin_unlock_irqrestore(&chip->spinlock, flags);
return 0; return 0;
} }
...@@ -447,7 +448,6 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, ...@@ -447,7 +448,6 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
chip->base = base; chip->base = base;
chip->reg = chip->base; chip->reg = chip->base;
chip->ch = i; chip->ch = i;
mutex_init(&chip->lock);
spin_lock_init(&chip->spinlock); spin_lock_init(&chip->spinlock);
ioh_gpio_setup(chip, num_ports[i]); ioh_gpio_setup(chip, num_ports[i]);
ret = gpiochip_add(&chip->gpio); ret = gpiochip_add(&chip->gpio);
......
...@@ -317,9 +317,7 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -317,9 +317,7 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS); for_each_set_bit(i, msm_gpio.enabled_irqs, NR_GPIO_IRQS) {
i < NR_GPIO_IRQS;
i = find_next_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS, i + 1)) {
if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS)) if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS))
generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip, generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
i)); i));
......
...@@ -23,7 +23,12 @@ ...@@ -23,7 +23,12 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pcf857x.h> #include <linux/i2c/pcf857x.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
static const struct i2c_device_id pcf857x_id[] = { static const struct i2c_device_id pcf857x_id[] = {
...@@ -60,7 +65,12 @@ struct pcf857x { ...@@ -60,7 +65,12 @@ struct pcf857x {
struct gpio_chip chip; struct gpio_chip chip;
struct i2c_client *client; struct i2c_client *client;
struct mutex lock; /* protect 'out' */ struct mutex lock; /* protect 'out' */
struct work_struct work; /* irq demux work */
struct irq_domain *irq_domain; /* for irq demux */
spinlock_t slock; /* protect irq demux */
unsigned out; /* software latch */ unsigned out; /* software latch */
unsigned status; /* current status */
int irq; /* real irq number */
int (*write)(struct i2c_client *client, unsigned data); int (*write)(struct i2c_client *client, unsigned data);
int (*read)(struct i2c_client *client); int (*read)(struct i2c_client *client);
...@@ -150,6 +160,100 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -150,6 +160,100 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
return irq_create_mapping(gpio->irq_domain, offset);
}
static void pcf857x_irq_demux_work(struct work_struct *work)
{
struct pcf857x *gpio = container_of(work,
struct pcf857x,
work);
unsigned long change, i, status, flags;
status = gpio->read(gpio->client);
spin_lock_irqsave(&gpio->slock, flags);
change = gpio->status ^ status;
for_each_set_bit(i, &change, gpio->chip.ngpio)
generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
gpio->status = status;
spin_unlock_irqrestore(&gpio->slock, flags);
}
static irqreturn_t pcf857x_irq_demux(int irq, void *data)
{
struct pcf857x *gpio = data;
/*
* pcf857x can't read/write data here,
* since i2c data access might go to sleep.
*/
schedule_work(&gpio->work);
return IRQ_HANDLED;
}
static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq,
irq_hw_number_t hw)
{
irq_set_chip_and_handler(virq,
&dummy_irq_chip,
handle_level_irq);
return 0;
}
static struct irq_domain_ops pcf857x_irq_domain_ops = {
.map = pcf857x_irq_domain_map,
};
static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
{
if (gpio->irq_domain)
irq_domain_remove(gpio->irq_domain);
if (gpio->irq)
free_irq(gpio->irq, gpio);
}
static int pcf857x_irq_domain_init(struct pcf857x *gpio,
struct pcf857x_platform_data *pdata,
struct device *dev)
{
int status;
gpio->irq_domain = irq_domain_add_linear(dev->of_node,
gpio->chip.ngpio,
&pcf857x_irq_domain_ops,
NULL);
if (!gpio->irq_domain)
goto fail;
/* enable real irq */
status = request_irq(pdata->irq, pcf857x_irq_demux, 0,
dev_name(dev), gpio);
if (status)
goto fail;
/* enable gpio_to_irq() */
INIT_WORK(&gpio->work, pcf857x_irq_demux_work);
gpio->chip.to_irq = pcf857x_to_irq;
gpio->irq = pdata->irq;
return 0;
fail:
pcf857x_irq_domain_cleanup(gpio);
return -EINVAL;
}
/*-------------------------------------------------------------------------*/
static int pcf857x_probe(struct i2c_client *client, static int pcf857x_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -168,6 +272,7 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -168,6 +272,7 @@ static int pcf857x_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
mutex_init(&gpio->lock); mutex_init(&gpio->lock);
spin_lock_init(&gpio->slock);
gpio->chip.base = pdata ? pdata->gpio_base : -1; gpio->chip.base = pdata ? pdata->gpio_base : -1;
gpio->chip.can_sleep = 1; gpio->chip.can_sleep = 1;
...@@ -179,6 +284,15 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -179,6 +284,15 @@ static int pcf857x_probe(struct i2c_client *client,
gpio->chip.direction_output = pcf857x_output; gpio->chip.direction_output = pcf857x_output;
gpio->chip.ngpio = id->driver_data; gpio->chip.ngpio = id->driver_data;
/* enable gpio_to_irq() if platform has settings */
if (pdata && pdata->irq) {
status = pcf857x_irq_domain_init(gpio, pdata, &client->dev);
if (status < 0) {
dev_err(&client->dev, "irq_domain init failed\n");
goto fail;
}
}
/* NOTE: the OnSemi jlc1562b is also largely compatible with /* NOTE: the OnSemi jlc1562b is also largely compatible with
* these parts, notably for output. It has a low-resolution * these parts, notably for output. It has a low-resolution
* DAC instead of pin change IRQs; and its inputs can be the * DAC instead of pin change IRQs; and its inputs can be the
...@@ -248,6 +362,7 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -248,6 +362,7 @@ static int pcf857x_probe(struct i2c_client *client,
* all-ones reset state. Otherwise it flags pins to be driven low. * all-ones reset state. Otherwise it flags pins to be driven low.
*/ */
gpio->out = pdata ? ~pdata->n_latch : ~0; gpio->out = pdata ? ~pdata->n_latch : ~0;
gpio->status = gpio->out;
status = gpiochip_add(&gpio->chip); status = gpiochip_add(&gpio->chip);
if (status < 0) if (status < 0)
...@@ -278,6 +393,10 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -278,6 +393,10 @@ static int pcf857x_probe(struct i2c_client *client,
fail: fail:
dev_dbg(&client->dev, "probe error %d for '%s'\n", dev_dbg(&client->dev, "probe error %d for '%s'\n",
status, client->name); status, client->name);
if (pdata && pdata->irq)
pcf857x_irq_domain_cleanup(gpio);
kfree(gpio); kfree(gpio);
return status; return status;
} }
...@@ -299,6 +418,9 @@ static int pcf857x_remove(struct i2c_client *client) ...@@ -299,6 +418,9 @@ static int pcf857x_remove(struct i2c_client *client)
} }
} }
if (pdata && pdata->irq)
pcf857x_irq_domain_cleanup(gpio);
status = gpiochip_remove(&gpio->chip); status = gpiochip_remove(&gpio->chip);
if (status == 0) if (status == 0)
kfree(gpio); kfree(gpio);
......
...@@ -92,9 +92,7 @@ struct pch_gpio_reg_data { ...@@ -92,9 +92,7 @@ struct pch_gpio_reg_data {
* @lock: Used for register access protection * @lock: Used for register access protection
* @irq_base: Save base of IRQ number for interrupt * @irq_base: Save base of IRQ number for interrupt
* @ioh: IOH ID * @ioh: IOH ID
* @spinlock: Used for register access protection in * @spinlock: Used for register access protection
* interrupt context pch_irq_mask,
* pch_irq_unmask and pch_irq_type;
*/ */
struct pch_gpio { struct pch_gpio {
void __iomem *base; void __iomem *base;
...@@ -102,7 +100,6 @@ struct pch_gpio { ...@@ -102,7 +100,6 @@ struct pch_gpio {
struct device *dev; struct device *dev;
struct gpio_chip gpio; struct gpio_chip gpio;
struct pch_gpio_reg_data pch_gpio_reg; struct pch_gpio_reg_data pch_gpio_reg;
struct mutex lock;
int irq_base; int irq_base;
enum pch_type_t ioh; enum pch_type_t ioh;
spinlock_t spinlock; spinlock_t spinlock;
...@@ -112,8 +109,9 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) ...@@ -112,8 +109,9 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
{ {
u32 reg_val; u32 reg_val;
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
unsigned long flags;
mutex_lock(&chip->lock); spin_lock_irqsave(&chip->spinlock, flags);
reg_val = ioread32(&chip->reg->po); reg_val = ioread32(&chip->reg->po);
if (val) if (val)
reg_val |= (1 << nr); reg_val |= (1 << nr);
...@@ -121,7 +119,7 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) ...@@ -121,7 +119,7 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
reg_val &= ~(1 << nr); reg_val &= ~(1 << nr);
iowrite32(reg_val, &chip->reg->po); iowrite32(reg_val, &chip->reg->po);
mutex_unlock(&chip->lock); spin_unlock_irqrestore(&chip->spinlock, flags);
} }
static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr) static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
...@@ -137,8 +135,9 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, ...@@ -137,8 +135,9 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
u32 pm; u32 pm;
u32 reg_val; u32 reg_val;
unsigned long flags;
mutex_lock(&chip->lock); spin_lock_irqsave(&chip->spinlock, flags);
pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
pm |= (1 << nr); pm |= (1 << nr);
iowrite32(pm, &chip->reg->pm); iowrite32(pm, &chip->reg->pm);
...@@ -149,8 +148,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, ...@@ -149,8 +148,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
else else
reg_val &= ~(1 << nr); reg_val &= ~(1 << nr);
iowrite32(reg_val, &chip->reg->po); iowrite32(reg_val, &chip->reg->po);
spin_unlock_irqrestore(&chip->spinlock, flags);
mutex_unlock(&chip->lock);
return 0; return 0;
} }
...@@ -159,12 +157,13 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) ...@@ -159,12 +157,13 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
{ {
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
u32 pm; u32 pm;
unsigned long flags;
mutex_lock(&chip->lock); spin_lock_irqsave(&chip->spinlock, flags);
pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
pm &= ~(1 << nr); pm &= ~(1 << nr);
iowrite32(pm, &chip->reg->pm); iowrite32(pm, &chip->reg->pm);
mutex_unlock(&chip->lock); spin_unlock_irqrestore(&chip->spinlock, flags);
return 0; return 0;
} }
...@@ -387,7 +386,6 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, ...@@ -387,7 +386,6 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
chip->reg = chip->base; chip->reg = chip->base;
pci_set_drvdata(pdev, chip); pci_set_drvdata(pdev, chip);
mutex_init(&chip->lock);
spin_lock_init(&chip->spinlock); spin_lock_init(&chip->spinlock);
pch_gpio_setup(chip); pch_gpio_setup(chip);
ret = gpiochip_add(&chip->gpio); ret = gpiochip_add(&chip->gpio);
......
...@@ -370,12 +370,10 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) ...@@ -370,12 +370,10 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
gedr = gedr & c->irq_mask; gedr = gedr & c->irq_mask;
writel_relaxed(gedr, c->regbase + GEDR_OFFSET); writel_relaxed(gedr, c->regbase + GEDR_OFFSET);
n = find_first_bit(&gedr, BITS_PER_LONG); for_each_set_bit(n, &gedr, BITS_PER_LONG) {
while (n < BITS_PER_LONG) {
loop = 1; loop = 1;
generic_handle_irq(gpio_to_irq(gpio_base + n)); generic_handle_irq(gpio_to_irq(gpio_base + n));
n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
} }
} }
} while (loop); } while (loop);
...@@ -589,19 +587,12 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) ...@@ -589,19 +587,12 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
iounmap(gpio_reg_base); iounmap(gpio_reg_base);
return PTR_ERR(clk); return PTR_ERR(clk);
} }
ret = clk_prepare(clk); ret = clk_prepare_enable(clk);
if (ret) { if (ret) {
clk_put(clk); clk_put(clk);
iounmap(gpio_reg_base); iounmap(gpio_reg_base);
return ret; return ret;
} }
ret = clk_enable(clk);
if (ret) {
clk_unprepare(clk);
clk_put(clk);
iounmap(gpio_reg_base);
return ret;
}
/* Initialize GPIO chips */ /* Initialize GPIO chips */
info = dev_get_platdata(&pdev->dev); info = dev_get_platdata(&pdev->dev);
......
...@@ -270,7 +270,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev) ...@@ -270,7 +270,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev)
kfree(sd); kfree(sd);
} }
static struct pci_device_id sdv_gpio_pci_ids[] __devinitdata = { static DEFINE_PCI_DEVICE_TABLE(sdv_gpio_pci_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) },
{ 0, }, { 0, },
}; };
......
...@@ -311,11 +311,9 @@ static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset) ...@@ -311,11 +311,9 @@ static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
static void sx150x_irq_mask(struct irq_data *d) static void sx150x_irq_mask(struct irq_data *d)
{ {
struct irq_chip *ic = irq_data_get_irq_chip(d); struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip;
unsigned n; unsigned n;
chip = container_of(ic, struct sx150x_chip, irq_chip);
n = d->irq - chip->irq_base; n = d->irq - chip->irq_base;
chip->irq_masked |= (1 << n); chip->irq_masked |= (1 << n);
chip->irq_update = n; chip->irq_update = n;
...@@ -323,27 +321,22 @@ static void sx150x_irq_mask(struct irq_data *d) ...@@ -323,27 +321,22 @@ static void sx150x_irq_mask(struct irq_data *d)
static void sx150x_irq_unmask(struct irq_data *d) static void sx150x_irq_unmask(struct irq_data *d)
{ {
struct irq_chip *ic = irq_data_get_irq_chip(d); struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip;
unsigned n; unsigned n;
chip = container_of(ic, struct sx150x_chip, irq_chip);
n = d->irq - chip->irq_base; n = d->irq - chip->irq_base;
chip->irq_masked &= ~(1 << n); chip->irq_masked &= ~(1 << n);
chip->irq_update = n; chip->irq_update = n;
} }
static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
{ {
struct irq_chip *ic = irq_data_get_irq_chip(d); struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip;
unsigned n, val = 0; unsigned n, val = 0;
if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
return -EINVAL; return -EINVAL;
chip = container_of(ic, struct sx150x_chip, irq_chip);
n = d->irq - chip->irq_base; n = d->irq - chip->irq_base;
if (flow_type & IRQ_TYPE_EDGE_RISING) if (flow_type & IRQ_TYPE_EDGE_RISING)
...@@ -391,22 +384,16 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) ...@@ -391,22 +384,16 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
static void sx150x_irq_bus_lock(struct irq_data *d) static void sx150x_irq_bus_lock(struct irq_data *d)
{ {
struct irq_chip *ic = irq_data_get_irq_chip(d); struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip;
chip = container_of(ic, struct sx150x_chip, irq_chip);
mutex_lock(&chip->lock); mutex_lock(&chip->lock);
} }
static void sx150x_irq_bus_sync_unlock(struct irq_data *d) static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
{ {
struct irq_chip *ic = irq_data_get_irq_chip(d); struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip;
unsigned n; unsigned n;
chip = container_of(ic, struct sx150x_chip, irq_chip);
if (chip->irq_update == NO_UPDATE_PENDING) if (chip->irq_update == NO_UPDATE_PENDING)
goto out; goto out;
...@@ -551,6 +538,7 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip, ...@@ -551,6 +538,7 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip,
for (n = 0; n < chip->dev_cfg->ngpios; ++n) { for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
irq = irq_base + n; irq = irq_base + n;
irq_set_chip_data(irq, chip);
irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq); irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
irq_set_nested_thread(irq, 1); irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mfd/tc3589x.h> #include <linux/mfd/tc3589x.h>
...@@ -29,6 +31,7 @@ struct tc3589x_gpio { ...@@ -29,6 +31,7 @@ struct tc3589x_gpio {
struct tc3589x *tc3589x; struct tc3589x *tc3589x;
struct device *dev; struct device *dev;
struct mutex irq_lock; struct mutex irq_lock;
struct irq_domain *domain;
int irq_base; int irq_base;
...@@ -92,11 +95,28 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip, ...@@ -92,11 +95,28 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
} }
/**
* tc3589x_gpio_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
*
* @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
* @irq: index of the interrupt requested in the chip IRQs
*
* Useful for drivers to request their own IRQs.
*/
static int tc3589x_gpio_irq_get_virq(struct tc3589x_gpio *tc3589x_gpio,
int irq)
{
if (!tc3589x_gpio)
return -EINVAL;
return irq_create_mapping(tc3589x_gpio->domain, irq);
}
static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
return tc3589x_gpio->irq_base + offset; return tc3589x_gpio_irq_get_virq(tc3589x_gpio, offset);
} }
static struct gpio_chip template_chip = { static struct gpio_chip template_chip = {
...@@ -113,7 +133,7 @@ static struct gpio_chip template_chip = { ...@@ -113,7 +133,7 @@ static struct gpio_chip template_chip = {
static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{ {
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - tc3589x_gpio->irq_base; int offset = d->hwirq;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
...@@ -175,7 +195,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) ...@@ -175,7 +195,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
static void tc3589x_gpio_irq_mask(struct irq_data *d) static void tc3589x_gpio_irq_mask(struct irq_data *d)
{ {
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - tc3589x_gpio->irq_base; int offset = d->hwirq;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
...@@ -185,7 +205,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d) ...@@ -185,7 +205,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
static void tc3589x_gpio_irq_unmask(struct irq_data *d) static void tc3589x_gpio_irq_unmask(struct irq_data *d)
{ {
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - tc3589x_gpio->irq_base; int offset = d->hwirq;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
...@@ -222,8 +242,9 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) ...@@ -222,8 +242,9 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
while (stat) { while (stat) {
int bit = __ffs(stat); int bit = __ffs(stat);
int line = i * 8 + bit; int line = i * 8 + bit;
int virq = tc3589x_gpio_irq_get_virq(tc3589x_gpio, line);
handle_nested_irq(tc3589x_gpio->irq_base + line); handle_nested_irq(virq);
stat &= ~(1 << bit); stat &= ~(1 << bit);
} }
...@@ -233,51 +254,78 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) ...@@ -233,51 +254,78 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio) static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hwirq)
{ {
int base = tc3589x_gpio->irq_base; struct tc3589x *tc3589x_gpio = d->host_data;
int irq;
for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { irq_set_chip_data(virq, tc3589x_gpio);
irq_set_chip_data(irq, tc3589x_gpio); irq_set_chip_and_handler(virq, &tc3589x_gpio_irq_chip,
irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip, handle_simple_irq);
handle_simple_irq); irq_set_nested_thread(virq, 1);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID); set_irq_flags(virq, IRQF_VALID);
#else #else
irq_set_noprobe(irq); irq_set_noprobe(virq);
#endif #endif
}
return 0; return 0;
} }
static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio) static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
{ {
int base = tc3589x_gpio->irq_base;
int irq;
for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
set_irq_flags(irq, 0); set_irq_flags(virq, 0);
#endif #endif
irq_set_chip_and_handler(irq, NULL, NULL); irq_set_chip_and_handler(virq, NULL, NULL);
irq_set_chip_data(irq, NULL); irq_set_chip_data(virq, NULL);
}
static struct irq_domain_ops tc3589x_irq_ops = {
.map = tc3589x_gpio_irq_map,
.unmap = tc3589x_gpio_irq_unmap,
.xlate = irq_domain_xlate_twocell,
};
static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
struct device_node *np)
{
int base = tc3589x_gpio->irq_base;
if (base) {
tc3589x_gpio->domain = irq_domain_add_legacy(
NULL, tc3589x_gpio->chip.ngpio, base,
0, &tc3589x_irq_ops, tc3589x_gpio);
}
else {
tc3589x_gpio->domain = irq_domain_add_linear(
np, tc3589x_gpio->chip.ngpio,
&tc3589x_irq_ops, tc3589x_gpio);
}
if (!tc3589x_gpio->domain) {
dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
return -ENOSYS;
} }
return 0;
} }
static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
{ {
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
struct tc3589x_gpio_platform_data *pdata; struct tc3589x_gpio_platform_data *pdata;
struct device_node *np = pdev->dev.of_node;
struct tc3589x_gpio *tc3589x_gpio; struct tc3589x_gpio *tc3589x_gpio;
int ret; int ret;
int irq; int irq;
pdata = tc3589x->pdata->gpio; pdata = tc3589x->pdata->gpio;
if (!pdata)
return -ENODEV; if (!(pdata || np)) {
dev_err(&pdev->dev, "No platform data or Device Tree found\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
...@@ -295,9 +343,14 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) ...@@ -295,9 +343,14 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
tc3589x_gpio->chip = template_chip; tc3589x_gpio->chip = template_chip;
tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
tc3589x_gpio->chip.dev = &pdev->dev; tc3589x_gpio->chip.dev = &pdev->dev;
tc3589x_gpio->chip.base = pdata->gpio_base; tc3589x_gpio->chip.base = (pdata) ? pdata->gpio_base : -1;
tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0); #ifdef CONFIG_OF_GPIO
tc3589x_gpio->chip.of_node = np;
#endif
tc3589x_gpio->irq_base = tc3589x->irq_base ?
tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0;
/* Bring the GPIO module out of reset */ /* Bring the GPIO module out of reset */
ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
...@@ -305,7 +358,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) ...@@ -305,7 +358,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto out_free; goto out_free;
ret = tc3589x_gpio_irq_init(tc3589x_gpio); ret = tc3589x_gpio_irq_init(tc3589x_gpio, np);
if (ret) if (ret)
goto out_free; goto out_free;
...@@ -313,7 +366,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) ...@@ -313,7 +366,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
"tc3589x-gpio", tc3589x_gpio); "tc3589x-gpio", tc3589x_gpio);
if (ret) { if (ret) {
dev_err(&pdev->dev, "unable to get irq: %d\n", ret); dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
goto out_removeirq; goto out_free;
} }
ret = gpiochip_add(&tc3589x_gpio->chip); ret = gpiochip_add(&tc3589x_gpio->chip);
...@@ -322,7 +375,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) ...@@ -322,7 +375,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
goto out_freeirq; goto out_freeirq;
} }
if (pdata->setup) if (pdata && pdata->setup)
pdata->setup(tc3589x, tc3589x_gpio->chip.base); pdata->setup(tc3589x, tc3589x_gpio->chip.base);
platform_set_drvdata(pdev, tc3589x_gpio); platform_set_drvdata(pdev, tc3589x_gpio);
...@@ -331,8 +384,6 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) ...@@ -331,8 +384,6 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
out_freeirq: out_freeirq:
free_irq(irq, tc3589x_gpio); free_irq(irq, tc3589x_gpio);
out_removeirq:
tc3589x_gpio_irq_remove(tc3589x_gpio);
out_free: out_free:
kfree(tc3589x_gpio); kfree(tc3589x_gpio);
return ret; return ret;
...@@ -346,7 +397,7 @@ static int __devexit tc3589x_gpio_remove(struct platform_device *pdev) ...@@ -346,7 +397,7 @@ static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
int irq = platform_get_irq(pdev, 0); int irq = platform_get_irq(pdev, 0);
int ret; int ret;
if (pdata->remove) if (pdata && pdata->remove)
pdata->remove(tc3589x, tc3589x_gpio->chip.base); pdata->remove(tc3589x, tc3589x_gpio->chip.base);
ret = gpiochip_remove(&tc3589x_gpio->chip); ret = gpiochip_remove(&tc3589x_gpio->chip);
...@@ -357,7 +408,6 @@ static int __devexit tc3589x_gpio_remove(struct platform_device *pdev) ...@@ -357,7 +408,6 @@ static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
} }
free_irq(irq, tc3589x_gpio); free_irq(irq, tc3589x_gpio);
tc3589x_gpio_irq_remove(tc3589x_gpio);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(tc3589x_gpio); kfree(tc3589x_gpio);
......
...@@ -70,7 +70,6 @@ static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset) ...@@ -70,7 +70,6 @@ static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset)
return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
GPIO_CFG_MASK); GPIO_CFG_MASK);
} }
static struct gpio_chip template_chip = { static struct gpio_chip template_chip = {
...@@ -92,7 +91,8 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev) ...@@ -92,7 +91,8 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
struct tps65912_gpio_data *tps65912_gpio; struct tps65912_gpio_data *tps65912_gpio;
int ret; int ret;
tps65912_gpio = kzalloc(sizeof(*tps65912_gpio), GFP_KERNEL); tps65912_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65912_gpio),
GFP_KERNEL);
if (tps65912_gpio == NULL) if (tps65912_gpio == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -105,28 +105,19 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev) ...@@ -105,28 +105,19 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
ret = gpiochip_add(&tps65912_gpio->gpio_chip); ret = gpiochip_add(&tps65912_gpio->gpio_chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
goto err; return ret;
} }
platform_set_drvdata(pdev, tps65912_gpio); platform_set_drvdata(pdev, tps65912_gpio);
return ret; return ret;
err:
kfree(tps65912_gpio);
return ret;
} }
static int __devexit tps65912_gpio_remove(struct platform_device *pdev) static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
{ {
struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev); struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&tps65912_gpio->gpio_chip);
if (ret == 0)
kfree(tps65912_gpio);
return ret; return gpiochip_remove(&tps65912_gpio->gpio_chip);
} }
static struct platform_driver tps65912_gpio_driver = { static struct platform_driver tps65912_gpio_driver = {
......
...@@ -250,7 +250,8 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev) ...@@ -250,7 +250,8 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
struct wm831x_gpio *wm831x_gpio; struct wm831x_gpio *wm831x_gpio;
int ret; int ret;
wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL); wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio),
GFP_KERNEL);
if (wm831x_gpio == NULL) if (wm831x_gpio == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -265,30 +266,20 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev) ...@@ -265,30 +266,20 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
ret = gpiochip_add(&wm831x_gpio->gpio_chip); ret = gpiochip_add(&wm831x_gpio->gpio_chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
ret); return ret;
goto err;
} }
platform_set_drvdata(pdev, wm831x_gpio); platform_set_drvdata(pdev, wm831x_gpio);
return ret; return ret;
err:
kfree(wm831x_gpio);
return ret;
} }
static int __devexit wm831x_gpio_remove(struct platform_device *pdev) static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
{ {
struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev); struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&wm831x_gpio->gpio_chip);
if (ret == 0)
kfree(wm831x_gpio);
return ret; return gpiochip_remove(&wm831x_gpio->gpio_chip);
} }
static struct platform_driver wm831x_gpio_driver = { static struct platform_driver wm831x_gpio_driver = {
......
...@@ -116,7 +116,8 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev) ...@@ -116,7 +116,8 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
struct wm8350_gpio_data *wm8350_gpio; struct wm8350_gpio_data *wm8350_gpio;
int ret; int ret;
wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL); wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio),
GFP_KERNEL);
if (wm8350_gpio == NULL) if (wm8350_gpio == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -131,30 +132,20 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev) ...@@ -131,30 +132,20 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
ret = gpiochip_add(&wm8350_gpio->gpio_chip); ret = gpiochip_add(&wm8350_gpio->gpio_chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
ret); return ret;
goto err;
} }
platform_set_drvdata(pdev, wm8350_gpio); platform_set_drvdata(pdev, wm8350_gpio);
return ret; return ret;
err:
kfree(wm8350_gpio);
return ret;
} }
static int __devexit wm8350_gpio_remove(struct platform_device *pdev) static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
{ {
struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev); struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
if (ret == 0)
kfree(wm8350_gpio);
return ret; return gpiochip_remove(&wm8350_gpio->gpio_chip);
} }
static struct platform_driver wm8350_gpio_driver = { static struct platform_driver wm8350_gpio_driver = {
......
...@@ -1773,56 +1773,102 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -1773,56 +1773,102 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
} }
} }
static int gpiolib_show(struct seq_file *s, void *unused) static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos)
{ {
struct gpio_chip *chip = NULL; struct gpio_chip *chip = NULL;
unsigned gpio; unsigned int gpio;
int started = 0; void *ret = NULL;
loff_t index = 0;
/* REVISIT this isn't locked against gpio_chip removal ... */ /* REVISIT this isn't locked against gpio_chip removal ... */
for (gpio = 0; gpio_is_valid(gpio); gpio++) { for (gpio = 0; gpio_is_valid(gpio); gpio++) {
struct device *dev; if (gpio_desc[gpio].chip == chip)
if (chip == gpio_desc[gpio].chip)
continue; continue;
chip = gpio_desc[gpio].chip; chip = gpio_desc[gpio].chip;
if (!chip) if (!chip)
continue; continue;
seq_printf(s, "%sGPIOs %d-%d", if (index++ >= *pos) {
started ? "\n" : "", ret = chip;
chip->base, chip->base + chip->ngpio - 1); break;
dev = chip->dev; }
if (dev)
seq_printf(s, ", %s/%s",
dev->bus ? dev->bus->name : "no-bus",
dev_name(dev));
if (chip->label)
seq_printf(s, ", %s", chip->label);
if (chip->can_sleep)
seq_printf(s, ", can sleep");
seq_printf(s, ":\n");
started = 1;
if (chip->dbg_show)
chip->dbg_show(s, chip);
else
gpiolib_dbg_show(s, chip);
} }
s->private = "";
return ret;
}
static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
struct gpio_chip *chip = v;
unsigned int gpio;
void *ret = NULL;
/* skip GPIOs provided by the current chip */
for (gpio = chip->base + chip->ngpio; gpio_is_valid(gpio); gpio++) {
chip = gpio_desc[gpio].chip;
if (chip) {
ret = chip;
break;
}
}
s->private = "\n";
++*pos;
return ret;
}
static void gpiolib_seq_stop(struct seq_file *s, void *v)
{
}
static int gpiolib_seq_show(struct seq_file *s, void *v)
{
struct gpio_chip *chip = v;
struct device *dev;
seq_printf(s, "%sGPIOs %d-%d", (char *)s->private,
chip->base, chip->base + chip->ngpio - 1);
dev = chip->dev;
if (dev)
seq_printf(s, ", %s/%s", dev->bus ? dev->bus->name : "no-bus",
dev_name(dev));
if (chip->label)
seq_printf(s, ", %s", chip->label);
if (chip->can_sleep)
seq_printf(s, ", can sleep");
seq_printf(s, ":\n");
if (chip->dbg_show)
chip->dbg_show(s, chip);
else
gpiolib_dbg_show(s, chip);
return 0; return 0;
} }
static const struct seq_operations gpiolib_seq_ops = {
.start = gpiolib_seq_start,
.next = gpiolib_seq_next,
.stop = gpiolib_seq_stop,
.show = gpiolib_seq_show,
};
static int gpiolib_open(struct inode *inode, struct file *file) static int gpiolib_open(struct inode *inode, struct file *file)
{ {
return single_open(file, gpiolib_show, NULL); return seq_open(file, &gpiolib_seq_ops);
} }
static const struct file_operations gpiolib_operations = { static const struct file_operations gpiolib_operations = {
.owner = THIS_MODULE,
.open = gpiolib_open, .open = gpiolib_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = seq_release,
}; };
static int __init gpiolib_debugfs_init(void) static int __init gpiolib_debugfs_init(void)
......
...@@ -60,6 +60,8 @@ struct device_node; ...@@ -60,6 +60,8 @@ struct device_node;
* @get: returns value for signal "offset"; for output signals this * @get: returns value for signal "offset"; for output signals this
* returns either the value actually sensed, or zero * returns either the value actually sensed, or zero
* @direction_output: configures signal "offset" as output, or returns error * @direction_output: configures signal "offset" as output, or returns error
* @set_debounce: optional hook for setting debounce time for specified gpio in
* interrupt triggered gpio chips
* @set: assigns output value for signal "offset" * @set: assigns output value for signal "offset"
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings; * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
* implementation may not sleep * implementation may not sleep
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* @setup: optional callback issued once the GPIOs are valid * @setup: optional callback issued once the GPIOs are valid
* @teardown: optional callback issued before the GPIOs are invalidated * @teardown: optional callback issued before the GPIOs are invalidated
* @context: optional parameter passed to setup() and teardown() * @context: optional parameter passed to setup() and teardown()
* @irq: optional interrupt number
* *
* In addition to the I2C_BOARD_INFO() state appropriate to each chip, * In addition to the I2C_BOARD_INFO() state appropriate to each chip,
* the i2c_board_info used with the pcf875x driver must provide its * the i2c_board_info used with the pcf875x driver must provide its
...@@ -39,6 +40,8 @@ struct pcf857x_platform_data { ...@@ -39,6 +40,8 @@ struct pcf857x_platform_data {
int gpio, unsigned ngpio, int gpio, unsigned ngpio,
void *context); void *context);
void *context; void *context;
int irq;
}; };
#endif /* __LINUX_PCF857X_H */ #endif /* __LINUX_PCF857X_H */
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