From 0df2c999f748c9528f6629f45baaa86118d60cd1 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 25 May 2012 21:36:15 +0800 Subject: [PATCH 01/19] gpio/of: fix a typo of comment message Signed-off-by: Dong Aisheng Signed-off-by: Grant Likely --- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index d18068a9f3ec..8389d4a0ec45 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -21,7 +21,7 @@ #include #include -/* Private data structure for of_gpiochip_is_match */ +/* Private data structure for of_gpiochip_find_and_xlate */ struct gg_data { enum of_gpio_flags *flags; struct of_phandle_args gpiospec; From 96b70641b937e99c1579cb6ebbcdb7b0af98cdd0 Mon Sep 17 00:00:00 2001 From: Andreas Schallenberg Date: Mon, 21 May 2012 09:52:43 +0200 Subject: [PATCH 02/19] gpio/tca6424: merge I2C transactions, remove cast This is a follow-up to ae79c1904 "[PATCH v2] Add support for TCA6424" merged in the v3.5 merge window. It fixes comments made when the patch was merged. - Use 3 byte transfers instead of two separate transfers (2+1 byte) - An unnecessary cast removed Signed-off-by: Andreas Schallenberg Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 1c313c710be3..de24af202447 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -98,12 +98,11 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val) if (chip->gpio_chip.ngpio <= 8) ret = i2c_smbus_write_byte_data(chip->client, reg, val); else if (chip->gpio_chip.ngpio == 24) { - ret = i2c_smbus_write_word_data(chip->client, + cpu_to_le32s(&val); + ret = i2c_smbus_write_i2c_block_data(chip->client, (reg << 2) | REG_ADDR_AI, - val & 0xffff); - ret = i2c_smbus_write_byte_data(chip->client, - (reg << 2) + 2, - (val & 0xff0000) >> 16); + 3, + (u8 *) &val); } else { switch (chip->chip_type) { @@ -135,22 +134,27 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val) { int ret; - if (chip->gpio_chip.ngpio <= 8) + if (chip->gpio_chip.ngpio <= 8) { ret = i2c_smbus_read_byte_data(chip->client, reg); - else if (chip->gpio_chip.ngpio == 24) { - ret = i2c_smbus_read_word_data(chip->client, reg << 2); - ret |= (i2c_smbus_read_byte_data(chip->client, - (reg << 2) + 2)<<16); + *val = ret; } - else + else if (chip->gpio_chip.ngpio == 24) { + *val = 0; + ret = i2c_smbus_read_i2c_block_data(chip->client, + (reg << 2) | REG_ADDR_AI, + 3, + (u8 *) val); + le32_to_cpus(val); + } else { ret = i2c_smbus_read_word_data(chip->client, reg << 1); + *val = ret; + } if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return ret; } - *val = (u32)ret; return 0; } From f942a7de047d8c599cc1a9a26293c8c7400450ea Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Fri, 1 Jun 2012 17:36:31 +0400 Subject: [PATCH 03/19] gpio: add a driver for GPIO pins found on AMD-8111 south bridge chips Add a driver to use GPIO pins available on several AMD south bridges (currently only AMD 8111 is supported). Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 12 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-amd8111.c | 246 ++++++++++++++++++++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 drivers/gpio/gpio-amd8111.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c4067d0141f7..c2dfa9f90b47 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -466,6 +466,18 @@ config GPIO_BT8XX If unsure, say N. +config GPIO_AMD8111 + tristate "AMD 8111 GPIO driver" + depends on PCI + help + The AMD 8111 south bridge contains 32 GPIO pins which can be used. + + Note, that usually system firmware/ACPI handles GPIO pins on their + own and users might easily break their systems with uncarefull usage + of this driver! + + If unsure, say N + config GPIO_LANGWELL bool "Intel Langwell/Penwell GPIO support" depends on PCI && X86 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 0f55662002c3..3a95b17dae86 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o +obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c new file mode 100644 index 000000000000..710fafcdd1b1 --- /dev/null +++ b/drivers/gpio/gpio-amd8111.c @@ -0,0 +1,246 @@ +/* + * GPIO driver for AMD 8111 south bridges + * + * Copyright (c) 2012 Dmitry Eremin-Solenikov + * + * Based on the AMD RNG driver: + * Copyright 2005 (c) MontaVista Software, Inc. + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik + * Copyright 2000,2001 Philipp Rumpf + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#include +#include +#include +#include +#include + +#define PMBASE_OFFSET 0xb0 +#define PMBASE_SIZE 0x30 + +#define AMD_REG_GPIO(i) (0x10 + (i)) + +#define AMD_GPIO_LTCH_STS 0x40 /* Latch status, w1 */ +#define AMD_GPIO_RTIN 0x20 /* Real Time in, ro */ +#define AMD_GPIO_DEBOUNCE 0x10 /* Debounce, rw */ +#define AMD_GPIO_MODE_MASK 0x0c /* Pin Mode Select, rw */ +#define AMD_GPIO_MODE_IN 0x00 +#define AMD_GPIO_MODE_OUT 0x04 +/* Enable alternative (e.g. clkout, IRQ, etc) function of the pin */ +#define AMD_GPIO_MODE_ALTFN 0x08 /* Or 0x09 */ +#define AMD_GPIO_X_MASK 0x03 /* In/Out specific, rw */ +#define AMD_GPIO_X_IN_ACTIVEHI 0x01 /* Active High */ +#define AMD_GPIO_X_IN_LATCH 0x02 /* Latched version is selected */ +#define AMD_GPIO_X_OUT_LOW 0x00 +#define AMD_GPIO_X_OUT_HI 0x01 +#define AMD_GPIO_X_OUT_CLK0 0x02 +#define AMD_GPIO_X_OUT_CLK1 0x03 + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_tbl); + +struct amd_gpio { + struct gpio_chip chip; + u32 pmbase; + void __iomem *pm; + struct pci_dev *pdev; + spinlock_t lock; /* guards hw registers and orig table */ + u8 orig[32]; +}; + +#define to_agp(chip) container_of(chip, struct amd_gpio, chip) + +static int amd_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct amd_gpio *agp = to_agp(chip); + + agp->orig[offset] = ioread8(agp->pm + AMD_REG_GPIO(offset)) & + (AMD_GPIO_DEBOUNCE | AMD_GPIO_MODE_MASK | AMD_GPIO_X_MASK); + + dev_dbg(&agp->pdev->dev, "Requested gpio %d, data %x\n", offset, agp->orig[offset]); + + return 0; +} + +static void amd_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct amd_gpio *agp = to_agp(chip); + + dev_dbg(&agp->pdev->dev, "Freed gpio %d, data %x\n", offset, agp->orig[offset]); + + iowrite8(agp->orig[offset], agp->pm + AMD_REG_GPIO(offset)); +} + +static void amd_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct amd_gpio *agp = to_agp(chip); + u8 temp; + unsigned long flags; + + spin_lock_irqsave(&agp->lock, flags); + temp = ioread8(agp->pm + AMD_REG_GPIO(offset)); + temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW); + iowrite8(temp, agp->pm + AMD_REG_GPIO(offset)); + spin_unlock_irqrestore(&agp->lock, flags); + + dev_dbg(&agp->pdev->dev, "Setting gpio %d, value %d, reg=%02x\n", offset, !!value, temp); +} + +static int amd_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct amd_gpio *agp = to_agp(chip); + u8 temp; + + temp = ioread8(agp->pm + AMD_REG_GPIO(offset)); + + dev_dbg(&agp->pdev->dev, "Getting gpio %d, reg=%02x\n", offset, temp); + + return (temp & AMD_GPIO_RTIN) ? 1 : 0; +} + +static int amd_gpio_dirout(struct gpio_chip *chip, unsigned offset, int value) +{ + struct amd_gpio *agp = to_agp(chip); + u8 temp; + unsigned long flags; + + spin_lock_irqsave(&agp->lock, flags); + temp = ioread8(agp->pm + AMD_REG_GPIO(offset)); + temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW); + iowrite8(temp, agp->pm + AMD_REG_GPIO(offset)); + spin_unlock_irqrestore(&agp->lock, flags); + + dev_dbg(&agp->pdev->dev, "Dirout gpio %d, value %d, reg=%02x\n", offset, !!value, temp); + + return 0; +} + +static int amd_gpio_dirin(struct gpio_chip *chip, unsigned offset) +{ + struct amd_gpio *agp = to_agp(chip); + u8 temp; + unsigned long flags; + + spin_lock_irqsave(&agp->lock, flags); + temp = ioread8(agp->pm + AMD_REG_GPIO(offset)); + temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_IN; + iowrite8(temp, agp->pm + AMD_REG_GPIO(offset)); + spin_unlock_irqrestore(&agp->lock, flags); + + dev_dbg(&agp->pdev->dev, "Dirin gpio %d, reg=%02x\n", offset, temp); + + return 0; +} + +static struct amd_gpio gp = { + .chip = { + .label = "AMD GPIO", + .owner = THIS_MODULE, + .base = -1, + .ngpio = 32, + .request = amd_gpio_request, + .free = amd_gpio_free, + .set = amd_gpio_set, + .get = amd_gpio_get, + .direction_output = amd_gpio_dirout, + .direction_input = amd_gpio_dirin, + }, +}; + +static int __init amd_gpio_init(void) +{ + int err = -ENODEV; + struct pci_dev *pdev = NULL; + const struct pci_device_id *ent; + + + /* We look for our device - AMD South Bridge + * I don't know about a system with two such bridges, + * so we can assume that there is max. one device. + * + * We can't use plain pci_driver mechanism, + * as the device is really a multiple function device, + * main driver that binds to the pci_device is an smbus + * driver and have to find & bind to the device this way. + */ + for_each_pci_dev(pdev) { + ent = pci_match_id(pci_tbl, pdev); + if (ent) + goto found; + } + /* Device not found. */ + goto out; + +found: + err = pci_read_config_dword(pdev, 0x58, &gp.pmbase); + if (err) + goto out; + err = -EIO; + gp.pmbase &= 0x0000FF00; + if (gp.pmbase == 0) + goto out; + if (!request_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE, "AMD GPIO")) { + dev_err(&pdev->dev, "AMD GPIO region 0x%x already in use!\n", + gp.pmbase + PMBASE_OFFSET); + err = -EBUSY; + goto out; + } + gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); + gp.pdev = pdev; + gp.chip.dev = &pdev->dev; + + spin_lock_init(&gp.lock); + + printk(KERN_INFO "AMD-8111 GPIO detected\n"); + err = gpiochip_add(&gp.chip); + if (err) { + printk(KERN_ERR "GPIO registering failed (%d)\n", + err); + release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); + goto out; + } +out: + return err; +} + +static void __exit amd_gpio_exit(void) +{ + int err = gpiochip_remove(&gp.chip); + WARN_ON(err); + ioport_unmap(gp.pm); + release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); +} + +module_init(amd_gpio_init); +module_exit(amd_gpio_exit); + +MODULE_AUTHOR("The Linux Kernel team"); +MODULE_DESCRIPTION("GPIO driver for AMD chipsets"); +MODULE_LICENSE("GPL"); From 224a1f90458b5005fa7aec5e8a6d64fd8eccb208 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 3 Jun 2012 13:40:19 +0100 Subject: [PATCH 04/19] gpiolib: wm8994: Use irq_domain mappings for gpios This has no practical impact at present since we don't support device tree so any user must have set an irq_base but this will in future allow a transition to device tree with minimal invasiveness. Signed-off-by: Mark Brown Signed-off-by: Linus Walleij --- drivers/gpio/gpio-wm8994.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 92ea5350dfe9..a1c7ba94b523 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -109,10 +110,7 @@ static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset) struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; - if (!wm8994->irq_base) - return -EINVAL; - - return wm8994->irq_base + offset; + return regmap_irq_get_virq(wm8994->irq_data, offset); } From f8d203c049af2faaa4a23e51e1626b7660b33d8e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 17:22:09 +0100 Subject: [PATCH 05/19] gpiolib: wm8994: Convert to devm_kzalloc() Signed-off-by: Mark Brown Signed-off-by: Linus Walleij --- drivers/gpio/gpio-wm8994.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index a1c7ba94b523..f2b3d19dd7a9 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -249,7 +249,8 @@ static int __devinit wm8994_gpio_probe(struct platform_device *pdev) struct wm8994_gpio *wm8994_gpio; int ret; - wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL); + wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio), + GFP_KERNEL); if (wm8994_gpio == NULL) return -ENOMEM; @@ -274,20 +275,14 @@ static int __devinit wm8994_gpio_probe(struct platform_device *pdev) return ret; err: - kfree(wm8994_gpio); return ret; } static int __devexit wm8994_gpio_remove(struct platform_device *pdev) { struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev); - int ret; - ret = gpiochip_remove(&wm8994_gpio->gpio_chip); - if (ret == 0) - kfree(wm8994_gpio); - - return ret; + return gpiochip_remove(&wm8994_gpio->gpio_chip); } static struct platform_driver wm8994_gpio_driver = { From 25b273baa5bf05923b053a2c80e7eedb7ee8d7e2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 18:13:53 +0100 Subject: [PATCH 06/19] MAINTAINERS: Add Wolfson gpiolib drivers to the Wolfson entry Signed-off-by: Mark Brown Signed-off-by: Linus Walleij --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index eb22272b2116..c6f6615bf633 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7578,6 +7578,7 @@ S: Supported F: Documentation/hwmon/wm83?? F: arch/arm/mach-s3c64xx/mach-crag6410* F: drivers/leds/leds-wm83*.c +F: drivers/gpio/gpio-*wm*.c F: drivers/hwmon/wm83??-hwmon.c F: drivers/input/misc/wm831x-on.c F: drivers/input/touchscreen/wm831x-ts.c From da03d7400adfe56e2a54d0e38aa12704ab2a0e13 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 11 Jun 2012 10:12:40 +0200 Subject: [PATCH 07/19] gpio: LPC32xx: Driver cleanup Since LPC32xx is now switched over to devicetree based GPIO, the unused lpc32xx_gpio_init() can be removed. Further, the driver title changed since it referred to the wrong file. Signed-off-by: Roland Stigge Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lpc32xx.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index c2199beca98a..c8c2a513ba84 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -1,5 +1,5 @@ /* - * arch/arm/mach-lpc32xx/gpiolib.c + * GPIO driver for LPC32xx SoC * * Author: Kevin Wells * @@ -457,13 +457,6 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { }, }; -/* Empty now, can be removed later when mach-lpc32xx is finally switched over - * to DT support - */ -void __init lpc32xx_gpio_init(void) -{ -} - static int lpc32xx_of_xlate(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags) { From 0c65ddd460086084079eeeb14d062c9a0c437ca0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 13 Jun 2012 21:58:08 -0700 Subject: [PATCH 08/19] gpio: pcf857x: share 8/16 bit access functions This patch adds 8/16 bit write/read functions, and shared gpio input/output/set/get functions. Signed-off-by: Kuninori Morimoto Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pcf857x.c | 93 +++++++++++++------------------------ 1 file changed, 31 insertions(+), 62 deletions(-) diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 2d1de9e7e9bd..076e236d0da7 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -61,61 +61,28 @@ struct pcf857x { struct i2c_client *client; struct mutex lock; /* protect 'out' */ unsigned out; /* software latch */ + + int (*write)(struct i2c_client *client, unsigned data); + int (*read)(struct i2c_client *client); }; /*-------------------------------------------------------------------------*/ /* Talk to 8-bit I/O expander */ -static int pcf857x_input8(struct gpio_chip *chip, unsigned offset) +static int i2c_write_le8(struct i2c_client *client, unsigned data) { - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - int status; - - mutex_lock(&gpio->lock); - gpio->out |= (1 << offset); - status = i2c_smbus_write_byte(gpio->client, gpio->out); - mutex_unlock(&gpio->lock); - - return status; + return i2c_smbus_write_byte(client, data); } -static int pcf857x_get8(struct gpio_chip *chip, unsigned offset) +static int i2c_read_le8(struct i2c_client *client) { - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - s32 value; - - value = i2c_smbus_read_byte(gpio->client); - return (value < 0) ? 0 : (value & (1 << offset)); + return (int)i2c_smbus_read_byte(client); } -static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value) -{ - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - unsigned bit = 1 << offset; - int status; - - mutex_lock(&gpio->lock); - if (value) - gpio->out |= bit; - else - gpio->out &= ~bit; - status = i2c_smbus_write_byte(gpio->client, gpio->out); - mutex_unlock(&gpio->lock); - - return status; -} - -static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value) -{ - pcf857x_output8(chip, offset, value); -} - -/*-------------------------------------------------------------------------*/ - /* Talk to 16-bit I/O expander */ -static int i2c_write_le16(struct i2c_client *client, u16 word) +static int i2c_write_le16(struct i2c_client *client, unsigned word) { u8 buf[2] = { word & 0xff, word >> 8, }; int status; @@ -135,29 +102,31 @@ static int i2c_read_le16(struct i2c_client *client) return (buf[1] << 8) | buf[0]; } -static int pcf857x_input16(struct gpio_chip *chip, unsigned offset) +/*-------------------------------------------------------------------------*/ + +static int pcf857x_input(struct gpio_chip *chip, unsigned offset) { struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); int status; mutex_lock(&gpio->lock); gpio->out |= (1 << offset); - status = i2c_write_le16(gpio->client, gpio->out); + status = gpio->write(gpio->client, gpio->out); mutex_unlock(&gpio->lock); return status; } -static int pcf857x_get16(struct gpio_chip *chip, unsigned offset) +static int pcf857x_get(struct gpio_chip *chip, unsigned offset) { struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); int value; - value = i2c_read_le16(gpio->client); + value = gpio->read(gpio->client); return (value < 0) ? 0 : (value & (1 << offset)); } -static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value) +static int pcf857x_output(struct gpio_chip *chip, unsigned offset, int value) { struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); unsigned bit = 1 << offset; @@ -168,15 +137,15 @@ static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value) gpio->out |= bit; else gpio->out &= ~bit; - status = i2c_write_le16(gpio->client, gpio->out); + status = gpio->write(gpio->client, gpio->out); mutex_unlock(&gpio->lock); return status; } -static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value) +static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value) { - pcf857x_output16(chip, offset, value); + pcf857x_output(chip, offset, value); } /*-------------------------------------------------------------------------*/ @@ -200,10 +169,15 @@ static int pcf857x_probe(struct i2c_client *client, mutex_init(&gpio->lock); - gpio->chip.base = pdata ? pdata->gpio_base : -1; - gpio->chip.can_sleep = 1; - gpio->chip.dev = &client->dev; - gpio->chip.owner = THIS_MODULE; + gpio->chip.base = pdata ? pdata->gpio_base : -1; + gpio->chip.can_sleep = 1; + gpio->chip.dev = &client->dev; + gpio->chip.owner = THIS_MODULE; + gpio->chip.get = pcf857x_get; + gpio->chip.set = pcf857x_set; + gpio->chip.direction_input = pcf857x_input; + gpio->chip.direction_output = pcf857x_output; + gpio->chip.ngpio = id->driver_data; /* NOTE: the OnSemi jlc1562b is also largely compatible with * these parts, notably for output. It has a low-resolution @@ -216,12 +190,9 @@ static int pcf857x_probe(struct i2c_client *client, * * NOTE: we don't distinguish here between *4 and *4a parts. */ - gpio->chip.ngpio = id->driver_data; if (gpio->chip.ngpio == 8) { - gpio->chip.direction_input = pcf857x_input8; - gpio->chip.get = pcf857x_get8; - gpio->chip.direction_output = pcf857x_output8; - gpio->chip.set = pcf857x_set8; + gpio->write = i2c_write_le8; + gpio->read = i2c_read_le8; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) @@ -238,10 +209,8 @@ static int pcf857x_probe(struct i2c_client *client, * NOTE: we don't distinguish here between '75 and '75c parts. */ } else if (gpio->chip.ngpio == 16) { - gpio->chip.direction_input = pcf857x_input16; - gpio->chip.get = pcf857x_get16; - gpio->chip.direction_output = pcf857x_output16; - gpio->chip.set = pcf857x_set16; + gpio->write = i2c_write_le16; + gpio->read = i2c_read_le16; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) status = -EIO; From 0bdfeddc49a80eeb4544ae50b46db7ed695accb8 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 20 Jun 2012 16:33:52 +0200 Subject: [PATCH 09/19] gpio: gpio-lpc32xx: Add gpio_to_irq mapping This patch helps mapping with gpio_to_irq for the GPIOs that are irq enabled. Signed-off-by: Roland Stigge Tested-by: Alexandre Pereira da Silva Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lpc32xx.c | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index c8c2a513ba84..8a420f13905e 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -28,6 +28,7 @@ #include #include #include +#include #define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) #define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) @@ -367,6 +368,66 @@ static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin) return -EINVAL; } +static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset) +{ + return IRQ_LPC32XX_P0_P1_IRQ; +} + +static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = { + IRQ_LPC32XX_GPIO_00, + IRQ_LPC32XX_GPIO_01, + IRQ_LPC32XX_GPIO_02, + IRQ_LPC32XX_GPIO_03, + IRQ_LPC32XX_GPIO_04, + IRQ_LPC32XX_GPIO_05, +}; + +static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset) +{ + if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table)) + return lpc32xx_gpio_to_irq_gpio_p3_table[offset]; + return -ENXIO; +} + +static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = { + IRQ_LPC32XX_GPI_00, + IRQ_LPC32XX_GPI_01, + IRQ_LPC32XX_GPI_02, + IRQ_LPC32XX_GPI_03, + IRQ_LPC32XX_GPI_04, + IRQ_LPC32XX_GPI_05, + IRQ_LPC32XX_GPI_06, + IRQ_LPC32XX_GPI_07, + IRQ_LPC32XX_GPI_08, + IRQ_LPC32XX_GPI_09, + -ENXIO, /* 10 */ + -ENXIO, /* 11 */ + -ENXIO, /* 12 */ + -ENXIO, /* 13 */ + -ENXIO, /* 14 */ + -ENXIO, /* 15 */ + -ENXIO, /* 16 */ + -ENXIO, /* 17 */ + -ENXIO, /* 18 */ + IRQ_LPC32XX_GPI_19, + -ENXIO, /* 20 */ + -ENXIO, /* 21 */ + -ENXIO, /* 22 */ + -ENXIO, /* 23 */ + -ENXIO, /* 24 */ + -ENXIO, /* 25 */ + -ENXIO, /* 26 */ + -ENXIO, /* 27 */ + IRQ_LPC32XX_GPI_28, +}; + +static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset) +{ + if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table)) + return lpc32xx_gpio_to_irq_gpi_p3_table[offset]; + return -ENXIO; +} + static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { { .chip = { @@ -376,6 +437,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .direction_output = lpc32xx_gpio_dir_output_p012, .set = lpc32xx_gpio_set_value_p012, .request = lpc32xx_gpio_request, + .to_irq = lpc32xx_gpio_to_irq_p01, .base = LPC32XX_GPIO_P0_GRP, .ngpio = LPC32XX_GPIO_P0_MAX, .names = gpio_p0_names, @@ -391,6 +453,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .direction_output = lpc32xx_gpio_dir_output_p012, .set = lpc32xx_gpio_set_value_p012, .request = lpc32xx_gpio_request, + .to_irq = lpc32xx_gpio_to_irq_p01, .base = LPC32XX_GPIO_P1_GRP, .ngpio = LPC32XX_GPIO_P1_MAX, .names = gpio_p1_names, @@ -421,6 +484,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .direction_output = lpc32xx_gpio_dir_output_p3, .set = lpc32xx_gpio_set_value_p3, .request = lpc32xx_gpio_request, + .to_irq = lpc32xx_gpio_to_irq_gpio_p3, .base = LPC32XX_GPIO_P3_GRP, .ngpio = LPC32XX_GPIO_P3_MAX, .names = gpio_p3_names, @@ -434,6 +498,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .direction_input = lpc32xx_gpio_dir_in_always, .get = lpc32xx_gpi_get_value, .request = lpc32xx_gpio_request, + .to_irq = lpc32xx_gpio_to_irq_gpi_p3, .base = LPC32XX_GPI_P3_GRP, .ngpio = LPC32XX_GPI_P3_MAX, .names = gpi_p3_names, From 31ba56f274d60d0b84efae4d15a9cd3e0486fa8c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 23 Jun 2012 13:29:25 +0100 Subject: [PATCH 10/19] gpiolib: Add support for Wolfson Microelectronics Arizona class devices The Arizona class devices provide some GPIOs for use in the system. This driver provides support for these via gpiolib. Currently interrupts are not supported, normally the GPIOs are outputs only. Signed-off-by: Mark Brown [Fold in WM5110 support patch] Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-arizona.c | 163 ++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 drivers/gpio/gpio-arizona.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c2dfa9f90b47..4002def0b524 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -253,6 +253,12 @@ config GPIO_GE_FPGA comment "I2C GPIO expanders:" +config GPIO_ARIZONA + tristate "Wolfson Microelectronics Arizona class devices" + depends on MFD_ARIZONA + help + Support for GPIOs on Wolfson Arizona class devices. + config GPIO_MAX7300 tristate "Maxim MAX7300 GPIO expander" depends on I2C diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 3a95b17dae86..d37048105a87 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o +obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c new file mode 100644 index 000000000000..8740d2eb06f8 --- /dev/null +++ b/drivers/gpio/gpio-arizona.c @@ -0,0 +1,163 @@ +/* + * gpiolib support for Wolfson Arizona class devices + * + * Copyright 2012 Wolfson Microelectronics PLC. + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct arizona_gpio { + struct arizona *arizona; + struct gpio_chip gpio_chip; +}; + +static inline struct arizona_gpio *to_arizona_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct arizona_gpio, gpio_chip); +} + +static int arizona_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ + struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip); + struct arizona *arizona = arizona_gpio->arizona; + + return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, + ARIZONA_GPN_DIR, ARIZONA_GPN_DIR); +} + +static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip); + struct arizona *arizona = arizona_gpio->arizona; + unsigned int val; + int ret; + + ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val); + if (ret < 0) + return ret; + + if (val & ARIZONA_GPN_LVL) + return 1; + else + return 0; +} + +static int arizona_gpio_direction_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip); + struct arizona *arizona = arizona_gpio->arizona; + + if (value) + value = ARIZONA_GPN_LVL; + + return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, + ARIZONA_GPN_DIR | ARIZONA_GPN_LVL, value); +} + +static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip); + struct arizona *arizona = arizona_gpio->arizona; + + if (value) + value = ARIZONA_GPN_LVL; + + regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, + ARIZONA_GPN_LVL, value); +} + +static struct gpio_chip template_chip = { + .label = "arizona", + .owner = THIS_MODULE, + .direction_input = arizona_gpio_direction_in, + .get = arizona_gpio_get, + .direction_output = arizona_gpio_direction_out, + .set = arizona_gpio_set, + .can_sleep = 1, +}; + +static int __devinit arizona_gpio_probe(struct platform_device *pdev) +{ + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct arizona_pdata *pdata = arizona->dev->platform_data; + struct arizona_gpio *arizona_gpio; + int ret; + + arizona_gpio = devm_kzalloc(&pdev->dev, sizeof(*arizona_gpio), + GFP_KERNEL); + if (arizona_gpio == NULL) + return -ENOMEM; + + arizona_gpio->arizona = arizona; + arizona_gpio->gpio_chip = template_chip; + arizona_gpio->gpio_chip.dev = &pdev->dev; + + switch (arizona->type) { + case WM5102: + case WM5110: + arizona_gpio->gpio_chip.ngpio = 5; + break; + default: + dev_err(&pdev->dev, "Unknown chip variant %d\n", + arizona->type); + return -EINVAL; + } + + if (pdata && pdata->gpio_base) + arizona_gpio->gpio_chip.base = pdata->gpio_base; + else + arizona_gpio->gpio_chip.base = -1; + + ret = gpiochip_add(&arizona_gpio->gpio_chip); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", + ret); + goto err; + } + + platform_set_drvdata(pdev, arizona_gpio); + + return ret; + +err: + return ret; +} + +static int __devexit arizona_gpio_remove(struct platform_device *pdev) +{ + struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev); + + return gpiochip_remove(&arizona_gpio->gpio_chip); +} + +static struct platform_driver arizona_gpio_driver = { + .driver.name = "arizona-gpio", + .driver.owner = THIS_MODULE, + .probe = arizona_gpio_probe, + .remove = __devexit_p(arizona_gpio_remove), +}; + +module_platform_driver(arizona_gpio_driver); + +MODULE_AUTHOR("Mark Brown "); +MODULE_DESCRIPTION("GPIO interface for Arizona devices"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:arizona-gpio"); From f447ed8b31da7b24c7c75c2d4624598135b41217 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Mon, 25 Jun 2012 21:18:21 -0700 Subject: [PATCH 11/19] gpio: samsung: add flags specifier to device-tree binding This adds a flags field to the gpio specifier for Samsung. I didn't want to add yet another field in the already quite long specifier, so I decided to compress it together with the Pull Up/Down settings instead. This is needed to, for example, have a gpio-keys input that is active low. Signed-off-by: Olof Johansson Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-samsung.txt | 9 +++++---- drivers/gpio/gpio-samsung.c | 5 ++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt index 8f50fe5e6c42..5375625e8cd2 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt @@ -11,14 +11,15 @@ Required properties: <[phandle of the gpio controller node] [pin number within the gpio controller] [mux function] - [pull up/down] + [flags and pull up/down] [drive strength]> Values for gpio specifier: - Pin number: is a value between 0 to 7. - - Pull Up/Down: 0 - Pull Up/Down Disabled. - 1 - Pull Down Enabled. - 3 - Pull Up Enabled. + - Flags and Pull Up/Down: 0 - Pull Up/Down Disabled. + 1 - Pull Down Enabled. + 3 - Pull Up Enabled. + Bit 16 (0x00010000) - Input is active low. - Drive Strength: 0 - 1x, 1 - 3x, 2 - 2x, diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index b6453d0e44ad..92f7b2bb79d4 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2681,11 +2681,14 @@ static int exynos_gpio_xlate(struct gpio_chip *gc, if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1]))) pr_warn("gpio_xlate: failed to set pin function\n"); - if (s3c_gpio_setpull(pin, gpiospec->args[2])) + if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff)) pr_warn("gpio_xlate: failed to set pin pull up/down\n"); if (s5p_gpio_set_drvstr(pin, gpiospec->args[3])) pr_warn("gpio_xlate: failed to set pin drive strength\n"); + if (flags) + *flags = gpiospec->args[2] >> 16; + return gpiospec->args[0]; } From 41920d16360ebc8c482911078a17d9994fb77612 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 29 Jun 2012 13:57:59 +0900 Subject: [PATCH 12/19] gpio: propagate of_parse_phandle_with_args errors Make of_get_named_gpio_flags propagate any error it receives from of_parse_phandle_with_args instead of inconditionally returning -EINVAL. Signed-off-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 8389d4a0ec45..a71aecac451f 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -73,7 +73,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, &gg_data.gpiospec); if (ret) { pr_debug("%s: can't parse gpios property\n", __func__); - return -EINVAL; + return ret; } gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); From aeb27748e3bc1e89ec590713e574cb6f885cc3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Fri, 22 Jun 2012 21:04:06 +0200 Subject: [PATCH 13/19] gpio/mxc: use the edge_sel feature if available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some mxc processors have an edge_sel feature, which allows the IRQ to be triggered by any edge. This patch makes use of this feature if available, which skips mxc_flip_edge(). Cc: Grant Likely Cc: Linus Walleij Acked-by: Sascha Hauer Cc: Signed-off-by: Benoît Thébaudeau Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/fsl-imx-gpio.txt | 2 +- arch/arm/boot/dts/imx51.dtsi | 8 +-- arch/arm/boot/dts/imx53.dtsi | 14 ++-- arch/arm/boot/dts/imx6q.dtsi | 14 ++-- arch/arm/mach-imx/mm-imx25.c | 10 +-- arch/arm/mach-imx/mm-imx3.c | 7 +- arch/arm/mach-imx/mm-imx5.c | 40 +++++------ drivers/gpio/gpio-mxc.c | 71 +++++++++++++++---- 8 files changed, 104 insertions(+), 62 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt index 4363ae4b3c14..33a0345eef32 100644 --- a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt +++ b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt @@ -14,7 +14,7 @@ Required properties: Example: gpio0: gpio@73f84000 { - compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; reg = <0x73f84000 0x4000>; interrupts = <50 51>; gpio-controller; diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index bfa65abe8ef2..9c95abcb3ce9 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -127,7 +127,7 @@ esdhc@70024000 { /* ESDHC4 */ }; gpio1: gpio@73f84000 { - compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; reg = <0x73f84000 0x4000>; interrupts = <50 51>; gpio-controller; @@ -137,7 +137,7 @@ gpio1: gpio@73f84000 { }; gpio2: gpio@73f88000 { - compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; reg = <0x73f88000 0x4000>; interrupts = <52 53>; gpio-controller; @@ -147,7 +147,7 @@ gpio2: gpio@73f88000 { }; gpio3: gpio@73f8c000 { - compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; reg = <0x73f8c000 0x4000>; interrupts = <54 55>; gpio-controller; @@ -157,7 +157,7 @@ gpio3: gpio@73f8c000 { }; gpio4: gpio@73f90000 { - compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; reg = <0x73f90000 0x4000>; interrupts = <56 57>; gpio-controller; diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index e3e869470cd3..506ed5c93642 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -129,7 +129,7 @@ esdhc@50024000 { /* ESDHC4 */ }; gpio1: gpio@53f84000 { - compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx53-gpio", "fsl,imx35-gpio"; reg = <0x53f84000 0x4000>; interrupts = <50 51>; gpio-controller; @@ -139,7 +139,7 @@ gpio1: gpio@53f84000 { }; gpio2: gpio@53f88000 { - compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx53-gpio", "fsl,imx35-gpio"; reg = <0x53f88000 0x4000>; interrupts = <52 53>; gpio-controller; @@ -149,7 +149,7 @@ gpio2: gpio@53f88000 { }; gpio3: gpio@53f8c000 { - compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx53-gpio", "fsl,imx35-gpio"; reg = <0x53f8c000 0x4000>; interrupts = <54 55>; gpio-controller; @@ -159,7 +159,7 @@ gpio3: gpio@53f8c000 { }; gpio4: gpio@53f90000 { - compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx53-gpio", "fsl,imx35-gpio"; reg = <0x53f90000 0x4000>; interrupts = <56 57>; gpio-controller; @@ -197,7 +197,7 @@ uart2: serial@53fc0000 { }; gpio5: gpio@53fdc000 { - compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx53-gpio", "fsl,imx35-gpio"; reg = <0x53fdc000 0x4000>; interrupts = <103 104>; gpio-controller; @@ -207,7 +207,7 @@ gpio5: gpio@53fdc000 { }; gpio6: gpio@53fe0000 { - compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx53-gpio", "fsl,imx35-gpio"; reg = <0x53fe0000 0x4000>; interrupts = <105 106>; gpio-controller; @@ -217,7 +217,7 @@ gpio6: gpio@53fe0000 { }; gpio7: gpio@53fe4000 { - compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx53-gpio", "fsl,imx35-gpio"; reg = <0x53fe4000 0x4000>; interrupts = <107 108>; gpio-controller; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 8c90cbac945f..da78fd83f625 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -260,7 +260,7 @@ gpt@02098000 { }; gpio1: gpio@0209c000 { - compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; reg = <0x0209c000 0x4000>; interrupts = <0 66 0x04 0 67 0x04>; gpio-controller; @@ -270,7 +270,7 @@ gpio1: gpio@0209c000 { }; gpio2: gpio@020a0000 { - compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; reg = <0x020a0000 0x4000>; interrupts = <0 68 0x04 0 69 0x04>; gpio-controller; @@ -280,7 +280,7 @@ gpio2: gpio@020a0000 { }; gpio3: gpio@020a4000 { - compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; reg = <0x020a4000 0x4000>; interrupts = <0 70 0x04 0 71 0x04>; gpio-controller; @@ -290,7 +290,7 @@ gpio3: gpio@020a4000 { }; gpio4: gpio@020a8000 { - compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; reg = <0x020a8000 0x4000>; interrupts = <0 72 0x04 0 73 0x04>; gpio-controller; @@ -300,7 +300,7 @@ gpio4: gpio@020a8000 { }; gpio5: gpio@020ac000 { - compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; reg = <0x020ac000 0x4000>; interrupts = <0 74 0x04 0 75 0x04>; gpio-controller; @@ -310,7 +310,7 @@ gpio5: gpio@020ac000 { }; gpio6: gpio@020b0000 { - compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; reg = <0x020b0000 0x4000>; interrupts = <0 76 0x04 0 77 0x04>; gpio-controller; @@ -320,7 +320,7 @@ gpio6: gpio@020b0000 { }; gpio7: gpio@020b4000 { - compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; reg = <0x020b4000 0x4000>; interrupts = <0 78 0x04 0 79 0x04>; gpio-controller; diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c index 6ff37140a4f8..8e8ddb81bd0b 100644 --- a/arch/arm/mach-imx/mm-imx25.c +++ b/arch/arm/mach-imx/mm-imx25.c @@ -90,11 +90,11 @@ static const struct resource imx25_audmux_res[] __initconst = { void __init imx25_soc_init(void) { - /* i.mx25 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0); - mxc_register_gpio("imx31-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0); - mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0); - mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0); + /* i.mx25 has the i.mx35 type gpio */ + mxc_register_gpio("imx35-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0); + mxc_register_gpio("imx35-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0); + mxc_register_gpio("imx35-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0); + mxc_register_gpio("imx35-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0); pinctrl_provide_dummies(); /* i.mx25 has the i.mx35 type sdma */ diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index a8983b9778d1..8e51e77b3c65 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c @@ -273,10 +273,9 @@ void __init imx35_soc_init(void) imx3_init_l2x0(); - /* i.mx35 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0); - mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0); - mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0); + mxc_register_gpio("imx35-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0); + mxc_register_gpio("imx35-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0); + mxc_register_gpio("imx35-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0); pinctrl_provide_dummies(); if (to_version == 1) { diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index 1d003053d562..d70d16cb7eb5 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -181,13 +181,13 @@ static const struct resource imx53_audmux_res[] __initconst = { void __init imx50_soc_init(void) { - /* i.mx50 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); - mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); - mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); - mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); - mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); - mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH); + /* i.mx50 has the i.mx35 type gpio */ + mxc_register_gpio("imx35-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); + mxc_register_gpio("imx35-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); + mxc_register_gpio("imx35-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); + mxc_register_gpio("imx35-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); + mxc_register_gpio("imx35-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); + mxc_register_gpio("imx35-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH); /* i.mx50 has the i.mx31 type audmux */ platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res, @@ -196,11 +196,11 @@ void __init imx50_soc_init(void) void __init imx51_soc_init(void) { - /* i.mx51 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH); - mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH); - mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH); - mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH); + /* i.mx51 has the i.mx35 type gpio */ + mxc_register_gpio("imx35-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH); + mxc_register_gpio("imx35-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH); + mxc_register_gpio("imx35-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH); + mxc_register_gpio("imx35-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH); pinctrl_provide_dummies(); @@ -218,14 +218,14 @@ void __init imx51_soc_init(void) void __init imx53_soc_init(void) { - /* i.mx53 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH); - mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH); - mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH); - mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH); - mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH); - mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH); - mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH); + /* i.mx53 has the i.mx35 type gpio */ + mxc_register_gpio("imx35-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH); + mxc_register_gpio("imx35-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH); + mxc_register_gpio("imx35-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH); + mxc_register_gpio("imx35-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH); + mxc_register_gpio("imx35-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH); + mxc_register_gpio("imx35-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH); + mxc_register_gpio("imx35-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH); pinctrl_provide_dummies(); /* i.mx53 has the i.mx35 type sdma */ diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index c337143b18f8..bb985e815533 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -38,7 +38,8 @@ enum mxc_gpio_hwtype { IMX1_GPIO, /* runs on i.mx1 */ IMX21_GPIO, /* runs on i.mx21 and i.mx27 */ - IMX31_GPIO, /* runs on all other i.mx */ + IMX31_GPIO, /* runs on i.mx31 */ + IMX35_GPIO, /* runs on all other i.mx */ }; /* device type dependent stuff */ @@ -50,6 +51,7 @@ struct mxc_gpio_hwdata { unsigned icr2_reg; unsigned imr_reg; unsigned isr_reg; + int edge_sel_reg; unsigned low_level; unsigned high_level; unsigned rise_edge; @@ -74,6 +76,7 @@ static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = { .icr2_reg = 0x2c, .imr_reg = 0x30, .isr_reg = 0x34, + .edge_sel_reg = -EINVAL, .low_level = 0x03, .high_level = 0x02, .rise_edge = 0x00, @@ -88,6 +91,22 @@ static struct mxc_gpio_hwdata imx31_gpio_hwdata = { .icr2_reg = 0x10, .imr_reg = 0x14, .isr_reg = 0x18, + .edge_sel_reg = -EINVAL, + .low_level = 0x00, + .high_level = 0x01, + .rise_edge = 0x02, + .fall_edge = 0x03, +}; + +static struct mxc_gpio_hwdata imx35_gpio_hwdata = { + .dr_reg = 0x00, + .gdir_reg = 0x04, + .psr_reg = 0x08, + .icr1_reg = 0x0c, + .icr2_reg = 0x10, + .imr_reg = 0x14, + .isr_reg = 0x18, + .edge_sel_reg = 0x1c, .low_level = 0x00, .high_level = 0x01, .rise_edge = 0x02, @@ -104,12 +123,13 @@ static struct mxc_gpio_hwdata *mxc_gpio_hwdata; #define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg) #define GPIO_IMR (mxc_gpio_hwdata->imr_reg) #define GPIO_ISR (mxc_gpio_hwdata->isr_reg) +#define GPIO_EDGE_SEL (mxc_gpio_hwdata->edge_sel_reg) #define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level) #define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level) #define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge) #define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge) -#define GPIO_INT_NONE 0x4 +#define GPIO_INT_BOTH_EDGES 0x4 static struct platform_device_id mxc_gpio_devtype[] = { { @@ -121,6 +141,9 @@ static struct platform_device_id mxc_gpio_devtype[] = { }, { .name = "imx31-gpio", .driver_data = IMX31_GPIO, + }, { + .name = "imx35-gpio", + .driver_data = IMX35_GPIO, }, { /* sentinel */ } @@ -130,6 +153,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = { { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], }, { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], }, { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], }, + { .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], }, { /* sentinel */ } }; @@ -160,15 +184,19 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) edge = GPIO_INT_FALL_EDGE; break; case IRQ_TYPE_EDGE_BOTH: - val = gpio_get_value(gpio); - if (val) { - edge = GPIO_INT_LOW_LEV; - pr_debug("mxc: set GPIO %d to low trigger\n", gpio); + if (GPIO_EDGE_SEL >= 0) { + edge = GPIO_INT_BOTH_EDGES; } else { - edge = GPIO_INT_HIGH_LEV; - pr_debug("mxc: set GPIO %d to high trigger\n", gpio); + val = gpio_get_value(gpio); + if (val) { + edge = GPIO_INT_LOW_LEV; + pr_debug("mxc: set GPIO %d to low trigger\n", gpio); + } else { + edge = GPIO_INT_HIGH_LEV; + pr_debug("mxc: set GPIO %d to high trigger\n", gpio); + } + port->both_edges |= 1 << (gpio & 31); } - port->both_edges |= 1 << (gpio & 31); break; case IRQ_TYPE_LEVEL_LOW: edge = GPIO_INT_LOW_LEV; @@ -180,10 +208,23 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) return -EINVAL; } - reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ - bit = gpio & 0xf; - val = readl(reg) & ~(0x3 << (bit << 1)); - writel(val | (edge << (bit << 1)), reg); + if (GPIO_EDGE_SEL >= 0) { + val = readl(port->base + GPIO_EDGE_SEL); + if (edge == GPIO_INT_BOTH_EDGES) + writel(val | (1 << (gpio & 0x1f)), + port->base + GPIO_EDGE_SEL); + else + writel(val & ~(1 << (gpio & 0x1f)), + port->base + GPIO_EDGE_SEL); + } + + if (edge != GPIO_INT_BOTH_EDGES) { + reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ + bit = gpio & 0xf; + val = readl(reg) & ~(0x3 << (bit << 1)); + writel(val | (edge << (bit << 1)), reg); + } + writel(1 << (gpio & 0x1f), port->base + GPIO_ISR); return 0; @@ -338,7 +379,9 @@ static void __devinit mxc_gpio_get_hw(struct platform_device *pdev) return; } - if (hwtype == IMX31_GPIO) + if (hwtype == IMX35_GPIO) + mxc_gpio_hwdata = &imx35_gpio_hwdata; + else if (hwtype == IMX31_GPIO) mxc_gpio_hwdata = &imx31_gpio_hwdata; else mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata; From 346720130aa49e1b711c0900e98fd12f4de972b0 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Wed, 11 Jul 2012 14:43:14 +0530 Subject: [PATCH 14/19] gpio/omap: move bank->dbck initialization to omap_gpio_mod_init() Since the bank->dbck initialization in a one time operation there is no need to keep this within gpio_debounce(). Therefore, moving clk_get(bank->dbck) to omap_gpio_mod_init(). Since the value of bank->dbck would be NULL at the beginning, this check has been removed. Signed-off-by: Tarun Kanti DebBarma Reported-by: Paul Walmsley Reviewed-by: Jon Hunter Cc: Kevin Hilman Cc: Rajendra Nayak Cc: Santosh Shilimkar Cc: Cousson, Benoit Reviewed-by: Paul Walmsley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index c4ed1722734c..afecdccfc66e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -889,12 +889,6 @@ static int gpio_debounce(struct gpio_chip *chip, unsigned offset, bank = container_of(chip, struct gpio_bank, chip); - if (!bank->dbck) { - bank->dbck = clk_get(bank->dev, "dbclk"); - if (IS_ERR(bank->dbck)) - dev_err(bank->dev, "Could not get gpio dbck\n"); - } - spin_lock_irqsave(&bank->lock, flags); _set_gpio_debounce(bank, offset, debounce); spin_unlock_irqrestore(&bank->lock, flags); @@ -966,6 +960,10 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) /* Initialize interface clk ungated, module enabled */ if (bank->regs->ctrl) __raw_writel(0, base + bank->regs->ctrl); + + bank->dbck = clk_get(bank->dev, "dbclk"); + if (IS_ERR(bank->dbck)) + dev_err(bank->dev, "Could not get gpio dbck\n"); } static __devinit void From 6a7b36aa4b0afbe7a9798feac16de47ad856f358 Mon Sep 17 00:00:00 2001 From: Chandrabhanu Mahapatra Date: Tue, 10 Jul 2012 19:05:37 +0530 Subject: [PATCH 15/19] GPIO: PCA953X: Increase size of invert variable to support 24 bit TCA6424 is a low voltage 24 bit I2C and SMBus I/O expander of pca953x family similar to its 16 bit predecessor TCA6416. It comes with three 8-bit active Input, Output, Polarity Inversion and Configuration registers each. The polarity of Input ports can be reversed by setting the appropiate bit in Polarity Inversion registers. The variables corresponding to Input, Output and Configuration registers have already been updated to support 24 bit values. This patch thus updates the invert variable of PCA953X platform data to support 24 bit. Signed-off-by: Chandrabhanu Mahapatra Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 11 ++++++----- include/linux/i2c/pca953x.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index de24af202447..266b910de43b 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -568,7 +568,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip) * WARNING: This is DEPRECATED and will be removed eventually! */ static void -pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) +pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) { struct device_node *node; const __be32 *val; @@ -596,13 +596,13 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) } #else static void -pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) +pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) { *gpio_base = -1; } #endif -static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert) +static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert) { int ret; @@ -621,7 +621,7 @@ static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert) return ret; } -static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert) +static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert) { int ret; u32 val = 0; @@ -657,8 +657,9 @@ static int __devinit pca953x_probe(struct i2c_client *client, { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; - int irq_base=0, invert=0; + int irq_base = 0; int ret; + u32 invert = 0; chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h index 139ba52667c8..3c98dd4f901f 100644 --- a/include/linux/i2c/pca953x.h +++ b/include/linux/i2c/pca953x.h @@ -11,7 +11,7 @@ struct pca953x_platform_data { unsigned gpio_base; /* initial polarity inversion setting */ - uint16_t invert; + u32 invert; /* interrupt base */ int irq_base; From ca3ffe910f9935d24e02bb5628a8cbcab119fd9a Mon Sep 17 00:00:00 2001 From: Leed Aguilar Date: Tue, 10 Jul 2012 19:05:53 +0530 Subject: [PATCH 16/19] gpio/pca953x: increase variables size to support 24 bit of data Increase variable size from u16 to u32 to allocate 24 bit of data required for the TCA6424 I/O expander device type. Signed-off-by: Leed Aguilar Signed-off-by: Chandrabhanu Mahapatra Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 266b910de43b..9c693ae17956 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -78,10 +78,10 @@ struct pca953x_chip { #ifdef CONFIG_GPIO_PCA953X_IRQ struct mutex irq_lock; - uint16_t irq_mask; - uint16_t irq_stat; - uint16_t irq_trig_raise; - uint16_t irq_trig_fall; + u32 irq_mask; + u32 irq_stat; + u32 irq_trig_raise; + u32 irq_trig_fall; int irq_base; #endif @@ -353,8 +353,8 @@ static void pca953x_irq_bus_lock(struct irq_data *d) static void pca953x_irq_bus_sync_unlock(struct irq_data *d) { struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - uint16_t new_irqs; - uint16_t level; + u32 new_irqs; + u32 level; /* Look for any newly setup interrupt */ new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; @@ -372,8 +372,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) { struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - uint16_t level = d->irq - chip->irq_base; - uint16_t mask = 1 << level; + u32 level = d->irq - chip->irq_base; + u32 mask = 1 << level; if (!(type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", @@ -403,12 +403,12 @@ static struct irq_chip pca953x_irq_chip = { .irq_set_type = pca953x_irq_set_type, }; -static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) +static u32 pca953x_irq_pending(struct pca953x_chip *chip) { u32 cur_stat; - uint16_t old_stat; - uint16_t pending; - uint16_t trigger; + u32 old_stat; + u32 pending; + u32 trigger; int ret, offset = 0; switch (chip->chip_type) { @@ -444,8 +444,8 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) static irqreturn_t pca953x_irq_handler(int irq, void *devid) { struct pca953x_chip *chip = devid; - uint16_t pending; - uint16_t level; + u32 pending; + u32 level; pending = pca953x_irq_pending(chip); From 6d9947101616b2681879c0f8f95415897470be44 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 16 Jul 2012 10:05:07 -0700 Subject: [PATCH 17/19] MAINTAINERS: add entry OMAP GPIO driver Since I've been maintaining this, making it official at the request of the GPIO maintainers. Cc: Grant Likely Cc: Linus Walleij Cc: Santosh Shilimkar Cc: Andrew Morton Signed-off-by: Kevin Hilman [corrected file path] Signed-off-by: Linus Walleij --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c6f6615bf633..eeb9b731a474 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4943,6 +4943,13 @@ S: Maintained F: drivers/usb/*/*omap* F: arch/arm/*omap*/usb* +OMAP GPIO DRIVER +M: Santosh Shilimkar +M: Kevin Hilman +L: linux-omap@vger.kernel.org +S: Maintained +F: drivers/gpio/gpio-omap.c + OMFS FILESYSTEM M: Bob Copeland L: linux-karma-devel@lists.sourceforge.net From e93545763021988def06fbda28fe5da133589a96 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 12:22:56 +0100 Subject: [PATCH 18/19] gpiolib: Defer failed gpio requests by default Since users must be explicitly provided with a GPIO number in order to request one the overwhelmingly common case for failing to request will be that the required GPIO driver has not yet registered and we should therefore defer until it has registered. In order to avoid having to code this logic in individual drivers have gpio_request() return -EPROBE_DEFER when failing to look up the GPIO. Drivers which don't want this behaviour can override it if they desire. Signed-off-by: Mark Brown Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 120b2a0e3167..de0213c9d11c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1186,7 +1186,7 @@ int gpio_request(unsigned gpio, const char *label) { struct gpio_desc *desc; struct gpio_chip *chip; - int status = -EINVAL; + int status = -EPROBE_DEFER; unsigned long flags; spin_lock_irqsave(&gpio_lock, flags); From 4fbb0022cba37eef4a263183fdb7dbee89b299f2 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 28 Jun 2012 00:32:14 +0200 Subject: [PATCH 19/19] gpio: of_get_named_gpio_flags() return -EPROBE_DEFER if GPIO not yet available of_get_named_gpio_flags() and of_get_named_gpio() return -EPROBE_DEFER if the respective GPIO is not (yet) available. This is useful if driver's probe() functions try to get a GPIO whose controller isn't probed yet. Thus, the driver can be probed again later on. The function still returns -EINVAL on other errors (parse error or node doesn't exist). This way, the case of an optional/intentionally missing GPIO is handled appropriately. Signed-off-by: Roland Stigge Acked-by: Alexandre Pereira da Silva Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a71aecac451f..a18c4aa68b1e 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -62,7 +62,10 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) int of_get_named_gpio_flags(struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags) { - struct gg_data gg_data = { .flags = flags, .out_gpio = -ENODEV }; + /* Return -EPROBE_DEFER to support probe() functions to be called + * later when the GPIO actually becomes available + */ + struct gg_data gg_data = { .flags = flags, .out_gpio = -EPROBE_DEFER }; int ret; /* .of_xlate might decide to not fill in the flags, so clear it. */