From a3cc68c37897f0656489a0d853d6e342fc6f076b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 27 May 2011 16:35:59 -0700 Subject: [PATCH 01/61] gpio/74x164: remove unnecessary defines and prototype Remove the #define GEN_74X164_GPIO_COUNT since it's only used in one place and it's meaning is obvious. Also remove the #define GEN_74X164_DRIVER_NAME and use spi->modalias to set the gpio chip's label and the string "74x164" for the driver name. Reorder the code slightly to remove the need to prototype gen_74x164_set_value. Signed-off-by: H Hartley Sweeten Signed-off-by: Grant Likely --- drivers/gpio/74x164.c | 27 +++++++++++---------------- include/linux/spi/74x164.h | 2 -- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/gpio/74x164.c b/drivers/gpio/74x164.c index 84e070219839..7fb60b6bf523 100644 --- a/drivers/gpio/74x164.c +++ b/drivers/gpio/74x164.c @@ -16,9 +16,6 @@ #include #include -#define GEN_74X164_GPIO_COUNT 8 - - struct gen_74x164_chip { struct spi_device *spi; struct gpio_chip gpio_chip; @@ -26,8 +23,6 @@ struct gen_74x164_chip { u8 port_config; }; -static void gen_74x164_set_value(struct gpio_chip *, unsigned, int); - static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc) { return container_of(gc, struct gen_74x164_chip, gpio_chip); @@ -39,13 +34,6 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip) &chip->port_config, sizeof(chip->port_config)); } -static int gen_74x164_direction_output(struct gpio_chip *gc, - unsigned offset, int val) -{ - gen_74x164_set_value(gc, offset, val); - return 0; -} - static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) { struct gen_74x164_chip *chip = gpio_to_chip(gc); @@ -73,6 +61,13 @@ static void gen_74x164_set_value(struct gpio_chip *gc, mutex_unlock(&chip->lock); } +static int gen_74x164_direction_output(struct gpio_chip *gc, + unsigned offset, int val) +{ + gen_74x164_set_value(gc, offset, val); + return 0; +} + static int __devinit gen_74x164_probe(struct spi_device *spi) { struct gen_74x164_chip *chip; @@ -104,12 +99,12 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) chip->spi = spi; - chip->gpio_chip.label = GEN_74X164_DRIVER_NAME, - chip->gpio_chip.direction_output = gen_74x164_direction_output; + chip->gpio_chip.label = spi->modalias; + chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; chip->gpio_chip.base = pdata->base; - chip->gpio_chip.ngpio = GEN_74X164_GPIO_COUNT; + chip->gpio_chip.ngpio = 8; chip->gpio_chip.can_sleep = 1; chip->gpio_chip.dev = &spi->dev; chip->gpio_chip.owner = THIS_MODULE; @@ -157,7 +152,7 @@ static int __devexit gen_74x164_remove(struct spi_device *spi) static struct spi_driver gen_74x164_driver = { .driver = { - .name = GEN_74X164_DRIVER_NAME, + .name = "74x164", .owner = THIS_MODULE, }, .probe = gen_74x164_probe, diff --git a/include/linux/spi/74x164.h b/include/linux/spi/74x164.h index d85c52f294a0..0aa6acc73317 100644 --- a/include/linux/spi/74x164.h +++ b/include/linux/spi/74x164.h @@ -1,8 +1,6 @@ #ifndef LINUX_SPI_74X164_H #define LINUX_SPI_74X164_H -#define GEN_74X164_DRIVER_NAME "74x164" - struct gen_74x164_chip_platform_data { /* number assigned to the first GPIO */ unsigned base; From 2bcc7ed5b83b0a59c6976476e8788675038fb11b Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 31 May 2011 16:23:43 +0800 Subject: [PATCH 02/61] leds: remove config option LEDS_GPIO_PLATFORM from Kconfig Since the commit a314c5c0040aab51ebb1ecfd37a9198a91962243 (leds/leds-gpio: merge platform_driver with of_platform_driver), the config option LEDS_GPIO_PLATFORM becomes useless, so remove it. Signed-off-by: Shawn Guo [grant.likely: also remove LEDS_GPIO_OF for same reason] Signed-off-by: Grant Likely --- drivers/leds/Kconfig | 19 +------------------ drivers/leds/leds-gpio.c | 6 +++--- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 23f0d5e99f35..9d7d9400bbf5 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -93,7 +93,7 @@ config LEDS_NET48XX config LEDS_NET5501 tristate "LED Support for Soekris net5501 series Error LED" depends on LEDS_TRIGGERS - depends on X86 && LEDS_GPIO_PLATFORM && GPIO_CS5535 + depends on X86 && GPIO_CS5535 select LEDS_TRIGGER_DEFAULT_ON default n help @@ -183,23 +183,6 @@ config LEDS_GPIO defined as platform devices and/or OpenFirmware platform devices. The code to use these bindings can be selected below. -config LEDS_GPIO_PLATFORM - bool "Platform device bindings for GPIO LEDs" - depends on LEDS_GPIO - default y - help - Let the leds-gpio driver drive LEDs which have been defined as - platform devices. If you don't know what this means, say yes. - -config LEDS_GPIO_OF - bool "OpenFirmware platform device bindings for GPIO LEDs" - depends on LEDS_GPIO && OF_DEVICE - default y - help - Let the leds-gpio driver drive LEDs which have been defined as - of_platform devices. For instance, LEDs which are listed in a "dts" - file. - config LEDS_LP3944 tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip" depends on LEDS_CLASS diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index b0480c8fbcbf..3d8bc327a68d 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -165,7 +165,7 @@ static inline int sizeof_gpio_leds_priv(int num_leds) } /* Code to create from OpenFirmware platform devices */ -#ifdef CONFIG_LEDS_GPIO_OF +#ifdef CONFIG_OF_GPIO static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node, *child; @@ -223,13 +223,13 @@ static const struct of_device_id of_gpio_leds_match[] = { { .compatible = "gpio-leds", }, {}, }; -#else +#else /* CONFIG_OF_GPIO */ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev) { return NULL; } #define of_gpio_leds_match NULL -#endif +#endif /* CONFIG_OF_GPIO */ static int __devinit gpio_led_probe(struct platform_device *pdev) From a26221a834fe30c22d440b954b2e11e607fa57f5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 3 Jun 2011 13:32:41 -0500 Subject: [PATCH 03/61] gpio/samsung: make Kconfig options def_bool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Samsung GPIO drivers are always built-in when the relevant platform is selected.  Change the Kconfig symbol to def_bool y dependant on the platform. Signed-off-by: H Hartley Sweeten Acked-by: Kyungmin Park Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4a7f63143455..2967002a9f82 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -87,32 +87,20 @@ config GPIO_IT8761E Say yes here to support GPIO functionality of IT8761E super I/O chip. config GPIO_EXYNOS4 - bool "Samsung Exynos4 GPIO library support" - default y if CPU_EXYNOS4210 - depends on ARM - help - Say yes here to support Samsung Exynos4 series SoCs GPIO library + def_bool y + depends on CPU_EXYNOS4210 config GPIO_PLAT_SAMSUNG - bool "Samsung SoCs GPIO library support" - default y if SAMSUNG_GPIOLIB_4BIT - depends on ARM - help - Say yes here to support Samsung SoCs GPIO library + def_bool y + depends on SAMSUNG_GPIOLIB_4BIT config GPIO_S5PC100 - bool "Samsung S5PC100 GPIO library support" - default y if CPU_S5PC100 - depends on ARM - help - Say yes here to support Samsung S5PC100 SoCs GPIO library + def_bool y + depends on CPU_S5PC100 config GPIO_S5PV210 - bool "Samsung S5PV210/S5PC110 GPIO library support" - default y if CPU_S5PV210 - depends on ARM - help - Say yes here to support Samsung S5PV210/S5PC110 SoCs GPIO library + def_bool y + depends on CPU_S5PV210 config GPIO_PL061 bool "PrimeCell PL061 GPIO support" From 7b2fa5702059a03c11f934224724b2f712a749ce Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 6 Jun 2011 09:37:58 -0600 Subject: [PATCH 04/61] gpio/mxs: Move Freescale mxs gpio driver to drivers/gpio GPIO drivers are getting moved to drivers/gpio for cleanup and consolidation. This patch moves the mxs driver. Follow up patches will clean it up and make it a fine upstanding example of a gpio driver. v2: Removed header file entirely and put struct definition directly into driver. The struct isn't used anywhere else in the kernel. Signed-off-by: Grant Likely Tested-by: Shawn Guo Acked-by: Sascha Hauer --- arch/arm/mach-mxs/Makefile | 2 +- arch/arm/mach-mxs/gpio.h | 34 ------------------- arch/arm/mach-mxs/mach-mx28evk.c | 1 - drivers/gpio/Kconfig | 4 +++ drivers/gpio/Makefile | 1 + .../gpio.c => drivers/gpio/gpio-mxs.c | 11 ++++-- 6 files changed, 15 insertions(+), 38 deletions(-) delete mode 100644 arch/arm/mach-mxs/gpio.h rename arch/arm/mach-mxs/gpio.c => drivers/gpio/gpio-mxs.c (98%) diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile index 58e892376bf2..6c38262a3aaa 100644 --- a/arch/arm/mach-mxs/Makefile +++ b/arch/arm/mach-mxs/Makefile @@ -1,5 +1,5 @@ # Common support -obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o +obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o obj-$(CONFIG_MXS_OCOTP) += ocotp.o obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/mach-mxs/gpio.h b/arch/arm/mach-mxs/gpio.h deleted file mode 100644 index 005bb06630b1..000000000000 --- a/arch/arm/mach-mxs/gpio.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * 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. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#ifndef __MXS_GPIO_H__ -#define __MXS_GPIO_H__ - -struct mxs_gpio_port { - void __iomem *base; - int id; - int irq; - int irq_high; - int virtual_irq_start; - struct gpio_chip chip; -}; - -int mxs_gpio_init(struct mxs_gpio_port*, int); - -#endif /* __MXS_GPIO_H__ */ diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c index eacdc6b0e70a..56767a5cce0e 100644 --- a/arch/arm/mach-mxs/mach-mx28evk.c +++ b/arch/arm/mach-mxs/mach-mx28evk.c @@ -26,7 +26,6 @@ #include #include "devices-mx28.h" -#include "gpio.h" #define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) #define MX28EVK_FEC_PHY_POWER MXS_GPIO_NR(2, 15) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4a7f63143455..48711749ffcf 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -93,6 +93,10 @@ config GPIO_EXYNOS4 help Say yes here to support Samsung Exynos4 series SoCs GPIO library +config GPIO_MXS + def_bool y + depends on ARCH_MXS + config GPIO_PLAT_SAMSUNG bool "Samsung SoCs GPIO library support" default y if SAMSUNG_GPIOLIB_4BIT diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index b605f8ec6fbe..f879cbe493d5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o +obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o diff --git a/arch/arm/mach-mxs/gpio.c b/drivers/gpio/gpio-mxs.c similarity index 98% rename from arch/arm/mach-mxs/gpio.c rename to drivers/gpio/gpio-mxs.c index 2c950fef71a8..e26bf309b214 100644 --- a/arch/arm/mach-mxs/gpio.c +++ b/drivers/gpio/gpio-mxs.c @@ -29,8 +29,6 @@ #include #include -#include "gpio.h" - static struct mxs_gpio_port *mxs_gpio_ports; static int gpio_table_size; @@ -50,6 +48,15 @@ static int gpio_table_size; #define GPIO_INT_LEV_MASK (1 << 0) #define GPIO_INT_POL_MASK (1 << 1) +struct mxs_gpio_port { + void __iomem *base; + int id; + int irq; + int irq_high; + int virtual_irq_start; + struct gpio_chip chip; +}; + /* Note: This driver assumes 32 GPIOs are handled in one register */ static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index) From 8d7cf8370d5fb75a3265408dceb1d6173eebfafd Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 6 Jun 2011 09:37:58 -0600 Subject: [PATCH 05/61] gpio/mxs: Change gpio-mxs into an upstanding gpio driver The patch makes necessary changes on gpio-mxs as below to turn it into an upstanding gpio driver. * Clean up the gpio port definition stuff * Use readl/writel to replace mach-specific accessors __raw_readl/__raw_writel * Change mxs_gpio_init into mxs_gpio_probe function And it then migrates mach-mxs to the updated driver by adding corresponding platform devices. Signed-off-by: Shawn Guo Acked-by: Arnd Bergmann Acked-by: Sascha Hauer Signed-off-by: Grant Likely --- arch/arm/mach-mxs/devices.c | 11 + arch/arm/mach-mxs/devices/Makefile | 1 + arch/arm/mach-mxs/devices/platform-gpio-mxs.c | 53 +++++ .../mach-mxs/include/mach/devices-common.h | 2 + arch/arm/mach-mxs/mm-mx23.c | 1 - arch/arm/mach-mxs/mm-mx28.c | 1 - drivers/gpio/gpio-mxs.c | 218 ++++++++++-------- 7 files changed, 192 insertions(+), 95 deletions(-) create mode 100644 arch/arm/mach-mxs/devices/platform-gpio-mxs.c diff --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c index cfdb6b284702..fe3e847930c9 100644 --- a/arch/arm/mach-mxs/devices.c +++ b/arch/arm/mach-mxs/devices.c @@ -88,3 +88,14 @@ int __init mxs_add_amba_device(const struct amba_device *dev) return amba_device_register(adev, &iomem_resource); } + +struct device mxs_apbh_bus = { + .init_name = "mxs_apbh", + .parent = &platform_bus, +}; + +static int __init mxs_device_init(void) +{ + return device_register(&mxs_apbh_bus); +} +core_initcall(mxs_device_init); diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile index 324f2824d38d..351915c683ff 100644 --- a/arch/arm/mach-mxs/devices/Makefile +++ b/arch/arm/mach-mxs/devices/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o +obj-y += platform-gpio-mxs.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o diff --git a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c new file mode 100644 index 000000000000..ed0885e414e0 --- /dev/null +++ b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c @@ -0,0 +1,53 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ +#include +#include +#include + +#include +#include +#include + +struct platform_device *__init mxs_add_gpio( + int id, resource_size_t iobase, int irq) +{ + struct resource res[] = { + { + .start = iobase, + .end = iobase + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = irq, + .end = irq, + .flags = IORESOURCE_IRQ, + }, + }; + + return platform_device_register_resndata(&mxs_apbh_bus, + "gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0); +} + +static int __init mxs_add_mxs_gpio(void) +{ + if (cpu_is_mx23()) { + mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0); + mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1); + mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2); + } + + if (cpu_is_mx28()) { + mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0); + mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1); + mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2); + mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3); + mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4); + } + + return 0; +} +postcore_initcall(mxs_add_mxs_gpio); diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h index 7a37469ed5bf..812d7a813a78 100644 --- a/arch/arm/mach-mxs/include/mach/devices-common.h +++ b/arch/arm/mach-mxs/include/mach/devices-common.h @@ -11,6 +11,8 @@ #include #include +extern struct device mxs_apbh_bus; + struct platform_device *mxs_add_platform_device_dmamask( const char *name, int id, const struct resource *res, unsigned int num_resources, diff --git a/arch/arm/mach-mxs/mm-mx23.c b/arch/arm/mach-mxs/mm-mx23.c index 5148cd64a6b7..1b2345ac1a87 100644 --- a/arch/arm/mach-mxs/mm-mx23.c +++ b/arch/arm/mach-mxs/mm-mx23.c @@ -41,5 +41,4 @@ void __init mx23_map_io(void) void __init mx23_init_irq(void) { icoll_init_irq(); - mx23_register_gpios(); } diff --git a/arch/arm/mach-mxs/mm-mx28.c b/arch/arm/mach-mxs/mm-mx28.c index 7e4cea32ebc6..b6e18ddb92c0 100644 --- a/arch/arm/mach-mxs/mm-mx28.c +++ b/arch/arm/mach-mxs/mm-mx28.c @@ -41,5 +41,4 @@ void __init mx28_map_io(void) void __init mx28_init_irq(void) { icoll_init_irq(); - mx28_register_gpios(); } diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index e26bf309b214..a28761428bb0 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -25,12 +25,12 @@ #include #include #include -#include -#include -#include +#include +#include +#include -static struct mxs_gpio_port *mxs_gpio_ports; -static int gpio_table_size; +#define MXS_SET 0x4 +#define MXS_CLR 0x8 #define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10) #define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10) @@ -61,36 +61,42 @@ struct mxs_gpio_port { static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index) { - __mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id)); + writel(1 << index, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); } static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index, int enable) { if (enable) { - __mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id)); - __mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id)); + writel(1 << index, + port->base + PINCTRL_IRQEN(port->id) + MXS_SET); + writel(1 << index, + port->base + PINCTRL_PIN2IRQ(port->id) + MXS_SET); } else { - __mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id)); + writel(1 << index, + port->base + PINCTRL_IRQEN(port->id) + MXS_CLR); } } static void mxs_gpio_ack_irq(struct irq_data *d) { + struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); u32 gpio = irq_to_gpio(d->irq); - clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f); + clear_gpio_irqstatus(port, gpio & 0x1f); } static void mxs_gpio_mask_irq(struct irq_data *d) { + struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); u32 gpio = irq_to_gpio(d->irq); - set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0); + set_gpio_irqenable(port, gpio & 0x1f, 0); } static void mxs_gpio_unmask_irq(struct irq_data *d) { + struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); u32 gpio = irq_to_gpio(d->irq); - set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1); + set_gpio_irqenable(port, gpio & 0x1f, 1); } static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset); @@ -99,7 +105,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) { u32 gpio = irq_to_gpio(d->irq); u32 pin_mask = 1 << (gpio & 31); - struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; + struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); void __iomem *pin_addr; int edge; @@ -123,16 +129,16 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) /* set level or edge */ pin_addr = port->base + PINCTRL_IRQLEV(port->id); if (edge & GPIO_INT_LEV_MASK) - __mxs_setl(pin_mask, pin_addr); + writel(pin_mask, pin_addr + MXS_SET); else - __mxs_clrl(pin_mask, pin_addr); + writel(pin_mask, pin_addr + MXS_CLR); /* set polarity */ pin_addr = port->base + PINCTRL_IRQPOL(port->id); if (edge & GPIO_INT_POL_MASK) - __mxs_setl(pin_mask, pin_addr); + writel(pin_mask, pin_addr + MXS_SET); else - __mxs_clrl(pin_mask, pin_addr); + writel(pin_mask, pin_addr + MXS_CLR); clear_gpio_irqstatus(port, gpio & 0x1f); @@ -143,13 +149,13 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) { u32 irq_stat; - struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq); + struct mxs_gpio_port *port = irq_get_handler_data(irq); u32 gpio_irq_no_base = port->virtual_irq_start; desc->irq_data.chip->irq_ack(&desc->irq_data); - irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) & - __raw_readl(port->base + PINCTRL_IRQEN(port->id)); + irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) & + readl(port->base + PINCTRL_IRQEN(port->id)); while (irq_stat != 0) { int irqoffset = fls(irq_stat) - 1; @@ -171,7 +177,7 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) { u32 gpio = irq_to_gpio(d->irq); u32 gpio_idx = gpio & 0x1f; - struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; + struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); if (enable) { if (port->irq_high && (gpio_idx >= 16)) @@ -205,9 +211,9 @@ static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset, void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id); if (dir) - __mxs_setl(1 << offset, pin_addr); + writel(1 << offset, pin_addr + MXS_SET); else - __mxs_clrl(1 << offset, pin_addr); + writel(1 << offset, pin_addr + MXS_CLR); } static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -215,7 +221,7 @@ static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset) struct mxs_gpio_port *port = container_of(chip, struct mxs_gpio_port, chip); - return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1; + return (readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1; } static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -225,9 +231,9 @@ static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value) void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id); if (value) - __mxs_setl(1 << offset, pin_addr); + writel(1 << offset, pin_addr + MXS_SET); else - __mxs_clrl(1 << offset, pin_addr); + writel(1 << offset, pin_addr + MXS_CLR); } static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset) @@ -252,87 +258,113 @@ static int mxs_gpio_direction_output(struct gpio_chip *chip, return 0; } -int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt) +static int __devinit mxs_gpio_probe(struct platform_device *pdev) { - int i, j; + static void __iomem *base; + struct mxs_gpio_port *port; + struct resource *iores = NULL; + int err, i; - /* save for local usage */ - mxs_gpio_ports = port; - gpio_table_size = cnt; + port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); + if (!port) + return -ENOMEM; - pr_info("MXS GPIO hardware\n"); + port->id = pdev->id; + port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; - for (i = 0; i < cnt; i++) { - /* disable the interrupt and clear the status */ - __raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i)); - __raw_writel(0, port[i].base + PINCTRL_IRQEN(i)); - - /* clear address has to be used to clear IRQSTAT bits */ - __mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i)); - - for (j = port[i].virtual_irq_start; - j < port[i].virtual_irq_start + 32; j++) { - irq_set_chip_and_handler(j, &gpio_irq_chip, - handle_level_irq); - set_irq_flags(j, IRQF_VALID); + /* + * map memory region only once, as all the gpio ports + * share the same one + */ + if (!base) { + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iores) { + err = -ENODEV; + goto out_kfree; } - /* setup one handler for each entry */ - irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler); - irq_set_handler_data(port[i].irq, &port[i]); + if (!request_mem_region(iores->start, resource_size(iores), + pdev->name)) { + err = -EBUSY; + goto out_kfree; + } - /* register gpio chip */ - port[i].chip.direction_input = mxs_gpio_direction_input; - port[i].chip.direction_output = mxs_gpio_direction_output; - port[i].chip.get = mxs_gpio_get; - port[i].chip.set = mxs_gpio_set; - port[i].chip.to_irq = mxs_gpio_to_irq; - port[i].chip.base = i * 32; - port[i].chip.ngpio = 32; - - /* its a serious configuration bug when it fails */ - BUG_ON(gpiochip_add(&port[i].chip) < 0); + base = ioremap(iores->start, resource_size(iores)); + if (!base) { + err = -ENOMEM; + goto out_release_mem; + } } + port->base = base; + + port->irq = platform_get_irq(pdev, 0); + if (port->irq < 0) { + err = -EINVAL; + goto out_iounmap; + } + + /* disable the interrupt and clear the status */ + writel(0, port->base + PINCTRL_PIN2IRQ(port->id)); + writel(0, port->base + PINCTRL_IRQEN(port->id)); + + /* clear address has to be used to clear IRQSTAT bits */ + writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); + + for (i = port->virtual_irq_start; + i < port->virtual_irq_start + 32; i++) { + irq_set_chip_and_handler(i, &gpio_irq_chip, + handle_level_irq); + set_irq_flags(i, IRQF_VALID); + irq_set_chip_data(i, port); + } + + /* setup one handler for each entry */ + irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); + irq_set_handler_data(port->irq, port); + + /* register gpio chip */ + port->chip.direction_input = mxs_gpio_direction_input; + port->chip.direction_output = mxs_gpio_direction_output; + port->chip.get = mxs_gpio_get; + port->chip.set = mxs_gpio_set; + port->chip.to_irq = mxs_gpio_to_irq; + port->chip.base = port->id * 32; + port->chip.ngpio = 32; + + err = gpiochip_add(&port->chip); + if (err) + goto out_iounmap; return 0; + +out_iounmap: + if (iores) + iounmap(port->base); +out_release_mem: + if (iores) + release_mem_region(iores->start, resource_size(iores)); +out_kfree: + kfree(port); + dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); + return err; } -#define MX23_GPIO_BASE MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR) -#define MX28_GPIO_BASE MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR) - -#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id) \ - { \ - .chip.label = "gpio-" #_id, \ - .id = _id, \ - .irq = _irq, \ - .base = _base, \ - .virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32, \ - } - -#ifdef CONFIG_SOC_IMX23 -static struct mxs_gpio_port mx23_gpio_ports[] = { - DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0), - DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1), - DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2), +static struct platform_driver mxs_gpio_driver = { + .driver = { + .name = "gpio-mxs", + .owner = THIS_MODULE, + }, + .probe = mxs_gpio_probe, }; -int __init mx23_register_gpios(void) +static int __init mxs_gpio_init(void) { - return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports)); + return platform_driver_register(&mxs_gpio_driver); } -#endif +postcore_initcall(mxs_gpio_init); -#ifdef CONFIG_SOC_IMX28 -static struct mxs_gpio_port mx28_gpio_ports[] = { - DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0), - DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1), - DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2), - DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3), - DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4), -}; - -int __init mx28_register_gpios(void) -{ - return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports)); -} -#endif +MODULE_AUTHOR("Freescale Semiconductor, " + "Daniel Mack , " + "Juergen Beisert "); +MODULE_DESCRIPTION("Freescale MXS GPIO"); +MODULE_LICENSE("GPL"); From d37a65bb4663bde7cf3dbc51aec7f264fa4d0ebf Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 6 Jun 2011 00:07:54 +0800 Subject: [PATCH 06/61] gpio/mxc: Move Freescale MXC gpio driver to drivers/gpio GPIO drivers are getting moved to drivers/gpio for cleanup and consolidation. This patch moves the plat-mxc driver. Follow up patches will clean it up and make it a fine upstanding gpio driver. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Signed-off-by: Grant Likely --- arch/arm/plat-mxc/Makefile | 2 +- drivers/gpio/Kconfig | 4 ++++ drivers/gpio/Makefile | 1 + arch/arm/plat-mxc/gpio.c => drivers/gpio/gpio-mxc.c | 0 4 files changed, 6 insertions(+), 1 deletion(-) rename arch/arm/plat-mxc/gpio.c => drivers/gpio/gpio-mxc.c (100%) diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index a1387875a491..d53c35fe2ea7 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o +obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o # MX51 uses the TZIC interrupt controller, older platforms use AVIC obj-$(CONFIG_MXC_TZIC) += tzic.o diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 48711749ffcf..1ee725aa021d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -97,6 +97,10 @@ config GPIO_MXS def_bool y depends on ARCH_MXS +config GPIO_MXC + def_bool y + depends on ARCH_MXC + config GPIO_PLAT_SAMSUNG bool "Samsung SoCs GPIO library support" default y if SAMSUNG_GPIOLIB_4BIT diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index f879cbe493d5..9c37339a57a7 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o +obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o diff --git a/arch/arm/plat-mxc/gpio.c b/drivers/gpio/gpio-mxc.c similarity index 100% rename from arch/arm/plat-mxc/gpio.c rename to drivers/gpio/gpio-mxc.c From b78d8e59a6f611e229fab8ec3014c58eba975000 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 6 Jun 2011 00:07:55 +0800 Subject: [PATCH 07/61] gpio/mxc: Change gpio-mxc into an upstanding gpio driver The patch makes necessary changes on gpio-mxc as below to turn it into an upstanding gpio driver. * Add a list to save all mx2 ports references, so that mx2_gpio_irq_handler can walk through all interrupt status registers * Use readl/writel to replace mach-specific accessors __raw_readl/__raw_writel * Change mxc_gpio_init into mxc_gpio_probe function * Move "struct mxc_gpio_port" into gpio-mxc.c, as it needs not to be public at all, and also make some other cleanup on plat-mxc/include/mach/gpio.h at the same time And the patch then migrates mach-imx and mach-mx5 to the updated driver by adding corresponding platform devices. Signed-off-by: Shawn Guo Acked-by: Olof Johansson Acked-by: Sascha Hauer Signed-off-by: Grant Likely --- arch/arm/mach-imx/mach-apf9328.c | 2 + arch/arm/mach-imx/mach-armadillo5x0.c | 2 + arch/arm/mach-imx/mach-bug.c | 2 + arch/arm/mach-imx/mach-cpuimx27.c | 2 + arch/arm/mach-imx/mach-cpuimx35.c | 2 + arch/arm/mach-imx/mach-eukrea_cpuimx25.c | 2 + arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 2 + arch/arm/mach-imx/mach-imx27ipcam.c | 2 + arch/arm/mach-imx/mach-imx27lite.c | 2 + arch/arm/mach-imx/mach-kzm_arm11_01.c | 2 + arch/arm/mach-imx/mach-mx1ads.c | 2 + arch/arm/mach-imx/mach-mx21ads.c | 2 + arch/arm/mach-imx/mach-mx25_3ds.c | 2 + arch/arm/mach-imx/mach-mx27_3ds.c | 2 + arch/arm/mach-imx/mach-mx27ads.c | 2 + arch/arm/mach-imx/mach-mx31_3ds.c | 2 + arch/arm/mach-imx/mach-mx31ads.c | 2 + arch/arm/mach-imx/mach-mx31lilly.c | 2 + arch/arm/mach-imx/mach-mx31lite.c | 2 + arch/arm/mach-imx/mach-mx31moboard.c | 2 + arch/arm/mach-imx/mach-mx35_3ds.c | 2 + arch/arm/mach-imx/mach-mxt_td60.c | 2 + arch/arm/mach-imx/mach-pca100.c | 2 + arch/arm/mach-imx/mach-pcm037.c | 2 + arch/arm/mach-imx/mach-pcm038.c | 2 + arch/arm/mach-imx/mach-pcm043.c | 2 + arch/arm/mach-imx/mach-qong.c | 2 + arch/arm/mach-imx/mach-scb9328.c | 2 + arch/arm/mach-imx/mach-vpr200.c | 2 + arch/arm/mach-imx/mm-imx1.c | 17 +- arch/arm/mach-imx/mm-imx21.c | 21 +- arch/arm/mach-imx/mm-imx25.c | 16 +- arch/arm/mach-imx/mm-imx27.c | 21 +- arch/arm/mach-imx/mm-imx31.c | 15 +- arch/arm/mach-imx/mm-imx35.c | 15 +- arch/arm/mach-mx5/board-cpuimx51.c | 2 + arch/arm/mach-mx5/board-cpuimx51sd.c | 2 + arch/arm/mach-mx5/board-mx50_rdp.c | 2 + arch/arm/mach-mx5/board-mx51_3ds.c | 2 + arch/arm/mach-mx5/board-mx51_babbage.c | 2 + arch/arm/mach-mx5/board-mx51_efikamx.c | 2 + arch/arm/mach-mx5/board-mx51_efikasb.c | 2 + arch/arm/mach-mx5/board-mx53_evk.c | 2 + arch/arm/mach-mx5/board-mx53_loco.c | 2 + arch/arm/mach-mx5/board-mx53_smd.c | 2 + arch/arm/mach-mx5/devices.c | 64 ------ arch/arm/mach-mx5/mm-mx50.c | 21 +- arch/arm/mach-mx5/mm.c | 25 ++- arch/arm/plat-mxc/devices.c | 11 + arch/arm/plat-mxc/devices/Makefile | 1 + arch/arm/plat-mxc/devices/platform-gpio-mxc.c | 32 +++ arch/arm/plat-mxc/include/mach/common.h | 12 +- .../plat-mxc/include/mach/devices-common.h | 2 + arch/arm/plat-mxc/include/mach/gpio.h | 27 --- drivers/gpio/gpio-mxc.c | 211 ++++++++++++------ 55 files changed, 355 insertions(+), 234 deletions(-) create mode 100644 arch/arm/plat-mxc/devices/platform-gpio-mxc.c diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c index 15e45c84e371..59d2a3b137d9 100644 --- a/arch/arm/mach-imx/mach-apf9328.c +++ b/arch/arm/mach-imx/mach-apf9328.c @@ -115,6 +115,8 @@ static struct platform_device *devices[] __initdata = { static void __init apf9328_init(void) { + imx1_soc_init(); + mxc_gpio_setup_multiple_pins(apf9328_pins, ARRAY_SIZE(apf9328_pins), "APF9328"); diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index ffb40ff619b1..ede2710f8b76 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c @@ -490,6 +490,8 @@ static struct platform_device *devices[] __initdata = { */ static void __init armadillo5x0_init(void) { + imx31_soc_init(); + mxc_iomux_setup_multiple_pins(armadillo5x0_pins, ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0"); diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c index 42e4f078a19c..f49470553bdf 100644 --- a/arch/arm/mach-imx/mach-bug.c +++ b/arch/arm/mach-imx/mach-bug.c @@ -42,6 +42,8 @@ static const unsigned int bug_pins[] __initconst = { static void __init bug_board_init(void) { + imx31_soc_init(); + mxc_iomux_setup_multiple_pins(bug_pins, ARRAY_SIZE(bug_pins), "uart-4"); imx31_add_imx_uart4(&uart_pdata); diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index 46a2e41d43d2..87887ac5806b 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -250,6 +250,8 @@ __setup("otg_mode=", eukrea_cpuimx27_otg_mode); static void __init eukrea_cpuimx27_init(void) { + imx27_soc_init(); + mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins, ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27"); diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index 3f8ef825fa6f..f39a478ba1a6 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -156,6 +156,8 @@ __setup("otg_mode=", eukrea_cpuimx35_otg_mode); */ static void __init eukrea_cpuimx35_init(void) { + imx35_soc_init(); + mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads, ARRAY_SIZE(eukrea_cpuimx35_pads)); diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c index 148cff2819b9..da36da52969d 100644 --- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c +++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c @@ -125,6 +125,8 @@ __setup("otg_mode=", eukrea_cpuimx25_otg_mode); static void __init eukrea_cpuimx25_init(void) { + imx25_soc_init(); + if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads, ARRAY_SIZE(eukrea_cpuimx25_pads))) printk(KERN_ERR "error setting cpuimx25 pads !\n"); diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index 7ae43b1ec517..c6269d60ddbc 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -231,6 +231,8 @@ static void __init visstrim_m10_board_init(void) { int ret; + imx27_soc_init(); + ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins, ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10"); if (ret) diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c index 9be6cd6fbf8c..272f793e9247 100644 --- a/arch/arm/mach-imx/mach-imx27ipcam.c +++ b/arch/arm/mach-imx/mach-imx27ipcam.c @@ -50,6 +50,8 @@ static const int mx27ipcam_pins[] __initconst = { static void __init mx27ipcam_init(void) { + imx27_soc_init(); + mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins), "mx27ipcam"); diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c index 841140516ede..d81a769fe895 100644 --- a/arch/arm/mach-imx/mach-imx27lite.c +++ b/arch/arm/mach-imx/mach-imx27lite.c @@ -59,6 +59,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = { static void __init mx27lite_init(void) { + imx27_soc_init(); + mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins), "imx27lite"); imx27_add_imx_uart0(&uart_pdata); diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c index 1ecae20cf4e3..e472a1d88058 100644 --- a/arch/arm/mach-imx/mach-kzm_arm11_01.c +++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c @@ -223,6 +223,8 @@ static int kzm_pins[] __initdata = { */ static void __init kzm_board_init(void) { + imx31_soc_init(); + mxc_iomux_setup_multiple_pins(kzm_pins, ARRAY_SIZE(kzm_pins), "kzm"); kzm_init_ext_uart(); diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c index 38ec5cbbda9b..5cd8bee46960 100644 --- a/arch/arm/mach-imx/mach-mx1ads.c +++ b/arch/arm/mach-imx/mach-mx1ads.c @@ -115,6 +115,8 @@ static struct i2c_board_info mx1ads_i2c_devices[] = { */ static void __init mx1ads_init(void) { + imx1_soc_init(); + mxc_gpio_setup_multiple_pins(mx1ads_pins, ARRAY_SIZE(mx1ads_pins), "mx1ads"); diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c index 74ac88978ddd..d389ecf9b5a8 100644 --- a/arch/arm/mach-imx/mach-mx21ads.c +++ b/arch/arm/mach-imx/mach-mx21ads.c @@ -279,6 +279,8 @@ static struct platform_device *platform_devices[] __initdata = { static void __init mx21ads_board_init(void) { + imx21_soc_init(); + mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins), "mx21ads"); diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c index 58ea3fdf0911..01534bb61305 100644 --- a/arch/arm/mach-imx/mach-mx25_3ds.c +++ b/arch/arm/mach-imx/mach-mx25_3ds.c @@ -219,6 +219,8 @@ static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = { static void __init mx25pdk_init(void) { + imx25_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads, ARRAY_SIZE(mx25pdk_pads)); diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index 6e1accf93f81..117ce0a50f4e 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -267,6 +267,8 @@ static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = { static void __init mx27pdk_init(void) { + imx27_soc_init(); + mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins), "mx27pdk"); mx27_3ds_sdhc1_enable_level_translator(); diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c index 1db79506f5e4..fc26ed71b9ed 100644 --- a/arch/arm/mach-imx/mach-mx27ads.c +++ b/arch/arm/mach-imx/mach-mx27ads.c @@ -288,6 +288,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = { static void __init mx27ads_board_init(void) { + imx27_soc_init(); + mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins), "mx27ads"); diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 9b982449cb52..ab2a6268b50b 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -689,6 +689,8 @@ static void __init mx31_3ds_init(void) { int ret; + imx31_soc_init(); + mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins), "mx31_3ds"); diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index f4dee0254634..0ce49478a479 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -516,6 +516,8 @@ static void __init mx31ads_init_irq(void) static void __init mx31ads_init(void) { + imx31_soc_init(); + mxc_init_extuart(); mxc_init_imx_uart(); mxc_init_i2c(); diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c index 410e676ae087..750368ddf0f9 100644 --- a/arch/arm/mach-imx/mach-mx31lilly.c +++ b/arch/arm/mach-imx/mach-mx31lilly.c @@ -243,6 +243,8 @@ core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444); static void __init mx31lilly_board_init(void) { + imx31_soc_init(); + switch (mx31lilly_baseboard) { case MX31LILLY_NOBOARD: break; diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index ac9b4cad320e..4b47fd9fdd89 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -230,6 +230,8 @@ static void __init mx31lite_init(void) { int ret; + imx31_soc_init(); + switch (mx31lite_baseboard) { case MX31LITE_NOBOARD: break; diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index eaa51e49ca95..a52fd36e2b52 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -507,6 +507,8 @@ core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444); */ static void __init mx31moboard_init(void) { + imx31_soc_init(); + mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins), "moboard"); diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index 882880ac1bbc..48b3c6fd5cf0 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -179,6 +179,8 @@ static const struct imxi2c_platform_data mx35_3ds_i2c0_data __initconst = { */ static void __init mx35_3ds_init(void) { + imx35_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads)); imx35_add_fec(NULL); diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c index 2774541511e7..c85876fed663 100644 --- a/arch/arm/mach-imx/mach-mxt_td60.c +++ b/arch/arm/mach-imx/mach-mxt_td60.c @@ -233,6 +233,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = { static void __init mxt_td60_board_init(void) { + imx27_soc_init(); + mxc_gpio_setup_multiple_pins(mxt_td60_pins, ARRAY_SIZE(mxt_td60_pins), "MXT_TD60"); diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index bbddc5a11c43..71083aa16038 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -357,6 +357,8 @@ static void __init pca100_init(void) { int ret; + imx27_soc_init(); + /* SSI unit */ mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index 89c213b81295..f45b7cd72c8a 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -576,6 +576,8 @@ static void __init pcm037_init(void) { int ret; + imx31_soc_init(); + mxc_iomux_set_gpr(MUX_PGP_UH2, 1); mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins), diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c index 853bb871c7ed..2d6a64bbac44 100644 --- a/arch/arm/mach-imx/mach-pcm038.c +++ b/arch/arm/mach-imx/mach-pcm038.c @@ -295,6 +295,8 @@ static const struct mxc_usbh_platform_data usbh2_pdata __initconst = { static void __init pcm038_init(void) { + imx27_soc_init(); + mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins), "PCM038"); diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 026441628dfa..163cc318cafb 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -356,6 +356,8 @@ static struct esdhc_platform_data sd1_pdata = { */ static void __init pcm043_init(void) { + imx35_soc_init(); + mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads)); mxc_audmux_v2_configure_port(3, diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index c16328715939..3626f486498a 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -244,6 +244,8 @@ static void __init qong_init_fpga(void) */ static void __init qong_init(void) { + imx31_soc_init(); + mxc_init_imx_uart(); qong_init_nor_mtd(); qong_init_fpga(); diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c index dcaee043628e..82805260e19c 100644 --- a/arch/arm/mach-imx/mach-scb9328.c +++ b/arch/arm/mach-imx/mach-scb9328.c @@ -129,6 +129,8 @@ static struct platform_device *devices[] __initdata = { */ static void __init scb9328_init(void) { + imx1_soc_init(); + imx1_add_imx_uart0(&uart_pdata); printk(KERN_INFO"Scb9328: Adding devices\n"); diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c index d74e3473d236..7d8e012a6335 100644 --- a/arch/arm/mach-imx/mach-vpr200.c +++ b/arch/arm/mach-imx/mach-vpr200.c @@ -267,6 +267,8 @@ static struct platform_device *devices[] __initdata = { */ static void __init vpr200_board_init(void) { + imx35_soc_init(); + mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads)); imx35_add_fec(NULL); diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c index 2e482ba5a0e7..b486595701b7 100644 --- a/arch/arm/mach-imx/mm-imx1.c +++ b/arch/arm/mach-imx/mm-imx1.c @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -44,15 +43,15 @@ void __init imx1_init_early(void) MX1_NUM_GPIO_PORT); } -static struct mxc_gpio_port imx1_gpio_ports[] = { - DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA), - DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB), - DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC), - DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD), -}; - void __init mx1_init_irq(void) { mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR)); - mxc_gpio_init(imx1_gpio_ports, ARRAY_SIZE(imx1_gpio_ports)); +} + +void __init imx1_soc_init(void) +{ + mxc_register_gpio(0, MX1_GPIO1_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTA, 0); + mxc_register_gpio(1, MX1_GPIO2_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTB, 0); + mxc_register_gpio(2, MX1_GPIO3_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTC, 0); + mxc_register_gpio(3, MX1_GPIO4_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTD, 0); } diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c index 7a0c500ac2c8..f0fb8bcce6f9 100644 --- a/arch/arm/mach-imx/mm-imx21.c +++ b/arch/arm/mach-imx/mm-imx21.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -70,17 +69,17 @@ void __init imx21_init_early(void) MX21_NUM_GPIO_PORT); } -static struct mxc_gpio_port imx21_gpio_ports[] = { - DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO), - DEFINE_IMX_GPIO_PORT(MX21, 1, 2), - DEFINE_IMX_GPIO_PORT(MX21, 2, 3), - DEFINE_IMX_GPIO_PORT(MX21, 3, 4), - DEFINE_IMX_GPIO_PORT(MX21, 4, 5), - DEFINE_IMX_GPIO_PORT(MX21, 5, 6), -}; - void __init mx21_init_irq(void) { mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR)); - mxc_gpio_init(imx21_gpio_ports, ARRAY_SIZE(imx21_gpio_ports)); +} + +void __init imx21_soc_init(void) +{ + mxc_register_gpio(0, MX21_GPIO1_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); + mxc_register_gpio(1, MX21_GPIO2_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); + mxc_register_gpio(2, MX21_GPIO3_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); + mxc_register_gpio(3, MX21_GPIO4_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); + mxc_register_gpio(4, MX21_GPIO5_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); + mxc_register_gpio(5, MX21_GPIO6_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); } diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c index 02f7b5c7fa8e..1b6d583f750a 100644 --- a/arch/arm/mach-imx/mm-imx25.c +++ b/arch/arm/mach-imx/mm-imx25.c @@ -27,7 +27,6 @@ #include #include #include -#include #include /* @@ -57,16 +56,15 @@ void __init imx25_init_early(void) mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR)); } -static struct mxc_gpio_port imx25_gpio_ports[] = { - DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1), - DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2), - DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3), - DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4), -}; - void __init mx25_init_irq(void) { mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR)); - mxc_gpio_init(imx25_gpio_ports, ARRAY_SIZE(imx25_gpio_ports)); } +void __init imx25_soc_init(void) +{ + mxc_register_gpio(0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0); + mxc_register_gpio(1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0); + mxc_register_gpio(2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0); + mxc_register_gpio(3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0); +} diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c index a6761a39f08c..d3700cec8ec5 100644 --- a/arch/arm/mach-imx/mm-imx27.c +++ b/arch/arm/mach-imx/mm-imx27.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -70,17 +69,17 @@ void __init imx27_init_early(void) MX27_NUM_GPIO_PORT); } -static struct mxc_gpio_port imx27_gpio_ports[] = { - DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO), - DEFINE_IMX_GPIO_PORT(MX27, 1, 2), - DEFINE_IMX_GPIO_PORT(MX27, 2, 3), - DEFINE_IMX_GPIO_PORT(MX27, 3, 4), - DEFINE_IMX_GPIO_PORT(MX27, 4, 5), - DEFINE_IMX_GPIO_PORT(MX27, 5, 6), -}; - void __init mx27_init_irq(void) { mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR)); - mxc_gpio_init(imx27_gpio_ports, ARRAY_SIZE(imx27_gpio_ports)); +} + +void __init imx27_soc_init(void) +{ + mxc_register_gpio(0, MX27_GPIO1_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); + mxc_register_gpio(1, MX27_GPIO2_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); + mxc_register_gpio(2, MX27_GPIO3_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); + mxc_register_gpio(3, MX27_GPIO4_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); + mxc_register_gpio(4, MX27_GPIO5_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); + mxc_register_gpio(5, MX27_GPIO6_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); } diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c index 86b9b45864d2..cb16ac661776 100644 --- a/arch/arm/mach-imx/mm-imx31.c +++ b/arch/arm/mach-imx/mm-imx31.c @@ -26,7 +26,6 @@ #include #include #include -#include #include static struct map_desc mx31_io_desc[] __initdata = { @@ -53,14 +52,14 @@ void __init imx31_init_early(void) mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR)); } -static struct mxc_gpio_port imx31_gpio_ports[] = { - DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1), - DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2), - DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3), -}; - void __init mx31_init_irq(void) { mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR)); - mxc_gpio_init(imx31_gpio_ports, ARRAY_SIZE(imx31_gpio_ports)); +} + +void __init imx31_soc_init(void) +{ + mxc_register_gpio(0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0); + mxc_register_gpio(1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0); + mxc_register_gpio(2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0); } diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c index c880e6d1ae55..648bfca0163e 100644 --- a/arch/arm/mach-imx/mm-imx35.c +++ b/arch/arm/mach-imx/mm-imx35.c @@ -27,7 +27,6 @@ #include #include #include -#include #include static struct map_desc mx35_io_desc[] __initdata = { @@ -50,14 +49,14 @@ void __init imx35_init_early(void) mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR)); } -static struct mxc_gpio_port imx35_gpio_ports[] = { - DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1), - DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2), - DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3), -}; - void __init mx35_init_irq(void) { mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR)); - mxc_gpio_init(imx35_gpio_ports, ARRAY_SIZE(imx35_gpio_ports)); +} + +void __init imx35_soc_init(void) +{ + mxc_register_gpio(0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0); + mxc_register_gpio(1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0); + mxc_register_gpio(2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0); } diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c index 4efa02ee1639..add0d42de7af 100644 --- a/arch/arm/mach-mx5/board-cpuimx51.c +++ b/arch/arm/mach-mx5/board-cpuimx51.c @@ -245,6 +245,8 @@ __setup("otg_mode=", eukrea_cpuimx51_otg_mode); */ static void __init eukrea_cpuimx51_init(void) { + imx51_soc_init(); + mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads, ARRAY_SIZE(eukrea_cpuimx51_pads)); diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c index 5ef25a596143..ff096d587299 100644 --- a/arch/arm/mach-mx5/board-cpuimx51sd.c +++ b/arch/arm/mach-mx5/board-cpuimx51sd.c @@ -264,6 +264,8 @@ static struct platform_device *platform_devices[] __initdata = { static void __init eukrea_cpuimx51sd_init(void) { + imx51_soc_init(); + mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads, ARRAY_SIZE(eukrea_cpuimx51sd_pads)); diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c index 11210e1ae42a..7de25c6712eb 100644 --- a/arch/arm/mach-mx5/board-mx50_rdp.c +++ b/arch/arm/mach-mx5/board-mx50_rdp.c @@ -192,6 +192,8 @@ static const struct imxi2c_platform_data i2c_data __initconst = { */ static void __init mx50_rdp_board_init(void) { + imx50_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads, ARRAY_SIZE(mx50_rdp_pads)); diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c index 63dfbeafbc1e..3112d15feebc 100644 --- a/arch/arm/mach-mx5/board-mx51_3ds.c +++ b/arch/arm/mach-mx5/board-mx51_3ds.c @@ -135,6 +135,8 @@ static struct spi_board_info mx51_3ds_spi_nor_device[] = { */ static void __init mx51_3ds_init(void) { + imx51_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads, ARRAY_SIZE(mx51_3ds_pads)); diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index c7b3fabf50f9..6021dd00ec75 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -340,6 +340,8 @@ static void __init mx51_babbage_init(void) iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 | MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP); + imx51_soc_init(); + #if defined(CONFIG_CPU_FREQ_IMX) get_cpu_op = mx51_get_cpu_op; #endif diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c index 6e362315291b..3be603b9075a 100644 --- a/arch/arm/mach-mx5/board-mx51_efikamx.c +++ b/arch/arm/mach-mx5/board-mx51_efikamx.c @@ -236,6 +236,8 @@ late_initcall(mx51_efikamx_power_init); static void __init mx51_efikamx_init(void) { + imx51_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads, ARRAY_SIZE(mx51efikamx_pads)); efika_board_common_init(); diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c index 474fc6e4c6df..4b2e522de0f8 100644 --- a/arch/arm/mach-mx5/board-mx51_efikasb.c +++ b/arch/arm/mach-mx5/board-mx51_efikasb.c @@ -248,6 +248,8 @@ static void __init mx51_efikasb_board_id(void) static void __init efikasb_board_init(void) { + imx51_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads, ARRAY_SIZE(mx51efikasb_pads)); efika_board_common_init(); diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c index f87d571882c6..0d9218a6e2d2 100644 --- a/arch/arm/mach-mx5/board-mx53_evk.c +++ b/arch/arm/mach-mx5/board-mx53_evk.c @@ -117,6 +117,8 @@ static const struct spi_imx_master mx53_evk_spi_data __initconst = { static void __init mx53_evk_board_init(void) { + imx53_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads, ARRAY_SIZE(mx53_evk_pads)); mx53_evk_init_uart(); diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 1b947e8c9c0c..359c3e248add 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -227,6 +227,8 @@ static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = { static void __init mx53_loco_board_init(void) { + imx53_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads, ARRAY_SIZE(mx53_loco_pads)); imx53_add_imx_uart(0, NULL); diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c index 817c08938f55..bc02894eafef 100644 --- a/arch/arm/mach-mx5/board-mx53_smd.c +++ b/arch/arm/mach-mx5/board-mx53_smd.c @@ -113,6 +113,8 @@ static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = { static void __init mx53_smd_board_init(void) { + imx53_soc_init(); + mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads, ARRAY_SIZE(mx53_smd_pads)); mx53_smd_init_uart(); diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c index 153ada53e575..371ca8c8414c 100644 --- a/arch/arm/mach-mx5/devices.c +++ b/arch/arm/mach-mx5/devices.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -119,66 +118,3 @@ struct platform_device mxc_usbh2_device = { .coherent_dma_mask = DMA_BIT_MASK(32), }, }; - -static struct mxc_gpio_port mxc_gpio_ports[] = { - { - .chip.label = "gpio-0", - .base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR), - .irq = MX51_MXC_INT_GPIO1_LOW, - .irq_high = MX51_MXC_INT_GPIO1_HIGH, - .virtual_irq_start = MXC_GPIO_IRQ_START - }, - { - .chip.label = "gpio-1", - .base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR), - .irq = MX51_MXC_INT_GPIO2_LOW, - .irq_high = MX51_MXC_INT_GPIO2_HIGH, - .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1 - }, - { - .chip.label = "gpio-2", - .base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR), - .irq = MX51_MXC_INT_GPIO3_LOW, - .irq_high = MX51_MXC_INT_GPIO3_HIGH, - .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2 - }, - { - .chip.label = "gpio-3", - .base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR), - .irq = MX51_MXC_INT_GPIO4_LOW, - .irq_high = MX51_MXC_INT_GPIO4_HIGH, - .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3 - }, - { - .chip.label = "gpio-4", - .base = MX53_IO_ADDRESS(MX53_GPIO5_BASE_ADDR), - .irq = MX53_INT_GPIO5_LOW, - .irq_high = MX53_INT_GPIO5_HIGH, - .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4 - }, - { - .chip.label = "gpio-5", - .base = MX53_IO_ADDRESS(MX53_GPIO6_BASE_ADDR), - .irq = MX53_INT_GPIO6_LOW, - .irq_high = MX53_INT_GPIO6_HIGH, - .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5 - }, - { - .chip.label = "gpio-6", - .base = MX53_IO_ADDRESS(MX53_GPIO7_BASE_ADDR), - .irq = MX53_INT_GPIO7_LOW, - .irq_high = MX53_INT_GPIO7_HIGH, - .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6 - }, -}; - -int __init imx51_register_gpios(void) -{ - return mxc_gpio_init(mxc_gpio_ports, 4); -} - -int __init imx53_register_gpios(void) -{ - return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports)); -} - diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c index b9c363b514a9..28c3f60f734f 100644 --- a/arch/arm/mach-mx5/mm-mx50.c +++ b/arch/arm/mach-mx5/mm-mx50.c @@ -26,7 +26,6 @@ #include #include #include -#include #include /* @@ -56,17 +55,17 @@ void __init imx50_init_early(void) mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR)); } -static struct mxc_gpio_port imx50_gpio_ports[] = { - DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH), - DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH), - DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), - DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), - DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), - DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), -}; - void __init mx50_init_irq(void) { tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR)); - mxc_gpio_init(imx50_gpio_ports, ARRAY_SIZE(imx50_gpio_ports)); +} + +void __init imx50_soc_init(void) +{ + mxc_register_gpio(0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); + mxc_register_gpio(1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); + mxc_register_gpio(2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); + mxc_register_gpio(3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); + mxc_register_gpio(4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); + mxc_register_gpio(5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH); } diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c index ff557301b42b..800bb8b21081 100644 --- a/arch/arm/mach-mx5/mm.c +++ b/arch/arm/mach-mx5/mm.c @@ -69,8 +69,6 @@ void __init imx53_init_early(void) mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR)); } -int imx51_register_gpios(void); - void __init mx51_init_irq(void) { unsigned long tzic_addr; @@ -86,11 +84,8 @@ void __init mx51_init_irq(void) panic("unable to map TZIC interrupt controller\n"); tzic_init_irq(tzic_virt); - imx51_register_gpios(); } -int imx53_register_gpios(void); - void __init mx53_init_irq(void) { unsigned long tzic_addr; @@ -103,5 +98,23 @@ void __init mx53_init_irq(void) panic("unable to map TZIC interrupt controller\n"); tzic_init_irq(tzic_virt); - imx53_register_gpios(); +} + +void __init imx51_soc_init(void) +{ + mxc_register_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH); + mxc_register_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH); + mxc_register_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH); + mxc_register_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH); +} + +void __init imx53_soc_init(void) +{ + mxc_register_gpio(0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH); + mxc_register_gpio(1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH); + mxc_register_gpio(2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH); + mxc_register_gpio(3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH); + mxc_register_gpio(4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH); + mxc_register_gpio(5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH); + mxc_register_gpio(6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH); } diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c index eee1b6096a08..fb166b20f60f 100644 --- a/arch/arm/plat-mxc/devices.c +++ b/arch/arm/plat-mxc/devices.c @@ -89,3 +89,14 @@ struct platform_device *__init imx_add_platform_device_dmamask( return pdev; } + +struct device mxc_aips_bus = { + .init_name = "mxc_aips", + .parent = &platform_bus, +}; + +static int __init mxc_device_init(void) +{ + return device_register(&mxc_aips_bus); +} +core_initcall(mxc_device_init); diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile index ad2922acf480..b41bf972b54b 100644 --- a/arch/arm/plat-mxc/devices/Makefile +++ b/arch/arm/plat-mxc/devices/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o +obj-y += platform-gpio-mxc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c new file mode 100644 index 000000000000..cf1b7fdfa20d --- /dev/null +++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c @@ -0,0 +1,32 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2011 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ +#include + +struct platform_device *__init mxc_register_gpio(int id, + resource_size_t iobase, resource_size_t iosize, int irq, int irq_high) +{ + struct resource res[] = { + { + .start = iobase, + .end = iobase + iosize - 1, + .flags = IORESOURCE_MEM, + }, { + .start = irq, + .end = irq, + .flags = IORESOURCE_IRQ, + }, { + .start = irq_high, + .end = irq_high, + .flags = IORESOURCE_IRQ, + }, + }; + + return platform_device_register_resndata(&mxc_aips_bus, + "gpio-mxc", id, res, ARRAY_SIZE(res), NULL, 0); +} diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index da7991832af6..91fa2632aa5e 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -43,6 +43,15 @@ extern void mx35_init_irq(void); extern void mx50_init_irq(void); extern void mx51_init_irq(void); extern void mx53_init_irq(void); +extern void imx1_soc_init(void); +extern void imx21_soc_init(void); +extern void imx25_soc_init(void); +extern void imx27_soc_init(void); +extern void imx31_soc_init(void); +extern void imx35_soc_init(void); +extern void imx50_soc_init(void); +extern void imx51_soc_init(void); +extern void imx53_soc_init(void); extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq); extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int); extern int mx1_clocks_init(unsigned long fref); @@ -55,7 +64,8 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2); extern int mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2); -extern int mxc_register_gpios(void); +extern struct platform_device *mxc_register_gpio(int id, + resource_size_t iobase, resource_size_t iosize, int irq, int irq_high); extern int mxc_register_device(struct platform_device *pdev, void *data); extern void mxc_set_cpu_type(unsigned int type); extern void mxc_arch_reset_init(void __iomem *); diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index fa8477337f91..03f626645374 100644 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -10,6 +10,8 @@ #include #include +extern struct device mxc_aips_bus; + struct platform_device *imx_add_platform_device_dmamask( const char *name, int id, const struct resource *res, unsigned int num_resources, diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h index a2747f12813e..31c820c1b796 100644 --- a/arch/arm/plat-mxc/include/mach/gpio.h +++ b/arch/arm/plat-mxc/include/mach/gpio.h @@ -36,31 +36,4 @@ #define gpio_to_irq(gpio) (MXC_GPIO_IRQ_START + (gpio)) #define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START) -struct mxc_gpio_port { - void __iomem *base; - int irq; - int irq_high; - int virtual_irq_start; - struct gpio_chip chip; - u32 both_edges; - spinlock_t lock; -}; - -#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high) \ - { \ - .chip.label = "gpio-" #_id, \ - .irq = _irq, \ - .irq_high = _irq_high, \ - .base = soc ## _IO_ADDRESS( \ - soc ## _GPIO ## _hwid ## _BASE_ADDR), \ - .virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32, \ - } - -#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq) \ - DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0) -#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid) \ - DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0) - -int mxc_gpio_init(struct mxc_gpio_port*, int); - #endif diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 6cd6d7f686f6..844079a83f25 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -24,11 +24,28 @@ #include #include #include +#include +#include #include #include -static struct mxc_gpio_port *mxc_gpio_ports; -static int gpio_table_size; +struct mxc_gpio_port { + struct list_head node; + void __iomem *base; + int irq; + int irq_high; + int virtual_irq_start; + struct gpio_chip chip; + u32 both_edges; + spinlock_t lock; +}; + +/* + * MX2 has one interrupt *for all* gpio ports. The list is used + * to save the references to all ports, so that mx2_gpio_irq_handler + * can walk through all interrupt status registers. + */ +static LIST_HEAD(mxc_gpio_ports); #define cpu_is_mx1_mx2() (cpu_is_mx1() || cpu_is_mx2()) @@ -50,7 +67,7 @@ static int gpio_table_size; static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index) { - __raw_writel(1 << index, port->base + GPIO_ISR); + writel(1 << index, port->base + GPIO_ISR); } static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index, @@ -58,27 +75,30 @@ static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index, { u32 l; - l = __raw_readl(port->base + GPIO_IMR); + l = readl(port->base + GPIO_IMR); l = (l & (~(1 << index))) | (!!enable << index); - __raw_writel(l, port->base + GPIO_IMR); + writel(l, port->base + GPIO_IMR); } static void gpio_ack_irq(struct irq_data *d) { + struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); u32 gpio = irq_to_gpio(d->irq); - _clear_gpio_irqstatus(&mxc_gpio_ports[gpio / 32], gpio & 0x1f); + _clear_gpio_irqstatus(port, gpio & 0x1f); } static void gpio_mask_irq(struct irq_data *d) { + struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); u32 gpio = irq_to_gpio(d->irq); - _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 0); + _set_gpio_irqenable(port, gpio & 0x1f, 0); } static void gpio_unmask_irq(struct irq_data *d) { + struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); u32 gpio = irq_to_gpio(d->irq); - _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1); + _set_gpio_irqenable(port, gpio & 0x1f, 1); } static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset); @@ -86,7 +106,7 @@ static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset); static int gpio_set_irq_type(struct irq_data *d, u32 type) { u32 gpio = irq_to_gpio(d->irq); - struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32]; + struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); u32 bit, val; int edge; void __iomem *reg = port->base; @@ -122,8 +142,8 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ bit = gpio & 0xf; - val = __raw_readl(reg) & ~(0x3 << (bit << 1)); - __raw_writel(val | (edge << (bit << 1)), reg); + val = readl(reg) & ~(0x3 << (bit << 1)); + writel(val | (edge << (bit << 1)), reg); _clear_gpio_irqstatus(port, gpio & 0x1f); return 0; @@ -137,7 +157,7 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ bit = gpio & 0xf; - val = __raw_readl(reg); + val = readl(reg); edge = (val >> (bit << 1)) & 3; val &= ~(0x3 << (bit << 1)); if (edge == GPIO_INT_HIGH_LEV) { @@ -151,7 +171,7 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) gpio, edge); return; } - __raw_writel(val | (edge << (bit << 1)), reg); + writel(val | (edge << (bit << 1)), reg); } /* handle 32 interrupts in one status register */ @@ -177,8 +197,7 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) u32 irq_stat; struct mxc_gpio_port *port = irq_get_handler_data(irq); - irq_stat = __raw_readl(port->base + GPIO_ISR) & - __raw_readl(port->base + GPIO_IMR); + irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR); mxc_gpio_irq_handler(port, irq_stat); } @@ -186,19 +205,18 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) /* MX2 has one interrupt *for all* gpio ports */ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) { - int i; u32 irq_msk, irq_stat; - struct mxc_gpio_port *port = irq_get_handler_data(irq); + struct mxc_gpio_port *port; /* walk through all interrupt status registers */ - for (i = 0; i < gpio_table_size; i++) { - irq_msk = __raw_readl(port[i].base + GPIO_IMR); + list_for_each_entry(port, &mxc_gpio_ports, node) { + irq_msk = readl(port->base + GPIO_IMR); if (!irq_msk) continue; - irq_stat = __raw_readl(port[i].base + GPIO_ISR) & irq_msk; + irq_stat = readl(port->base + GPIO_ISR) & irq_msk; if (irq_stat) - mxc_gpio_irq_handler(&port[i], irq_stat); + mxc_gpio_irq_handler(port, irq_stat); } } @@ -215,7 +233,7 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) { u32 gpio = irq_to_gpio(d->irq); u32 gpio_idx = gpio & 0x1F; - struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32]; + struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); if (enable) { if (port->irq_high && (gpio_idx >= 16)) @@ -250,12 +268,12 @@ static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, unsigned long flags; spin_lock_irqsave(&port->lock, flags); - l = __raw_readl(port->base + GPIO_GDIR); + l = readl(port->base + GPIO_GDIR); if (dir) l |= 1 << offset; else l &= ~(1 << offset); - __raw_writel(l, port->base + GPIO_GDIR); + writel(l, port->base + GPIO_GDIR); spin_unlock_irqrestore(&port->lock, flags); } @@ -268,8 +286,8 @@ static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) unsigned long flags; spin_lock_irqsave(&port->lock, flags); - l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset); - __raw_writel(l, reg); + l = (readl(reg) & (~(1 << offset))) | (!!value << offset); + writel(l, reg); spin_unlock_irqrestore(&port->lock, flags); } @@ -278,7 +296,7 @@ static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) struct mxc_gpio_port *port = container_of(chip, struct mxc_gpio_port, chip); - return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1; + return (readl(port->base + GPIO_PSR) >> offset) & 1; } static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset) @@ -301,61 +319,116 @@ static int mxc_gpio_direction_output(struct gpio_chip *chip, */ static struct lock_class_key gpio_lock_class; -int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) +static int __devinit mxc_gpio_probe(struct platform_device *pdev) { - int i, j; + struct mxc_gpio_port *port; + struct resource *iores; + int err, i; - /* save for local usage */ - mxc_gpio_ports = port; - gpio_table_size = cnt; + port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL); + if (!port) + return -ENOMEM; - printk(KERN_INFO "MXC GPIO hardware\n"); + port->virtual_irq_start = MXC_GPIO_IRQ_START + pdev->id * 32; - for (i = 0; i < cnt; i++) { - /* disable the interrupt and clear the status */ - __raw_writel(0, port[i].base + GPIO_IMR); - __raw_writel(~0, port[i].base + GPIO_ISR); - for (j = port[i].virtual_irq_start; - j < port[i].virtual_irq_start + 32; j++) { - irq_set_lockdep_class(j, &gpio_lock_class); - irq_set_chip_and_handler(j, &gpio_irq_chip, - handle_level_irq); - set_irq_flags(j, IRQF_VALID); - } + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iores) { + err = -ENODEV; + goto out_kfree; + } - /* register gpio chip */ - port[i].chip.direction_input = mxc_gpio_direction_input; - port[i].chip.direction_output = mxc_gpio_direction_output; - port[i].chip.get = mxc_gpio_get; - port[i].chip.set = mxc_gpio_set; - port[i].chip.base = i * 32; - port[i].chip.ngpio = 32; + if (!request_mem_region(iores->start, resource_size(iores), + pdev->name)) { + err = -EBUSY; + goto out_kfree; + } - spin_lock_init(&port[i].lock); + port->base = ioremap(iores->start, resource_size(iores)); + if (!port->base) { + err = -ENOMEM; + goto out_release_mem; + } - /* its a serious configuration bug when it fails */ - BUG_ON( gpiochip_add(&port[i].chip) < 0 ); + port->irq_high = platform_get_irq(pdev, 1); + port->irq = platform_get_irq(pdev, 0); + if (port->irq < 0) { + err = -EINVAL; + goto out_iounmap; + } - if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) { - /* setup one handler for each entry */ - irq_set_chained_handler(port[i].irq, - mx3_gpio_irq_handler); - irq_set_handler_data(port[i].irq, &port[i]); - if (port[i].irq_high) { - /* setup handler for GPIO 16 to 31 */ - irq_set_chained_handler(port[i].irq_high, - mx3_gpio_irq_handler); - irq_set_handler_data(port[i].irq_high, - &port[i]); - } - } + /* disable the interrupt and clear the status */ + writel(0, port->base + GPIO_IMR); + writel(~0, port->base + GPIO_ISR); + + for (i = port->virtual_irq_start; + i < port->virtual_irq_start + 32; i++) { + irq_set_lockdep_class(i, &gpio_lock_class); + irq_set_chip_and_handler(i, &gpio_irq_chip, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + irq_set_chip_data(i, port); } if (cpu_is_mx2()) { /* setup one handler for all GPIO interrupts */ - irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler); - irq_set_handler_data(port[0].irq, port); + if (pdev->id == 0) + irq_set_chained_handler(port->irq, + mx2_gpio_irq_handler); + } else { + /* setup one handler for each entry */ + irq_set_chained_handler(port->irq, mx3_gpio_irq_handler); + irq_set_handler_data(port->irq, port); + if (port->irq_high > 0) { + /* setup handler for GPIO 16 to 31 */ + irq_set_chained_handler(port->irq_high, + mx3_gpio_irq_handler); + irq_set_handler_data(port->irq_high, port); + } } + /* register gpio chip */ + port->chip.direction_input = mxc_gpio_direction_input; + port->chip.direction_output = mxc_gpio_direction_output; + port->chip.get = mxc_gpio_get; + port->chip.set = mxc_gpio_set; + port->chip.base = pdev->id * 32; + port->chip.ngpio = 32; + + spin_lock_init(&port->lock); + + err = gpiochip_add(&port->chip); + if (err) + goto out_iounmap; + + list_add_tail(&port->node, &mxc_gpio_ports); + return 0; + +out_iounmap: + iounmap(port->base); +out_release_mem: + release_mem_region(iores->start, resource_size(iores)); +out_kfree: + kfree(port); + dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); + return err; } + +static struct platform_driver mxc_gpio_driver = { + .driver = { + .name = "gpio-mxc", + .owner = THIS_MODULE, + }, + .probe = mxc_gpio_probe, +}; + +static int __init gpio_mxc_init(void) +{ + return platform_driver_register(&mxc_gpio_driver); +} +postcore_initcall(gpio_mxc_init); + +MODULE_AUTHOR("Freescale Semiconductor, " + "Daniel Mack , " + "Juergen Beisert "); +MODULE_DESCRIPTION("Freescale MXC GPIO"); +MODULE_LICENSE("GPL"); From 2ce420da39078a6135d1c004a0e4436fdc1458b4 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 6 Jun 2011 13:22:41 +0800 Subject: [PATCH 08/61] gpio/mxc: convert gpio-mxc to use basic_mmio_gpio library The gpio-mxc controller complies with basic_mmio_gpio library. The patch convert the driver to use the library. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mxc.c | 85 ++++++++--------------------------------- 2 files changed, 16 insertions(+), 70 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 1ee725aa021d..57d7bc547f4b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -100,6 +100,7 @@ config GPIO_MXS config GPIO_MXC def_bool y depends on ARCH_MXC + select GPIO_BASIC_MMIO_CORE config GPIO_PLAT_SAMSUNG bool "Samsung SoCs GPIO library support" diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 844079a83f25..b351952893bb 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -35,9 +36,8 @@ struct mxc_gpio_port { int irq; int irq_high; int virtual_irq_start; - struct gpio_chip chip; + struct bgpio_chip bgc; u32 both_edges; - spinlock_t lock; }; /* @@ -101,8 +101,6 @@ static void gpio_unmask_irq(struct irq_data *d) _set_gpio_irqenable(port, gpio & 0x1f, 1); } -static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset); - static int gpio_set_irq_type(struct irq_data *d, u32 type) { u32 gpio = irq_to_gpio(d->irq); @@ -120,7 +118,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) edge = GPIO_INT_FALL_EDGE; break; case IRQ_TYPE_EDGE_BOTH: - val = mxc_gpio_get(&port->chip, gpio & 31); + val = gpio_get_value(gpio & 31); if (val) { edge = GPIO_INT_LOW_LEV; pr_debug("mxc: set GPIO %d to low trigger\n", gpio); @@ -259,60 +257,6 @@ static struct irq_chip gpio_irq_chip = { .irq_set_wake = gpio_set_wake_irq, }; -static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, - int dir) -{ - struct mxc_gpio_port *port = - container_of(chip, struct mxc_gpio_port, chip); - u32 l; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - l = readl(port->base + GPIO_GDIR); - if (dir) - l |= 1 << offset; - else - l &= ~(1 << offset); - writel(l, port->base + GPIO_GDIR); - spin_unlock_irqrestore(&port->lock, flags); -} - -static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct mxc_gpio_port *port = - container_of(chip, struct mxc_gpio_port, chip); - void __iomem *reg = port->base + GPIO_DR; - u32 l; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - l = (readl(reg) & (~(1 << offset))) | (!!value << offset); - writel(l, reg); - spin_unlock_irqrestore(&port->lock, flags); -} - -static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct mxc_gpio_port *port = - container_of(chip, struct mxc_gpio_port, chip); - - return (readl(port->base + GPIO_PSR) >> offset) & 1; -} - -static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - _set_gpio_direction(chip, offset, 0); - return 0; -} - -static int mxc_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - mxc_gpio_set(chip, offset, value); - _set_gpio_direction(chip, offset, 1); - return 0; -} - /* * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. @@ -385,24 +329,25 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) } } - /* register gpio chip */ - port->chip.direction_input = mxc_gpio_direction_input; - port->chip.direction_output = mxc_gpio_direction_output; - port->chip.get = mxc_gpio_get; - port->chip.set = mxc_gpio_set; - port->chip.base = pdev->id * 32; - port->chip.ngpio = 32; - - spin_lock_init(&port->lock); - - err = gpiochip_add(&port->chip); + err = bgpio_init(&port->bgc, &pdev->dev, 4, + port->base + GPIO_PSR, + port->base + GPIO_DR, NULL, + port->base + GPIO_GDIR, NULL, false); if (err) goto out_iounmap; + port->bgc.gc.base = pdev->id * 32; + + err = gpiochip_add(&port->bgc.gc); + if (err) + goto out_bgpio_remove; + list_add_tail(&port->node, &mxc_gpio_ports); return 0; +out_bgpio_remove: + bgpio_remove(&port->bgc); out_iounmap: iounmap(port->base); out_release_mem: From c6b52c13de4415ed5774be8c076685715de56096 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 1 Jun 2011 10:09:19 -0700 Subject: [PATCH 09/61] gpio/ep93xx: move driver to drivers/gpio The GPIO driver should reside in drivers/gpio. v3: Change Kconfig option to def_bool y v2: Make the Kconfig symbol a silent option, dependent on ARCH_EP93XX Signed-off-by: H Hartley Sweeten Signed-off-by: Grant Likely --- arch/arm/mach-ep93xx/Makefile | 2 +- drivers/gpio/Kconfig | 4 ++++ drivers/gpio/Makefile | 1 + arch/arm/mach-ep93xx/gpio.c => drivers/gpio/gpio-ep93xx.c | 0 4 files changed, 6 insertions(+), 1 deletion(-) rename arch/arm/mach-ep93xx/gpio.c => drivers/gpio/gpio-ep93xx.c (100%) diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index 33ee2c863d18..6b7c41d155df 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux kernel. # -obj-y := core.o clock.o dma-m2p.o gpio.o +obj-y := core.o clock.o dma-m2p.o obj-m := obj-n := obj- := diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2967002a9f82..21271a5209ab 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -86,6 +86,10 @@ config GPIO_IT8761E help Say yes here to support GPIO functionality of IT8761E super I/O chip. +config GPIO_EP93XX + def_bool y + depends on ARCH_EP93XX + config GPIO_EXYNOS4 def_bool y depends on CPU_EXYNOS4210 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index b605f8ec6fbe..e6e503229c86 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o +obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o diff --git a/arch/arm/mach-ep93xx/gpio.c b/drivers/gpio/gpio-ep93xx.c similarity index 100% rename from arch/arm/mach-ep93xx/gpio.c rename to drivers/gpio/gpio-ep93xx.c From 121a2dd860f8348fb014b660f133a0cb9a16273e Mon Sep 17 00:00:00 2001 From: David Jander Date: Wed, 1 Jun 2011 10:57:27 +0200 Subject: [PATCH 10/61] gpio/pca953x.c: Interrupt pin is active-low The interrupt pin of the PCA953x is active low, and on the rising edge no interrupt should be produced. Signed-off-by: David Jander Signed-off-by: Grant Likely --- drivers/gpio/pca953x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 0451d7ac94ac..63022b17014a 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -493,7 +493,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ret = request_threaded_irq(client->irq, NULL, pca953x_irq_handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, dev_name(&client->dev), chip); if (ret) { From c103de240439dfee24ac50eb99c8be3a30d13323 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 4 Jun 2011 18:38:28 -0600 Subject: [PATCH 11/61] gpio: reorganize drivers Sort the gpio makefile and enforce the naming convention gpio-*.c for gpio drivers. v2: cleaned up filenames in Kconfig and comment blocks v3: fixup use of BASIC_MMIO to GENERIC_GPIO for mxc Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 42 +++------- drivers/gpio/Makefile | 81 ++++++++++--------- drivers/gpio/{74x164.c => gpio-74x164.c} | 0 drivers/gpio/{ab8500-gpio.c => gpio-ab8500.c} | 0 .../gpio/{adp5520-gpio.c => gpio-adp5520.c} | 0 .../gpio/{adp5588-gpio.c => gpio-adp5588.c} | 0 drivers/gpio/{bt8xxgpio.c => gpio-bt8xx.c} | 0 drivers/gpio/{cs5535-gpio.c => gpio-cs5535.c} | 0 drivers/gpio/gpio-ep93xx.c | 2 - drivers/gpio/gpio-exynos4.c | 5 +- .../{basic_mmio_gpio.c => gpio-generic.c} | 6 +- .../gpio/{it8761e_gpio.c => gpio-it8761e.c} | 2 +- drivers/gpio/{janz-ttl.c => gpio-janz-ttl.c} | 0 .../gpio/{langwell_gpio.c => gpio-langwell.c} | 4 +- drivers/gpio/{max7300.c => gpio-max7300.c} | 2 - drivers/gpio/{max7301.c => gpio-max7301.c} | 2 - drivers/gpio/{max730x.c => gpio-max730x.c} | 2 - drivers/gpio/{max732x.c => gpio-max732x.c} | 2 +- drivers/gpio/{mc33880.c => gpio-mc33880.c} | 2 +- drivers/gpio/{mcp23s08.c => gpio-mcp23s08.c} | 2 +- drivers/gpio/{ml_ioh_gpio.c => gpio-ml-ioh.c} | 0 drivers/gpio/{pca953x.c => gpio-pca953x.c} | 2 +- drivers/gpio/{pcf857x.c => gpio-pcf857x.c} | 2 +- drivers/gpio/{pch_gpio.c => gpio-pch.c} | 0 drivers/gpio/{pl061.c => gpio-pl061.c} | 4 +- drivers/gpio/gpio-plat-samsung.c | 3 +- .../gpio/{rdc321x-gpio.c => gpio-rdc321x.c} | 0 drivers/gpio/gpio-s5pc100.c | 5 +- drivers/gpio/gpio-s5pv210.c | 5 +- drivers/gpio/{sch_gpio.c => gpio-sch.c} | 2 +- drivers/gpio/{stmpe-gpio.c => gpio-stmpe.c} | 0 drivers/gpio/{sx150x.c => gpio-sx150x.c} | 0 .../gpio/{tc3589x-gpio.c => gpio-tc3589x.c} | 0 .../gpio/{timbgpio.c => gpio-timberdale.c} | 2 +- .../gpio/{tps65910-gpio.c => gpio-tps65910.c} | 2 +- .../gpio/{twl4030-gpio.c => gpio-twl4030.c} | 2 +- drivers/gpio/gpio-u300.c | 5 +- .../gpio/{ucb1400_gpio.c => gpio-ucb1400.c} | 0 drivers/gpio/{vr41xx_giu.c => gpio-vr41xx.c} | 0 drivers/gpio/{vx855_gpio.c => gpio-vx855.c} | 0 drivers/gpio/{wm831x-gpio.c => gpio-wm831x.c} | 2 +- .../gpio/{wm8350-gpiolib.c => gpio-wm8350.c} | 2 +- drivers/gpio/{wm8994-gpio.c => gpio-wm8994.c} | 2 +- drivers/gpio/{xilinx_gpio.c => gpio-xilinx.c} | 0 44 files changed, 83 insertions(+), 111 deletions(-) rename drivers/gpio/{74x164.c => gpio-74x164.c} (100%) rename drivers/gpio/{ab8500-gpio.c => gpio-ab8500.c} (100%) rename drivers/gpio/{adp5520-gpio.c => gpio-adp5520.c} (100%) rename drivers/gpio/{adp5588-gpio.c => gpio-adp5588.c} (100%) rename drivers/gpio/{bt8xxgpio.c => gpio-bt8xx.c} (100%) rename drivers/gpio/{cs5535-gpio.c => gpio-cs5535.c} (100%) rename drivers/gpio/{basic_mmio_gpio.c => gpio-generic.c} (99%) rename drivers/gpio/{it8761e_gpio.c => gpio-it8761e.c} (98%) rename drivers/gpio/{janz-ttl.c => gpio-janz-ttl.c} (100%) rename drivers/gpio/{langwell_gpio.c => gpio-langwell.c} (99%) rename drivers/gpio/{max7300.c => gpio-max7300.c} (98%) rename drivers/gpio/{max7301.c => gpio-max7301.c} (98%) rename drivers/gpio/{max730x.c => gpio-max730x.c} (99%) rename drivers/gpio/{max732x.c => gpio-max732x.c} (99%) rename drivers/gpio/{mc33880.c => gpio-mc33880.c} (98%) rename drivers/gpio/{mcp23s08.c => gpio-mcp23s08.c} (99%) rename drivers/gpio/{ml_ioh_gpio.c => gpio-ml-ioh.c} (100%) rename drivers/gpio/{pca953x.c => gpio-pca953x.c} (99%) rename drivers/gpio/{pcf857x.c => gpio-pcf857x.c} (99%) rename drivers/gpio/{pch_gpio.c => gpio-pch.c} (100%) rename drivers/gpio/{pl061.c => gpio-pl061.c} (99%) rename drivers/gpio/{rdc321x-gpio.c => gpio-rdc321x.c} (100%) rename drivers/gpio/{sch_gpio.c => gpio-sch.c} (99%) rename drivers/gpio/{stmpe-gpio.c => gpio-stmpe.c} (100%) rename drivers/gpio/{sx150x.c => gpio-sx150x.c} (100%) rename drivers/gpio/{tc3589x-gpio.c => gpio-tc3589x.c} (100%) rename drivers/gpio/{timbgpio.c => gpio-timberdale.c} (99%) rename drivers/gpio/{tps65910-gpio.c => gpio-tps65910.c} (98%) rename drivers/gpio/{twl4030-gpio.c => gpio-twl4030.c} (99%) rename drivers/gpio/{ucb1400_gpio.c => gpio-ucb1400.c} (100%) rename drivers/gpio/{vr41xx_giu.c => gpio-vr41xx.c} (100%) rename drivers/gpio/{vx855_gpio.c => gpio-vx855.c} (100%) rename drivers/gpio/{wm831x-gpio.c => gpio-wm831x.c} (99%) rename drivers/gpio/{wm8350-gpiolib.c => gpio-wm8350.c} (98%) rename drivers/gpio/{wm8994-gpio.c => gpio-wm8994.c} (99%) rename drivers/gpio/{xilinx_gpio.c => gpio-xilinx.c} (100%) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f8b6e7d27e4c..89a6a34cc515 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -63,6 +63,9 @@ config GPIO_SYSFS Kernel drivers may also request that a particular GPIO be exported to userspace; this can be useful when debugging. +config GPIO_GENERIC + tristate + # put drivers in the right section, in alphabetical order config GPIO_MAX730X @@ -70,16 +73,11 @@ config GPIO_MAX730X comment "Memory mapped GPIO drivers:" -config GPIO_BASIC_MMIO_CORE - tristate +config GPIO_GENERIC_PLATFORM + tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" + select GPIO_GENERIC help - Provides core functionality for basic memory-mapped GPIO controllers. - -config GPIO_BASIC_MMIO - tristate "Basic memory-mapped GPIO controllers support" - select GPIO_BASIC_MMIO_CORE - help - Say yes here to support basic memory-mapped GPIO controllers. + Say yes here to support basic platform_device memory-mapped GPIO controllers. config GPIO_IT8761E tristate "IT8761E GPIO support" @@ -94,14 +92,14 @@ config GPIO_EXYNOS4 def_bool y depends on CPU_EXYNOS4210 -config GPIO_MXS - def_bool y - depends on ARCH_MXS - config GPIO_MXC def_bool y depends on ARCH_MXC - select GPIO_BASIC_MMIO_CORE + select GPIO_GENERIC + +config GPIO_MXS + def_bool y + depends on ARCH_MXS config GPIO_PLAT_SAMSUNG def_bool y @@ -150,9 +148,6 @@ config GPIO_SCH The Intel Tunnel Creek processor has 5 GPIOs powered by the core power rail and 9 from suspend power supply. - This driver can also be built as a module. If so, the module - will be called sch-gpio. - config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" depends on MFD_SUPPORT && PCI @@ -215,9 +210,6 @@ config GPIO_PCA953X 16 bits: pca9535, pca9539, pca9555, tca6416 - This driver can also be built as a module. If so, the module - will be called pca953x. - config GPIO_PCA953X_IRQ bool "Interrupt controller support for PCA953x" depends on GPIO_PCA953X=y @@ -309,17 +301,12 @@ config GPIO_ADP5520 This option enables support for on-chip GPIO found on Analog Devices ADP5520 PMICs. - To compile this driver as a module, choose M here: the module will - be called adp5520-gpio. - config GPIO_ADP5588 tristate "ADP5588 I2C GPIO expander" depends on I2C help This option enables support for 18 GPIOs found on Analog Devices ADP5588 GPIO Expanders. - To compile this driver as a module, choose M here: the module will be - called adp5588-gpio. config GPIO_ADP5588_IRQ bool "Interrupt controller support for ADP5588" @@ -441,9 +428,6 @@ config GPIO_UCB1400 This enables support for the Philips UCB1400 GPIO pins. The UCB1400 is an AC97 audio codec. - To compile this driver as a module, choose M here: the - module will be called ucb1400_gpio. - comment "MODULbus GPIO expanders:" config GPIO_JANZ_TTL @@ -454,7 +438,7 @@ config GPIO_JANZ_TTL This driver provides support for driving the pins in output mode only. Input mode is not supported. -config AB8500_GPIO +config GPIO_AB8500 bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions" depends on AB8500_CORE && BROKEN help diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 66923cf3ad6a..68e3bfd35e0f 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -4,50 +4,53 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o -obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o -obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o -obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o -obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o +# Device drivers. Generally keep list sorted alphabetically +obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o + +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_BT8XX) += gpio-bt8xx.o +obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o +obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o +obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o +obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o +obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o +obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o +obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o +obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o +obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o +obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o +obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o +obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o +obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o +obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o +obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o +obj-$(CONFIG_GPIO_PCH) += gpio-pch.o +obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o +obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o + obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o -obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o -obj-$(CONFIG_GPIO_MAX730X) += max730x.o -obj-$(CONFIG_GPIO_MAX7300) += max7300.o -obj-$(CONFIG_GPIO_MAX7301) += max7301.o -obj-$(CONFIG_GPIO_MAX732X) += max732x.o -obj-$(CONFIG_GPIO_MC33880) += mc33880.o -obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o -obj-$(CONFIG_GPIO_74X164) += 74x164.o -obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o -obj-$(CONFIG_GPIO_PCA953X) += pca953x.o -obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o -obj-$(CONFIG_GPIO_PCH) += pch_gpio.o -obj-$(CONFIG_GPIO_PL061) += pl061.o -obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o -obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o -obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o -obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o -obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o -obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o -obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o -obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o -obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o -obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o -obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o -obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o -obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o -obj-$(CONFIG_GPIO_SCH) += sch_gpio.o + +obj-$(CONFIG_GPIO_SCH) += gpio-sch.o +obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o +obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o +obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o +obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o +obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o +obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_MACH_U300) += gpio-u300.o -obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o -obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o -obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o -obj-$(CONFIG_GPIO_SX150X) += sx150x.o -obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o -obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o -obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o -obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o +obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o +obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o +obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o +obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o +obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o +obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o +obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o diff --git a/drivers/gpio/74x164.c b/drivers/gpio/gpio-74x164.c similarity index 100% rename from drivers/gpio/74x164.c rename to drivers/gpio/gpio-74x164.c diff --git a/drivers/gpio/ab8500-gpio.c b/drivers/gpio/gpio-ab8500.c similarity index 100% rename from drivers/gpio/ab8500-gpio.c rename to drivers/gpio/gpio-ab8500.c diff --git a/drivers/gpio/adp5520-gpio.c b/drivers/gpio/gpio-adp5520.c similarity index 100% rename from drivers/gpio/adp5520-gpio.c rename to drivers/gpio/gpio-adp5520.c diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/gpio-adp5588.c similarity index 100% rename from drivers/gpio/adp5588-gpio.c rename to drivers/gpio/gpio-adp5588.c diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/gpio-bt8xx.c similarity index 100% rename from drivers/gpio/bt8xxgpio.c rename to drivers/gpio/gpio-bt8xx.c diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/gpio-cs5535.c similarity index 100% rename from drivers/gpio/cs5535-gpio.c rename to drivers/gpio/gpio-cs5535.c diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 415dce37b88c..c33c9a80e149 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -1,6 +1,4 @@ /* - * linux/arch/arm/mach-ep93xx/gpio.c - * * Generic EP93xx GPIO handling * * Copyright (c) 2008 Ryan Mallon diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c index d54ca6adb660..6093a14037c3 100644 --- a/drivers/gpio/gpio-exynos4.c +++ b/drivers/gpio/gpio-exynos4.c @@ -1,10 +1,9 @@ -/* linux/arch/arm/mach-exynos4/gpiolib.c +/* + * EXYNOS4 - GPIOlib support * * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * EXYNOS4 - GPIOlib support - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/gpio-generic.c similarity index 99% rename from drivers/gpio/basic_mmio_gpio.c rename to drivers/gpio/gpio-generic.c index 8152e9f516b0..231714def4d2 100644 --- a/drivers/gpio/basic_mmio_gpio.c +++ b/drivers/gpio/gpio-generic.c @@ -1,5 +1,5 @@ /* - * Driver for basic memory-mapped GPIO controllers. + * Generic driver for memory-mapped GPIO controllers. * * Copyright 2008 MontaVista Software, Inc. * Copyright 2008,2010 Anton Vorontsov @@ -404,7 +404,7 @@ int __devinit bgpio_init(struct bgpio_chip *bgc, } EXPORT_SYMBOL_GPL(bgpio_init); -#ifdef CONFIG_GPIO_BASIC_MMIO +#ifdef CONFIG_GPIO_GENERIC_PLATFORM static void __iomem *bgpio_map(struct platform_device *pdev, const char *name, @@ -541,7 +541,7 @@ static void __exit bgpio_platform_exit(void) } module_exit(bgpio_platform_exit); -#endif /* CONFIG_GPIO_BASIC_MMIO */ +#endif /* CONFIG_GPIO_GENERIC_PLATFORM */ MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); MODULE_AUTHOR("Anton Vorontsov "); diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/gpio-it8761e.c similarity index 98% rename from drivers/gpio/it8761e_gpio.c rename to drivers/gpio/gpio-it8761e.c index 48fc43c4bdd1..278b81317010 100644 --- a/drivers/gpio/it8761e_gpio.c +++ b/drivers/gpio/gpio-it8761e.c @@ -1,5 +1,5 @@ /* - * it8761_gpio.c - GPIO interface for IT8761E Super I/O chip + * GPIO interface for IT8761E Super I/O chip * * Author: Denis Turischev * diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c similarity index 100% rename from drivers/gpio/janz-ttl.c rename to drivers/gpio/gpio-janz-ttl.c diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/gpio-langwell.c similarity index 99% rename from drivers/gpio/langwell_gpio.c rename to drivers/gpio/gpio-langwell.c index bd6571e0097a..e7a7ea760efc 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/gpio-langwell.c @@ -1,4 +1,6 @@ -/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver +/* + * Moorestown platform Langwell chip GPIO driver + * * Copyright (c) 2008 - 2009, Intel Corporation. * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/gpio/max7300.c b/drivers/gpio/gpio-max7300.c similarity index 98% rename from drivers/gpio/max7300.c rename to drivers/gpio/gpio-max7300.c index 962f661c18c7..a5ca0ab1b372 100644 --- a/drivers/gpio/max7300.c +++ b/drivers/gpio/gpio-max7300.c @@ -1,6 +1,4 @@ /* - * drivers/gpio/max7300.c - * * Copyright (C) 2009 Wolfram Sang, Pengutronix * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/gpio/max7301.c b/drivers/gpio/gpio-max7301.c similarity index 98% rename from drivers/gpio/max7301.c rename to drivers/gpio/gpio-max7301.c index 92a100ddef6b..741acfcbe761 100644 --- a/drivers/gpio/max7301.c +++ b/drivers/gpio/gpio-max7301.c @@ -1,6 +1,4 @@ /* - * drivers/gpio/max7301.c - * * Copyright (C) 2006 Juergen Beisert, Pengutronix * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix * Copyright (C) 2009 Wolfram Sang, Pengutronix diff --git a/drivers/gpio/max730x.c b/drivers/gpio/gpio-max730x.c similarity index 99% rename from drivers/gpio/max730x.c rename to drivers/gpio/gpio-max730x.c index 94ce773f95f8..05e2dac60b3b 100644 --- a/drivers/gpio/max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -1,6 +1,4 @@ /** - * drivers/gpio/max7301.c - * * Copyright (C) 2006 Juergen Beisert, Pengutronix * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix * Copyright (C) 2009 Wolfram Sang, Pengutronix diff --git a/drivers/gpio/max732x.c b/drivers/gpio/gpio-max732x.c similarity index 99% rename from drivers/gpio/max732x.c rename to drivers/gpio/gpio-max732x.c index ad6951edc16c..9504120812a5 100644 --- a/drivers/gpio/max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -1,5 +1,5 @@ /* - * max732x.c - I2C Port Expander with 8/16 I/O + * MAX732x I2C Port Expander with 8/16 I/O * * Copyright (C) 2007 Marvell International Ltd. * Copyright (C) 2008 Jack Ren diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/gpio-mc33880.c similarity index 98% rename from drivers/gpio/mc33880.c rename to drivers/gpio/gpio-mc33880.c index 4ec797593bdb..b3b4652e89ec 100644 --- a/drivers/gpio/mc33880.c +++ b/drivers/gpio/gpio-mc33880.c @@ -1,5 +1,5 @@ /* - * mc33880.c MC33880 high-side/low-side switch GPIO driver + * MC33880 high-side/low-side switch GPIO driver * Copyright (c) 2009 Intel Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c similarity index 99% rename from drivers/gpio/mcp23s08.c rename to drivers/gpio/gpio-mcp23s08.c index 40e076083ec0..0083ec051de5 100644 --- a/drivers/gpio/mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -1,5 +1,5 @@ /* - * mcp23s08.c - SPI gpio expander driver + * MCP23S08 SPI gpio expander driver */ #include diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/gpio-ml-ioh.c similarity index 100% rename from drivers/gpio/ml_ioh_gpio.c rename to drivers/gpio/gpio-ml-ioh.c diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/gpio-pca953x.c similarity index 99% rename from drivers/gpio/pca953x.c rename to drivers/gpio/gpio-pca953x.c index 63022b17014a..a610864b7e13 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1,5 +1,5 @@ /* - * pca953x.c - 4/8/16 bit I/O ports + * PCA953x 4/8/16 bit I/O ports * * Copyright (C) 2005 Ben Gardner * Copyright (C) 2007 Marvell International Ltd. diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/gpio-pcf857x.c similarity index 99% rename from drivers/gpio/pcf857x.c rename to drivers/gpio/gpio-pcf857x.c index 879b473aab5a..7369fdda92b0 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -1,5 +1,5 @@ /* - * pcf857x - driver for pcf857x, pca857x, and pca967x I2C GPIO expanders + * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders * * Copyright (C) 2007 David Brownell * diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/gpio-pch.c similarity index 100% rename from drivers/gpio/pch_gpio.c rename to drivers/gpio/gpio-pch.c diff --git a/drivers/gpio/pl061.c b/drivers/gpio/gpio-pl061.c similarity index 99% rename from drivers/gpio/pl061.c rename to drivers/gpio/gpio-pl061.c index 6fcb28cdd862..2c5a18f32bf3 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -1,7 +1,5 @@ /* - * linux/drivers/gpio/pl061.c - * - * Copyright (C) 2008, 2009 Provigent Ltd. + * Copyright (C) 2008, 2009 Provigent Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c index ea37c0461788..ef67f1952a72 100644 --- a/drivers/gpio/gpio-plat-samsung.c +++ b/drivers/gpio/gpio-plat-samsung.c @@ -1,5 +1,4 @@ -/* arch/arm/plat-samsung/gpiolib.c - * +/* * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/gpio-rdc321x.c similarity index 100% rename from drivers/gpio/rdc321x-gpio.c rename to drivers/gpio/gpio-rdc321x.c diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c index 2842394b28b5..7f87b0c76e0b 100644 --- a/drivers/gpio/gpio-s5pc100.c +++ b/drivers/gpio/gpio-s5pc100.c @@ -1,4 +1,5 @@ -/* linux/arch/arm/mach-s5pc100/gpiolib.c +/* + * S5PC100 - GPIOlib support * * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com @@ -6,8 +7,6 @@ * Copyright 2009 Samsung Electronics Co * Kyungmin Park * - * S5PC100 - GPIOlib support - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c index 1ba20a703e05..eb12f1602de9 100644 --- a/drivers/gpio/gpio-s5pv210.c +++ b/drivers/gpio/gpio-s5pv210.c @@ -1,10 +1,9 @@ -/* linux/arch/arm/mach-s5pv210/gpiolib.c +/* + * S5PV210 - GPIOlib support * * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * S5PV210 - GPIOlib support - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/gpio-sch.c similarity index 99% rename from drivers/gpio/sch_gpio.c rename to drivers/gpio/gpio-sch.c index 56060421cdff..163515845494 100644 --- a/drivers/gpio/sch_gpio.c +++ b/drivers/gpio/gpio-sch.c @@ -1,5 +1,5 @@ /* - * sch_gpio.c - GPIO interface for Intel Poulsbo SCH + * GPIO interface for Intel Poulsbo SCH * * Copyright (c) 2010 CompuLab Ltd * Author: Denis Turischev diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/gpio-stmpe.c similarity index 100% rename from drivers/gpio/stmpe-gpio.c rename to drivers/gpio/gpio-stmpe.c diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/gpio-sx150x.c similarity index 100% rename from drivers/gpio/sx150x.c rename to drivers/gpio/gpio-sx150x.c diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/gpio-tc3589x.c similarity index 100% rename from drivers/gpio/tc3589x-gpio.c rename to drivers/gpio/gpio-tc3589x.c diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/gpio-timberdale.c similarity index 99% rename from drivers/gpio/timbgpio.c rename to drivers/gpio/gpio-timberdale.c index 0265872e57d1..c593bd46bfb6 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/gpio-timberdale.c @@ -1,5 +1,5 @@ /* - * timbgpio.c timberdale FPGA GPIO driver + * Timberdale FPGA GPIO driver * Copyright (c) 2009 Intel Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/gpio/tps65910-gpio.c b/drivers/gpio/gpio-tps65910.c similarity index 98% rename from drivers/gpio/tps65910-gpio.c rename to drivers/gpio/gpio-tps65910.c index 8d1ddfdd63eb..41710332cb00 100644 --- a/drivers/gpio/tps65910-gpio.c +++ b/drivers/gpio/gpio-tps65910.c @@ -1,5 +1,5 @@ /* - * tps65910-gpio.c -- TI TPS6591x + * TI TPS6591x GPIO driver * * Copyright 2010 Texas Instruments Inc. * diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/gpio-twl4030.c similarity index 99% rename from drivers/gpio/twl4030-gpio.c rename to drivers/gpio/gpio-twl4030.c index 57635ac35a73..b8b4f228757c 100644 --- a/drivers/gpio/twl4030-gpio.c +++ b/drivers/gpio/gpio-twl4030.c @@ -1,5 +1,5 @@ /* - * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips + * Access to GPIOs on TWL4030/TPS659x0 chips * * Copyright (C) 2006-2007 Texas Instruments, Inc. * Copyright (C) 2006 MontaVista Software, Inc. diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c index d92790140fe5..fd2dfeeefdf3 100644 --- a/drivers/gpio/gpio-u300.c +++ b/drivers/gpio/gpio-u300.c @@ -1,11 +1,8 @@ /* - * - * arch/arm/mach-u300/gpio.c - * + * U300 GPIO module. * * Copyright (C) 2007-2009 ST-Ericsson AB * License terms: GNU General Public License (GPL) version 2 - * U300 GPIO module. * This can driver either of the two basic GPIO cores * available in the U300 platforms: * COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0) diff --git a/drivers/gpio/ucb1400_gpio.c b/drivers/gpio/gpio-ucb1400.c similarity index 100% rename from drivers/gpio/ucb1400_gpio.c rename to drivers/gpio/gpio-ucb1400.c diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/gpio-vr41xx.c similarity index 100% rename from drivers/gpio/vr41xx_giu.c rename to drivers/gpio/gpio-vr41xx.c diff --git a/drivers/gpio/vx855_gpio.c b/drivers/gpio/gpio-vx855.c similarity index 100% rename from drivers/gpio/vx855_gpio.c rename to drivers/gpio/gpio-vx855.c diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/gpio-wm831x.c similarity index 99% rename from drivers/gpio/wm831x-gpio.c rename to drivers/gpio/gpio-wm831x.c index 309644cf4d9b..31a9ed7bba83 100644 --- a/drivers/gpio/wm831x-gpio.c +++ b/drivers/gpio/gpio-wm831x.c @@ -1,5 +1,5 @@ /* - * wm831x-gpio.c -- gpiolib support for Wolfson WM831x PMICs + * gpiolib support for Wolfson WM831x PMICs * * Copyright 2009 Wolfson Microelectronics PLC. * diff --git a/drivers/gpio/wm8350-gpiolib.c b/drivers/gpio/gpio-wm8350.c similarity index 98% rename from drivers/gpio/wm8350-gpiolib.c rename to drivers/gpio/gpio-wm8350.c index 359999290f55..a06af5154838 100644 --- a/drivers/gpio/wm8350-gpiolib.c +++ b/drivers/gpio/gpio-wm8350.c @@ -1,5 +1,5 @@ /* - * wm835x-gpiolib.c -- gpiolib support for Wolfson WM835x PMICs + * gpiolib support for Wolfson WM835x PMICs * * Copyright 2009 Wolfson Microelectronics PLC. * diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/gpio-wm8994.c similarity index 99% rename from drivers/gpio/wm8994-gpio.c rename to drivers/gpio/gpio-wm8994.c index c822baacd8fc..96198f3fab73 100644 --- a/drivers/gpio/wm8994-gpio.c +++ b/drivers/gpio/gpio-wm8994.c @@ -1,5 +1,5 @@ /* - * wm8994-gpio.c -- gpiolib support for Wolfson WM8994 + * gpiolib support for Wolfson WM8994 * * Copyright 2009 Wolfson Microelectronics PLC. * diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/gpio-xilinx.c similarity index 100% rename from drivers/gpio/xilinx_gpio.c rename to drivers/gpio/gpio-xilinx.c From e4ea933363d39b5858f55682550314b4ea1285cc Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 7 Jun 2011 16:25:37 +0800 Subject: [PATCH 12/61] gpio/mxc: convert gpio-mxc to use generic irq chip The patch converts gpio-mxc driver to use generic irq chip. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mxc.c | 88 +++++++++++++---------------------------- 2 files changed, 29 insertions(+), 60 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 89a6a34cc515..4e2d612590fe 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -96,6 +96,7 @@ config GPIO_MXC def_bool y depends on ARCH_MXC select GPIO_GENERIC + select GENERIC_IRQ_CHIP config GPIO_MXS def_bool y diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index b351952893bb..950e53a636fa 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -65,46 +65,11 @@ static LIST_HEAD(mxc_gpio_ports); /* Note: This driver assumes 32 GPIOs are handled in one register */ -static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index) -{ - writel(1 << index, port->base + GPIO_ISR); -} - -static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index, - int enable) -{ - u32 l; - - l = readl(port->base + GPIO_IMR); - l = (l & (~(1 << index))) | (!!enable << index); - writel(l, port->base + GPIO_IMR); -} - -static void gpio_ack_irq(struct irq_data *d) -{ - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - _clear_gpio_irqstatus(port, gpio & 0x1f); -} - -static void gpio_mask_irq(struct irq_data *d) -{ - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - _set_gpio_irqenable(port, gpio & 0x1f, 0); -} - -static void gpio_unmask_irq(struct irq_data *d) -{ - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - _set_gpio_irqenable(port, gpio & 0x1f, 1); -} - static int gpio_set_irq_type(struct irq_data *d, u32 type) { u32 gpio = irq_to_gpio(d->irq); - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mxc_gpio_port *port = gc->private; u32 bit, val; int edge; void __iomem *reg = port->base; @@ -142,7 +107,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) bit = gpio & 0xf; val = readl(reg) & ~(0x3 << (bit << 1)); writel(val | (edge << (bit << 1)), reg); - _clear_gpio_irqstatus(port, gpio & 0x1f); + writel(1 << (gpio & 0x1f), port->base + GPIO_ISR); return 0; } @@ -231,7 +196,8 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) { u32 gpio = irq_to_gpio(d->irq); u32 gpio_idx = gpio & 0x1F; - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mxc_gpio_port *port = gc->private; if (enable) { if (port->irq_high && (gpio_idx >= 16)) @@ -248,26 +214,33 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) return 0; } -static struct irq_chip gpio_irq_chip = { - .name = "GPIO", - .irq_ack = gpio_ack_irq, - .irq_mask = gpio_mask_irq, - .irq_unmask = gpio_unmask_irq, - .irq_set_type = gpio_set_irq_type, - .irq_set_wake = gpio_set_wake_irq, -}; +static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; -/* - * This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; + gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start, + port->base, handle_level_irq); + gc->private = port; + + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_ack, + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_set_type = gpio_set_irq_type; + ct->chip.irq_set_wake = gpio_set_wake_irq, + ct->regs.ack = GPIO_ISR; + ct->regs.mask = GPIO_IMR; + + irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, + IRQ_NOREQUEST, 0); +} static int __devinit mxc_gpio_probe(struct platform_device *pdev) { struct mxc_gpio_port *port; struct resource *iores; - int err, i; + int err; port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL); if (!port) @@ -304,13 +277,8 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) writel(0, port->base + GPIO_IMR); writel(~0, port->base + GPIO_ISR); - for (i = port->virtual_irq_start; - i < port->virtual_irq_start + 32; i++) { - irq_set_lockdep_class(i, &gpio_lock_class); - irq_set_chip_and_handler(i, &gpio_irq_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID); - irq_set_chip_data(i, port); - } + /* gpio-mxc can be a generic irq chip */ + mxc_gpio_init_gc(port); if (cpu_is_mx2()) { /* setup one handler for all GPIO interrupts */ From 06f88a8ae9085e555baf81edbf967764d87dc12f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 6 Jun 2011 22:31:29 +0800 Subject: [PATCH 13/61] gpio/mxs: convert gpio-mxs to use basic_mmio_gpio library The gpio-mxs controller complies with basic_mmio_gpio library. This patch converts the driver to use the library. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mxs.c | 80 ++++++++++------------------------------- 2 files changed, 19 insertions(+), 62 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4e2d612590fe..531bfb6c8748 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -101,6 +101,7 @@ config GPIO_MXC config GPIO_MXS def_bool y depends on ARCH_MXS + select GPIO_GENERIC config GPIO_PLAT_SAMSUNG def_bool y diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index a28761428bb0..9d2dba7199c9 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #define MXS_SET 0x4 @@ -54,7 +55,7 @@ struct mxs_gpio_port { int irq; int irq_high; int virtual_irq_start; - struct gpio_chip chip; + struct bgpio_chip bgc; }; /* Note: This driver assumes 32 GPIOs are handled in one register */ @@ -99,8 +100,6 @@ static void mxs_gpio_unmask_irq(struct irq_data *d) set_gpio_irqenable(port, gpio & 0x1f, 1); } -static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset); - static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) { u32 gpio = irq_to_gpio(d->irq); @@ -203,61 +202,15 @@ static struct irq_chip gpio_irq_chip = { .irq_set_wake = mxs_gpio_set_wake_irq, }; -static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset, - int dir) +static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) { + struct bgpio_chip *bgc = to_bgpio_chip(gc); struct mxs_gpio_port *port = - container_of(chip, struct mxs_gpio_port, chip); - void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id); - - if (dir) - writel(1 << offset, pin_addr + MXS_SET); - else - writel(1 << offset, pin_addr + MXS_CLR); -} - -static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct mxs_gpio_port *port = - container_of(chip, struct mxs_gpio_port, chip); - - return (readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1; -} - -static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct mxs_gpio_port *port = - container_of(chip, struct mxs_gpio_port, chip); - void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id); - - if (value) - writel(1 << offset, pin_addr + MXS_SET); - else - writel(1 << offset, pin_addr + MXS_CLR); -} - -static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct mxs_gpio_port *port = - container_of(chip, struct mxs_gpio_port, chip); + container_of(bgc, struct mxs_gpio_port, bgc); return port->virtual_irq_start + offset; } -static int mxs_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - mxs_set_gpio_direction(chip, offset, 0); - return 0; -} - -static int mxs_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - mxs_gpio_set(chip, offset, value); - mxs_set_gpio_direction(chip, offset, 1); - return 0; -} - static int __devinit mxs_gpio_probe(struct platform_device *pdev) { static void __iomem *base; @@ -322,21 +275,24 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); irq_set_handler_data(port->irq, port); - /* register gpio chip */ - port->chip.direction_input = mxs_gpio_direction_input; - port->chip.direction_output = mxs_gpio_direction_output; - port->chip.get = mxs_gpio_get; - port->chip.set = mxs_gpio_set; - port->chip.to_irq = mxs_gpio_to_irq; - port->chip.base = port->id * 32; - port->chip.ngpio = 32; - - err = gpiochip_add(&port->chip); + err = bgpio_init(&port->bgc, &pdev->dev, 4, + port->base + PINCTRL_DIN(port->id), + port->base + PINCTRL_DOUT(port->id), NULL, + port->base + PINCTRL_DOE(port->id), NULL, false); if (err) goto out_iounmap; + port->bgc.gc.to_irq = mxs_gpio_to_irq; + port->bgc.gc.base = port->id * 32; + + err = gpiochip_add(&port->bgc.gc); + if (err) + goto out_bgpio_remove; + return 0; +out_bgpio_remove: + bgpio_remove(&port->bgc); out_iounmap: if (iores) iounmap(port->base); From 6161715e3f1adecae9e7c160930add4040fa10e9 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 7 Jun 2011 22:00:53 +0800 Subject: [PATCH 14/61] gpio/mxs: remove irq_high related implementation The irq_high stuff was mistakenly copied from mxc gpio driver. The mxs gpio controller has only one irq line for each 32-pin gpio port. The patch remove irq_high related codes. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- drivers/gpio/gpio-mxs.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 9d2dba7199c9..ddde0f44ba70 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -53,7 +53,6 @@ struct mxs_gpio_port { void __iomem *base; int id; int irq; - int irq_high; int virtual_irq_start; struct bgpio_chip bgc; }; @@ -174,21 +173,12 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) */ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) { - u32 gpio = irq_to_gpio(d->irq); - u32 gpio_idx = gpio & 0x1f; struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); - if (enable) { - if (port->irq_high && (gpio_idx >= 16)) - enable_irq_wake(port->irq_high); - else - enable_irq_wake(port->irq); - } else { - if (port->irq_high && (gpio_idx >= 16)) - disable_irq_wake(port->irq_high); - else - disable_irq_wake(port->irq); - } + if (enable) + enable_irq_wake(port->irq); + else + disable_irq_wake(port->irq); return 0; } From 498c17cf6a935335c8652165cae5dc196340b3e9 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 7 Jun 2011 22:00:54 +0800 Subject: [PATCH 15/61] gpio/mxs: convert gpio-mxs to use generic irq chip The patch converts gpio-mxs driver to use generic irq chip. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mxs.c | 95 +++++++++++++++-------------------------- 2 files changed, 35 insertions(+), 61 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 531bfb6c8748..b84666a69afa 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -102,6 +102,7 @@ config GPIO_MXS def_bool y depends on ARCH_MXS select GPIO_GENERIC + select GENERIC_IRQ_CHIP config GPIO_PLAT_SAMSUNG def_bool y diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index ddde0f44ba70..d8cafba8c829 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -59,51 +59,12 @@ struct mxs_gpio_port { /* Note: This driver assumes 32 GPIOs are handled in one register */ -static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index) -{ - writel(1 << index, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); -} - -static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index, - int enable) -{ - if (enable) { - writel(1 << index, - port->base + PINCTRL_IRQEN(port->id) + MXS_SET); - writel(1 << index, - port->base + PINCTRL_PIN2IRQ(port->id) + MXS_SET); - } else { - writel(1 << index, - port->base + PINCTRL_IRQEN(port->id) + MXS_CLR); - } -} - -static void mxs_gpio_ack_irq(struct irq_data *d) -{ - struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - clear_gpio_irqstatus(port, gpio & 0x1f); -} - -static void mxs_gpio_mask_irq(struct irq_data *d) -{ - struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - set_gpio_irqenable(port, gpio & 0x1f, 0); -} - -static void mxs_gpio_unmask_irq(struct irq_data *d) -{ - struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - set_gpio_irqenable(port, gpio & 0x1f, 1); -} - static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) { u32 gpio = irq_to_gpio(d->irq); u32 pin_mask = 1 << (gpio & 31); - struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mxs_gpio_port *port = gc->private; void __iomem *pin_addr; int edge; @@ -138,7 +99,8 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) else writel(pin_mask, pin_addr + MXS_CLR); - clear_gpio_irqstatus(port, gpio & 0x1f); + writel(1 << (gpio & 0x1f), + port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); return 0; } @@ -173,7 +135,8 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) */ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) { - struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mxs_gpio_port *port = gc->private; if (enable) enable_irq_wake(port->irq); @@ -183,14 +146,26 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) return 0; } -static struct irq_chip gpio_irq_chip = { - .name = "mxs gpio", - .irq_ack = mxs_gpio_ack_irq, - .irq_mask = mxs_gpio_mask_irq, - .irq_unmask = mxs_gpio_unmask_irq, - .irq_set_type = mxs_gpio_set_irq_type, - .irq_set_wake = mxs_gpio_set_wake_irq, -}; +static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start, + port->base, handle_level_irq); + gc->private = port; + + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_ack, + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_set_type = mxs_gpio_set_irq_type; + ct->chip.irq_set_wake = mxs_gpio_set_wake_irq, + ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR; + ct->regs.mask = PINCTRL_IRQEN(port->id); + + irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); +} static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) { @@ -206,7 +181,7 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) static void __iomem *base; struct mxs_gpio_port *port; struct resource *iores = NULL; - int err, i; + int err; port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); if (!port) @@ -246,20 +221,18 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) goto out_iounmap; } - /* disable the interrupt and clear the status */ - writel(0, port->base + PINCTRL_PIN2IRQ(port->id)); + /* + * select the pin interrupt functionality but initially + * disable the interrupts + */ + writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id)); writel(0, port->base + PINCTRL_IRQEN(port->id)); /* clear address has to be used to clear IRQSTAT bits */ writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); - for (i = port->virtual_irq_start; - i < port->virtual_irq_start + 32; i++) { - irq_set_chip_and_handler(i, &gpio_irq_chip, - handle_level_irq); - set_irq_flags(i, IRQF_VALID); - irq_set_chip_data(i, port); - } + /* gpio-mxs can be a generic irq chip */ + mxs_gpio_init_gc(port); /* setup one handler for each entry */ irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); From 47732cb4fdee72e6ea4d2ae40d72da4d2cedf97e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 7 Jun 2011 13:52:01 -0700 Subject: [PATCH 16/61] gpio/ep93xx: fix pr_fmt output With this driver now being moved from arch/arm/mach-ep93xx/gpio.c to drivers/gpio/gpio-ep93xx.c the prefix "ep93xx" is now redundant in the pr_* output. Using KBUILD_MODNAME is sufficient. Signed-off-by: H Hartley Sweeten Signed-off-by: Grant Likely --- drivers/gpio/gpio-ep93xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index c33c9a80e149..3d427b905c0c 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -11,7 +11,7 @@ * published by the Free Software Foundation. */ -#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include From 910c8fb6b4b8c9e0be576b6a78f4cccf228a4bfd Mon Sep 17 00:00:00 2001 From: David Jander Date: Wed, 8 Jun 2011 11:34:37 -0600 Subject: [PATCH 17/61] gpio/pca953x: Fix IRQ support. It seems that in the normal case, IRQ_NOREQUEST needs to be explicitly cleared, otherwise claiming the interrupt fails. In the case of sparse interrupts, the descriptor needs to be allocated first. Signed-off-by: David Jander Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index a610864b7e13..ce5736e83620 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -474,12 +474,16 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, * this purpose. */ chip->irq_stat &= chip->reg_direction; - chip->irq_base = pdata->irq_base; mutex_init(&chip->irq_lock); + chip->irq_base = irq_alloc_descs(-1, pdata->irq_base, chip->gpio_chip.ngpio, -1); + if (chip->irq_base < 0) + goto out_failed; + for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { int irq = lvl + chip->irq_base; + irq_clear_status_flags(irq, IRQ_NOREQUEST); irq_set_chip_data(irq, chip); irq_set_chip_and_handler(irq, &pca953x_irq_chip, handle_simple_irq); From 17e8b42c17c3e9735ea03c4e6b67cedf5de170f4 Mon Sep 17 00:00:00 2001 From: David Jander Date: Wed, 8 Jun 2011 11:34:41 -0600 Subject: [PATCH 18/61] gpio/pca953x: Interrupt pin is active-low The interrupt pin of the PCA953x is active low, and on the rising edge no interrupt should be produced. Signed-off-by: David Jander Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index ce5736e83620..17e55701394b 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -497,7 +497,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ret = request_threaded_irq(client->irq, NULL, pca953x_irq_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, dev_name(&client->dev), chip); if (ret) { dev_err(&client->dev, "failed to request irq %d\n", From 6dd599f8af0166805951f4421a78ba716d78321a Mon Sep 17 00:00:00 2001 From: David Jander Date: Wed, 8 Jun 2011 11:37:45 -0600 Subject: [PATCH 19/61] gpio/pca953x: Fix warning of enabled interrupts in handler When using nested threaded irqs, use handle_nested_irq(). This function does not call the chip handler, so no handler is set. Signed-off-by: David Jander Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 17e55701394b..4b8446e98de5 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -437,7 +437,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) do { level = __ffs(pending); - generic_handle_irq(level + chip->irq_base); + handle_nested_irq(level + chip->irq_base); pending &= ~(1 << level); } while (pending); @@ -485,8 +485,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, irq_clear_status_flags(irq, IRQ_NOREQUEST); irq_set_chip_data(irq, chip); - irq_set_chip_and_handler(irq, &pca953x_irq_chip, - handle_simple_irq); + irq_set_chip(irq, &pca953x_irq_chip); + irq_set_nested_thread(irq, true); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else From 1e4c88420e0da3c855c17770a807cabd5b16dd7a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 8 Jun 2011 14:35:33 -0700 Subject: [PATCH 20/61] gpio/ep93xx: convert to platform_driver and use basic_mmio_gpio library This converts the gpio-ep93xx driver into a platform_driver and uses the basic_mmio_gpio library. Signed-off-by: H Hartley Sweeten Signed-off-by: Grant Likely --- arch/arm/mach-ep93xx/core.c | 27 ++-- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-ep93xx.c | 242 ++++++++++++++++++------------------ 3 files changed, 141 insertions(+), 129 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 82079545adc4..a6b3fb208775 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -174,14 +174,10 @@ struct sys_timer ep93xx_timer = { /************************************************************************* * EP93xx IRQ handling *************************************************************************/ -extern void ep93xx_gpio_init_irq(void); - void __init ep93xx_init_irq(void) { vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); - - ep93xx_gpio_init_irq(); } @@ -240,6 +236,24 @@ unsigned int ep93xx_chip_revision(void) return v; } +/************************************************************************* + * EP93xx GPIO + *************************************************************************/ +static struct resource ep93xx_gpio_resource[] = { + { + .start = EP93XX_GPIO_PHYS_BASE, + .end = EP93XX_GPIO_PHYS_BASE + 0xcc - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ep93xx_gpio_device = { + .name = "gpio-ep93xx", + .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_gpio_resource), + .resource = ep93xx_gpio_resource, +}; + /************************************************************************* * EP93xx peripheral handling *************************************************************************/ @@ -866,14 +880,13 @@ void __init ep93xx_register_ac97(void) platform_device_register(&ep93xx_pcm_device); } -extern void ep93xx_gpio_init(void); - void __init ep93xx_init_devices(void) { /* Disallow access to MaverickCrunch initially */ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); - ep93xx_gpio_init(); + /* Get the GPIO working early, other devices need it */ + platform_device_register(&ep93xx_gpio_device); amba_device_register(&uart1_device, &iomem_resource); amba_device_register(&uart2_device, &iomem_resource); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b84666a69afa..9f06e63fbc8e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -87,6 +87,7 @@ config GPIO_IT8761E config GPIO_EP93XX def_bool y depends on ARCH_EP93XX + select GPIO_GENERIC config GPIO_EXYNOS4 def_bool y diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 3d427b905c0c..dc3870d4a4e1 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -2,6 +2,7 @@ * Generic EP93xx GPIO handling * * Copyright (c) 2008 Ryan Mallon + * Copyright (c) 2011 H Hartley Sweeten * * Based on code originally from: * linux/arch/arm/mach-ep93xx/core.c @@ -14,14 +15,20 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include -#include +#include #include #include #include +#include +#include #include +struct ep93xx_gpio { + void __iomem *mmio_base; + struct bgpio_chip bgc[8]; +}; + /************************************************************************* * Interrupt handling for EP93xx on-chip GPIOs *************************************************************************/ @@ -223,7 +230,7 @@ static struct irq_chip ep93xx_gpio_irq_chip = { .irq_set_type = ep93xx_gpio_irq_type, }; -void __init ep93xx_gpio_init_irq(void) +static void ep93xx_gpio_init_irq(void) { int gpio_irq; @@ -258,87 +265,33 @@ void __init ep93xx_gpio_init_irq(void) /************************************************************************* * gpiolib interface for EP93xx on-chip GPIOs *************************************************************************/ -struct ep93xx_gpio_chip { - struct gpio_chip chip; - - void __iomem *data_reg; - void __iomem *data_dir_reg; +struct ep93xx_gpio_bank { + const char *label; + int data; + int dir; + int base; + bool has_debounce; }; -#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip) - -static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - unsigned long flags; - u8 v; - - local_irq_save(flags); - v = __raw_readb(ep93xx_chip->data_dir_reg); - v &= ~(1 << offset); - __raw_writeb(v, ep93xx_chip->data_dir_reg); - local_irq_restore(flags); - - return 0; -} - -static int ep93xx_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int val) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - unsigned long flags; - int line; - u8 v; - - local_irq_save(flags); - - /* Set the value */ - v = __raw_readb(ep93xx_chip->data_reg); - if (val) - v |= (1 << offset); - else - v &= ~(1 << offset); - __raw_writeb(v, ep93xx_chip->data_reg); - - /* Drive as an output */ - line = chip->base + offset; - if (line <= EP93XX_GPIO_LINE_MAX_IRQ) { - /* Ports A/B/F */ - ep93xx_gpio_int_mask(line); - ep93xx_gpio_update_int_params(line >> 3); +#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _debounce) \ + { \ + .label = _label, \ + .data = _data, \ + .dir = _dir, \ + .base = _base, \ + .has_debounce = _debounce, \ } - v = __raw_readb(ep93xx_chip->data_dir_reg); - v |= (1 << offset); - __raw_writeb(v, ep93xx_chip->data_dir_reg); - - local_irq_restore(flags); - - return 0; -} - -static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - - return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset)); -} - -static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - unsigned long flags; - u8 v; - - local_irq_save(flags); - v = __raw_readb(ep93xx_chip->data_reg); - if (val) - v |= (1 << offset); - else - v &= ~(1 << offset); - __raw_writeb(v, ep93xx_chip->data_reg); - local_irq_restore(flags); -} +static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = { + EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true), + EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true), + EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false), + EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false), + EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false), + EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true), + EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false), + EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false), +}; static int ep93xx_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, unsigned debounce) @@ -354,55 +307,100 @@ static int ep93xx_gpio_set_debounce(struct gpio_chip *chip, return 0; } -#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \ - { \ - .chip = { \ - .label = name, \ - .direction_input = ep93xx_gpio_direction_input, \ - .direction_output = ep93xx_gpio_direction_output, \ - .get = ep93xx_gpio_get, \ - .set = ep93xx_gpio_set, \ - .base = base_gpio, \ - .ngpio = 8, \ - }, \ - .data_reg = EP93XX_GPIO_REG(dr), \ - .data_dir_reg = EP93XX_GPIO_REG(ddr), \ +static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev, + void __iomem *mmio_base, struct ep93xx_gpio_bank *bank) +{ + void __iomem *data = mmio_base + bank->data; + void __iomem *dir = mmio_base + bank->dir; + int err; + + err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false); + if (err) + return err; + + bgc->gc.label = bank->label; + bgc->gc.base = bank->base; + + if (bank->has_debounce) + bgc->gc.set_debounce = ep93xx_gpio_set_debounce; + + return gpiochip_add(&bgc->gc); +} + +static int __devinit ep93xx_gpio_probe(struct platform_device *pdev) +{ + struct ep93xx_gpio *ep93xx_gpio; + struct resource *res; + void __iomem *mmio; + int i; + int ret; + + ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL); + if (!ep93xx_gpio) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENXIO; + goto exit_free; } -static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = { - EP93XX_GPIO_BANK("A", 0x00, 0x10, 0), - EP93XX_GPIO_BANK("B", 0x04, 0x14, 8), - EP93XX_GPIO_BANK("C", 0x08, 0x18, 40), - EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24), - EP93XX_GPIO_BANK("E", 0x20, 0x24, 32), - EP93XX_GPIO_BANK("F", 0x30, 0x34, 16), - EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48), - EP93XX_GPIO_BANK("H", 0x40, 0x44, 56), -}; + if (!request_mem_region(res->start, resource_size(res), pdev->name)) { + ret = -EBUSY; + goto exit_free; + } -void __init ep93xx_gpio_init(void) -{ - int i; + mmio = ioremap(res->start, resource_size(res)); + if (!mmio) { + ret = -ENXIO; + goto exit_release; + } + ep93xx_gpio->mmio_base = mmio; - /* Set Ports C, D, E, G, and H for GPIO use */ + /* Default all ports to GPIO */ ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | - EP93XX_SYSCON_DEVCFG_GONK | - EP93XX_SYSCON_DEVCFG_EONIDE | - EP93XX_SYSCON_DEVCFG_GONIDE | - EP93XX_SYSCON_DEVCFG_HONIDE); + EP93XX_SYSCON_DEVCFG_GONK | + EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) { - struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip; + struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i]; + struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i]; - /* - * Ports A, B, and F support input debouncing when - * used as interrupts. - */ - if (!strcmp(chip->label, "A") || - !strcmp(chip->label, "B") || - !strcmp(chip->label, "F")) - chip->set_debounce = ep93xx_gpio_set_debounce; - - gpiochip_add(chip); + if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank)) + dev_warn(&pdev->dev, "Unable to add gpio bank %s\n", + bank->label); } + + ep93xx_gpio_init_irq(); + + return 0; + +exit_release: + release_mem_region(res->start, resource_size(res)); +exit_free: + kfree(ep93xx_gpio); + dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret); + return ret; } + +static struct platform_driver ep93xx_gpio_driver = { + .driver = { + .name = "gpio-ep93xx", + .owner = THIS_MODULE, + }, + .probe = ep93xx_gpio_probe, +}; + +static int __init ep93xx_gpio_init(void) +{ + pr_info("%s\n", __func__); + return platform_driver_register(&ep93xx_gpio_driver); +} +postcore_initcall(ep93xx_gpio_init); + +MODULE_AUTHOR("Ryan Mallon " + "H Hartley Sweeten "); +MODULE_DESCRIPTION("EP93XX GPIO driver"); +MODULE_LICENSE("GPL"); From ab1c847af5271495c9c00c931284d7cd46840bd0 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 9 Jun 2011 12:40:21 -0600 Subject: [PATCH 21/61] gpio/ep93xx: Remove superfluous debug pr_info statement Reported-by: H Hartley Sweeten Signed-off-by: Grant Likely --- drivers/gpio/gpio-ep93xx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index dc3870d4a4e1..3bfd3417ab11 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -395,7 +395,6 @@ static struct platform_driver ep93xx_gpio_driver = { static int __init ep93xx_gpio_init(void) { - pr_info("%s\n", __func__); return platform_driver_register(&ep93xx_gpio_driver); } postcore_initcall(ep93xx_gpio_init); From b57e3c2692b04ac0b2f14bb94c63291fad1d7309 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 10 Jun 2011 09:08:17 -0700 Subject: [PATCH 22/61] gpio/ep93xx: Add missing EP93XX_GPIO_PHYS_BASE define The patch to convert of the ep93xx gpio driver to a platform_driver is missing the define for the memory resource that is passed to the driver. This is needed to prevent a build error. Signed-off-by: H Hartley Sweeten Signed-off-by: Grant Likely --- arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 9ac4d1055097..c4a7b84ef06d 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -98,6 +98,7 @@ #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) +#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000) #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) #define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) From 27810c5e7f8f2ddf036c16b5e40fd22abdc041f9 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 10 Jun 2011 18:16:15 -0700 Subject: [PATCH 23/61] gpio/vr41xx: Convert use of struct resource to resource_size(ptr) Remove miscellaneous use of direct calculation by using resource_size(). Signed-off-by: Joe Perches Signed-off-by: Grant Likely --- drivers/gpio/gpio-vr41xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c index a365be040b36..98723cb9ac68 100644 --- a/drivers/gpio/gpio-vr41xx.c +++ b/drivers/gpio/gpio-vr41xx.c @@ -518,7 +518,7 @@ static int __devinit giu_probe(struct platform_device *pdev) if (!res) return -EBUSY; - giu_base = ioremap(res->start, res->end - res->start + 1); + giu_base = ioremap(res->start, resource_size(res)); if (!giu_base) return -ENOMEM; From 5523f86beab2b87d42cd58aca9bd5cee5466c6e3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 12 Jun 2011 01:33:29 +0800 Subject: [PATCH 24/61] gpio/mxc: fix a bug with gpio_get_value calling When calling gpio_get_value, the gpio number other than bit offset should be passed as the argument. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- drivers/gpio/gpio-mxc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 950e53a636fa..2f6a81b8f12e 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -83,7 +83,7 @@ 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 & 31); + val = gpio_get_value(gpio); if (val) { edge = GPIO_INT_LOW_LEV; pr_debug("mxc: set GPIO %d to low trigger\n", gpio); From 12610be33df5563d3f8cb141f231d4dc5b2a317f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Jun 2011 10:47:15 +0200 Subject: [PATCH 25/61] gpio/74x164: fix clash with gpiolib namespace The 74x164 GPIO driver has a static inline helper called gpio_to_chip which clashes with the gpiolib namespace if we try to expose the function with the same name from gpiolib, and it's still confusing even if we don't do that. So rename it to gpio_to_74x164_chip(). Reported-by: H Hartley Sweeten Signed-off-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/gpio/gpio-74x164.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 7fb60b6bf523..ff525c0958dd 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -23,7 +23,7 @@ struct gen_74x164_chip { u8 port_config; }; -static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc) +static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) { return container_of(gc, struct gen_74x164_chip, gpio_chip); } @@ -36,7 +36,7 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip) static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) { - struct gen_74x164_chip *chip = gpio_to_chip(gc); + struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); int ret; mutex_lock(&chip->lock); @@ -49,7 +49,7 @@ static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) static void gen_74x164_set_value(struct gpio_chip *gc, unsigned offset, int val) { - struct gen_74x164_chip *chip = gpio_to_chip(gc); + struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); mutex_lock(&chip->lock); if (val) From ea5a9607cb2a3c7e5e9fcb1b3d75b8f88eca5766 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 15 Jun 2011 14:52:43 -0600 Subject: [PATCH 26/61] gpio/tegra: Move Tegra gpio driver to drivers/gpio As part of the gpio driver consolidation, this patch moves the Tegra driver into drivers/gpio Signed-off-by: Grant Likely Acked-by: Olof Johansson Acked-by: Colin Cross --- arch/arm/mach-tegra/Makefile | 1 - drivers/gpio/Makefile | 1 + arch/arm/mach-tegra/gpio.c => drivers/gpio/gpio-tegra.c | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename arch/arm/mach-tegra/gpio.c => drivers/gpio/gpio-tegra.c (100%) diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 823c703e573c..ed58ef9019b5 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -4,7 +4,6 @@ obj-y += io.o obj-y += irq.o obj-y += clock.o obj-y += timer.o -obj-y += gpio.o obj-y += pinmux.o obj-y += powergate.o obj-y += fuse.o diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index b605f8ec6fbe..85d85a3f0a44 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_PCH) += pch_gpio.o obj-$(CONFIG_GPIO_PL061) += pl061.o obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o +obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o diff --git a/arch/arm/mach-tegra/gpio.c b/drivers/gpio/gpio-tegra.c similarity index 100% rename from arch/arm/mach-tegra/gpio.c rename to drivers/gpio/gpio-tegra.c From df2212270ce94f12e9caed6ca04c7077672d588e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 15 Jun 2011 14:54:14 -0600 Subject: [PATCH 27/61] gpio/tegra: add devicetree support Add support for decoding gpios from the device tree Signed-off-by: Grant Likely Acked-by: Olof Johansson --- Documentation/devicetree/bindings/gpio/gpio_nvidia.txt | 7 +++++++ drivers/gpio/gpio-tegra.c | 10 ++++++++++ 2 files changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio_nvidia.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt new file mode 100644 index 000000000000..afb3ff3134c8 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt @@ -0,0 +1,7 @@ +NVIDIA Tegra 2 GPIO controller + +Required properties: +- compatible : "nvidia,tegra250-gpio" +- #gpio-cells : Should be two. The first cell is the pin number and the + second cell is used to specify optional parameters (currently unused). +- gpio-controller : Marks the device node as a GPIO controller. diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 919d63837736..13afb881ffc3 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -23,6 +23,7 @@ #include #include +#include #include @@ -340,6 +341,15 @@ static int __init tegra_gpio_init(void) } } +#ifdef CONFIG_OF_GPIO + /* + * This isn't ideal, but it gets things hooked up until this + * driver is converted into a platform_device + */ + tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL, + "nvidia,tegra250-gpio"); +#endif /* CONFIG_OF_GPIO */ + gpiochip_add(&tegra_gpio_chip); for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { From df3c851716424fda0c7b14c4cae71cea467a9944 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 21 Apr 2011 09:08:15 -0700 Subject: [PATCH 28/61] gpio/omap: _clear_gpio_irqbank: fix flushing of posted write In commit 78a1a6d3411de1a8b0dc1cb92754b5f12f251912 (ARM: OMAP4: Update the GPIO support) braces were mistakenly added to included the register read-back inside the cpu_is_* checking. Remove the braces, ensuring that a register read-back is done, even when the IRQSTATUS2 register is not written. Note that the register read-back might be IRQSTATUS1 or IRQSTATUS2 depending on the CPU, but a read-back of any register in that region will cause a flush of the posted writes. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 01f74a8459d9..2ca814294c5e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -700,12 +700,11 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) else if (cpu_is_omap44xx()) reg = bank->base + OMAP4_GPIO_IRQSTATUS1; - if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) { + if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) __raw_writel(gpio_mask, reg); /* Flush posted write for the irq status to avoid spurious interrupts */ __raw_readl(reg); - } } static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) From bdba15db4d81940776ab96ea9f558b7388b0f7fe Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 21 Apr 2011 08:44:45 -0700 Subject: [PATCH 29/61] gpio/omap: remove MPUIO handling from _clear_gpio_irqbank() Remove the OMAP1 #ifdef and MPUIO special case for _clear_gpio_irqbank() The MPUIOs do not need a register access to ack/clear the IRQ status, since reading the IRQ status clears it. In addition, the MPUIO irq_chip has an empty ack method, so _clear_gpio_irqbank() is never used for MPUIOs. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 2ca814294c5e..7135810a77bc 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -657,12 +657,6 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) void __iomem *reg = bank->base; switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - /* MPUIO irqstatus is reset by reading the status register, - * so do nothing here */ - return; -#endif #ifdef CONFIG_ARCH_OMAP15XX case METHOD_GPIO_1510: reg += OMAP1510_GPIO_INT_STATUS; From d5f46247e77a63bc3bb4b3f979281e5c700c218e Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 21 Apr 2011 09:23:00 -0700 Subject: [PATCH 30/61] gpio/omap: move bank width into struct gpio_bank Rather than having a file-global bank_width variable, move it into struct gpio_bank so it can be bank-specific. Note the bank width is already passed per-bank via platform_data, so current code would be incorrect if any banks had different width. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 7135810a77bc..3f436c033611 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -54,6 +54,7 @@ struct gpio_bank { struct device *dev; bool dbck_flag; int stride; + u32 width; }; #ifdef CONFIG_ARCH_OMAP3 @@ -79,8 +80,6 @@ static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; */ static struct gpio_bank *gpio_bank; -static int bank_width; - /* TODO: Analyze removing gpio_bank_count usage from driver code */ int gpio_bank_count; @@ -870,7 +869,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) if (bank->non_wakeup_gpios & (1 << gpio)) { printk(KERN_ERR "Unable to modify wakeup on " "non-wakeup GPIO%d\n", - (bank - gpio_bank) * 32 + gpio); + (bank - gpio_bank) * bank->width + gpio); return -EINVAL; } spin_lock_irqsave(&bank->lock, flags); @@ -1545,14 +1544,14 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) } else { bank->chip.label = "gpio"; bank->chip.base = gpio; - gpio += bank_width; + gpio += bank->width; } - bank->chip.ngpio = bank_width; + bank->chip.ngpio = bank->width; gpiochip_add(&bank->chip); for (j = bank->virtual_irq_start; - j < bank->virtual_irq_start + bank_width; j++) { + j < bank->virtual_irq_start + bank->width; j++) { irq_set_lockdep_class(j, &gpio_lock_class); irq_set_chip_data(j, bank); if (bank_is_mpuio(bank)) @@ -1602,7 +1601,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) bank->dev = &pdev->dev; bank->dbck_flag = pdata->dbck_flag; bank->stride = pdata->bank_stride; - bank_width = pdata->bank_width; + bank->width = pdata->bank_width; spin_lock_init(&bank->lock); From c390aad0330f330ce9818ef5269169bbae335da9 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 21 Apr 2011 09:33:36 -0700 Subject: [PATCH 31/61] gpio/omap: _get_gpio_irqbank_mask: replace hard-coded mask with bank->width Replace hard-coded mask values with bank->width which is already coming from platform_data. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 3f436c033611..0766aa1c3f31 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -710,46 +710,40 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) void __iomem *reg = bank->base; int inv = 0; u32 l; - u32 mask; + u32 mask = (1 << bank->width) - 1; switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride; - mask = 0xffff; inv = 1; break; #endif #ifdef CONFIG_ARCH_OMAP15XX case METHOD_GPIO_1510: reg += OMAP1510_GPIO_INT_MASK; - mask = 0xffff; inv = 1; break; #endif #ifdef CONFIG_ARCH_OMAP16XX case METHOD_GPIO_1610: reg += OMAP1610_GPIO_IRQENABLE1; - mask = 0xffff; break; #endif #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) case METHOD_GPIO_7XX: reg += OMAP7XX_GPIO_INT_MASK; - mask = 0xffffffff; inv = 1; break; #endif #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_IRQENABLE1; - mask = 0xffffffff; break; #endif #if defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_44XX: reg += OMAP4_GPIO_IRQSTATUSSET0; - mask = 0xffffffff; break; #endif default: From 129fd2230733ff0457e76d6aabde136cf8666bc0 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 22 Apr 2011 07:59:07 -0700 Subject: [PATCH 32/61] gpio/omap: replace get_gpio_index() by using bank width The get_gpio_index() function, littered with cpu_is_* checks can be easily replaced by using bitops based on the GPIO bank width. Do so. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 42 ++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0766aa1c3f31..72811a3b9158 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -83,6 +83,9 @@ static struct gpio_bank *gpio_bank; /* TODO: Analyze removing gpio_bank_count usage from driver code */ int gpio_bank_count; +#define GPIO_INDEX(bank, gpio) (gpio % bank->width) +#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) + static inline struct gpio_bank *get_gpio_bank(int gpio) { if (cpu_is_omap15xx()) { @@ -108,17 +111,6 @@ static inline struct gpio_bank *get_gpio_bank(int gpio) return NULL; } -static inline int get_gpio_index(int gpio) -{ - if (cpu_is_omap7xx()) - return gpio & 0x1f; - if (cpu_is_omap24xx()) - return gpio & 0x1f; - if (cpu_is_omap34xx() || cpu_is_omap44xx()) - return gpio & 0x1f; - return gpio & 0x0f; -} - static inline int gpio_valid(int gpio) { if (gpio < 0) @@ -313,7 +305,7 @@ static int _get_gpio_datain(struct gpio_bank *bank, int gpio) return -EINVAL; } return (__raw_readl(reg) - & (1 << get_gpio_index(gpio))) != 0; + & (GPIO_BIT(bank, gpio))) != 0; } static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) @@ -359,7 +351,7 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) return -EINVAL; } - return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0; + return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; } #define MOD_REG_BIT(reg, bit_mask, set) \ @@ -396,7 +388,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, else debounce = (debounce / 0x1f) - 1; - l = 1 << get_gpio_index(gpio); + l = GPIO_BIT(bank, gpio); if (bank->method == METHOD_GPIO_44XX) reg += OMAP4_GPIO_DEBOUNCINGTIME; @@ -640,7 +632,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type) bank = irq_data_get_irq_chip_data(d); spin_lock_irqsave(&bank->lock, flags); - retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type); + retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type); spin_unlock_irqrestore(&bank->lock, flags); if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) @@ -702,7 +694,7 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) { - _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); + _clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); } static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) @@ -830,7 +822,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) { - _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable); + _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio), enable); } /* @@ -883,10 +875,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) static void _reset_gpio(struct gpio_bank *bank, int gpio) { - _set_gpio_direction(bank, get_gpio_index(gpio), 1); + _set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1); _set_gpio_irqenable(bank, gpio, 0); _clear_gpio_irqstatus(bank, gpio); - _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE); + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); } /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ @@ -899,7 +891,7 @@ static int gpio_wake_enable(struct irq_data *d, unsigned int enable) if (check_gpio(gpio) < 0) return -ENODEV; bank = irq_data_get_irq_chip_data(d); - retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable); + retval = _set_gpio_wakeup(bank, GPIO_INDEX(bank, gpio), enable); return retval; } @@ -1079,7 +1071,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) gpio_irq = bank->virtual_irq_start; for (; isr != 0; isr >>= 1, gpio_irq++) { - gpio_index = get_gpio_index(irq_to_gpio(gpio_irq)); + gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq)); if (!(isr & 1)) continue; @@ -1135,7 +1127,7 @@ static void gpio_mask_irq(struct irq_data *d) spin_lock_irqsave(&bank->lock, flags); _set_gpio_irqenable(bank, gpio, 0); - _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE); + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); spin_unlock_irqrestore(&bank->lock, flags); } @@ -1143,13 +1135,13 @@ static void gpio_unmask_irq(struct irq_data *d) { unsigned int gpio = d->irq - IH_GPIO_BASE; struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int irq_mask = 1 << get_gpio_index(gpio); + unsigned int irq_mask = GPIO_BIT(bank, gpio); u32 trigger = irqd_get_trigger_type(d); unsigned long flags; spin_lock_irqsave(&bank->lock, flags); if (trigger) - _set_gpio_triggering(bank, get_gpio_index(gpio), trigger); + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); /* For level-triggered GPIOs, the clearing must be done after * the HW source is cleared, thus after the handler has run */ @@ -1352,7 +1344,7 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset) gpio = chip->base + offset; bank = get_gpio_bank(gpio); reg = bank->base; - mask = 1 << get_gpio_index(gpio); + mask = GPIO_BIT(bank, gpio); if (gpio_is_input(bank, mask)) return _get_gpio_datain(bank, gpio); From a8be8dafd00e3ccf4f85e2f30babf42be5076324 Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Fri, 22 Apr 2011 16:38:16 +0530 Subject: [PATCH 33/61] gpio/omap: remove get_gpio_bank() use chip info to get the pointer to the struct gpio_bank for a given GPIO bank and remove get_gpio_bank(). Signed-off-by: Charulatha V --- drivers/gpio/gpio-omap.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 72811a3b9158..25a7ee6bddb0 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -86,31 +86,6 @@ int gpio_bank_count; #define GPIO_INDEX(bank, gpio) (gpio % bank->width) #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) -static inline struct gpio_bank *get_gpio_bank(int gpio) -{ - if (cpu_is_omap15xx()) { - if (OMAP_GPIO_IS_MPUIO(gpio)) - return &gpio_bank[0]; - return &gpio_bank[1]; - } - if (cpu_is_omap16xx()) { - if (OMAP_GPIO_IS_MPUIO(gpio)) - return &gpio_bank[0]; - return &gpio_bank[1 + (gpio >> 4)]; - } - if (cpu_is_omap7xx()) { - if (OMAP_GPIO_IS_MPUIO(gpio)) - return &gpio_bank[0]; - return &gpio_bank[1 + (gpio >> 5)]; - } - if (cpu_is_omap24xx()) - return &gpio_bank[gpio >> 5]; - if (cpu_is_omap34xx() || cpu_is_omap44xx()) - return &gpio_bank[gpio >> 5]; - BUG(); - return NULL; -} - static inline int gpio_valid(int gpio) { if (gpio < 0) @@ -1266,7 +1241,7 @@ static struct platform_device omap_mpuio_device = { static inline void mpuio_init(void) { - struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0)); + struct gpio_bank *bank = &gpio_bank[0]; platform_set_drvdata(&omap_mpuio_device, bank); if (platform_driver_register(&omap_mpuio_driver) == 0) @@ -1342,7 +1317,7 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset) u32 mask; gpio = chip->base + offset; - bank = get_gpio_bank(gpio); + bank = container_of(chip, struct gpio_bank, chip); reg = bank->base; mask = GPIO_BIT(bank, gpio); From fa87931acb8203a1f40a3c637863ad238f70cd40 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 20 Apr 2011 16:31:23 -0700 Subject: [PATCH 34/61] gpio/omap: consolidate direction, input, output, remove #ifdefs Add register offset fields to GPIO platform_data for registers. This patch adds registers that control direction, input and output data. Using these register offsets in the common driver allows removal of #ifdefs and greatly improves readability. Also create dedicated data out functions: one for banks with dedicated set/clear registers, and another for banks with a single mask register. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio15xx.c | 14 ++ arch/arm/mach-omap1/gpio16xx.c | 19 ++ arch/arm/mach-omap1/gpio7xx.c | 19 ++ arch/arm/mach-omap2/gpio.c | 16 ++ arch/arm/plat-omap/include/plat/gpio.h | 10 + drivers/gpio/gpio-omap.c | 243 +++++-------------------- 6 files changed, 121 insertions(+), 200 deletions(-) diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 04c4b04cf54e..a622d567b53e 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -34,11 +34,18 @@ static struct __initdata resource omap15xx_mpu_gpio_resources[] = { }, }; +static struct omap_gpio_reg_offs omap15xx_mpuio_regs = { + .direction = OMAP_MPUIO_IO_CNTL, + .datain = OMAP_MPUIO_INPUT_LATCH, + .dataout = OMAP_MPUIO_OUTPUT, +}; + static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = { .virtual_irq_start = IH_MPUIO_BASE, .bank_type = METHOD_MPUIO, .bank_width = 16, .bank_stride = 1, + .regs = &omap15xx_mpuio_regs, }; static struct __initdata platform_device omap15xx_mpu_gpio = { @@ -64,10 +71,17 @@ static struct __initdata resource omap15xx_gpio_resources[] = { }, }; +static struct omap_gpio_reg_offs omap15xx_gpio_regs = { + .direction = OMAP1510_GPIO_DIR_CONTROL, + .datain = OMAP1510_GPIO_DATA_INPUT, + .dataout = OMAP1510_GPIO_DATA_OUTPUT, +}; + static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { .virtual_irq_start = IH_GPIO_BASE, .bank_type = METHOD_GPIO_1510, .bank_width = 16, + .regs = &omap15xx_gpio_regs, }; static struct __initdata platform_device omap15xx_gpio = { diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 5dd0d4c82b24..4ff6ff36ab73 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -37,11 +37,18 @@ static struct __initdata resource omap16xx_mpu_gpio_resources[] = { }, }; +static struct omap_gpio_reg_offs omap16xx_mpuio_regs = { + .direction = OMAP_MPUIO_IO_CNTL, + .datain = OMAP_MPUIO_INPUT_LATCH, + .dataout = OMAP_MPUIO_OUTPUT, +}; + static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { .virtual_irq_start = IH_MPUIO_BASE, .bank_type = METHOD_MPUIO, .bank_width = 16, .bank_stride = 1, + .regs = &omap16xx_mpuio_regs, }; static struct __initdata platform_device omap16xx_mpu_gpio = { @@ -67,10 +74,19 @@ static struct __initdata resource omap16xx_gpio1_resources[] = { }, }; +static struct omap_gpio_reg_offs omap16xx_gpio_regs = { + .direction = OMAP1610_GPIO_DIRECTION, + .set_dataout = OMAP1610_GPIO_SET_DATAOUT, + .clr_dataout = OMAP1610_GPIO_CLEAR_DATAOUT, + .datain = OMAP1610_GPIO_DATAIN, + .dataout = OMAP1610_GPIO_DATAOUT, +}; + static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { .virtual_irq_start = IH_GPIO_BASE, .bank_type = METHOD_GPIO_1610, .bank_width = 16, + .regs = &omap16xx_gpio_regs, }; static struct __initdata platform_device omap16xx_gpio1 = { @@ -100,6 +116,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = { .virtual_irq_start = IH_GPIO_BASE + 16, .bank_type = METHOD_GPIO_1610, .bank_width = 16, + .regs = &omap16xx_gpio_regs, }; static struct __initdata platform_device omap16xx_gpio2 = { @@ -129,6 +146,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = { .virtual_irq_start = IH_GPIO_BASE + 32, .bank_type = METHOD_GPIO_1610, .bank_width = 16, + .regs = &omap16xx_gpio_regs, }; static struct __initdata platform_device omap16xx_gpio3 = { @@ -158,6 +176,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = { .virtual_irq_start = IH_GPIO_BASE + 48, .bank_type = METHOD_GPIO_1610, .bank_width = 16, + .regs = &omap16xx_gpio_regs, }; static struct __initdata platform_device omap16xx_gpio4 = { diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index 1204c8b871af..efe4dccaa4f2 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -39,11 +39,18 @@ static struct __initdata resource omap7xx_mpu_gpio_resources[] = { }, }; +static struct omap_gpio_reg_offs omap7xx_mpuio_regs = { + .direction = OMAP_MPUIO_IO_CNTL / 2, + .datain = OMAP_MPUIO_INPUT_LATCH / 2, + .dataout = OMAP_MPUIO_OUTPUT / 2, +}; + static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = { .virtual_irq_start = IH_MPUIO_BASE, .bank_type = METHOD_MPUIO, .bank_width = 32, .bank_stride = 2, + .regs = &omap7xx_mpuio_regs, }; static struct __initdata platform_device omap7xx_mpu_gpio = { @@ -69,10 +76,17 @@ static struct __initdata resource omap7xx_gpio1_resources[] = { }, }; +static struct omap_gpio_reg_offs omap7xx_gpio_regs = { + .direction = OMAP7XX_GPIO_DIR_CONTROL, + .datain = OMAP7XX_GPIO_DATA_INPUT, + .dataout = OMAP7XX_GPIO_DATA_OUTPUT, +}; + static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = { .virtual_irq_start = IH_GPIO_BASE, .bank_type = METHOD_GPIO_7XX, .bank_width = 32, + .regs = &omap7xx_gpio_regs, }; static struct __initdata platform_device omap7xx_gpio1 = { @@ -102,6 +116,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = { .virtual_irq_start = IH_GPIO_BASE + 32, .bank_type = METHOD_GPIO_7XX, .bank_width = 32, + .regs = &omap7xx_gpio_regs, }; static struct __initdata platform_device omap7xx_gpio2 = { @@ -131,6 +146,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = { .virtual_irq_start = IH_GPIO_BASE + 64, .bank_type = METHOD_GPIO_7XX, .bank_width = 32, + .regs = &omap7xx_gpio_regs, }; static struct __initdata platform_device omap7xx_gpio3 = { @@ -160,6 +176,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = { .virtual_irq_start = IH_GPIO_BASE + 96, .bank_type = METHOD_GPIO_7XX, .bank_width = 32, + .regs = &omap7xx_gpio_regs, }; static struct __initdata platform_device omap7xx_gpio4 = { @@ -189,6 +206,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = { .virtual_irq_start = IH_GPIO_BASE + 128, .bank_type = METHOD_GPIO_7XX, .bank_width = 32, + .regs = &omap7xx_gpio_regs, }; static struct __initdata platform_device omap7xx_gpio5 = { @@ -218,6 +236,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = { .virtual_irq_start = IH_GPIO_BASE + 160, .bank_type = METHOD_GPIO_7XX, .bank_width = 32, + .regs = &omap7xx_gpio_regs, }; static struct __initdata platform_device omap7xx_gpio6 = { diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 9529842ae054..357e06956b0c 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -61,13 +61,29 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->dbck_flag = dev_attr->dbck_flag; pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1); + pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL); + if (!pdata) { + pr_err("gpio%d: Memory allocation failed\n", id); + return -ENOMEM; + } + switch (oh->class->rev) { case 0: case 1: pdata->bank_type = METHOD_GPIO_24XX; + pdata->regs->direction = OMAP24XX_GPIO_OE; + pdata->regs->datain = OMAP24XX_GPIO_DATAIN; + pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT; + pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT; + pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT; break; case 2: pdata->bank_type = METHOD_GPIO_44XX; + pdata->regs->direction = OMAP4_GPIO_OE; + pdata->regs->datain = OMAP4_GPIO_DATAIN; + pdata->regs->dataout = OMAP4_GPIO_DATAOUT; + pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT; + pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT; break; default: WARN(1, "Invalid gpio bank_type\n"); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index ec97e00cb581..268bccd0f7f6 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -174,12 +174,22 @@ struct omap_gpio_dev_attr { bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ }; +struct omap_gpio_reg_offs { + u16 direction; + u16 datain; + u16 dataout; + u16 set_dataout; + u16 clr_dataout; +}; + struct omap_gpio_platform_data { u16 virtual_irq_start; int bank_type; int bank_width; /* GPIO bank width */ int bank_stride; /* Only needed for omap1 MPUIO */ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ + + struct omap_gpio_reg_offs *regs; }; /* TODO: Analyze removing gpio_bank_count usage from driver code */ diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 25a7ee6bddb0..945642143e1b 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -55,6 +55,10 @@ struct gpio_bank { bool dbck_flag; int stride; u32 width; + + void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); + + struct omap_gpio_reg_offs *regs; }; #ifdef CONFIG_ARCH_OMAP3 @@ -125,41 +129,7 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) void __iomem *reg = bank->base; u32 l; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - reg += OMAP_MPUIO_IO_CNTL / bank->stride; - break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DIR_CONTROL; - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_DIRECTION; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_DIR_CONTROL; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - reg += OMAP24XX_GPIO_OE; - break; -#endif -#if defined(CONFIG_ARCH_OMAP4) - case METHOD_GPIO_44XX: - reg += OMAP4_GPIO_OE; - break; -#endif - default: - WARN_ON(1); - return; - } + reg += bank->regs->direction; l = __raw_readl(reg); if (is_input) l |= 1 << gpio; @@ -168,163 +138,52 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) __raw_writel(l, reg); } -static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) + +/* set data out value using dedicate set/clear register */ +static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable) { void __iomem *reg = bank->base; - u32 l = 0; + u32 l = GPIO_BIT(bank, gpio); - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - reg += OMAP_MPUIO_OUTPUT / bank->stride; - l = __raw_readl(reg); - if (enable) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DATA_OUTPUT; - l = __raw_readl(reg); - if (enable) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - if (enable) - reg += OMAP1610_GPIO_SET_DATAOUT; - else - reg += OMAP1610_GPIO_CLEAR_DATAOUT; - l = 1 << gpio; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_DATA_OUTPUT; - l = __raw_readl(reg); - if (enable) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - if (enable) - reg += OMAP24XX_GPIO_SETDATAOUT; - else - reg += OMAP24XX_GPIO_CLEARDATAOUT; - l = 1 << gpio; - break; -#endif -#ifdef CONFIG_ARCH_OMAP4 - case METHOD_GPIO_44XX: - if (enable) - reg += OMAP4_GPIO_SETDATAOUT; - else - reg += OMAP4_GPIO_CLEARDATAOUT; - l = 1 << gpio; - break; -#endif - default: - WARN_ON(1); - return; - } + if (enable) + reg += bank->regs->set_dataout; + else + reg += bank->regs->clr_dataout; + + __raw_writel(l, reg); +} + +/* set data out value using mask register */ +static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable) +{ + void __iomem *reg = bank->base + bank->regs->dataout; + u32 gpio_bit = GPIO_BIT(bank, gpio); + u32 l; + + l = __raw_readl(reg); + if (enable) + l |= gpio_bit; + else + l &= ~gpio_bit; __raw_writel(l, reg); } static int _get_gpio_datain(struct gpio_bank *bank, int gpio) { - void __iomem *reg; + void __iomem *reg = bank->base + bank->regs->datain; if (check_gpio(gpio) < 0) return -EINVAL; - reg = bank->base; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - reg += OMAP_MPUIO_INPUT_LATCH / bank->stride; - break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DATA_INPUT; - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_DATAIN; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_DATA_INPUT; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - reg += OMAP24XX_GPIO_DATAIN; - break; -#endif -#ifdef CONFIG_ARCH_OMAP4 - case METHOD_GPIO_44XX: - reg += OMAP4_GPIO_DATAIN; - break; -#endif - default: - return -EINVAL; - } - return (__raw_readl(reg) - & (GPIO_BIT(bank, gpio))) != 0; + + return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; } static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) { - void __iomem *reg; + void __iomem *reg = bank->base + bank->regs->dataout; if (check_gpio(gpio) < 0) return -EINVAL; - reg = bank->base; - - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - reg += OMAP_MPUIO_OUTPUT / bank->stride; - break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DATA_OUTPUT; - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_DATAOUT; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_DATA_OUTPUT; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - reg += OMAP24XX_GPIO_DATAOUT; - break; -#endif -#ifdef CONFIG_ARCH_OMAP4 - case METHOD_GPIO_44XX: - reg += OMAP4_GPIO_DATAOUT; - break; -#endif - default: - return -EINVAL; - } return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; } @@ -1281,31 +1140,8 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset) static int gpio_is_input(struct gpio_bank *bank, int mask) { - void __iomem *reg = bank->base; + void __iomem *reg = bank->base + bank->regs->direction; - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_IO_CNTL / bank->stride; - break; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DIR_CONTROL; - break; - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_DIRECTION; - break; - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_DIR_CONTROL; - break; - case METHOD_GPIO_24XX: - reg += OMAP24XX_GPIO_OE; - break; - case METHOD_GPIO_44XX: - reg += OMAP4_GPIO_OE; - break; - default: - WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method"); - return -EINVAL; - } return __raw_readl(reg) & mask; } @@ -1334,7 +1170,7 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value) bank = container_of(chip, struct gpio_bank, chip); spin_lock_irqsave(&bank->lock, flags); - _set_gpio_dataout(bank, offset, value); + bank->set_dataout(bank, offset, value); _set_gpio_direction(bank, offset, 0); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -1368,7 +1204,7 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) bank = container_of(chip, struct gpio_bank, chip); spin_lock_irqsave(&bank->lock, flags); - _set_gpio_dataout(bank, offset, value); + bank->set_dataout(bank, offset, value); spin_unlock_irqrestore(&bank->lock, flags); } @@ -1564,6 +1400,13 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; + bank->regs = pdata->regs; + + if (bank->regs->set_dataout && bank->regs->clr_dataout) + bank->set_dataout = _set_gpio_dataout_reg; + else + bank->set_dataout = _set_gpio_dataout_mask; + spin_lock_init(&bank->lock); /* Static mapping, never released */ From eef4bec7bf2fa9953f6b8f371d5914d014f45d40 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 21 Apr 2011 09:17:35 -0700 Subject: [PATCH 35/61] gpio/omap: consolidate IRQ status handling, remove #ifdefs Cleanup IRQ status handling by passing IRQ status register offsets via platform data. Cleans up clearing of GPIO IRQ status and GPIO ISR handler. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio15xx.c | 2 + arch/arm/mach-omap1/gpio16xx.c | 2 + arch/arm/mach-omap1/gpio7xx.c | 2 + arch/arm/mach-omap2/gpio.c | 4 ++ arch/arm/plat-omap/include/plat/gpio.h | 2 + drivers/gpio/gpio-omap.c | 66 ++------------------------ 6 files changed, 17 insertions(+), 61 deletions(-) diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index a622d567b53e..487a08749655 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -38,6 +38,7 @@ static struct omap_gpio_reg_offs omap15xx_mpuio_regs = { .direction = OMAP_MPUIO_IO_CNTL, .datain = OMAP_MPUIO_INPUT_LATCH, .dataout = OMAP_MPUIO_OUTPUT, + .irqstatus = OMAP_MPUIO_GPIO_INT, }; static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = { @@ -75,6 +76,7 @@ static struct omap_gpio_reg_offs omap15xx_gpio_regs = { .direction = OMAP1510_GPIO_DIR_CONTROL, .datain = OMAP1510_GPIO_DATA_INPUT, .dataout = OMAP1510_GPIO_DATA_OUTPUT, + .irqstatus = OMAP1510_GPIO_INT_STATUS, }; static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 4ff6ff36ab73..3e52b7f3d9cb 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -41,6 +41,7 @@ static struct omap_gpio_reg_offs omap16xx_mpuio_regs = { .direction = OMAP_MPUIO_IO_CNTL, .datain = OMAP_MPUIO_INPUT_LATCH, .dataout = OMAP_MPUIO_OUTPUT, + .irqstatus = OMAP_MPUIO_GPIO_INT, }; static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { @@ -80,6 +81,7 @@ static struct omap_gpio_reg_offs omap16xx_gpio_regs = { .clr_dataout = OMAP1610_GPIO_CLEAR_DATAOUT, .datain = OMAP1610_GPIO_DATAIN, .dataout = OMAP1610_GPIO_DATAOUT, + .irqstatus = OMAP1610_GPIO_IRQSTATUS1, }; static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index efe4dccaa4f2..35e8b31688d0 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -43,6 +43,7 @@ static struct omap_gpio_reg_offs omap7xx_mpuio_regs = { .direction = OMAP_MPUIO_IO_CNTL / 2, .datain = OMAP_MPUIO_INPUT_LATCH / 2, .dataout = OMAP_MPUIO_OUTPUT / 2, + .irqstatus = OMAP_MPUIO_GPIO_INT / 2, }; static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = { @@ -80,6 +81,7 @@ static struct omap_gpio_reg_offs omap7xx_gpio_regs = { .direction = OMAP7XX_GPIO_DIR_CONTROL, .datain = OMAP7XX_GPIO_DATA_INPUT, .dataout = OMAP7XX_GPIO_DATA_OUTPUT, + .irqstatus = OMAP7XX_GPIO_INT_STATUS, }; static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = { diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 357e06956b0c..7c5e67d0b635 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -76,6 +76,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT; pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT; pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT; + pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1; + pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2; break; case 2: pdata->bank_type = METHOD_GPIO_44XX; @@ -84,6 +86,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->dataout = OMAP4_GPIO_DATAOUT; pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT; pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT; + pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0; + pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1; break; default: WARN(1, "Invalid gpio bank_type\n"); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 268bccd0f7f6..aedd732ef464 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -180,6 +180,8 @@ struct omap_gpio_reg_offs { u16 dataout; u16 set_dataout; u16 clr_dataout; + u16 irqstatus; + u16 irqstatus2; }; struct omap_gpio_platform_data { diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 945642143e1b..bdf0132b70ec 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -481,46 +481,14 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) { void __iomem *reg = bank->base; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_STATUS; - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_IRQSTATUS1; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_INT_STATUS; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - reg += OMAP24XX_GPIO_IRQSTATUS1; - break; -#endif -#if defined(CONFIG_ARCH_OMAP4) - case METHOD_GPIO_44XX: - reg += OMAP4_GPIO_IRQSTATUS0; - break; -#endif - default: - WARN_ON(1); - return; - } + reg += bank->regs->irqstatus; __raw_writel(gpio_mask, reg); /* Workaround for clearing DSP GPIO interrupts to allow retention */ - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2; - else if (cpu_is_omap44xx()) - reg = bank->base + OMAP4_GPIO_IRQSTATUS1; - - if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) + if (bank->regs->irqstatus2) { + reg = bank->base + bank->regs->irqstatus2; __raw_writel(gpio_mask, reg); + } /* Flush posted write for the irq status to avoid spurious interrupts */ __raw_readl(reg); @@ -841,31 +809,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); bank = irq_get_handler_data(irq); -#ifdef CONFIG_ARCH_OMAP1 - if (bank->method == METHOD_MPUIO) - isr_reg = bank->base + - OMAP_MPUIO_GPIO_INT / bank->stride; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - if (bank->method == METHOD_GPIO_1510) - isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS; -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (bank->method == METHOD_GPIO_1610) - isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - if (bank->method == METHOD_GPIO_7XX) - isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - if (bank->method == METHOD_GPIO_24XX) - isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; -#endif -#if defined(CONFIG_ARCH_OMAP4) - if (bank->method == METHOD_GPIO_44XX) - isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0; -#endif + isr_reg = bank->base + bank->regs->irqstatus; if (WARN_ON(!isr_reg)) goto exit; From 28f3b5a073b6dbafbb78cae65b22ea90547d7a87 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 21 Apr 2011 09:53:06 -0700 Subject: [PATCH 36/61] gpio/omap: conslidate enable/disable of GPIO IRQs, remove ifdefs Cleanup GPIO IRQ enable/disable handling by removing SoC-specific Also split enable/disable IRQ into separate functions for better readability and also facilitate potentially moving to generic irq_chip in the future. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio15xx.c | 4 + arch/arm/mach-omap1/gpio16xx.c | 5 + arch/arm/mach-omap1/gpio7xx.c | 4 + arch/arm/mach-omap2/gpio.c | 6 ++ arch/arm/plat-omap/include/plat/gpio.h | 5 + drivers/gpio/gpio-omap.c | 137 ++++++------------------- 6 files changed, 58 insertions(+), 103 deletions(-) diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 487a08749655..91756245e860 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -39,6 +39,8 @@ static struct omap_gpio_reg_offs omap15xx_mpuio_regs = { .datain = OMAP_MPUIO_INPUT_LATCH, .dataout = OMAP_MPUIO_OUTPUT, .irqstatus = OMAP_MPUIO_GPIO_INT, + .irqenable = OMAP_MPUIO_GPIO_MASKIT, + .irqenable_inv = true, }; static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = { @@ -77,6 +79,8 @@ static struct omap_gpio_reg_offs omap15xx_gpio_regs = { .datain = OMAP1510_GPIO_DATA_INPUT, .dataout = OMAP1510_GPIO_DATA_OUTPUT, .irqstatus = OMAP1510_GPIO_INT_STATUS, + .irqenable = OMAP1510_GPIO_INT_MASK, + .irqenable_inv = true, }; static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 3e52b7f3d9cb..a6d4a71ea4af 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -42,6 +42,8 @@ static struct omap_gpio_reg_offs omap16xx_mpuio_regs = { .datain = OMAP_MPUIO_INPUT_LATCH, .dataout = OMAP_MPUIO_OUTPUT, .irqstatus = OMAP_MPUIO_GPIO_INT, + .irqenable = OMAP_MPUIO_GPIO_MASKIT, + .irqenable_inv = true, }; static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { @@ -82,6 +84,9 @@ static struct omap_gpio_reg_offs omap16xx_gpio_regs = { .datain = OMAP1610_GPIO_DATAIN, .dataout = OMAP1610_GPIO_DATAOUT, .irqstatus = OMAP1610_GPIO_IRQSTATUS1, + .irqenable = OMAP1610_GPIO_IRQENABLE1, + .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1, + .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1, }; static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index 35e8b31688d0..12bcd9f2864a 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -44,6 +44,8 @@ static struct omap_gpio_reg_offs omap7xx_mpuio_regs = { .datain = OMAP_MPUIO_INPUT_LATCH / 2, .dataout = OMAP_MPUIO_OUTPUT / 2, .irqstatus = OMAP_MPUIO_GPIO_INT / 2, + .irqenable = OMAP_MPUIO_GPIO_MASKIT / 2, + .irqenable_inv = true, }; static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = { @@ -82,6 +84,8 @@ static struct omap_gpio_reg_offs omap7xx_gpio_regs = { .datain = OMAP7XX_GPIO_DATA_INPUT, .dataout = OMAP7XX_GPIO_DATA_OUTPUT, .irqstatus = OMAP7XX_GPIO_INT_STATUS, + .irqenable = OMAP7XX_GPIO_INT_MASK, + .irqenable_inv = true, }; static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = { diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 7c5e67d0b635..cc26677a12f8 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -78,6 +78,9 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT; pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1; pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2; + pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1; + pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1; + pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1; break; case 2: pdata->bank_type = METHOD_GPIO_44XX; @@ -88,6 +91,9 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT; pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0; pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1; + pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0; + pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0; + pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0; break; default: WARN(1, "Invalid gpio bank_type\n"); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index aedd732ef464..c7e3a56340c0 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -182,6 +182,11 @@ struct omap_gpio_reg_offs { u16 clr_dataout; u16 irqstatus; u16 irqstatus2; + u16 irqenable; + u16 set_irqenable; + u16 clr_irqenable; + + bool irqenable_inv; }; struct omap_gpio_platform_data { diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index bdf0132b70ec..6afca28a8c67 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -502,129 +502,60 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) { void __iomem *reg = bank->base; - int inv = 0; u32 l; u32 mask = (1 << bank->width) - 1; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride; - inv = 1; - break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_MASK; - inv = 1; - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_IRQENABLE1; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_INT_MASK; - inv = 1; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - reg += OMAP24XX_GPIO_IRQENABLE1; - break; -#endif -#if defined(CONFIG_ARCH_OMAP4) - case METHOD_GPIO_44XX: - reg += OMAP4_GPIO_IRQSTATUSSET0; - break; -#endif - default: - WARN_ON(1); - return 0; - } - + reg += bank->regs->irqenable; l = __raw_readl(reg); - if (inv) + if (bank->regs->irqenable_inv) l = ~l; l &= mask; return l; } -static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) +static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) { void __iomem *reg = bank->base; u32 l; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride; + if (bank->regs->set_irqenable) { + reg += bank->regs->set_irqenable; + l = gpio_mask; + } else { + reg += bank->regs->irqenable; l = __raw_readl(reg); - if (enable) - l &= ~(gpio_mask); + if (bank->regs->irqenable_inv) + l &= ~gpio_mask; else l |= gpio_mask; - break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_MASK; - l = __raw_readl(reg); - if (enable) - l &= ~(gpio_mask); - else - l |= gpio_mask; - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - if (enable) - reg += OMAP1610_GPIO_SET_IRQENABLE1; - else - reg += OMAP1610_GPIO_CLEAR_IRQENABLE1; - l = gpio_mask; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_INT_MASK; - l = __raw_readl(reg); - if (enable) - l &= ~(gpio_mask); - else - l |= gpio_mask; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - if (enable) - reg += OMAP24XX_GPIO_SETIRQENABLE1; - else - reg += OMAP24XX_GPIO_CLEARIRQENABLE1; - l = gpio_mask; - break; -#endif -#ifdef CONFIG_ARCH_OMAP4 - case METHOD_GPIO_44XX: - if (enable) - reg += OMAP4_GPIO_IRQSTATUSSET0; - else - reg += OMAP4_GPIO_IRQSTATUSCLR0; - l = gpio_mask; - break; -#endif - default: - WARN_ON(1); - return; } + + __raw_writel(l, reg); +} + +static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) +{ + void __iomem *reg = bank->base; + u32 l; + + if (bank->regs->clr_irqenable) { + reg += bank->regs->clr_irqenable; + l = gpio_mask; + } else { + reg += bank->regs->irqenable; + l = __raw_readl(reg); + if (bank->regs->irqenable_inv) + l |= gpio_mask; + else + l &= ~gpio_mask; + } + __raw_writel(l, reg); } static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) { - _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio), enable); + _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); } /* @@ -831,9 +762,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) /* clear edge sensitive interrupts before handler(s) are called so that we don't miss any interrupt occurred while executing them */ - _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0); + _disable_gpio_irqbank(bank, isr_saved & ~level_mask); _clear_gpio_irqbank(bank, isr_saved & ~level_mask); - _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1); + _enable_gpio_irqbank(bank, isr_saved & ~level_mask); /* if there is only edge sensitive GPIO pin interrupts configured, we could unmask GPIO bank interrupt immediately */ From f8b46b58348f151e45274c93ebe51467cf10e2f2 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 21 Apr 2011 13:23:34 -0700 Subject: [PATCH 37/61] gpio/omap: convert MPUIO IRQ over to generic irq_chip MPUIO banks have their own dedicated IRQ chip interface, separate from the "normal" GPIO banks. Convert the MPUIO IRQ chip over to using the new generic IRQ chip interface. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 74 ++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 6afca28a8c67..e5667baf5004 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -877,45 +877,8 @@ static struct irq_chip gpio_irq_chip = { #ifdef CONFIG_ARCH_OMAP1 -/* MPUIO uses the always-on 32k clock */ - -static void mpuio_ack_irq(struct irq_data *d) -{ - /* The ISR is reset automatically, so do nothing here. */ -} - -static void mpuio_mask_irq(struct irq_data *d) -{ - unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE); - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - - _set_gpio_irqenable(bank, gpio, 0); -} - -static void mpuio_unmask_irq(struct irq_data *d) -{ - unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE); - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - - _set_gpio_irqenable(bank, gpio, 1); -} - -static struct irq_chip mpuio_irq_chip = { - .name = "MPUIO", - .irq_ack = mpuio_ack_irq, - .irq_mask = mpuio_mask_irq, - .irq_unmask = mpuio_unmask_irq, - .irq_set_type = gpio_irq_type, -#ifdef CONFIG_ARCH_OMAP16XX - /* REVISIT: assuming only 16xx supports MPUIO wake events */ - .irq_set_wake = gpio_wake_enable, -#endif -}; - - #define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO) - #ifdef CONFIG_ARCH_OMAP16XX #include @@ -988,8 +951,6 @@ static inline void mpuio_init(void) {} #else -extern struct irq_chip mpuio_irq_chip; - #define bank_is_mpuio(bank) 0 static inline void mpuio_init(void) {} @@ -1189,6 +1150,30 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) } } +static __init void +omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start, + unsigned int num) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base, + handle_simple_irq); + ct = gc->chip_types; + + /* NOTE: No ack required, reading IRQ status clears it. */ + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + ct->chip.irq_set_type = gpio_irq_type; + /* REVISIT: assuming only 16xx supports MPUIO wake events */ + if (cpu_is_omap16xx()) + ct->chip.irq_set_wake = gpio_wake_enable, + + ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride; + irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); +} + static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) { int j; @@ -1226,12 +1211,13 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) j < bank->virtual_irq_start + bank->width; j++) { irq_set_lockdep_class(j, &gpio_lock_class); irq_set_chip_data(j, bank); - if (bank_is_mpuio(bank)) - irq_set_chip(j, &mpuio_irq_chip); - else + if (bank_is_mpuio(bank)) { + omap_mpuio_alloc_gc(bank, j, bank->width); + } else { irq_set_chip(j, &gpio_irq_chip); - irq_set_handler(j, handle_simple_irq); - set_irq_flags(j, IRQF_VALID); + irq_set_handler(j, handle_simple_irq); + set_irq_flags(j, IRQF_VALID); + } } irq_set_chained_handler(bank->irq, gpio_irq_handler); irq_set_handler_data(bank->irq, bank); From 7a6f8416e22a6d9f4708847bb2d88f0719b0f49e Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 22 Apr 2011 08:15:46 -0700 Subject: [PATCH 38/61] gpio/omap: remove useless gpio_valid() & check_gpio() checks These functions are useless. They are only called in a few places, and where they are called, the GPIO has already been converted from an IRQ or masked, so these functions will never fail. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 45 ---------------------------------------- 1 file changed, 45 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index e5667baf5004..857ec3939fdd 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -90,40 +90,6 @@ int gpio_bank_count; #define GPIO_INDEX(bank, gpio) (gpio % bank->width) #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) -static inline int gpio_valid(int gpio) -{ - if (gpio < 0) - return -1; - if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) { - if (gpio >= OMAP_MAX_GPIO_LINES + 16) - return -1; - return 0; - } - if (cpu_is_omap15xx() && gpio < 16) - return 0; - if ((cpu_is_omap16xx()) && gpio < 64) - return 0; - if (cpu_is_omap7xx() && gpio < 192) - return 0; - if (cpu_is_omap2420() && gpio < 128) - return 0; - if (cpu_is_omap2430() && gpio < 160) - return 0; - if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192) - return 0; - return -1; -} - -static int check_gpio(int gpio) -{ - if (unlikely(gpio_valid(gpio) < 0)) { - printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio); - dump_stack(); - return -1; - } - return 0; -} - static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) { void __iomem *reg = bank->base; @@ -172,9 +138,6 @@ static int _get_gpio_datain(struct gpio_bank *bank, int gpio) { void __iomem *reg = bank->base + bank->regs->datain; - if (check_gpio(gpio) < 0) - return -EINVAL; - return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; } @@ -182,9 +145,6 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) { void __iomem *reg = bank->base + bank->regs->dataout; - if (check_gpio(gpio) < 0) - return -EINVAL; - return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; } @@ -453,9 +413,6 @@ static int gpio_irq_type(struct irq_data *d, unsigned type) else gpio = d->irq - IH_GPIO_BASE; - if (check_gpio(gpio) < 0) - return -EINVAL; - if (type & ~IRQ_TYPE_SENSE_MASK) return -EINVAL; @@ -621,8 +578,6 @@ static int gpio_wake_enable(struct irq_data *d, unsigned int enable) struct gpio_bank *bank; int retval; - if (check_gpio(gpio) < 0) - return -ENODEV; bank = irq_data_get_irq_chip_data(d); retval = _set_gpio_wakeup(bank, GPIO_INDEX(bank, gpio), enable); From f64ad1a0e21a4948894c7a1b6f2f03b5e7151ddf Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 22 Apr 2011 09:45:27 -0700 Subject: [PATCH 39/61] gpio/omap: cleanup _set_gpio_wakeup(), remove ifdefs Make _set_gpio_wakeup() generic by removing ifdefs. Code for the various SoCs/bank-methods was already the same, except for the non-wakeup GPIO checking. But that flag is set on a per-SoC basis, so can be used for all SoCs. While here, use dev_err() and remove GPIO bank calculation assumption based on subtracting bank pointers. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 50 +++++++++++++--------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 857ec3939fdd..dbe0cf36e909 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -525,42 +525,24 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena */ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) { - unsigned long uninitialized_var(flags); + u32 gpio_bit = GPIO_BIT(bank, gpio); + unsigned long flags; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_MPUIO: - case METHOD_GPIO_1610: - spin_lock_irqsave(&bank->lock, flags); - if (enable) - bank->suspend_wakeup |= (1 << gpio); - else - bank->suspend_wakeup &= ~(1 << gpio); - spin_unlock_irqrestore(&bank->lock, flags); - return 0; -#endif -#ifdef CONFIG_ARCH_OMAP2PLUS - case METHOD_GPIO_24XX: - case METHOD_GPIO_44XX: - if (bank->non_wakeup_gpios & (1 << gpio)) { - printk(KERN_ERR "Unable to modify wakeup on " - "non-wakeup GPIO%d\n", - (bank - gpio_bank) * bank->width + gpio); - return -EINVAL; - } - spin_lock_irqsave(&bank->lock, flags); - if (enable) - bank->suspend_wakeup |= (1 << gpio); - else - bank->suspend_wakeup &= ~(1 << gpio); - spin_unlock_irqrestore(&bank->lock, flags); - return 0; -#endif - default: - printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n", - bank->method); + if (bank->non_wakeup_gpios & gpio_bit) { + dev_err(bank->dev, + "Unable to modify wakeup on non-wakeup GPIO%d\n", gpio); return -EINVAL; } + + spin_lock_irqsave(&bank->lock, flags); + if (enable) + bank->suspend_wakeup |= gpio_bit; + else + bank->suspend_wakeup &= ~gpio_bit; + + spin_unlock_irqrestore(&bank->lock, flags); + + return 0; } static void _reset_gpio(struct gpio_bank *bank, int gpio) @@ -579,7 +561,7 @@ static int gpio_wake_enable(struct irq_data *d, unsigned int enable) int retval; bank = irq_data_get_irq_chip_data(d); - retval = _set_gpio_wakeup(bank, GPIO_INDEX(bank, gpio), enable); + retval = _set_gpio_wakeup(bank, gpio, enable); return retval; } From 9942da0e4b037a852b230208410141768d473deb Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 22 Apr 2011 12:02:05 -0700 Subject: [PATCH 40/61] gpio/omap: debounce remove SoC specific registers, use pdata Use register offsets passed in from pdata for accessing debounce registers. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 4 ++++ arch/arm/plat-omap/include/plat/gpio.h | 2 ++ drivers/gpio/gpio-omap.c | 15 +++------------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index cc26677a12f8..316d930651f1 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -81,6 +81,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1; pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1; pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1; + pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL; + pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN; break; case 2: pdata->bank_type = METHOD_GPIO_44XX; @@ -94,6 +96,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0; pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0; pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0; + pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME; + pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE; break; default: WARN(1, "Invalid gpio bank_type\n"); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index c7e3a56340c0..7a3f067ee532 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -185,6 +185,8 @@ struct omap_gpio_reg_offs { u16 irqenable; u16 set_irqenable; u16 clr_irqenable; + u16 debounce; + u16 debounce_en; bool irqenable_inv; }; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index dbe0cf36e909..f212d236f908 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -168,7 +168,7 @@ do { \ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, unsigned debounce) { - void __iomem *reg = bank->base; + void __iomem *reg; u32 val; u32 l; @@ -184,19 +184,10 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, l = GPIO_BIT(bank, gpio); - if (bank->method == METHOD_GPIO_44XX) - reg += OMAP4_GPIO_DEBOUNCINGTIME; - else - reg += OMAP24XX_GPIO_DEBOUNCE_VAL; - + reg = bank->base + bank->regs->debounce; __raw_writel(debounce, reg); - reg = bank->base; - if (bank->method == METHOD_GPIO_44XX) - reg += OMAP4_GPIO_DEBOUNCENABLE; - else - reg += OMAP24XX_GPIO_DEBOUNCE_EN; - + reg = bank->base + bank->regs->debounce_en; val = __raw_readl(reg); if (debounce) { From e5ff4440cf5206fbb99d9a354ed9024eb3da047d Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 22 Apr 2011 14:37:16 -0700 Subject: [PATCH 41/61] gpio/omap: cleanup show revision, remove cpu_is checks, display only once Remove cpu_is_* checks from gpio_show_revision() by passing in the revision address offset from platform data. SoCs with no revision register (15xx, 7xx, and all MPUIOs) use -1 (actually, USHRT_MAX) to signify no register. While here, all GPIO banks are assumed to be the same revision, so fix show_revision() to only show the revision for the first bank it finds. This removes duplicate GPIO revision prints during boot. Thanks to Charulatha V for finding/fixing a few -1s that were missed in the original patch. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio15xx.c | 2 ++ arch/arm/mach-omap1/gpio16xx.c | 2 ++ arch/arm/mach-omap1/gpio7xx.c | 2 ++ arch/arm/mach-omap2/gpio.c | 2 ++ arch/arm/plat-omap/include/plat/gpio.h | 1 + drivers/gpio/gpio-omap.c | 14 ++++++-------- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 91756245e860..f79c6aef11af 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -35,6 +35,7 @@ static struct __initdata resource omap15xx_mpu_gpio_resources[] = { }; static struct omap_gpio_reg_offs omap15xx_mpuio_regs = { + .revision = USHRT_MAX, .direction = OMAP_MPUIO_IO_CNTL, .datain = OMAP_MPUIO_INPUT_LATCH, .dataout = OMAP_MPUIO_OUTPUT, @@ -75,6 +76,7 @@ static struct __initdata resource omap15xx_gpio_resources[] = { }; static struct omap_gpio_reg_offs omap15xx_gpio_regs = { + .revision = USHRT_MAX, .direction = OMAP1510_GPIO_DIR_CONTROL, .datain = OMAP1510_GPIO_DATA_INPUT, .dataout = OMAP1510_GPIO_DATA_OUTPUT, diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index a6d4a71ea4af..c69b3b104286 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -38,6 +38,7 @@ static struct __initdata resource omap16xx_mpu_gpio_resources[] = { }; static struct omap_gpio_reg_offs omap16xx_mpuio_regs = { + .revision = USHRT_MAX, .direction = OMAP_MPUIO_IO_CNTL, .datain = OMAP_MPUIO_INPUT_LATCH, .dataout = OMAP_MPUIO_OUTPUT, @@ -78,6 +79,7 @@ static struct __initdata resource omap16xx_gpio1_resources[] = { }; static struct omap_gpio_reg_offs omap16xx_gpio_regs = { + .revision = OMAP1610_GPIO_REVISION, .direction = OMAP1610_GPIO_DIRECTION, .set_dataout = OMAP1610_GPIO_SET_DATAOUT, .clr_dataout = OMAP1610_GPIO_CLEAR_DATAOUT, diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index 12bcd9f2864a..d7f2ad3e6ac7 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -40,6 +40,7 @@ static struct __initdata resource omap7xx_mpu_gpio_resources[] = { }; static struct omap_gpio_reg_offs omap7xx_mpuio_regs = { + .revision = USHRT_MAX, .direction = OMAP_MPUIO_IO_CNTL / 2, .datain = OMAP_MPUIO_INPUT_LATCH / 2, .dataout = OMAP_MPUIO_OUTPUT / 2, @@ -80,6 +81,7 @@ static struct __initdata resource omap7xx_gpio1_resources[] = { }; static struct omap_gpio_reg_offs omap7xx_gpio_regs = { + .revision = USHRT_MAX, .direction = OMAP7XX_GPIO_DIR_CONTROL, .datain = OMAP7XX_GPIO_DATA_INPUT, .dataout = OMAP7XX_GPIO_DATA_OUTPUT, diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 316d930651f1..9a46d7773a48 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -71,6 +71,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) case 0: case 1: pdata->bank_type = METHOD_GPIO_24XX; + pdata->regs->revision = OMAP24XX_GPIO_REVISION; pdata->regs->direction = OMAP24XX_GPIO_OE; pdata->regs->datain = OMAP24XX_GPIO_DATAIN; pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT; @@ -86,6 +87,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) break; case 2: pdata->bank_type = METHOD_GPIO_44XX; + pdata->regs->revision = OMAP4_GPIO_REVISION; pdata->regs->direction = OMAP4_GPIO_OE; pdata->regs->datain = OMAP4_GPIO_DATAIN; pdata->regs->dataout = OMAP4_GPIO_DATAOUT; diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 7a3f067ee532..91e8de3db085 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -175,6 +175,7 @@ struct omap_gpio_dev_attr { }; struct omap_gpio_reg_offs { + u16 revision; u16 direction; u16 datain; u16 dataout; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f212d236f908..501ca3d6a49e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -984,19 +984,17 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset) static void __init omap_gpio_show_rev(struct gpio_bank *bank) { + static bool called; u32 rev; - if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO)) - rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION); - else if (cpu_is_omap24xx() || cpu_is_omap34xx()) - rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION); - else if (cpu_is_omap44xx()) - rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION); - else + if (called || bank->regs->revision == USHRT_MAX) return; - printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n", + rev = __raw_readw(bank->base + bank->regs->revision); + pr_info("OMAP GPIO hardware version %d.%d\n", (rev >> 4) & 0x0f, rev & 0x0f); + + called = true; } /* This lock class tells lockdep that GPIO irqs are in a different From c609c05db10dcb020f6869186e548a0596a78896 Mon Sep 17 00:00:00 2001 From: David Jander Date: Tue, 14 Jun 2011 11:00:54 +0200 Subject: [PATCH 42/61] gpio/pca953x: Fix IRQ support. It seems that in the normal case, IRQ_NOREQUEST needs to be explicitly cleared, otherwise claiming the interrupt fails. In the case of sparse interrupts, the descriptor needs to be allocated first. Signed-off-by: David Jander Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 4b8446e98de5..5e4d3f23156a 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -517,8 +517,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, static void pca953x_irq_teardown(struct pca953x_chip *chip) { - if (chip->irq_base != -1) + if (chip->irq_base != -1) { + irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); free_irq(chip->client->irq, chip); + } } #else /* CONFIG_GPIO_PCA953X_IRQ */ static int pca953x_irq_setup(struct pca953x_chip *chip, From c6dcf592437e5919cb03af5dcfe369702e6a4a7c Mon Sep 17 00:00:00 2001 From: David Jander Date: Tue, 14 Jun 2011 11:00:55 +0200 Subject: [PATCH 43/61] gpio/pca953x: Remove dynamic platform data pointer In the case that we obtain device-tree data to fill in platform_data, the new platform data struct was dynamically allocated, but the pointer to it was not used everywhere it should. It seems easier to fix this issue by removing the dynamic allocation altogether since its data is only used during driver probing. Signed-off-by: David Jander Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 77 ++++++++++++++----------------------- 1 file changed, 28 insertions(+), 49 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 5e4d3f23156a..e6805b97d047 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -85,7 +85,6 @@ struct pca953x_chip { #endif struct i2c_client *client; - struct pca953x_platform_data *dyn_pdata; struct gpio_chip gpio_chip; const char *const *names; int chip_type; @@ -446,13 +445,13 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) } static int pca953x_irq_setup(struct pca953x_chip *chip, - const struct i2c_device_id *id) + const struct i2c_device_id *id, + int irq_base) { struct i2c_client *client = chip->client; - struct pca953x_platform_data *pdata = client->dev.platform_data; int ret, offset = 0; - if (pdata->irq_base != -1 + if (irq_base != -1 && (id->driver_data & PCA_INT)) { int lvl; @@ -476,7 +475,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, chip->irq_stat &= chip->reg_direction; mutex_init(&chip->irq_lock); - chip->irq_base = irq_alloc_descs(-1, pdata->irq_base, chip->gpio_chip.ngpio, -1); + chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); if (chip->irq_base < 0) goto out_failed; @@ -524,12 +523,12 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip) } #else /* CONFIG_GPIO_PCA953X_IRQ */ static int pca953x_irq_setup(struct pca953x_chip *chip, - const struct i2c_device_id *id) + const struct i2c_device_id *id, + int irq_base) { struct i2c_client *client = chip->client; - struct pca953x_platform_data *pdata = client->dev.platform_data; - if (pdata->irq_base != -1 && (id->driver_data & PCA_INT)) + if (irq_base != -1 && (id->driver_data & PCA_INT)) dev_warn(&client->dev, "interrupt support not compiled in\n"); return 0; @@ -547,45 +546,35 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip) /* * Translate OpenFirmware node properties into platform_data */ -static struct pca953x_platform_data * -pca953x_get_alt_pdata(struct i2c_client *client) +void +pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) { - struct pca953x_platform_data *pdata; struct device_node *node; const __be32 *val; int size; node = client->dev.of_node; if (node == NULL) - return NULL; + return; - pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL); - if (pdata == NULL) { - dev_err(&client->dev, "Unable to allocate platform_data\n"); - return NULL; - } - - pdata->gpio_base = -1; + *gpio_base = -1; val = of_get_property(node, "linux,gpio-base", &size); if (val) { if (size != sizeof(*val)) dev_warn(&client->dev, "%s: wrong linux,gpio-base\n", node->full_name); else - pdata->gpio_base = be32_to_cpup(val); + *gpio_base = be32_to_cpup(val); } val = of_get_property(node, "polarity", NULL); if (val) - pdata->invert = *val; - - return pdata; + *invert = *val; } #else -static struct pca953x_platform_data * -pca953x_get_alt_pdata(struct i2c_client *client) +void +pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) { - return NULL; } #endif @@ -647,6 +636,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; + int irq_base=-1, invert=0; int ret = 0; chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); @@ -654,26 +644,17 @@ static int __devinit pca953x_probe(struct i2c_client *client, return -ENOMEM; pdata = client->dev.platform_data; - if (pdata == NULL) { - pdata = pca953x_get_alt_pdata(client); - /* - * Unlike normal platform_data, this is allocated - * dynamically and must be freed in the driver - */ - chip->dyn_pdata = pdata; - } - - if (pdata == NULL) { - dev_dbg(&client->dev, "no platform data\n"); - ret = -EINVAL; - goto out_failed; + if (pdata) { + irq_base = pdata->irq_base; + chip->gpio_start = pdata->gpio_base; + invert = pdata->invert; + chip->names = pdata->names; + } else { + pca953x_get_alt_pdata(client, &chip->gpio_start, &invert); } chip->client = client; - chip->gpio_start = pdata->gpio_base; - - chip->names = pdata->names; chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE); mutex_init(&chip->i2c_lock); @@ -684,13 +665,13 @@ static int __devinit pca953x_probe(struct i2c_client *client, pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK); if (chip->chip_type == PCA953X_TYPE) - device_pca953x_init(chip, pdata->invert); + device_pca953x_init(chip, invert); else if (chip->chip_type == PCA957X_TYPE) - device_pca957x_init(chip, pdata->invert); + device_pca957x_init(chip, invert); else goto out_failed; - ret = pca953x_irq_setup(chip, id); + ret = pca953x_irq_setup(chip, id, irq_base); if (ret) goto out_failed; @@ -698,7 +679,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, if (ret) goto out_failed_irq; - if (pdata->setup) { + if (pdata && pdata->setup) { ret = pdata->setup(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); if (ret < 0) @@ -711,7 +692,6 @@ static int __devinit pca953x_probe(struct i2c_client *client, out_failed_irq: pca953x_irq_teardown(chip); out_failed: - kfree(chip->dyn_pdata); kfree(chip); return ret; } @@ -722,7 +702,7 @@ static int pca953x_remove(struct i2c_client *client) struct pca953x_chip *chip = i2c_get_clientdata(client); int ret = 0; - if (pdata->teardown) { + if (pdata && pdata->teardown) { ret = pdata->teardown(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); if (ret < 0) { @@ -740,7 +720,6 @@ static int pca953x_remove(struct i2c_client *client) } pca953x_irq_teardown(chip); - kfree(chip->dyn_pdata); kfree(chip); return 0; } From a57339b4b5daf23b4cec450b37906d5f8b5fa722 Mon Sep 17 00:00:00 2001 From: David Jander Date: Tue, 14 Jun 2011 11:00:56 +0200 Subject: [PATCH 44/61] gpio/pca953x: Deprecate meaningless device-tree bindings The property 'polarity' is handled by the GPIO core, and the 'gpio-base' should be assigned automatically. It is meaningless in the device-tree, since GPIO's are identified by the "chip-name"/offset pair. This way, the whole pca953x_get_alt_pdata() can hopefully soon go away. We still need to check whether we really want GPIO-interrupt functionality by simply looking if the I2C node has an interrupts property defined, since this property is not used for anything else. Signed-off-by: David Jander Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index e6805b97d047..c43b8ff626a7 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -21,7 +21,6 @@ #include #ifdef CONFIG_OF_GPIO #include -#include #endif #define PCA953X_INPUT 0 @@ -545,6 +544,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip) #ifdef CONFIG_OF_GPIO /* * Translate OpenFirmware node properties into platform_data + * WARNING: This is DEPRECATED and will be removed eventually! */ void pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) @@ -559,6 +559,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) *gpio_base = -1; val = of_get_property(node, "linux,gpio-base", &size); + WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__); if (val) { if (size != sizeof(*val)) dev_warn(&client->dev, "%s: wrong linux,gpio-base\n", @@ -568,6 +569,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) } val = of_get_property(node, "polarity", NULL); + WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__); if (val) *invert = *val; } @@ -636,7 +638,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; - int irq_base=-1, invert=0; + int irq_base=0, invert=0; int ret = 0; chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); @@ -651,6 +653,11 @@ static int __devinit pca953x_probe(struct i2c_client *client, chip->names = pdata->names; } else { pca953x_get_alt_pdata(client, &chip->gpio_start, &invert); +#ifdef CONFIG_OF_GPIO + /* If I2C node has no interrupts property, disable GPIO interrupts */ + if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL) + irq_base = -1; +#endif } chip->client = client; From 33300571b1111264fd0c5701733f7576323f3e35 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 14 Jun 2011 19:12:57 +0800 Subject: [PATCH 45/61] gpio/ml-ioh: fix off-by-one for displaying variable i in dev_err with the "for (; i != 0; i--)" sytax, i-- will be executed after the iteration. thus dev_err shows wrong i value. Switch to "while(--i >= 0)" which is better in readability. Signed-off-by: Axel Lin Signed-off-by: Grant Likely --- drivers/gpio/gpio-ml-ioh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 1bc621ac3536..a9016f56ed7e 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -233,7 +233,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, return 0; err_gpiochip_add: - for (; i != 0; i--) { + while (--i >= 0) { chip--; ret = gpiochip_remove(&chip->gpio); if (ret) From bf859f84a19f8e562af4a990a287b5e3edabc572 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 3 Jun 2011 11:07:16 -0600 Subject: [PATCH 46/61] gpio/dt: Refine GPIO device tree binding Allow for multiple named gpio properties Signed-off-by: Grant Likely --- .../devicetree/bindings/gpio/gpio.txt | 46 +++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index edaa84d288a1..4e16ba4feab0 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -4,17 +4,45 @@ Specifying GPIO information for devices 1) gpios property ----------------- -Nodes that makes use of GPIOs should define them using `gpios' property, -format of which is: <&gpio-controller1-phandle gpio1-specifier - &gpio-controller2-phandle gpio2-specifier - 0 /* holes are permitted, means no GPIO 3 */ - &gpio-controller4-phandle gpio4-specifier - ...>; +Nodes that makes use of GPIOs should specify them using one or more +properties, each containing a 'gpio-list': -Note that gpio-specifier length is controller dependent. + gpio-list ::= [gpio-list] + single-gpio ::= + gpio-phandle : phandle to gpio controller node + gpio-specifier : Array of #gpio-cells specifying specific gpio + (controller specific) + +GPIO properties should be named "[-]gpios". Exact +meaning of each gpios property must be documented in the device tree +binding for each device. + +For example, the following could be used to describe gpios pins to use +as chip select lines; with chip selects 0, 1 and 3 populated, and chip +select 2 left empty: + + gpio1: gpio1 { + gpio-controller + #gpio-cells = <2>; + }; + gpio2: gpio2 { + gpio-controller + #gpio-cells = <1>; + }; + [...] + chipsel-gpios = <&gpio1 12 0>, + <&gpio1 13 0>, + <0>, /* holes are permitted, means no GPIO 2 */ + <&gpio2 2>; + +Note that gpio-specifier length is controller dependent. In the +above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2 +only uses one. gpio-specifier may encode: bank, pin position inside the bank, whether pin is open-drain and whether pin is logically inverted. +Exact meaning of each specifier cell is controller specific, and must +be documented in the device tree binding for the device. Example of the node using GPIOs: @@ -28,8 +56,8 @@ and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller. 2) gpio-controller nodes ------------------------ -Every GPIO controller node must have #gpio-cells property defined, -this information will be used to translate gpio-specifiers. +Every GPIO controller node must both an empty "gpio-controller" +property, and have #gpio-cells contain the size of the gpio-specifier. Example of two SOC GPIO banks defined as gpio-controller nodes: From a6b0919140b49e0871584362ae0cf1d18c476058 Mon Sep 17 00:00:00 2001 From: John Bonesio Date: Mon, 27 Jun 2011 16:49:57 -0700 Subject: [PATCH 47/61] of/gpio: Add new method for getting gpios under different property names This patch adds a new routine, of_get_named_gpio_flags(), which takes the property name as a parameter rather than assuming "gpios". of_get_gpio_flags() is modified to call of_get_named_gpio_flags() with "gpios" as the property parameter. Signed-off-by: John Bonesio [grant.likely: Tidied up whitespace and tweaked kerneldoc comments.] Signed-off-by: Grant Likely --- drivers/of/gpio.c | 11 ++++++----- include/linux/of_gpio.h | 42 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 905960338fb2..3007662ac614 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c @@ -21,8 +21,9 @@ #include /** - * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API + * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API * @np: device node to get GPIO from + * @propname: property name containing gpio specifier(s) * @index: index of the GPIO * @flags: a flags pointer to fill in * @@ -30,8 +31,8 @@ * value on the error condition. If @flags is not NULL the function also fills * in flags for the GPIO. */ -int of_get_gpio_flags(struct device_node *np, int index, - enum of_gpio_flags *flags) +int of_get_named_gpio_flags(struct device_node *np, const char *propname, + int index, enum of_gpio_flags *flags) { int ret; struct device_node *gpio_np; @@ -40,7 +41,7 @@ int of_get_gpio_flags(struct device_node *np, int index, const void *gpio_spec; const __be32 *gpio_cells; - ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index, + ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index, &gpio_np, &gpio_spec); if (ret) { pr_debug("%s: can't parse gpios property\n", __func__); @@ -79,7 +80,7 @@ int of_get_gpio_flags(struct device_node *np, int index, pr_debug("%s exited with status %d\n", __func__, ret); return ret; } -EXPORT_SYMBOL(of_get_gpio_flags); +EXPORT_SYMBOL(of_get_named_gpio_flags); /** * of_gpio_count - Count GPIOs for a device diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 6598c04dab01..aec8025c786a 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -46,8 +46,9 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) return container_of(gc, struct of_mm_gpio_chip, gc); } -extern int of_get_gpio_flags(struct device_node *np, int index, - enum of_gpio_flags *flags); +extern int of_get_named_gpio_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags); + extern unsigned int of_gpio_count(struct device_node *np); extern int of_mm_gpiochip_add(struct device_node *np, @@ -60,8 +61,8 @@ extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np); #else /* CONFIG_OF_GPIO */ /* Drivers may not strictly depend on the GPIO support, so let them link. */ -static inline int of_get_gpio_flags(struct device_node *np, int index, - enum of_gpio_flags *flags) +static inline int of_get_named_gpio_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags) { return -ENOSYS; } @@ -77,7 +78,38 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { } #endif /* CONFIG_OF_GPIO */ /** - * of_get_gpio - Get a GPIO number to use with GPIO API + * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API + * @np: device node to get GPIO from + * @index: index of the GPIO + * @flags: a flags pointer to fill in + * + * Returns GPIO number to use with Linux generic GPIO API, or one of the errno + * value on the error condition. If @flags is not NULL the function also fills + * in flags for the GPIO. + */ +static inline int of_get_gpio_flags(struct device_node *np, int index, + enum of_gpio_flags *flags) +{ + return of_get_named_gpio_flags(np, "gpios", index, flags); +} + +/** + * of_get_named_gpio() - Get a GPIO number to use with GPIO API + * @np: device node to get GPIO from + * @propname: Name of property containing gpio specifier(s) + * @index: index of the GPIO + * + * Returns GPIO number to use with Linux generic GPIO API, or one of the errno + * value on the error condition. + */ +static inline int of_get_named_gpio(struct device_node *np, + const char *propname, int index) +{ + return of_get_named_gpio_flags(np, propname, index, NULL); +} + +/** + * of_get_gpio() - Get a GPIO number to use with GPIO API * @np: device node to get GPIO from * @index: index of the GPIO * From f7f678a06326ebafe9005203c0b2fa06885fd12c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 5 Jul 2011 14:15:18 -0600 Subject: [PATCH 48/61] gpio/tegra: Use engineering names in DT compatible property Engineering names are more stable than marketing names. Hence, use them for Device Tree compatible properties instead. Signed-off-by: Stephen Warren Signed-off-by: Grant Likely --- Documentation/devicetree/bindings/gpio/gpio_nvidia.txt | 2 +- drivers/gpio/gpio-tegra.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt index afb3ff3134c8..64aac39e6edc 100644 --- a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt +++ b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt @@ -1,7 +1,7 @@ NVIDIA Tegra 2 GPIO controller Required properties: -- compatible : "nvidia,tegra250-gpio" +- compatible : "nvidia,tegra20-gpio" - #gpio-cells : Should be two. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). - gpio-controller : Marks the device node as a GPIO controller. diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 13afb881ffc3..747eb40e8afe 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -347,7 +347,7 @@ static int __init tegra_gpio_init(void) * driver is converted into a platform_device */ tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL, - "nvidia,tegra250-gpio"); + "nvidia,tegra20-gpio"); #endif /* CONFIG_OF_GPIO */ gpiochip_add(&tegra_gpio_chip); From 07bfc9152365332477083768d0af9ab21bb2019d Mon Sep 17 00:00:00 2001 From: ashishj3 Date: Wed, 6 Jul 2011 16:02:13 +0530 Subject: [PATCH 49/61] GPIO: DA9052 GPIO module v3 DA9052 PMIC has 16 bit GPIO bus for peripheral control. This patch add support for the GPIO pins on the DA9052. Signed-off-by: David Dajun Chen Signed-off-by: Ashish Jangam Acked-by: Arnd Bergmann Acked-by: Mark Brown Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-da9052.c | 278 +++++++++++++++++++++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 drivers/gpio/gpio-da9052.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9f06e63fbc8e..a4ac78b6a0f8 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -68,6 +68,12 @@ config GPIO_GENERIC # put drivers in the right section, in alphabetical order +config GPIO_DA9052 + tristate "Dialog DA9052 GPIO" + depends on PMIC_DA9052 + help + Say yes here to enable the GPIO driver for the DA9052 chip. + config GPIO_MAX730X tristate diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 0fbdd75996e3..b847fb5b847c 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o +obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c new file mode 100644 index 000000000000..c23761f42199 --- /dev/null +++ b/drivers/gpio/gpio-da9052.c @@ -0,0 +1,278 @@ +/* + * GPIO Driver for Dialog DA9052 PMICs. + * + * Copyright(c) 2011 Dialog Semiconductor Ltd. + * + * Author: David Dajun Chen + * + * 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 +#include +#include + +#define DA9052_INPUT 1 +#define DA9052_OUTPUT_OPENDRAIN 2 +#define DA9052_OUTPUT_PUSHPULL 3 + +#define DA9052_SUPPLY_VDD_IO1 0 + +#define DA9052_DEBOUNCING_OFF 0 +#define DA9052_DEBOUNCING_ON 1 + +#define DA9052_OUTPUT_LOWLEVEL 0 + +#define DA9052_ACTIVE_LOW 0 +#define DA9052_ACTIVE_HIGH 1 + +#define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8 +#define DA9052_GPIO_SHIFT_COUNT(no) (no%8) +#define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0 +#define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F +#define DA9052_GPIO_NIBBLE_SHIFT 4 + +struct da9052_gpio { + struct da9052 *da9052; + struct gpio_chip gp; +}; + +static inline struct da9052_gpio *to_da9052_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct da9052_gpio, gp); +} + +static unsigned char da9052_gpio_port_odd(unsigned offset) +{ + return offset % 2; +} + +static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct da9052_gpio *gpio = to_da9052_gpio(gc); + int da9052_port_direction = 0; + int ret; + + ret = da9052_reg_read(gpio->da9052, + DA9052_GPIO_0_1_REG + (offset >> 1)); + if (ret < 0) + return ret; + + if (da9052_gpio_port_odd(offset)) { + da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN; + da9052_port_direction >>= 4; + } else { + da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN; + } + + switch (da9052_port_direction) { + case DA9052_INPUT: + if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER) + ret = da9052_reg_read(gpio->da9052, + DA9052_STATUS_C_REG); + else + ret = da9052_reg_read(gpio->da9052, + DA9052_STATUS_D_REG); + if (ret < 0) + return ret; + if (ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset))) + return 1; + else + return 0; + case DA9052_OUTPUT_PUSHPULL: + if (da9052_gpio_port_odd(offset)) + return ret & DA9052_GPIO_ODD_PORT_MODE; + else + return ret & DA9052_GPIO_EVEN_PORT_MODE; + default: + return -EINVAL; + } +} + +static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct da9052_gpio *gpio = to_da9052_gpio(gc); + unsigned char register_value = 0; + int ret; + + if (da9052_gpio_port_odd(offset)) { + if (value) { + register_value = DA9052_GPIO_ODD_PORT_MODE; + ret = da9052_reg_update(gpio->da9052, (offset >> 1) + + DA9052_GPIO_0_1_REG, + DA9052_GPIO_ODD_PORT_MODE, + register_value); + if (ret != 0) + dev_err(gpio->da9052->dev, + "Failed to updated gpio odd reg,%d", + ret); + } + } else { + if (value) { + register_value = DA9052_GPIO_EVEN_PORT_MODE; + ret = da9052_reg_update(gpio->da9052, (offset >> 1) + + DA9052_GPIO_0_1_REG, + DA9052_GPIO_EVEN_PORT_MODE, + register_value); + if (ret != 0) + dev_err(gpio->da9052->dev, + "Failed to updated gpio even reg,%d", + ret); + } + } +} + +static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct da9052_gpio *gpio = to_da9052_gpio(gc); + unsigned char register_value; + int ret; + + /* Format: function - 2 bits type - 1 bit mode - 1 bit */ + register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 | + DA9052_DEBOUNCING_ON << 3; + + if (da9052_gpio_port_odd(offset)) + ret = da9052_reg_update(gpio->da9052, (offset >> 1) + + DA9052_GPIO_0_1_REG, + DA9052_GPIO_MASK_UPPER_NIBBLE, + (register_value << + DA9052_GPIO_NIBBLE_SHIFT)); + else + ret = da9052_reg_update(gpio->da9052, (offset >> 1) + + DA9052_GPIO_0_1_REG, + DA9052_GPIO_MASK_LOWER_NIBBLE, + register_value); + + return ret; +} + +static int da9052_gpio_direction_output(struct gpio_chip *gc, + unsigned offset, int value) +{ + struct da9052_gpio *gpio = to_da9052_gpio(gc); + unsigned char register_value; + int ret; + + /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */ + register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 | + value << 3; + + if (da9052_gpio_port_odd(offset)) + ret = da9052_reg_update(gpio->da9052, (offset >> 1) + + DA9052_GPIO_0_1_REG, + DA9052_GPIO_MASK_UPPER_NIBBLE, + (register_value << + DA9052_GPIO_NIBBLE_SHIFT)); + else + ret = da9052_reg_update(gpio->da9052, (offset >> 1) + + DA9052_GPIO_0_1_REG, + DA9052_GPIO_MASK_LOWER_NIBBLE, + register_value); + + return ret; +} + +static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset) +{ + struct da9052_gpio *gpio = to_da9052_gpio(gc); + struct da9052 *da9052 = gpio->da9052; + + return da9052->irq_base + DA9052_IRQ_GPI0 + offset; +} + +static struct gpio_chip reference_gp __devinitdata = { + .label = "da9052-gpio", + .owner = THIS_MODULE, + .get = da9052_gpio_get, + .set = da9052_gpio_set, + .direction_input = da9052_gpio_direction_input, + .direction_output = da9052_gpio_direction_output, + .to_irq = da9052_gpio_to_irq, + .can_sleep = 1; + .ngpio = 16; + .base = -1; +}; + +static int __devinit da9052_gpio_probe(struct platform_device *pdev) +{ + struct da9052_gpio *gpio; + struct da9052_pdata *pdata; + int ret; + + gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); + if (gpio == NULL) + return -ENOMEM; + + gpio->da9052 = dev_get_drvdata(pdev->dev.parent); + pdata = gpio->da9052->dev->platform_data; + + gpio->da9052 = dev_get_drvdata(pdev->dev.parent); + gpio->gp = reference_gp; + if (pdata && pdata->gpio_base) + gpio->gp.base = pdata->gpio_base; + + ret = gpiochip_add(&gpio->gp); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); + goto err_mem; + } + + platform_set_drvdata(pdev, gpio); + + return 0; + +err_mem: + kfree(gpio); + return ret; +} + +static int __devexit da9052_gpio_remove(struct platform_device *pdev) +{ + struct da9052_gpio *gpio = platform_get_drvdata(pdev); + int ret; + + ret = gpiochip_remove(&gpio->gp); + if (ret == 0) + kfree(gpio); + + return ret; +} + +static struct platform_driver da9052_gpio_driver = { + .probe = da9052_gpio_probe, + .remove = __devexit_p(da9052_gpio_remove), + .driver = { + .name = "da9052-gpio", + .owner = THIS_MODULE, + }, +}; + +static int __init da9052_gpio_init(void) +{ + return platform_driver_register(&da9052_gpio_driver); +} +module_init(da9052_gpio_init); + +static void __exit da9052_gpio_exit(void) +{ + return platform_driver_unregister(&da9052_gpio_driver); +} +module_exit(da9052_gpio_exit); + +MODULE_AUTHOR("David Dajun Chen "); +MODULE_DESCRIPTION("DA9052 GPIO Device Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9052-gpio"); From 6eae1ace68ab775e9d47f1f8e40c811ac39f733f Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 6 Jul 2011 11:54:19 -0600 Subject: [PATCH 50/61] gpio: Move mpc5200 gpio driver to drivers/gpio GPIO drivers are getting consolidated into drivers/gpio. While at it, change the driver name to mpc5200-gpio* to avoid collisions. Signed-off-by: Grant Likely --- arch/powerpc/platforms/52xx/Kconfig | 8 -------- arch/powerpc/platforms/52xx/Makefile | 1 - drivers/gpio/Kconfig | 4 ++++ drivers/gpio/Makefile | 1 + .../mpc52xx_gpio.c => drivers/gpio/gpio-mpc5200.c | 12 ++++-------- 5 files changed, 9 insertions(+), 17 deletions(-) rename arch/powerpc/platforms/52xx/mpc52xx_gpio.c => drivers/gpio/gpio-mpc5200.c (98%) diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 47ea1be1481b..90f4496017e4 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -55,14 +55,6 @@ config PPC_MPC5200_BUGFIX It is safe to say 'Y' here -config PPC_MPC5200_GPIO - bool "MPC5200 GPIO support" - depends on PPC_MPC52xx - select ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO - help - Enable gpiolib support for mpc5200 based boards - config PPC_MPC5200_LPBFIFO tristate "MPC5200 LocalPlus bus FIFO driver" depends on PPC_MPC52xx diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index 2bc8cd0c5cfc..4e62486791e9 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile @@ -14,5 +14,4 @@ ifeq ($(CONFIG_PPC_LITE5200),y) obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o endif -obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o obj-$(CONFIG_PPC_MPC5200_LPBFIFO) += mpc52xx_lpbfifo.o diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a4ac78b6a0f8..47eae6ea5dd2 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -99,6 +99,10 @@ config GPIO_EXYNOS4 def_bool y depends on CPU_EXYNOS4210 +config GPIO_MPC5200 + def_bool y + depends on PPC_MPC52xx + config GPIO_MXC def_bool y depends on ARCH_MXC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index b847fb5b847c..720711251391 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o +obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/drivers/gpio/gpio-mpc5200.c similarity index 98% rename from arch/powerpc/platforms/52xx/mpc52xx_gpio.c rename to drivers/gpio/gpio-mpc5200.c index 1757d1db4b51..52d3ed208105 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c +++ b/drivers/gpio/gpio-mpc5200.c @@ -184,15 +184,13 @@ static int mpc52xx_gpiochip_remove(struct platform_device *ofdev) } static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { - { - .compatible = "fsl,mpc5200-gpio-wkup", - }, + { .compatible = "fsl,mpc5200-gpio-wkup", }, {} }; static struct platform_driver mpc52xx_wkup_gpiochip_driver = { .driver = { - .name = "gpio_wkup", + .name = "mpc5200-gpio-wkup", .owner = THIS_MODULE, .of_match_table = mpc52xx_wkup_gpiochip_match, }, @@ -341,15 +339,13 @@ static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev } static const struct of_device_id mpc52xx_simple_gpiochip_match[] = { - { - .compatible = "fsl,mpc5200-gpio", - }, + { .compatible = "fsl,mpc5200-gpio", }, {} }; static struct platform_driver mpc52xx_simple_gpiochip_driver = { .driver = { - .name = "gpio", + .name = "mpc5200-gpio", .owner = THIS_MODULE, .of_match_table = mpc52xx_simple_gpiochip_match, }, From fb1492186276ba52d99b58121b8a9a87f20cc9f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 7 Jul 2011 14:50:16 +0200 Subject: [PATCH 51/61] gpio/mxc: add missing initialization of basic_mmio_gpio shadow variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bgpio_init() function does not initialise the shadow register for the GPIO direction register. Thus, when configuring the first GPIO with gpio_set_direction() all other GPIOs of the same bank will be configured as inputs. Since the bgpio layer cannot know whether the register is readable, the initialisation should be done by the caller of bgpio_init(). Also, the 'data' shadow variable that is used inside basic_mmio_gpio to cache the current value of the GPIO_DR register is initialised from the GPIO_PSR register within bgpio_init(). Thus when setting the output value of a certain GPIO, the other GPIO outputs of the same bank will be set or cleared depending on the pin state of the GPIO inputs during bgpio_init(). Signed-off-by: Lothar Waßmann Signed-off-by: Grant Likely --- drivers/gpio/gpio-mxc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 2f6a81b8f12e..71ba316854ca 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -305,6 +305,8 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) goto out_iounmap; port->bgc.gc.base = pdev->id * 32; + port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir); + port->bgc.data = port->bgc.read_reg(port->bgc.reg_set); err = gpiochip_add(&port->bgc.gc); if (err) From e7fc6ae7446710a487510d212137a43289bbe90e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 7 Jul 2011 00:37:41 +0800 Subject: [PATCH 52/61] gpio/mxc: get rid of the uses of cpu_is_mx() The patch removes all the uses of cpu_is_mx(). Instead, it utilizes platform_device_id to distinguish the different gpio types, IMX1_GPIO on i.mx1, IMX21_GPIO on i.mx21 and i.mx27, IMX31_GPIO on all other i.mx SoCs. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- arch/arm/mach-imx/mm-imx1.c | 12 +- arch/arm/mach-imx/mm-imx21.c | 12 +- arch/arm/mach-imx/mm-imx25.c | 9 +- arch/arm/mach-imx/mm-imx27.c | 13 +- arch/arm/mach-imx/mm-imx31.c | 6 +- arch/arm/mach-imx/mm-imx35.c | 7 +- arch/arm/mach-mx5/mm-mx50.c | 13 +- arch/arm/mach-mx5/mm.c | 24 ++-- arch/arm/plat-mxc/devices/platform-gpio-mxc.c | 4 +- arch/arm/plat-mxc/include/mach/common.h | 2 +- drivers/gpio/gpio-mxc.c | 125 +++++++++++++++--- 11 files changed, 163 insertions(+), 64 deletions(-) diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c index b486595701b7..2bded591d5c2 100644 --- a/arch/arm/mach-imx/mm-imx1.c +++ b/arch/arm/mach-imx/mm-imx1.c @@ -50,8 +50,12 @@ void __init mx1_init_irq(void) void __init imx1_soc_init(void) { - mxc_register_gpio(0, MX1_GPIO1_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTA, 0); - mxc_register_gpio(1, MX1_GPIO2_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTB, 0); - mxc_register_gpio(2, MX1_GPIO3_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTC, 0); - mxc_register_gpio(3, MX1_GPIO4_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTD, 0); + mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256, + MX1_GPIO_INT_PORTA, 0); + mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256, + MX1_GPIO_INT_PORTB, 0); + mxc_register_gpio("imx1-gpio", 2, MX1_GPIO3_BASE_ADDR, SZ_256, + MX1_GPIO_INT_PORTC, 0); + mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256, + MX1_GPIO_INT_PORTD, 0); } diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c index f0fb8bcce6f9..6d7d518686a5 100644 --- a/arch/arm/mach-imx/mm-imx21.c +++ b/arch/arm/mach-imx/mm-imx21.c @@ -76,10 +76,10 @@ void __init mx21_init_irq(void) void __init imx21_soc_init(void) { - mxc_register_gpio(0, MX21_GPIO1_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); - mxc_register_gpio(1, MX21_GPIO2_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); - mxc_register_gpio(2, MX21_GPIO3_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); - mxc_register_gpio(3, MX21_GPIO4_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); - mxc_register_gpio(4, MX21_GPIO5_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); - mxc_register_gpio(5, MX21_GPIO6_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 1, MX21_GPIO2_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 2, MX21_GPIO3_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 3, MX21_GPIO4_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 4, MX21_GPIO5_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0); } diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c index 1b6d583f750a..9a1591c2508d 100644 --- a/arch/arm/mach-imx/mm-imx25.c +++ b/arch/arm/mach-imx/mm-imx25.c @@ -63,8 +63,9 @@ void __init mx25_init_irq(void) void __init imx25_soc_init(void) { - mxc_register_gpio(0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0); - mxc_register_gpio(1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0); - mxc_register_gpio(2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0); - mxc_register_gpio(3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0); + /* 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); } diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c index d3700cec8ec5..133b30003ddb 100644 --- a/arch/arm/mach-imx/mm-imx27.c +++ b/arch/arm/mach-imx/mm-imx27.c @@ -76,10 +76,11 @@ void __init mx27_init_irq(void) void __init imx27_soc_init(void) { - mxc_register_gpio(0, MX27_GPIO1_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); - mxc_register_gpio(1, MX27_GPIO2_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); - mxc_register_gpio(2, MX27_GPIO3_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); - mxc_register_gpio(3, MX27_GPIO4_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); - mxc_register_gpio(4, MX27_GPIO5_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); - mxc_register_gpio(5, MX27_GPIO6_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); + /* i.mx27 has the i.mx21 type gpio */ + mxc_register_gpio("imx21-gpio", 0, MX27_GPIO1_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 1, MX27_GPIO2_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 2, MX27_GPIO3_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 3, MX27_GPIO4_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 4, MX27_GPIO5_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0); + mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0); } diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c index cb16ac661776..6d103c01b8b9 100644 --- a/arch/arm/mach-imx/mm-imx31.c +++ b/arch/arm/mach-imx/mm-imx31.c @@ -59,7 +59,7 @@ void __init mx31_init_irq(void) void __init imx31_soc_init(void) { - mxc_register_gpio(0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0); - mxc_register_gpio(1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0); - mxc_register_gpio(2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0); + mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0); + mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0); + mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0); } diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c index 648bfca0163e..bb068bc8dab7 100644 --- a/arch/arm/mach-imx/mm-imx35.c +++ b/arch/arm/mach-imx/mm-imx35.c @@ -56,7 +56,8 @@ void __init mx35_init_irq(void) void __init imx35_soc_init(void) { - mxc_register_gpio(0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0); - mxc_register_gpio(1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0); - mxc_register_gpio(2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0); + /* 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); } diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c index 28c3f60f734f..77e374c726fa 100644 --- a/arch/arm/mach-mx5/mm-mx50.c +++ b/arch/arm/mach-mx5/mm-mx50.c @@ -62,10 +62,11 @@ void __init mx50_init_irq(void) void __init imx50_soc_init(void) { - mxc_register_gpio(0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); - mxc_register_gpio(1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); - mxc_register_gpio(2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); - mxc_register_gpio(3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); - mxc_register_gpio(4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); - mxc_register_gpio(5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH); + /* 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); } diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c index 800bb8b21081..665843d6c2b2 100644 --- a/arch/arm/mach-mx5/mm.c +++ b/arch/arm/mach-mx5/mm.c @@ -102,19 +102,21 @@ void __init mx53_init_irq(void) void __init imx51_soc_init(void) { - mxc_register_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH); - mxc_register_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH); - mxc_register_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH); - mxc_register_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH); + /* i.mx51 has the i.mx31 type gpio */ + mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH); + mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH); + mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH); + mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH); } void __init imx53_soc_init(void) { - mxc_register_gpio(0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH); - mxc_register_gpio(1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH); - mxc_register_gpio(2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH); - mxc_register_gpio(3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH); - mxc_register_gpio(4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH); - mxc_register_gpio(5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH); - mxc_register_gpio(6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH); + /* 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); } diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c index cf1b7fdfa20d..a7919a241032 100644 --- a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c +++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c @@ -8,7 +8,7 @@ */ #include -struct platform_device *__init mxc_register_gpio(int id, +struct platform_device *__init mxc_register_gpio(char *name, int id, resource_size_t iobase, resource_size_t iosize, int irq, int irq_high) { struct resource res[] = { @@ -28,5 +28,5 @@ struct platform_device *__init mxc_register_gpio(int id, }; return platform_device_register_resndata(&mxc_aips_bus, - "gpio-mxc", id, res, ARRAY_SIZE(res), NULL, 0); + name, id, res, ARRAY_SIZE(res), NULL, 0); } diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index 91fa2632aa5e..4e3d97890d69 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -64,7 +64,7 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2); extern int mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2); -extern struct platform_device *mxc_register_gpio(int id, +extern struct platform_device *mxc_register_gpio(char *name, int id, resource_size_t iobase, resource_size_t iosize, int irq, int irq_high); extern int mxc_register_device(struct platform_device *pdev, void *data); extern void mxc_set_cpu_type(unsigned int type); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 71ba316854ca..3775dccef4ad 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -27,9 +27,29 @@ #include #include #include -#include #include +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 */ +}; + +/* device type dependent stuff */ +struct mxc_gpio_hwdata { + unsigned dr_reg; + unsigned gdir_reg; + unsigned psr_reg; + unsigned icr1_reg; + unsigned icr2_reg; + unsigned imr_reg; + unsigned isr_reg; + unsigned low_level; + unsigned high_level; + unsigned rise_edge; + unsigned fall_edge; +}; + struct mxc_gpio_port { struct list_head node; void __iomem *base; @@ -40,6 +60,66 @@ struct mxc_gpio_port { u32 both_edges; }; +static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = { + .dr_reg = 0x1c, + .gdir_reg = 0x00, + .psr_reg = 0x24, + .icr1_reg = 0x28, + .icr2_reg = 0x2c, + .imr_reg = 0x30, + .isr_reg = 0x34, + .low_level = 0x03, + .high_level = 0x02, + .rise_edge = 0x00, + .fall_edge = 0x01, +}; + +static struct mxc_gpio_hwdata imx31_gpio_hwdata = { + .dr_reg = 0x00, + .gdir_reg = 0x04, + .psr_reg = 0x08, + .icr1_reg = 0x0c, + .icr2_reg = 0x10, + .imr_reg = 0x14, + .isr_reg = 0x18, + .low_level = 0x00, + .high_level = 0x01, + .rise_edge = 0x02, + .fall_edge = 0x03, +}; + +static enum mxc_gpio_hwtype mxc_gpio_hwtype; +static struct mxc_gpio_hwdata *mxc_gpio_hwdata; + +#define GPIO_DR (mxc_gpio_hwdata->dr_reg) +#define GPIO_GDIR (mxc_gpio_hwdata->gdir_reg) +#define GPIO_PSR (mxc_gpio_hwdata->psr_reg) +#define GPIO_ICR1 (mxc_gpio_hwdata->icr1_reg) +#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_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 + +static struct platform_device_id mxc_gpio_devtype[] = { + { + .name = "imx1-gpio", + .driver_data = IMX1_GPIO, + }, { + .name = "imx21-gpio", + .driver_data = IMX21_GPIO, + }, { + .name = "imx31-gpio", + .driver_data = IMX31_GPIO, + }, { + /* sentinel */ + } +}; + /* * MX2 has one interrupt *for all* gpio ports. The list is used * to save the references to all ports, so that mx2_gpio_irq_handler @@ -47,22 +127,6 @@ struct mxc_gpio_port { */ static LIST_HEAD(mxc_gpio_ports); -#define cpu_is_mx1_mx2() (cpu_is_mx1() || cpu_is_mx2()) - -#define GPIO_DR (cpu_is_mx1_mx2() ? 0x1c : 0x00) -#define GPIO_GDIR (cpu_is_mx1_mx2() ? 0x00 : 0x04) -#define GPIO_PSR (cpu_is_mx1_mx2() ? 0x24 : 0x08) -#define GPIO_ICR1 (cpu_is_mx1_mx2() ? 0x28 : 0x0C) -#define GPIO_ICR2 (cpu_is_mx1_mx2() ? 0x2C : 0x10) -#define GPIO_IMR (cpu_is_mx1_mx2() ? 0x30 : 0x14) -#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18) - -#define GPIO_INT_LOW_LEV (cpu_is_mx1_mx2() ? 0x3 : 0x0) -#define GPIO_INT_HIGH_LEV (cpu_is_mx1_mx2() ? 0x2 : 0x1) -#define GPIO_INT_RISE_EDGE (cpu_is_mx1_mx2() ? 0x0 : 0x2) -#define GPIO_INT_FALL_EDGE (cpu_is_mx1_mx2() ? 0x1 : 0x3) -#define GPIO_INT_NONE 0x4 - /* Note: This driver assumes 32 GPIOs are handled in one register */ static int gpio_set_irq_type(struct irq_data *d, u32 type) @@ -236,12 +300,36 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) IRQ_NOREQUEST, 0); } +static void __devinit mxc_gpio_get_hw(struct platform_device *pdev) +{ + enum mxc_gpio_hwtype hwtype = pdev->id_entry->driver_data; + + if (mxc_gpio_hwtype) { + /* + * The driver works with a reasonable presupposition, + * that is all gpio ports must be the same type when + * running on one soc. + */ + BUG_ON(mxc_gpio_hwtype != hwtype); + return; + } + + if (hwtype == IMX31_GPIO) + mxc_gpio_hwdata = &imx31_gpio_hwdata; + else + mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata; + + mxc_gpio_hwtype = hwtype; +} + static int __devinit mxc_gpio_probe(struct platform_device *pdev) { struct mxc_gpio_port *port; struct resource *iores; int err; + mxc_gpio_get_hw(pdev); + port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL); if (!port) return -ENOMEM; @@ -280,7 +368,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) /* gpio-mxc can be a generic irq chip */ mxc_gpio_init_gc(port); - if (cpu_is_mx2()) { + if (mxc_gpio_hwtype == IMX21_GPIO) { /* setup one handler for all GPIO interrupts */ if (pdev->id == 0) irq_set_chained_handler(port->irq, @@ -334,6 +422,7 @@ static struct platform_driver mxc_gpio_driver = { .owner = THIS_MODULE, }, .probe = mxc_gpio_probe, + .id_table = mxc_gpio_devtype, }; static int __init gpio_mxc_init(void) From 14305e685dff531583e95c5076f633f2fe2b141c Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 7 Jul 2011 00:37:42 +0800 Subject: [PATCH 53/61] ARM: mxc: use ARCH_NR_GPIOS to define gpio number The patch removes MXC_GPIO_IRQS and instead uses ARCH_NR_GPIOS to define gpio number. This change is need when we change mxc gpio driver to be device tree aware. When migrating the driver to device tree, pdev->id becomes unusable. It requires driver get gpio range from gpio core, which will dynamically allocates number from ARCH_NR_GPIOS to 0. As a bonus point, it removes lines of '#if' and make the code a little bit cleaner. The side effect is the waste of number. But this is not a point when we go single image. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- arch/arm/plat-mxc/include/mach/irqs.h | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h index 35c89bcdf758..00e812bbd81d 100644 --- a/arch/arm/plat-mxc/include/mach/irqs.h +++ b/arch/arm/plat-mxc/include/mach/irqs.h @@ -11,6 +11,8 @@ #ifndef __ASM_ARCH_MXC_IRQS_H__ #define __ASM_ARCH_MXC_IRQS_H__ +#include + /* * SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64 */ @@ -22,30 +24,13 @@ #define MXC_GPIO_IRQ_START MXC_INTERNAL_IRQS -/* these are ordered by size to support multi-SoC kernels */ -#if defined CONFIG_SOC_IMX53 -#define MXC_GPIO_IRQS (32 * 7) -#elif defined CONFIG_ARCH_MX2 -#define MXC_GPIO_IRQS (32 * 6) -#elif defined CONFIG_SOC_IMX50 -#define MXC_GPIO_IRQS (32 * 6) -#elif defined CONFIG_ARCH_MX1 -#define MXC_GPIO_IRQS (32 * 4) -#elif defined CONFIG_ARCH_MX25 -#define MXC_GPIO_IRQS (32 * 4) -#elif defined CONFIG_SOC_IMX51 -#define MXC_GPIO_IRQS (32 * 4) -#elif defined CONFIG_ARCH_MX3 -#define MXC_GPIO_IRQS (32 * 3) -#endif - /* * The next 16 interrupts are for board specific purposes. Since * the kernel can only run on one machine at a time, we can re-use * these. If you need more, increase MXC_BOARD_IRQS, but keep it * within sensible limits. */ -#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + MXC_GPIO_IRQS) +#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + ARCH_NR_GPIOS) #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1 #define MXC_BOARD_IRQS 80 From 8937cb602bea120248cef64961fc46836a394c8a Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 7 Jul 2011 00:37:43 +0800 Subject: [PATCH 54/61] gpio/mxc: add device tree probe support The patch adds device tree probe support for gpio-mxc driver. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- .../devicetree/bindings/gpio/fsl-imx-gpio.txt | 22 ++++++++++++ drivers/gpio/gpio-mxc.c | 34 +++++++++++++++---- 2 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt diff --git a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt new file mode 100644 index 000000000000..4363ae4b3c14 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt @@ -0,0 +1,22 @@ +* Freescale i.MX/MXC GPIO controller + +Required properties: +- compatible : Should be "fsl,-gpio" +- reg : Address and length of the register set for the device +- interrupts : Should be the port interrupt shared by all 32 pins, if + one number. If two numbers, the first one is the interrupt shared + by low 16 pins and the second one is for high 16 pins. +- 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 optional parameters (currently + unused). + +Example: + +gpio0: gpio@73f84000 { + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f84000 0x4000>; + interrupts = <50 51>; + gpio-controller; + #gpio-cells = <2>; +}; diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 3775dccef4ad..89fda58db90d 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include enum mxc_gpio_hwtype { @@ -120,6 +122,13 @@ static struct platform_device_id mxc_gpio_devtype[] = { } }; +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], }, + { /* sentinel */ } +}; + /* * MX2 has one interrupt *for all* gpio ports. The list is used * to save the references to all ports, so that mx2_gpio_irq_handler @@ -302,7 +311,13 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) static void __devinit mxc_gpio_get_hw(struct platform_device *pdev) { - enum mxc_gpio_hwtype hwtype = pdev->id_entry->driver_data; + const struct of_device_id *of_id = + of_match_device(mxc_gpio_dt_ids, &pdev->dev); + enum mxc_gpio_hwtype hwtype; + + if (of_id) + pdev->id_entry = of_id->data; + hwtype = pdev->id_entry->driver_data; if (mxc_gpio_hwtype) { /* @@ -324,6 +339,7 @@ static void __devinit mxc_gpio_get_hw(struct platform_device *pdev) static int __devinit mxc_gpio_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct mxc_gpio_port *port; struct resource *iores; int err; @@ -334,8 +350,6 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) if (!port) return -ENOMEM; - port->virtual_irq_start = MXC_GPIO_IRQ_START + pdev->id * 32; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iores) { err = -ENODEV; @@ -365,9 +379,6 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) writel(0, port->base + GPIO_IMR); writel(~0, port->base + GPIO_ISR); - /* gpio-mxc can be a generic irq chip */ - mxc_gpio_init_gc(port); - if (mxc_gpio_hwtype == IMX21_GPIO) { /* setup one handler for all GPIO interrupts */ if (pdev->id == 0) @@ -400,6 +411,16 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) if (err) goto out_bgpio_remove; + /* + * In dt case, we use gpio number range dynamically + * allocated by gpio core. + */ + port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base : + pdev->id * 32); + + /* gpio-mxc can be a generic irq chip */ + mxc_gpio_init_gc(port); + list_add_tail(&port->node, &mxc_gpio_ports); return 0; @@ -420,6 +441,7 @@ static struct platform_driver mxc_gpio_driver = { .driver = { .name = "gpio-mxc", .owner = THIS_MODULE, + .of_match_table = mxc_gpio_dt_ids, }, .probe = mxc_gpio_probe, .id_table = mxc_gpio_devtype, From cd27918dc9d2b730fbb898ff075d4fbfb7f674aa Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 11 Jul 2011 08:53:38 +0800 Subject: [PATCH 55/61] gpio/da9052: remove a redundant assignment for gpio->da9052 We just set it twice in da9052_gpio_probe. Signed-off-by: Axel Lin Signed-off-by: Grant Likely --- drivers/gpio/gpio-da9052.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index c23761f42199..038f5eb8b13d 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -219,7 +219,6 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev) gpio->da9052 = dev_get_drvdata(pdev->dev.parent); pdata = gpio->da9052->dev->platform_data; - gpio->da9052 = dev_get_drvdata(pdev->dev.parent); gpio->gp = reference_gp; if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; From 8ff37c38a26dbdba16f07d48c13bf5f212a98c89 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Thu, 14 Jul 2011 21:59:26 +0200 Subject: [PATCH 56/61] mcp23s08: remove unused work queue Never accessed anywhere. Signed-off-by: Peter Korsgaard Signed-off-by: Grant Likely --- drivers/gpio/gpio-mcp23s08.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 0083ec051de5..da3e04f0909b 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -60,8 +59,6 @@ struct mcp23s08 { struct gpio_chip chip; - struct work_struct work; - const struct mcp23s08_ops *ops; }; From eb5064db408eaffa332f93ddcc19c0b653849093 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 14 Jul 2011 22:17:13 -0700 Subject: [PATCH 57/61] gpio/tegra: dt: add binding for gpio polarity Allocate one bit in the available extra cell to indicate if the gpio should be considered logically inverted. Signed-off-by: Olof Johansson Acked-by: Stephen Warren Signed-off-by: Grant Likely --- Documentation/devicetree/bindings/gpio/gpio_nvidia.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt index 64aac39e6edc..eb4b530d64e1 100644 --- a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt +++ b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt @@ -3,5 +3,6 @@ NVIDIA Tegra 2 GPIO controller Required properties: - compatible : "nvidia,tegra20-gpio" - #gpio-cells : Should be two. The first cell is the pin number and the - second cell is used to specify optional parameters (currently unused). + second cell is used to specify optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) - gpio-controller : Marks the device node as a GPIO controller. From 1bb6f9b042eb1428ba927d2e851a00df6308877a Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 15 Jul 2011 10:25:30 +0200 Subject: [PATCH 58/61] mcp23s08: get rid of setup/teardown callbacks There's no in-tree users, and bus notifiers are more generic anyway. Signed-off-by: Peter Korsgaard Signed-off-by: Grant Likely --- drivers/gpio/gpio-mcp23s08.c | 19 ------------------- include/linux/spi/mcp23s08.h | 9 --------- 2 files changed, 28 deletions(-) diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index da3e04f0909b..ef61234c0e03 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -432,14 +432,6 @@ static int mcp23s08_probe(struct spi_device *spi) * handled here... */ - if (pdata->setup) { - status = pdata->setup(spi, - pdata->base, data->ngpio, - pdata->context); - if (status < 0) - dev_dbg(&spi->dev, "setup --> %d\n", status); - } - return 0; fail: @@ -459,20 +451,9 @@ static int mcp23s08_probe(struct spi_device *spi) static int mcp23s08_remove(struct spi_device *spi) { struct mcp23s08_driver_data *data = spi_get_drvdata(spi); - struct mcp23s08_platform_data *pdata = spi->dev.platform_data; unsigned addr; int status = 0; - if (pdata->teardown) { - status = pdata->teardown(spi, - pdata->base, data->ngpio, - pdata->context); - if (status < 0) { - dev_err(&spi->dev, "%s --> %d\n", "teardown", status); - return status; - } - } - for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { int tmp; diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h index c42cff8ca191..2d676d5aaa89 100644 --- a/include/linux/spi/mcp23s08.h +++ b/include/linux/spi/mcp23s08.h @@ -22,13 +22,4 @@ struct mcp23s08_platform_data { * base to base+15 (or base+31 for s17 variant). */ unsigned base; - - void *context; /* param to setup/teardown */ - - int (*setup)(struct spi_device *spi, - int gpio, unsigned ngpio, - void *context); - int (*teardown)(struct spi_device *spi, - int gpio, unsigned ngpio, - void *context); }; From d62b98f305a6b0d32fbdc72ac6ba3d4f4768adeb Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 15 Jul 2011 10:25:31 +0200 Subject: [PATCH 59/61] mcp23s08: isolate spi specific parts Change spi member of struct mcp23s08 to be a ops-specific opaque data pointer, and move spi specific knowledge out of mcp23s08_probe_one(). No functional change, but is needed to add i2c support. Signed-off-by: Peter Korsgaard Signed-off-by: Grant Likely --- drivers/gpio/gpio-mcp23s08.c | 81 +++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index ef61234c0e03..7b78f940868e 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -50,7 +50,6 @@ struct mcp23s08_ops { }; struct mcp23s08 { - struct spi_device *spi; u8 addr; u16 cache[11]; @@ -60,6 +59,7 @@ struct mcp23s08 { struct gpio_chip chip; const struct mcp23s08_ops *ops; + void *data; /* ops specific data */ }; /* A given spi_device can represent up to eight mcp23sxx chips @@ -73,6 +73,8 @@ struct mcp23s08_driver_data { struct mcp23s08 chip[]; }; +#ifdef CONFIG_SPI_MASTER + static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) { u8 tx[2], rx[1]; @@ -80,7 +82,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) tx[0] = mcp->addr | 0x01; tx[1] = reg; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx); + status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); return (status < 0) ? status : rx[0]; } @@ -91,7 +93,7 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) tx[0] = mcp->addr; tx[1] = reg; tx[2] = val; - return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); + return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); } static int @@ -106,7 +108,7 @@ mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) tx[1] = reg; tmp = (u8 *)vals; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n); + status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n); if (status >= 0) { while (n--) vals[n] = tmp[n]; /* expand to 16bit */ @@ -121,7 +123,7 @@ static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg) tx[0] = mcp->addr | 0x01; tx[1] = reg << 1; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx); + status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); return (status < 0) ? status : (rx[0] | (rx[1] << 8)); } @@ -133,7 +135,7 @@ static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) tx[1] = reg << 1; tx[2] = val; tx[3] = val >> 8; - return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); + return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); } static int @@ -147,7 +149,7 @@ mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) tx[0] = mcp->addr | 0x01; tx[1] = reg << 1; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, + status = spi_write_then_read(mcp->data, tx, sizeof tx, (u8 *)vals, n * 2); if (status >= 0) { while (n--) @@ -169,6 +171,7 @@ static const struct mcp23s08_ops mcp23s17_ops = { .read_regs = mcp23s17_read_regs, }; +#endif /* CONFIG_SPI_MASTER */ /*----------------------------------------------------------------------*/ @@ -296,17 +299,16 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip) /*----------------------------------------------------------------------*/ -static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, +static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, + void *data, unsigned addr, unsigned type, unsigned base, unsigned pullups) { - struct mcp23s08_driver_data *data = spi_get_drvdata(spi); - struct mcp23s08 *mcp = data->mcp[addr]; - int status; + int status; mutex_init(&mcp->lock); - mcp->spi = spi; - mcp->addr = 0x40 | (addr << 1); + mcp->data = data; + mcp->addr = addr; mcp->chip.direction_input = mcp23s08_direction_input; mcp->chip.get = mcp23s08_get; @@ -314,18 +316,29 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, mcp->chip.set = mcp23s08_set; mcp->chip.dbg_show = mcp23s08_dbg_show; - if (type == MCP_TYPE_S17) { - mcp->ops = &mcp23s17_ops; - mcp->chip.ngpio = 16; - mcp->chip.label = "mcp23s17"; - } else { + switch (type) { +#ifdef CONFIG_SPI_MASTER + case MCP_TYPE_S08: mcp->ops = &mcp23s08_ops; mcp->chip.ngpio = 8; mcp->chip.label = "mcp23s08"; + break; + + case MCP_TYPE_S17: + mcp->ops = &mcp23s17_ops; + mcp->chip.ngpio = 16; + mcp->chip.label = "mcp23s17"; + break; +#endif /* CONFIG_SPI_MASTER */ + + default: + dev_err(dev, "invalid device type (%d)\n", type); + return -EINVAL; } + mcp->chip.base = base; mcp->chip.can_sleep = 1; - mcp->chip.dev = &spi->dev; + mcp->chip.dev = dev; mcp->chip.owner = THIS_MODULE; /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, @@ -371,11 +384,13 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, status = gpiochip_add(&mcp->chip); fail: if (status < 0) - dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n", - addr, status); + dev_dbg(dev, "can't setup chip %d, --> %d\n", + addr, status); return status; } +#ifdef CONFIG_SPI_MASTER + static int mcp23s08_probe(struct spi_device *spi) { struct mcp23s08_platform_data *pdata; @@ -418,7 +433,8 @@ static int mcp23s08_probe(struct spi_device *spi) continue; chips--; data->mcp[addr] = &data->chip[chips]; - status = mcp23s08_probe_one(spi, addr, type, base, + status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, + 0x40 | (addr << 1), type, base, pdata->chip[addr].pullups); if (status < 0) goto fail; @@ -488,11 +504,28 @@ static struct spi_driver mcp23s08_driver = { }, }; +static int __init mcp23s08_spi_init(void) +{ + return spi_register_driver(&mcp23s08_driver); +} + +static void mcp23s08_spi_exit(void) +{ + spi_unregister_driver(&mcp23s08_driver); +} + +#else + +static int __init mcp23s08_spi_init(void) { return 0; } +static void mcp23s08_spi_exit(void) { } + +#endif /* CONFIG_SPI_MASTER */ + /*----------------------------------------------------------------------*/ static int __init mcp23s08_init(void) { - return spi_register_driver(&mcp23s08_driver); + return mcp23s08_spi_init(); } /* register after spi postcore initcall and before * subsys initcalls that may rely on these GPIOs @@ -501,7 +534,7 @@ subsys_initcall(mcp23s08_init); static void __exit mcp23s08_exit(void) { - spi_unregister_driver(&mcp23s08_driver); + mcp23s08_spi_exit(); } module_exit(mcp23s08_exit); From 752ad5e82dfd83851e44a2b9da8761994cd7e61c Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 15 Jul 2011 10:25:32 +0200 Subject: [PATCH 60/61] mcp23s08: add i2c support Add i2c bindings for the mcp230xx devices. This is quite a lot simpler than the spi one as there's no funky sub addressing done (one struct i2c_client per struct gpio_chip). The mcp23s08_platform_data structure is reused for i2c, even though only a single mcp23s08_chip_info structure is needed. To use, simply fill out a platform_data structure and pass it in i2c_board_info, E.G.: static const struct mcp23s08_platform_data mcp23017_data = { .chip[0] = { .pullups = 0x00ff, }, .base = 240, }; static struct i2c_board_info __initdata i2c_devs[] = { { I2C_BOARD_INFO("mcp23017", 0x20), .platform_data = &smartview_mcp23017_data, }, ... }; Signed-off-by: Peter Korsgaard Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 7 +- drivers/gpio/gpio-mcp23s08.c | 192 ++++++++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 47eae6ea5dd2..363498697c2c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -412,10 +412,11 @@ config GPIO_MAX7301 GPIO driver for Maxim MAX7301 SPI-based GPIO expander. config GPIO_MCP23S08 - tristate "Microchip MCP23Sxx I/O expander" - depends on SPI_MASTER + tristate "Microchip MCP23xxx I/O expander" + depends on SPI_MASTER || I2C help - SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders. + SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 + I/O expanders. This provides a GPIO interface supporting inputs and outputs. config GPIO_MC33880 diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 7b78f940868e..1ef46e6c2a2a 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -1,11 +1,12 @@ /* - * MCP23S08 SPI gpio expander driver + * MCP23S08 SPI/GPIO gpio expander driver */ #include #include #include #include +#include #include #include #include @@ -16,13 +17,13 @@ */ #define MCP_TYPE_S08 0 #define MCP_TYPE_S17 1 +#define MCP_TYPE_008 2 +#define MCP_TYPE_017 3 /* Registers are all 8 bits wide. * * The mcp23s17 has twice as many bits, and can be configured to work * with either 16 bit registers or with two adjacent 8 bit banks. - * - * Also, there are I2C versions of both chips. */ #define MCP_IODIR 0x00 /* init/reset: all ones */ #define MCP_IPOL 0x01 @@ -73,6 +74,72 @@ struct mcp23s08_driver_data { struct mcp23s08 chip[]; }; +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_I2C + +static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) +{ + return i2c_smbus_read_byte_data(mcp->data, reg); +} + +static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) +{ + return i2c_smbus_write_byte_data(mcp->data, reg, val); +} + +static int +mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) +{ + while (n--) { + int ret = mcp23008_read(mcp, reg++); + if (ret < 0) + return ret; + *vals++ = ret; + } + + return 0; +} + +static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg) +{ + return i2c_smbus_read_word_data(mcp->data, reg << 1); +} + +static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) +{ + return i2c_smbus_write_word_data(mcp->data, reg << 1, val); +} + +static int +mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) +{ + while (n--) { + int ret = mcp23017_read(mcp, reg++); + if (ret < 0) + return ret; + *vals++ = ret; + } + + return 0; +} + +static const struct mcp23s08_ops mcp23008_ops = { + .read = mcp23008_read, + .write = mcp23008_write, + .read_regs = mcp23008_read_regs, +}; + +static const struct mcp23s08_ops mcp23017_ops = { + .read = mcp23017_read, + .write = mcp23017_write, + .read_regs = mcp23017_read_regs, +}; + +#endif /* CONFIG_I2C */ + +/*----------------------------------------------------------------------*/ + #ifdef CONFIG_SPI_MASTER static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) @@ -331,6 +398,20 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, break; #endif /* CONFIG_SPI_MASTER */ +#ifdef CONFIG_I2C + case MCP_TYPE_008: + mcp->ops = &mcp23008_ops; + mcp->chip.ngpio = 8; + mcp->chip.label = "mcp23008"; + break; + + case MCP_TYPE_017: + mcp->ops = &mcp23017_ops; + mcp->chip.ngpio = 16; + mcp->chip.label = "mcp23017"; + break; +#endif /* CONFIG_I2C */ + default: dev_err(dev, "invalid device type (%d)\n", type); return -EINVAL; @@ -389,6 +470,91 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, return status; } +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_I2C + +static int __devinit mcp230xx_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mcp23s08_platform_data *pdata; + struct mcp23s08 *mcp; + int status; + + pdata = client->dev.platform_data; + if (!pdata || !gpio_is_valid(pdata->base)) { + dev_dbg(&client->dev, "invalid or missing platform data\n"); + return -EINVAL; + } + + mcp = kzalloc(sizeof *mcp, GFP_KERNEL); + if (!mcp) + return -ENOMEM; + + status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, + id->driver_data, pdata->base, + pdata->chip[0].pullups); + if (status) + goto fail; + + i2c_set_clientdata(client, mcp); + + return 0; + +fail: + kfree(mcp); + + return status; +} + +static int __devexit mcp230xx_remove(struct i2c_client *client) +{ + struct mcp23s08 *mcp = i2c_get_clientdata(client); + int status; + + status = gpiochip_remove(&mcp->chip); + if (status == 0) + kfree(mcp); + + return status; +} + +static const struct i2c_device_id mcp230xx_id[] = { + { "mcp23008", MCP_TYPE_008 }, + { "mcp23017", MCP_TYPE_017 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, mcp230xx_id); + +static struct i2c_driver mcp230xx_driver = { + .driver = { + .name = "mcp230xx", + .owner = THIS_MODULE, + }, + .probe = mcp230xx_probe, + .remove = __devexit_p(mcp230xx_remove), + .id_table = mcp230xx_id, +}; + +static int __init mcp23s08_i2c_init(void) +{ + return i2c_add_driver(&mcp230xx_driver); +} + +static void mcp23s08_i2c_exit(void) +{ + i2c_del_driver(&mcp230xx_driver); +} + +#else + +static int __init mcp23s08_i2c_init(void) { return 0; } +static void mcp23s08_i2c_exit(void) { } + +#endif /* CONFIG_I2C */ + +/*----------------------------------------------------------------------*/ + #ifdef CONFIG_SPI_MASTER static int mcp23s08_probe(struct spi_device *spi) @@ -525,9 +691,24 @@ static void mcp23s08_spi_exit(void) { } static int __init mcp23s08_init(void) { - return mcp23s08_spi_init(); + int ret; + + ret = mcp23s08_spi_init(); + if (ret) + goto spi_fail; + + ret = mcp23s08_i2c_init(); + if (ret) + goto i2c_fail; + + return 0; + + i2c_fail: + mcp23s08_spi_exit(); + spi_fail: + return ret; } -/* register after spi postcore initcall and before +/* register after spi/i2c postcore initcall and before * subsys initcalls that may rely on these GPIOs */ subsys_initcall(mcp23s08_init); @@ -535,6 +716,7 @@ subsys_initcall(mcp23s08_init); static void __exit mcp23s08_exit(void) { mcp23s08_spi_exit(); + mcp23s08_i2c_exit(); } module_exit(mcp23s08_exit); From 591567a5ea25852f20b7ef2953f6f72020121199 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 19 Jul 2011 21:16:56 +0800 Subject: [PATCH 61/61] gpio/mxc/mxs: fix build error introduced by the irq_gc_ack() renaming The following commit renames irq_gc_ack() to irq_gc_ack_set_bit(), and makes gpio-mxc and gpio-mxs fail to build. 659fb32d1b67476f4ade25e9ea0e2642a5b9c4b5 genirq: replace irq_gc_ack() with {set,clr}_bit variants (fwd) The patch fixed a couple of typo of comma to semicolon. Signed-off-by: Shawn Guo Signed-off-by: Grant Likely --- drivers/gpio/gpio-mxc.c | 4 ++-- drivers/gpio/gpio-mxs.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 89fda58db90d..4340acae3bd3 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -297,11 +297,11 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) gc->private = port; ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack, + ct->chip.irq_ack = irq_gc_ack_set_bit; ct->chip.irq_mask = irq_gc_mask_clr_bit; ct->chip.irq_unmask = irq_gc_mask_set_bit; ct->chip.irq_set_type = gpio_set_irq_type; - ct->chip.irq_set_wake = gpio_set_wake_irq, + ct->chip.irq_set_wake = gpio_set_wake_irq; ct->regs.ack = GPIO_ISR; ct->regs.mask = GPIO_IMR; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index d8cafba8c829..af55a8577c2e 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -156,11 +156,11 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port) gc->private = port; ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack, + ct->chip.irq_ack = irq_gc_ack_set_bit; ct->chip.irq_mask = irq_gc_mask_clr_bit; ct->chip.irq_unmask = irq_gc_mask_set_bit; ct->chip.irq_set_type = mxs_gpio_set_irq_type; - ct->chip.irq_set_wake = mxs_gpio_set_wake_irq, + ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR; ct->regs.mask = PINCTRL_IRQEN(port->id);