From 1bc857f700fb14bbcb990a81b1255f39807ae59e Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 26 Jul 2011 10:54:55 +0100 Subject: ARM: gpio: omap: convert drivers to use asm/gpio.h rather than mach/gpio.h Signed-off-by: Russell King --- drivers/gpio/gpio-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0599854e2217..9c27244fd680 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include struct gpio_bank { -- cgit v1.2.3-59-g8ed1b From 75482dc3ded2be0b04ee00294f8db94a38748096 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 26 Jul 2011 10:57:37 +0100 Subject: ARM: gpio: nomadik: convert drivers to use asm/gpio.h rather than mach/gpio.h Signed-off-by: Russell King --- drivers/gpio/gpio-nomadik.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 2c212c732d76..f7f0406ed880 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -28,7 +28,7 @@ #include #include -#include +#include /* * The GPIO module in the Nomadik family of Systems-on-Chip is an -- cgit v1.2.3-59-g8ed1b From 0f33286190634eeb3ec7638045980c39c98380f4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:33:30 +0100 Subject: ARM: 7032/1: plat-nomadik: break out GPIO driver specifics The <[plat|mach]/gpio.h> file is included from upper directories and deal with generic GPIO and gpiolib stuff. Break out the platform and driver specific defines and functions into its own header file. Cc: Srinidhi Kasagar Cc: Alessandro Rubini Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-nomadik/board-nhk8815.c | 1 + arch/arm/mach-nomadik/cpu-8815.c | 2 +- arch/arm/mach-nomadik/i2c-8815nhk.c | 2 +- arch/arm/mach-ux500/board-mop500-pins.c | 2 +- arch/arm/mach-ux500/board-mop500.c | 1 + arch/arm/mach-ux500/board-u5500-sdi.c | 2 +- arch/arm/mach-ux500/board-u5500.c | 2 +- arch/arm/mach-ux500/cpu-db5500.c | 2 +- arch/arm/mach-ux500/cpu-db8500.c | 2 +- arch/arm/mach-ux500/devices-common.c | 2 +- arch/arm/plat-nomadik/include/plat/gpio-nomadik.h | 85 +++++++++++++++++++++++ arch/arm/plat-nomadik/include/plat/gpio.h | 69 ------------------ drivers/gpio/gpio-nomadik.c | 1 + 13 files changed, 96 insertions(+), 77 deletions(-) create mode 100644 arch/arm/plat-nomadik/include/plat/gpio-nomadik.h (limited to 'drivers/gpio') diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 139930350d93..97d7186484ca 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index ac58e3b03b1a..dc67717db6f0 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -21,8 +21,8 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c index abfe25a08d6b..0fc2f6f1cc97 100644 --- a/arch/arm/mach-nomadik/i2c-8815nhk.c +++ b/arch/arm/mach-nomadik/i2c-8815nhk.c @@ -3,8 +3,8 @@ #include #include #include -#include #include +#include /* * There are two busses in the 8815NHK. diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index f26fd76f72b4..15b23e4bd488 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -6,10 +6,10 @@ #include #include -#include #include #include +#include #include #include "pins-db8500.h" diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index cd54abaccd96..537ab63c1dc9 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c index 739fb4c5b160..63c3f8058ffc 100644 --- a/arch/arm/mach-ux500/board-u5500-sdi.c +++ b/arch/arm/mach-ux500/board-u5500-sdi.c @@ -7,9 +7,9 @@ #include #include -#include #include +#include #include #include diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index e58f0f562426..2d9e191bd30a 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -17,6 +16,7 @@ #include #include +#include #include #include diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 22705d246fc7..9de1af008094 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 4598b06c8c55..13e8890a8b8a 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -14,12 +14,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index 13a4ce046ae5..c563e5418d80 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h new file mode 100644 index 000000000000..3ba4d8f8073b --- /dev/null +++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h @@ -0,0 +1,85 @@ +/* + * Structures and registers for GPIO access in the Nomadik SoC + * + * Copyright (C) 2008 STMicroelectronics + * Author: Prafulla WADASKAR + * Copyright (C) 2009 Alessandro Rubini + * + * 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. + */ + +#ifndef __PLAT_NOMADIK_GPIO +#define __PLAT_NOMADIK_GPIO + +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +/* Pull up/down values */ +enum nmk_gpio_pull { + NMK_GPIO_PULL_NONE, + NMK_GPIO_PULL_UP, + NMK_GPIO_PULL_DOWN, +}; + +/* Sleep mode */ +enum nmk_gpio_slpm { + NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_NOCHANGE, + NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, +}; + +extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); +extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); +extern int nmk_gpio_set_mode(int gpio, int gpio_mode); +extern int nmk_gpio_get_mode(int gpio); + +extern void nmk_gpio_wakeups_suspend(void); +extern void nmk_gpio_wakeups_resume(void); + +extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); + +/* + * Platform data to register a block: only the initial gpio/irq number. + */ +struct nmk_gpio_platform_data { + char *name; + int first_gpio; + int first_irq; + int num_gpio; + u32 (*get_secondary_status)(unsigned int bank); + void (*set_ioforce)(bool enable); + bool supports_sleepmode; +}; + +#endif /* __PLAT_NOMADIK_GPIO */ diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index b894a531f324..78c0c0fbadb7 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -14,73 +14,4 @@ #include -/* - * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving - * the "gpio" namespace for generic and cross-machine functions - */ - -/* Register in the logic block */ -#define NMK_GPIO_DAT 0x00 -#define NMK_GPIO_DATS 0x04 -#define NMK_GPIO_DATC 0x08 -#define NMK_GPIO_PDIS 0x0c -#define NMK_GPIO_DIR 0x10 -#define NMK_GPIO_DIRS 0x14 -#define NMK_GPIO_DIRC 0x18 -#define NMK_GPIO_SLPC 0x1c -#define NMK_GPIO_AFSLA 0x20 -#define NMK_GPIO_AFSLB 0x24 - -#define NMK_GPIO_RIMSC 0x40 -#define NMK_GPIO_FIMSC 0x44 -#define NMK_GPIO_IS 0x48 -#define NMK_GPIO_IC 0x4c -#define NMK_GPIO_RWIMSC 0x50 -#define NMK_GPIO_FWIMSC 0x54 -#define NMK_GPIO_WKS 0x58 - -/* Alternate functions: function C is set in hw by setting both A and B */ -#define NMK_GPIO_ALT_GPIO 0 -#define NMK_GPIO_ALT_A 1 -#define NMK_GPIO_ALT_B 2 -#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) - -/* Pull up/down values */ -enum nmk_gpio_pull { - NMK_GPIO_PULL_NONE, - NMK_GPIO_PULL_UP, - NMK_GPIO_PULL_DOWN, -}; - -/* Sleep mode */ -enum nmk_gpio_slpm { - NMK_GPIO_SLPM_INPUT, - NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, - NMK_GPIO_SLPM_NOCHANGE, - NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, -}; - -extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); -extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); -extern int nmk_gpio_set_mode(int gpio, int gpio_mode); -extern int nmk_gpio_get_mode(int gpio); - -extern void nmk_gpio_wakeups_suspend(void); -extern void nmk_gpio_wakeups_resume(void); - -extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); - -/* - * Platform data to register a block: only the initial gpio/irq number. - */ -struct nmk_gpio_platform_data { - char *name; - int first_gpio; - int first_irq; - int num_gpio; - u32 (*get_secondary_status)(unsigned int bank); - void (*set_ioforce)(bool enable); - bool supports_sleepmode; -}; - #endif /* __ASM_PLAT_GPIO_H */ diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index f7f0406ed880..740caed2b278 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -27,6 +27,7 @@ #include #include +#include #include #include -- cgit v1.2.3-59-g8ed1b From eb3cf18cccc33d86179674ac1c49dcbc142fc2d9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:34:26 +0100 Subject: ARM: 7033/1: mach-u300: break out GPIO driver specifics The file is included from upper directories and deal with generic GPIO and gpiolib stuff. Break out the platform and driver specific defines and functions into its own header file. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/include/mach/gpio-u300.h | 253 ++++++++++++++++++++++++++++ arch/arm/mach-u300/include/mach/gpio.h | 249 +-------------------------- arch/arm/mach-u300/mmc.c | 2 +- drivers/gpio/gpio-u300.c | 1 + 4 files changed, 259 insertions(+), 246 deletions(-) create mode 100644 arch/arm/mach-u300/include/mach/gpio-u300.h (limited to 'drivers/gpio') diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.h new file mode 100644 index 000000000000..a6119062add9 --- /dev/null +++ b/arch/arm/mach-u300/include/mach/gpio-u300.h @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2007-2011 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * GPIO block resgister definitions and inline macros for + * U300 GPIO COH 901 335 or COH 901 571/3 + * Author: Linus Walleij + */ + +#ifndef __MACH_U300_GPIO_U300_H +#define __MACH_U300_GPIO_U300_H + +#include +#include +#include +#include + +/* Switch type depending on platform/chip variant */ +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) +#define U300_COH901335 +#endif +#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335) +#define U300_COH901571_3 +#endif + +/* Get base address for regs here */ +#include "u300-regs.h" +/* IRQ numbers */ +#include "irqs.h" + +/* + * This is the GPIO block definitions. GPIO (General Purpose I/O) can be + * used for anything, and often is. The event/enable etc figures are for + * the lowermost pin (pin 0 on each port), shift this left to match your + * pin if you're gonna use these values. + */ +#ifdef U300_COH901335 +#define U300_GPIO_PORTX_SPACING (0x1C) +/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ +#define U300_GPIO_PXPDIR (0x00) +#define U300_GPIO_PXPDOR (0x00) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_GPIO_PXPCR (0x04) +#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) +#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) +#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) +/* Port X Interrupt Event Register 32bit (R/W) */ +#define U300_GPIO_PXIEV (0x08) +#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) +#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_GPIO_PXIEN (0x0C) +#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_GPIO_PXIFR (0x10) +#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) +#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_GPIO_PXICR (0x14) +#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) +#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) +/* Port X Pull-up Enable Register 32bit (R/W) */ +#define U300_GPIO_PXPER (0x18) +#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) +/* Control Register 32bit (R/W) */ +#define U300_GPIO_CR (0x54) +#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) +/* three ports of 8 bits each = GPIO pins 0..23 */ +#define U300_GPIO_NUM_PORTS 3 +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) +#endif + +#ifdef U300_COH901571_3 +/* + * Control Register 32bit (R/W) + * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores + * gives the number of GPIO pins. + * bit 8-2 (mask 0x000001FC) contains the core version ID. + */ +#define U300_GPIO_CR (0x00) +#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL) +#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) +#define U300_GPIO_PORTX_SPACING (0x30) +/* Port X Pin Data INPUT Register 32bit (R/W) */ +#define U300_GPIO_PXPDIR (0x04) +/* Port X Pin Data OUTPUT Register 32bit (R/W) */ +#define U300_GPIO_PXPDOR (0x08) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_GPIO_PXPCR (0x0C) +#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) +#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) +#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) +/* Port X Pull-up Enable Register 32bit (R/W) */ +#define U300_GPIO_PXPER (0x10) +#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) +/* Port X Interrupt Event Register 32bit (R/W) */ +#define U300_GPIO_PXIEV (0x14) +#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) +#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_GPIO_PXIEN (0x18) +#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_GPIO_PXIFR (0x1C) +#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) +#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_GPIO_PXICR (0x20) +#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) +#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) +#ifdef CONFIG_MACH_U300_BS335 +/* seven ports of 8 bits each = GPIO pins 0..55 */ +#define U300_GPIO_NUM_PORTS 7 +#else +/* five ports of 8 bits each = GPIO pins 0..39 */ +#define U300_GPIO_NUM_PORTS 5 +#endif +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) +#endif + +/* + * Individual pin assignments for the B26/S26. Notice that the + * actual usage of these pins depends on the PAD MUX settings, that + * is why the same number can potentially appear several times. + * In the reference design each pin is only used for one purpose. + * These were determined by inspecting the B26/S26 schematic: + * 2/1911-ROA 128 1603 + */ +#ifdef CONFIG_MACH_U300_BS2X +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */ +#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */ +#define U300_GPIO_PIN_CAM_SLEEP 4 +#define U300_GPIO_PIN_CAM_REG_EN 5 +#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */ +#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */ +#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */ +#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */ +#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */ +#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */ +#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */ +#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ +#endif + +/* + * Individual pin assignments for the B330/S330 and B365/S365. + * Notice that the actual usage of these pins depends on the + * PAD MUX settings, that is why the same number can potentially + * appear several times. In the reference design each pin is only + * used for one purpose. These were determined by inspecting the + * S365 schematic. + */ +#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \ + defined(CONFIG_MACH_U300_BS335) +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_UART_CTS 2 +#define U300_GPIO_PIN_UART_RTS 3 +#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */ +#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */ +#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */ +#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */ + +#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */ +#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */ +#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */ +#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */ +#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */ +#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */ +#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */ +#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */ +#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */ +#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */ +#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */ +#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */ +#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */ +#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */ +#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */ +#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */ +#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */ +#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */ +#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */ +#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */ +#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */ + +#ifdef CONFIG_MACH_U300_BS335 + +#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */ +#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */ +#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */ +#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */ +#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */ +#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */ +#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */ +#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */ +#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */ +#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */ +#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */ +#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */ +#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */ +#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */ +#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */ +#endif + +#endif + +#endif /* __MACH_U300_GPIO_U300_H */ diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h index 9a890e2b74c7..6a3f24d92438 100644 --- a/arch/arm/mach-u300/include/mach/gpio.h +++ b/arch/arm/mach-u300/include/mach/gpio.h @@ -13,252 +13,8 @@ #ifndef __MACH_U300_GPIO_H #define __MACH_U300_GPIO_H -#include -#include -#include -#include - #define __ARM_GPIOLIB_COMPLEX -/* Switch type depending on platform/chip variant */ -#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) -#define U300_COH901335 -#endif -#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335) -#define U300_COH901571_3 -#endif - -/* Get base address for regs here */ -#include "u300-regs.h" -/* IRQ numbers */ -#include "irqs.h" - -/* - * This is the GPIO block definitions. GPIO (General Purpose I/O) can be - * used for anything, and often is. The event/enable etc figures are for - * the lowermost pin (pin 0 on each port), shift this left to match your - * pin if you're gonna use these values. - */ -#ifdef U300_COH901335 -#define U300_GPIO_PORTX_SPACING (0x1C) -/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ -#define U300_GPIO_PXPDIR (0x00) -#define U300_GPIO_PXPDOR (0x00) -/* Port X Pin Config Register 32bit (R/W) */ -#define U300_GPIO_PXPCR (0x04) -#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) -#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) -#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) -/* Port X Interrupt Event Register 32bit (R/W) */ -#define U300_GPIO_PXIEV (0x08) -#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) -#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) -/* Port X Interrupt Enable Register 32bit (R/W) */ -#define U300_GPIO_PXIEN (0x0C) -#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) -/* Port X Interrupt Force Register 32bit (R/W) */ -#define U300_GPIO_PXIFR (0x10) -#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) -#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) -/* Port X Interrupt Config Register 32bit (R/W) */ -#define U300_GPIO_PXICR (0x14) -#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) -#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) -/* Port X Pull-up Enable Register 32bit (R/W) */ -#define U300_GPIO_PXPER (0x18) -#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) -/* Control Register 32bit (R/W) */ -#define U300_GPIO_CR (0x54) -#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) -/* three ports of 8 bits each = GPIO pins 0..23 */ -#define U300_GPIO_NUM_PORTS 3 -#define U300_GPIO_PINS_PER_PORT 8 -#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) -#endif - -#ifdef U300_COH901571_3 -/* - * Control Register 32bit (R/W) - * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores - * gives the number of GPIO pins. - * bit 8-2 (mask 0x000001FC) contains the core version ID. - */ -#define U300_GPIO_CR (0x00) -#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL) -#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) -#define U300_GPIO_PORTX_SPACING (0x30) -/* Port X Pin Data INPUT Register 32bit (R/W) */ -#define U300_GPIO_PXPDIR (0x04) -/* Port X Pin Data OUTPUT Register 32bit (R/W) */ -#define U300_GPIO_PXPDOR (0x08) -/* Port X Pin Config Register 32bit (R/W) */ -#define U300_GPIO_PXPCR (0x0C) -#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) -#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) -#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) -/* Port X Pull-up Enable Register 32bit (R/W) */ -#define U300_GPIO_PXPER (0x10) -#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) -/* Port X Interrupt Event Register 32bit (R/W) */ -#define U300_GPIO_PXIEV (0x14) -#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) -#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) -/* Port X Interrupt Enable Register 32bit (R/W) */ -#define U300_GPIO_PXIEN (0x18) -#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) -/* Port X Interrupt Force Register 32bit (R/W) */ -#define U300_GPIO_PXIFR (0x1C) -#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) -#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) -/* Port X Interrupt Config Register 32bit (R/W) */ -#define U300_GPIO_PXICR (0x20) -#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) -#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) -#ifdef CONFIG_MACH_U300_BS335 -/* seven ports of 8 bits each = GPIO pins 0..55 */ -#define U300_GPIO_NUM_PORTS 7 -#else -/* five ports of 8 bits each = GPIO pins 0..39 */ -#define U300_GPIO_NUM_PORTS 5 -#endif -#define U300_GPIO_PINS_PER_PORT 8 -#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) -#endif - -/* - * Individual pin assignments for the B26/S26. Notice that the - * actual usage of these pins depends on the PAD MUX settings, that - * is why the same number can potentially appear several times. - * In the reference design each pin is only used for one purpose. - * These were determined by inspecting the B26/S26 schematic: - * 2/1911-ROA 128 1603 - */ -#ifdef CONFIG_MACH_U300_BS2X -#define U300_GPIO_PIN_UART_RX 0 -#define U300_GPIO_PIN_UART_TX 1 -#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */ -#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */ -#define U300_GPIO_PIN_CAM_SLEEP 4 -#define U300_GPIO_PIN_CAM_REG_EN 5 -#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */ -#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */ -#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */ -#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */ -#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ -#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ -#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */ -#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */ -#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */ -#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */ -#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */ -#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */ -#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ -#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ -#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ -#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ -#endif - -/* - * Individual pin assignments for the B330/S330 and B365/S365. - * Notice that the actual usage of these pins depends on the - * PAD MUX settings, that is why the same number can potentially - * appear several times. In the reference design each pin is only - * used for one purpose. These were determined by inspecting the - * S365 schematic. - */ -#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \ - defined(CONFIG_MACH_U300_BS335) -#define U300_GPIO_PIN_UART_RX 0 -#define U300_GPIO_PIN_UART_TX 1 -#define U300_GPIO_PIN_UART_CTS 2 -#define U300_GPIO_PIN_UART_RTS 3 -#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */ -#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */ -#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */ -#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */ - -#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */ -#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */ -#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */ -#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ -#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ -#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */ -#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */ -#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */ -#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */ -#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */ -#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */ -#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ -#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ -#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ -#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */ -#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */ -#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */ -#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */ -#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */ -#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */ -#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */ -#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */ -#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */ -#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */ -#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */ -#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */ -#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */ -#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */ -#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */ - -#ifdef CONFIG_MACH_U300_BS335 - -#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */ -#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */ -#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */ -#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */ -#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */ -#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */ -#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */ -#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */ -#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */ -#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */ -#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */ -#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */ -#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */ -#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */ -#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */ -#endif - -#endif - -/* translates a pin number to a port number */ -#define PIN_TO_PORT(val) (val >> 3) - /* These can be found in arch/arm/mach-u300/gpio.c */ extern int gpio_is_valid(int number); extern int gpio_request(unsigned gpio, const char *label); @@ -278,6 +34,9 @@ extern void gpio_set_value(unsigned gpio, int value); #define gpio_get_value_cansleep gpio_get_value #define gpio_set_value_cansleep gpio_set_value +/* translates a pin number to a port number */ +#define PIN_TO_PORT(val) (val >> 3) + /* wrappers to sleep-enable the previous two functions */ static inline unsigned gpio_to_irq(unsigned gpio) { @@ -294,4 +53,4 @@ static inline unsigned irq_to_gpio(unsigned irq) return (irq - IRQ_U300_GPIO_PORT0) << 3; } -#endif +#endif /* __MACH_U300_GPIO_H */ diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index 677ccef5cd32..d9a5c92db74a 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -13,12 +13,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include "mmc.h" #include "padmux.h" diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c index 53e8255cb0ba..92f2b8c06de1 100644 --- a/drivers/gpio/gpio-u300.c +++ b/drivers/gpio/gpio-u300.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Reference to GPIO block clock */ static struct clk *clk; -- cgit v1.2.3-59-g8ed1b From db23c7332b5391646c32585b06328da0463418f8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:37:10 +0100 Subject: ARM: 7035/1: mach-ks8695: move GPIO driver to GPIO subsystem As per example from the other ARM boards, push the KS8695 GPIO driver down to the GPIO subsystem so it can be consolidated. Cc: zeal Cc: Ben Dooks Acked-by: Daniel Silverstone Acked-by: Simtec Linux Team Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ks8695/Makefile | 2 +- arch/arm/mach-ks8695/gpio.c | 318 ------------------------------------------ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-ks8695.c | 318 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 320 insertions(+), 319 deletions(-) delete mode 100644 arch/arm/mach-ks8695/gpio.c create mode 100644 drivers/gpio/gpio-ks8695.c (limited to 'drivers/gpio') diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile index 7e3e8160ed30..853efd9133c6 100644 --- a/arch/arm/mach-ks8695/Makefile +++ b/arch/arm/mach-ks8695/Makefile @@ -3,7 +3,7 @@ # Makefile for KS8695 architecture support # -obj-y := cpu.o irq.o time.o gpio.o devices.o +obj-y := cpu.o irq.o time.o devices.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c deleted file mode 100644 index b3fdfe1d262f..000000000000 --- a/arch/arm/mach-ks8695/gpio.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * arch/arm/mach-ks8695/gpio.c - * - * Copyright (C) 2006 Andrew Victor - * Updated to GPIOLIB, Copyright 2008 Simtec Electronics - * Daniel Silverstone - * - * 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. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -/* - * Configure a GPIO line for either GPIO function, or its internal - * function (Interrupt, Timer, etc). - */ -static void ks8695_gpio_mode(unsigned int pin, short gpio) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned long x, flags; - - if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ - return; - - local_irq_save(flags); - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - if (gpio) /* GPIO: set bit to 0 */ - x &= ~enable[pin]; - else /* Internal function: set bit to 1 */ - x |= enable[pin]; - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); - - local_irq_restore(flags); -} - - -static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; - -/* - * Configure GPIO pin as external interrupt source. - */ -int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - /* Set IRQ triggering type */ - irq_set_irq_type(gpio_irq[pin], type); - - /* enable interrupt mode */ - ks8695_gpio_mode(pin, 0); - - return 0; -} -EXPORT_SYMBOL(ks8695_gpio_interrupt); - - - -/* .... Generic GPIO interface .............................................. */ - -/* - * Configure the GPIO line as an input. - */ -static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Configure the GPIO line as an output, with default state. - */ -static int ks8695_gpio_direction_output(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - /* set pin as output */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x |= IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Set the state of an output GPIO line. - */ -static void ks8695_gpio_set_value(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return; - - local_irq_save(flags); - - /* set output line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - local_irq_restore(flags); -} - - -/* - * Read the state of a GPIO line. - */ -static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - return (x & IOPD(pin)) != 0; -} - - -/* - * Map GPIO line to IRQ number. - */ -static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) -{ - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - return gpio_irq[pin]; -} - -/* - * Map IRQ number to GPIO line. - */ -int irq_to_gpio(unsigned int irq) -{ - if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3)) - return -EINVAL; - - return (irq - KS8695_IRQ_EXTERN0); -} -EXPORT_SYMBOL(irq_to_gpio); - -/* GPIOLIB interface */ - -static struct gpio_chip ks8695_gpio_chip = { - .label = "KS8695", - .direction_input = ks8695_gpio_direction_input, - .direction_output = ks8695_gpio_direction_output, - .get = ks8695_gpio_get_value, - .set = ks8695_gpio_set_value, - .to_irq = ks8695_gpio_to_irq, - .base = 0, - .ngpio = 16, - .can_sleep = 0, -}; - -/* Register the GPIOs */ -void ks8695_register_gpios(void) -{ - if (gpiochip_add(&ks8695_gpio_chip)) - printk(KERN_ERR "Unable to register core GPIOs\n"); -} - -/* .... Debug interface ..................................................... */ - -#ifdef CONFIG_DEBUG_FS - -static int ks8695_gpio_show(struct seq_file *s, void *unused) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; - unsigned long mode, ctrl, data; - int i; - - mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - - seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); - - for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { - seq_printf(s, "%i:\t", i); - - seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); - - if (i <= KS8695_GPIO_3) { - if (ctrl & enable[i]) { - seq_printf(s, "EXT%i ", i); - - switch ((ctrl & intmask[i]) >> (4 * i)) { - case IOPC_TM_LOW: - seq_printf(s, "(Low)"); break; - case IOPC_TM_HIGH: - seq_printf(s, "(High)"); break; - case IOPC_TM_RISING: - seq_printf(s, "(Rising)"); break; - case IOPC_TM_FALLING: - seq_printf(s, "(Falling)"); break; - case IOPC_TM_EDGE: - seq_printf(s, "(Edges)"); break; - } - } - else - seq_printf(s, "GPIO\t"); - } - else if (i <= KS8695_GPIO_5) { - if (ctrl & enable[i]) - seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); - else - seq_printf(s, "GPIO\t"); - } - else - seq_printf(s, "GPIO\t"); - - seq_printf(s, "\t"); - - seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); - } - return 0; -} - -static int ks8695_gpio_open(struct inode *inode, struct file *file) -{ - return single_open(file, ks8695_gpio_show, NULL); -} - -static const struct file_operations ks8695_gpio_operations = { - .open = ks8695_gpio_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init ks8695_gpio_debugfs_init(void) -{ - /* /sys/kernel/debug/ks8695_gpio */ - (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations); - return 0; -} -postcore_initcall(ks8695_gpio_debugfs_init); - -#endif diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 9588948c96f0..27295cbadaf3 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -18,6 +18,7 @@ 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_MACH_KS8695) += gpio-ks8695.o obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c new file mode 100644 index 000000000000..b3fdfe1d262f --- /dev/null +++ b/drivers/gpio/gpio-ks8695.c @@ -0,0 +1,318 @@ +/* + * arch/arm/mach-ks8695/gpio.c + * + * Copyright (C) 2006 Andrew Victor + * Updated to GPIOLIB, Copyright 2008 Simtec Electronics + * Daniel Silverstone + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/* + * Configure a GPIO line for either GPIO function, or its internal + * function (Interrupt, Timer, etc). + */ +static void ks8695_gpio_mode(unsigned int pin, short gpio) +{ + unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; + unsigned long x, flags; + + if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ + return; + + local_irq_save(flags); + + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); + if (gpio) /* GPIO: set bit to 0 */ + x &= ~enable[pin]; + else /* Internal function: set bit to 1 */ + x |= enable[pin]; + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); + + local_irq_restore(flags); +} + + +static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; + +/* + * Configure GPIO pin as external interrupt source. + */ +int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ + return -EINVAL; + + local_irq_save(flags); + + /* set pin as input */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + x &= ~IOPM(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); + + local_irq_restore(flags); + + /* Set IRQ triggering type */ + irq_set_irq_type(gpio_irq[pin], type); + + /* enable interrupt mode */ + ks8695_gpio_mode(pin, 0); + + return 0; +} +EXPORT_SYMBOL(ks8695_gpio_interrupt); + + + +/* .... Generic GPIO interface .............................................. */ + +/* + * Configure the GPIO line as an input. + */ +static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_15) + return -EINVAL; + + /* set pin to GPIO mode */ + ks8695_gpio_mode(pin, 1); + + local_irq_save(flags); + + /* set pin as input */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + x &= ~IOPM(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); + + local_irq_restore(flags); + + return 0; +} + + +/* + * Configure the GPIO line as an output, with default state. + */ +static int ks8695_gpio_direction_output(struct gpio_chip *gc, + unsigned int pin, int state) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_15) + return -EINVAL; + + /* set pin to GPIO mode */ + ks8695_gpio_mode(pin, 1); + + local_irq_save(flags); + + /* set line state */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + if (state) + x |= IOPD(pin); + else + x &= ~IOPD(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); + + /* set pin as output */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + x |= IOPM(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); + + local_irq_restore(flags); + + return 0; +} + + +/* + * Set the state of an output GPIO line. + */ +static void ks8695_gpio_set_value(struct gpio_chip *gc, + unsigned int pin, int state) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_15) + return; + + local_irq_save(flags); + + /* set output line state */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + if (state) + x |= IOPD(pin); + else + x &= ~IOPD(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); + + local_irq_restore(flags); +} + + +/* + * Read the state of a GPIO line. + */ +static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) +{ + unsigned long x; + + if (pin > KS8695_GPIO_15) + return -EINVAL; + + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + return (x & IOPD(pin)) != 0; +} + + +/* + * Map GPIO line to IRQ number. + */ +static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) +{ + if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ + return -EINVAL; + + return gpio_irq[pin]; +} + +/* + * Map IRQ number to GPIO line. + */ +int irq_to_gpio(unsigned int irq) +{ + if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3)) + return -EINVAL; + + return (irq - KS8695_IRQ_EXTERN0); +} +EXPORT_SYMBOL(irq_to_gpio); + +/* GPIOLIB interface */ + +static struct gpio_chip ks8695_gpio_chip = { + .label = "KS8695", + .direction_input = ks8695_gpio_direction_input, + .direction_output = ks8695_gpio_direction_output, + .get = ks8695_gpio_get_value, + .set = ks8695_gpio_set_value, + .to_irq = ks8695_gpio_to_irq, + .base = 0, + .ngpio = 16, + .can_sleep = 0, +}; + +/* Register the GPIOs */ +void ks8695_register_gpios(void) +{ + if (gpiochip_add(&ks8695_gpio_chip)) + printk(KERN_ERR "Unable to register core GPIOs\n"); +} + +/* .... Debug interface ..................................................... */ + +#ifdef CONFIG_DEBUG_FS + +static int ks8695_gpio_show(struct seq_file *s, void *unused) +{ + unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; + unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; + unsigned long mode, ctrl, data; + int i; + + mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); + data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + + seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); + + for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { + seq_printf(s, "%i:\t", i); + + seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); + + if (i <= KS8695_GPIO_3) { + if (ctrl & enable[i]) { + seq_printf(s, "EXT%i ", i); + + switch ((ctrl & intmask[i]) >> (4 * i)) { + case IOPC_TM_LOW: + seq_printf(s, "(Low)"); break; + case IOPC_TM_HIGH: + seq_printf(s, "(High)"); break; + case IOPC_TM_RISING: + seq_printf(s, "(Rising)"); break; + case IOPC_TM_FALLING: + seq_printf(s, "(Falling)"); break; + case IOPC_TM_EDGE: + seq_printf(s, "(Edges)"); break; + } + } + else + seq_printf(s, "GPIO\t"); + } + else if (i <= KS8695_GPIO_5) { + if (ctrl & enable[i]) + seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); + else + seq_printf(s, "GPIO\t"); + } + else + seq_printf(s, "GPIO\t"); + + seq_printf(s, "\t"); + + seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); + } + return 0; +} + +static int ks8695_gpio_open(struct inode *inode, struct file *file) +{ + return single_open(file, ks8695_gpio_show, NULL); +} + +static const struct file_operations ks8695_gpio_operations = { + .open = ks8695_gpio_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init ks8695_gpio_debugfs_init(void) +{ + /* /sys/kernel/debug/ks8695_gpio */ + (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations); + return 0; +} +postcore_initcall(ks8695_gpio_debugfs_init); + +#endif -- cgit v1.2.3-59-g8ed1b From e24e4498cb4930bf785e46f98e7be7becece8b4c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:37:38 +0100 Subject: ARM: 7036/1: mach-ks8695: break out GPIO driver specifics The file is included from upper directories and deal with generic GPIO and gpiolib stuff. Break out the platform and driver specific defines and functions into its own header file. Cc: zeal Cc: Ben Dooks Acked-by: Daniel Silverstone Acked-by: Simtec Linux Team Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ks8695/board-acs5k.c | 1 + arch/arm/mach-ks8695/board-dsm320.c | 1 + arch/arm/mach-ks8695/board-micrel.c | 1 + arch/arm/mach-ks8695/include/mach/gpio-ks8695.h | 39 +++++++++++++++++++++++++ arch/arm/mach-ks8695/include/mach/gpio.h | 27 ----------------- drivers/gpio/gpio-ks8695.c | 1 + 6 files changed, 43 insertions(+), 27 deletions(-) create mode 100644 arch/arm/mach-ks8695/include/mach/gpio-ks8695.h (limited to 'drivers/gpio') diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c index dee45cbb1533..3d7d11436aa5 100644 --- a/arch/arm/mach-ks8695/board-acs5k.c +++ b/arch/arm/mach-ks8695/board-acs5k.c @@ -34,6 +34,7 @@ #include #include +#include #include "generic.h" diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c index e3ccf1a5e0d8..c3c867ac4155 100644 --- a/arch/arm/mach-ks8695/board-dsm320.c +++ b/arch/arm/mach-ks8695/board-dsm320.c @@ -29,6 +29,7 @@ #include #include +#include #include "generic.h" diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c index e8877788b85d..9b9c47cc6471 100644 --- a/arch/arm/mach-ks8695/board-micrel.c +++ b/arch/arm/mach-ks8695/board-micrel.c @@ -18,6 +18,7 @@ #include #include +#include #include #include "generic.h" diff --git a/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h b/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h new file mode 100644 index 000000000000..6eb034d60325 --- /dev/null +++ b/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006 Andrew Victor + * + * 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. + */ + +#ifndef __MACH_KS8659_GPIO_H +#define __MACH_KS8659_GPIO_H + +#include + +#define KS8695_GPIO_0 0 +#define KS8695_GPIO_1 1 +#define KS8695_GPIO_2 2 +#define KS8695_GPIO_3 3 +#define KS8695_GPIO_4 4 +#define KS8695_GPIO_5 5 +#define KS8695_GPIO_6 6 +#define KS8695_GPIO_7 7 +#define KS8695_GPIO_8 8 +#define KS8695_GPIO_9 9 +#define KS8695_GPIO_10 10 +#define KS8695_GPIO_11 11 +#define KS8695_GPIO_12 12 +#define KS8695_GPIO_13 13 +#define KS8695_GPIO_14 14 +#define KS8695_GPIO_15 15 + +/* + * Configure GPIO pin as external interrupt source. + */ +extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type); + +/* Register the GPIOs */ +extern void ks8695_register_gpios(void); + +#endif /* __MACH_KS8659_GPIO_H */ diff --git a/arch/arm/mach-ks8695/include/mach/gpio.h b/arch/arm/mach-ks8695/include/mach/gpio.h index 994267b02af8..f5fda36e4512 100644 --- a/arch/arm/mach-ks8695/include/mach/gpio.h +++ b/arch/arm/mach-ks8695/include/mach/gpio.h @@ -11,36 +11,9 @@ #ifndef __ASM_ARCH_GPIO_H_ #define __ASM_ARCH_GPIO_H_ -#include - -#define KS8695_GPIO_0 0 -#define KS8695_GPIO_1 1 -#define KS8695_GPIO_2 2 -#define KS8695_GPIO_3 3 -#define KS8695_GPIO_4 4 -#define KS8695_GPIO_5 5 -#define KS8695_GPIO_6 6 -#define KS8695_GPIO_7 7 -#define KS8695_GPIO_8 8 -#define KS8695_GPIO_9 9 -#define KS8695_GPIO_10 10 -#define KS8695_GPIO_11 11 -#define KS8695_GPIO_12 12 -#define KS8695_GPIO_13 13 -#define KS8695_GPIO_14 14 -#define KS8695_GPIO_15 15 - -/* - * Configure GPIO pin as external interrupt source. - */ -extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type); - /* * Map IRQ number to GPIO line. */ extern int irq_to_gpio(unsigned int irq); -/* Register the GPIOs */ -extern void ks8695_register_gpios(void); - #endif diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c index b3fdfe1d262f..a3ac66ea364b 100644 --- a/drivers/gpio/gpio-ks8695.c +++ b/drivers/gpio/gpio-ks8695.c @@ -31,6 +31,7 @@ #include #include +#include /* * Configure a GPIO line for either GPIO function, or its internal -- cgit v1.2.3-59-g8ed1b From 8338d87fea2c001b4f5a07f9217df89956d1fddd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:39:28 +0100 Subject: ARM: 7038/1: mach-davinci: move GPIO driver to GPIO subsystem As per example from the other ARM boards, push the DaVinci GPIO driver down to the GPIO subsystem so it can be consolidated. Cc: Sekhar Nori Cc: Kevin Hilman Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-davinci/Makefile | 2 +- arch/arm/mach-davinci/gpio.c | 458 ----------------------------------------- drivers/gpio/Makefile | 1 + drivers/gpio/gpio-davinci.c | 458 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 460 insertions(+), 459 deletions(-) delete mode 100644 arch/arm/mach-davinci/gpio.c create mode 100644 drivers/gpio/gpio-davinci.c (limited to 'drivers/gpio') diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 0b87a1ca2bb3..8f3c8ee43ffa 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -5,7 +5,7 @@ # Common objects obj-y := time.o clock.o serial.o io.o psc.o \ - gpio.o dma.o usb.o common.o sram.o aemif.o + dma.o usb.o common.o sram.o aemif.o obj-$(CONFIG_DAVINCI_MUX) += mux.o diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c deleted file mode 100644 index a8066e8edade..000000000000 --- a/arch/arm/mach-davinci/gpio.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * TI DaVinci GPIO Support - * - * Copyright (c) 2006-2007 David Brownell - * Copyright (c) 2007, MontaVista Software, Inc. - * - * 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 - -struct davinci_gpio_regs { - u32 dir; - u32 out_data; - u32 set_data; - u32 clr_data; - u32 in_data; - u32 set_rising; - u32 clr_rising; - u32 set_falling; - u32 clr_falling; - u32 intstat; -}; - -#define chip2controller(chip) \ - container_of(chip, struct davinci_gpio_controller, chip) - -static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; -static void __iomem *gpio_base; - -static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) -{ - void __iomem *ptr; - - if (gpio < 32 * 1) - ptr = gpio_base + 0x10; - else if (gpio < 32 * 2) - ptr = gpio_base + 0x38; - else if (gpio < 32 * 3) - ptr = gpio_base + 0x60; - else if (gpio < 32 * 4) - ptr = gpio_base + 0x88; - else if (gpio < 32 * 5) - ptr = gpio_base + 0xb0; - else - ptr = NULL; - return ptr; -} - -static inline struct davinci_gpio_regs __iomem *irq2regs(int irq) -{ - struct davinci_gpio_regs __iomem *g; - - g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq); - - return g; -} - -static int __init davinci_gpio_irq_setup(void); - -/*--------------------------------------------------------------------------*/ - -/* board setup code *MUST* setup pinmux and enable the GPIO clock. */ -static inline int __davinci_direction(struct gpio_chip *chip, - unsigned offset, bool out, int value) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; - unsigned long flags; - u32 temp; - u32 mask = 1 << offset; - - spin_lock_irqsave(&d->lock, flags); - temp = __raw_readl(&g->dir); - if (out) { - temp &= ~mask; - __raw_writel(mask, value ? &g->set_data : &g->clr_data); - } else { - temp |= mask; - } - __raw_writel(temp, &g->dir); - spin_unlock_irqrestore(&d->lock, flags); - - return 0; -} - -static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) -{ - return __davinci_direction(chip, offset, false, 0); -} - -static int -davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) -{ - return __davinci_direction(chip, offset, true, value); -} - -/* - * Read the pin's value (works even if it's set up as output); - * returns zero/nonzero. - * - * Note that changes are synched to the GPIO clock, so reading values back - * right after you've set them may give old values. - */ -static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; - - return (1 << offset) & __raw_readl(&g->in_data); -} - -/* - * Assuming the pin is muxed as a gpio output, set its output value. - */ -static void -davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; - - __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); -} - -static int __init davinci_gpio_setup(void) -{ - int i, base; - unsigned ngpio; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct davinci_gpio_regs *regs; - - if (soc_info->gpio_type != GPIO_TYPE_DAVINCI) - return 0; - - /* - * The gpio banks conceptually expose a segmented bitmap, - * and "ngpio" is one more than the largest zero-based - * bit index that's valid. - */ - ngpio = soc_info->gpio_num; - if (ngpio == 0) { - pr_err("GPIO setup: how many GPIOs?\n"); - return -EINVAL; - } - - if (WARN_ON(DAVINCI_N_GPIO < ngpio)) - ngpio = DAVINCI_N_GPIO; - - gpio_base = ioremap(soc_info->gpio_base, SZ_4K); - if (WARN_ON(!gpio_base)) - return -ENOMEM; - - for (i = 0, base = 0; base < ngpio; i++, base += 32) { - chips[i].chip.label = "DaVinci"; - - chips[i].chip.direction_input = davinci_direction_in; - chips[i].chip.get = davinci_gpio_get; - chips[i].chip.direction_output = davinci_direction_out; - chips[i].chip.set = davinci_gpio_set; - - chips[i].chip.base = base; - chips[i].chip.ngpio = ngpio - base; - if (chips[i].chip.ngpio > 32) - chips[i].chip.ngpio = 32; - - spin_lock_init(&chips[i].lock); - - regs = gpio2regs(base); - chips[i].regs = regs; - chips[i].set_data = ®s->set_data; - chips[i].clr_data = ®s->clr_data; - chips[i].in_data = ®s->in_data; - - gpiochip_add(&chips[i].chip); - } - - soc_info->gpio_ctlrs = chips; - soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); - - davinci_gpio_irq_setup(); - return 0; -} -pure_initcall(davinci_gpio_setup); - -/*--------------------------------------------------------------------------*/ -/* - * We expect irqs will normally be set up as input pins, but they can also be - * used as output pins ... which is convenient for testing. - * - * NOTE: The first few GPIOs also have direct INTC hookups in addition - * to their GPIOBNK0 irq, with a bit less overhead. - * - * All those INTC hookups (direct, plus several IRQ banks) can also - * serve as EDMA event triggers. - */ - -static void gpio_irq_disable(struct irq_data *d) -{ - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); - - __raw_writel(mask, &g->clr_falling); - __raw_writel(mask, &g->clr_rising); -} - -static void gpio_irq_enable(struct irq_data *d) -{ - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); - unsigned status = irqd_get_trigger_type(d); - - status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; - if (!status) - status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; - - if (status & IRQ_TYPE_EDGE_FALLING) - __raw_writel(mask, &g->set_falling); - if (status & IRQ_TYPE_EDGE_RISING) - __raw_writel(mask, &g->set_rising); -} - -static int gpio_irq_type(struct irq_data *d, unsigned trigger) -{ - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); - - if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - return -EINVAL; - - return 0; -} - -static struct irq_chip gpio_irqchip = { - .name = "GPIO", - .irq_enable = gpio_irq_enable, - .irq_disable = gpio_irq_disable, - .irq_set_type = gpio_irq_type, - .flags = IRQCHIP_SET_TYPE_MASKED, -}; - -static void -gpio_irq_handler(unsigned irq, struct irq_desc *desc) -{ - struct davinci_gpio_regs __iomem *g; - u32 mask = 0xffff; - struct davinci_gpio_controller *d; - - d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc); - g = (struct davinci_gpio_regs __iomem *)d->regs; - - /* we only care about one bank */ - if (irq & 1) - mask <<= 16; - - /* temporarily mask (level sensitive) parent IRQ */ - desc->irq_data.chip->irq_mask(&desc->irq_data); - desc->irq_data.chip->irq_ack(&desc->irq_data); - while (1) { - u32 status; - int n; - int res; - - /* ack any irqs */ - status = __raw_readl(&g->intstat) & mask; - if (!status) - break; - __raw_writel(status, &g->intstat); - - /* now demux them to the right lowlevel handler */ - n = d->irq_base; - if (irq & 1) { - n += 16; - status >>= 16; - } - - while (status) { - res = ffs(status); - n += res; - generic_handle_irq(n - 1); - status >>= res; - } - } - desc->irq_data.chip->irq_unmask(&desc->irq_data); - /* now it may re-trigger */ -} - -static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - - if (d->irq_base >= 0) - return d->irq_base + offset; - else - return -ENODEV; -} - -static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_soc_info *soc_info = &davinci_soc_info; - - /* NOTE: we assume for now that only irqs in the first gpio_chip - * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). - */ - if (offset < soc_info->gpio_unbanked) - return soc_info->gpio_irq + offset; - else - return -ENODEV; -} - -static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger) -{ - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); - - if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - return -EINVAL; - - __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) - ? &g->set_falling : &g->clr_falling); - __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) - ? &g->set_rising : &g->clr_rising); - - return 0; -} - -/* - * NOTE: for suspend/resume, probably best to make a platform_device with - * suspend_late/resume_resume calls hooking into results of the set_wake() - * calls ... so if no gpios are wakeup events the clock can be disabled, - * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0 - * (dm6446) can be set appropriately for GPIOV33 pins. - */ - -static int __init davinci_gpio_irq_setup(void) -{ - unsigned gpio, irq, bank; - struct clk *clk; - u32 binten = 0; - unsigned ngpio, bank_irq; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct davinci_gpio_regs __iomem *g; - - ngpio = soc_info->gpio_num; - - bank_irq = soc_info->gpio_irq; - if (bank_irq == 0) { - printk(KERN_ERR "Don't know first GPIO bank IRQ.\n"); - return -EINVAL; - } - - clk = clk_get(NULL, "gpio"); - if (IS_ERR(clk)) { - printk(KERN_ERR "Error %ld getting gpio clock?\n", - PTR_ERR(clk)); - return PTR_ERR(clk); - } - clk_enable(clk); - - /* Arrange gpio_to_irq() support, handling either direct IRQs or - * banked IRQs. Having GPIOs in the first GPIO bank use direct - * IRQs, while the others use banked IRQs, would need some setup - * tweaks to recognize hardware which can do that. - */ - for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { - chips[bank].chip.to_irq = gpio_to_irq_banked; - chips[bank].irq_base = soc_info->gpio_unbanked - ? -EINVAL - : (soc_info->intc_irq_num + gpio); - } - - /* - * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO - * controller only handling trigger modes. We currently assume no - * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. - */ - if (soc_info->gpio_unbanked) { - static struct irq_chip gpio_irqchip_unbanked; - - /* pass "bank 0" GPIO IRQs to AINTC */ - chips[0].chip.to_irq = gpio_to_irq_unbanked; - binten = BIT(0); - - /* AINTC handles mask/unmask; GPIO handles triggering */ - irq = bank_irq; - gpio_irqchip_unbanked = *irq_get_chip(irq); - gpio_irqchip_unbanked.name = "GPIO-AINTC"; - gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked; - - /* default trigger: both edges */ - g = gpio2regs(0); - __raw_writel(~0, &g->set_falling); - __raw_writel(~0, &g->set_rising); - - /* set the direct IRQs up to use that irqchip */ - for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { - irq_set_chip(irq, &gpio_irqchip_unbanked); - irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); - irq_set_chip_data(irq, (__force void *)g); - irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); - } - - goto done; - } - - /* - * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we - * then chain through our own handler. - */ - for (gpio = 0, irq = gpio_to_irq(0), bank = 0; - gpio < ngpio; - bank++, bank_irq++) { - unsigned i; - - /* disabled by default, enabled only as needed */ - g = gpio2regs(gpio); - __raw_writel(~0, &g->clr_falling); - __raw_writel(~0, &g->clr_rising); - - /* set up all irqs in this bank */ - irq_set_chained_handler(bank_irq, gpio_irq_handler); - - /* - * Each chip handles 32 gpios, and each irq bank consists of 16 - * gpio irqs. Pass the irq bank's corresponding controller to - * the chained irq handler. - */ - irq_set_handler_data(bank_irq, &chips[gpio / 32]); - - for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { - irq_set_chip(irq, &gpio_irqchip); - irq_set_chip_data(irq, (__force void *)g); - irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); - irq_set_handler(irq, handle_simple_irq); - set_irq_flags(irq, IRQF_VALID); - } - - binten |= BIT(bank); - } - -done: - /* BINTEN -- per-bank interrupt enable. genirq would also let these - * bits be set/cleared dynamically. - */ - __raw_writel(binten, gpio_base + 0x08); - - printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); - - return 0; -} diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 27295cbadaf3..a26fffacdfa5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -14,6 +14,7 @@ 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_ARCH_DAVINCI) += gpio-davinci.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-davinci.c b/drivers/gpio/gpio-davinci.c new file mode 100644 index 000000000000..a8066e8edade --- /dev/null +++ b/drivers/gpio/gpio-davinci.c @@ -0,0 +1,458 @@ +/* + * TI DaVinci GPIO Support + * + * Copyright (c) 2006-2007 David Brownell + * Copyright (c) 2007, MontaVista Software, Inc. + * + * 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 + +struct davinci_gpio_regs { + u32 dir; + u32 out_data; + u32 set_data; + u32 clr_data; + u32 in_data; + u32 set_rising; + u32 clr_rising; + u32 set_falling; + u32 clr_falling; + u32 intstat; +}; + +#define chip2controller(chip) \ + container_of(chip, struct davinci_gpio_controller, chip) + +static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; +static void __iomem *gpio_base; + +static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) +{ + void __iomem *ptr; + + if (gpio < 32 * 1) + ptr = gpio_base + 0x10; + else if (gpio < 32 * 2) + ptr = gpio_base + 0x38; + else if (gpio < 32 * 3) + ptr = gpio_base + 0x60; + else if (gpio < 32 * 4) + ptr = gpio_base + 0x88; + else if (gpio < 32 * 5) + ptr = gpio_base + 0xb0; + else + ptr = NULL; + return ptr; +} + +static inline struct davinci_gpio_regs __iomem *irq2regs(int irq) +{ + struct davinci_gpio_regs __iomem *g; + + g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq); + + return g; +} + +static int __init davinci_gpio_irq_setup(void); + +/*--------------------------------------------------------------------------*/ + +/* board setup code *MUST* setup pinmux and enable the GPIO clock. */ +static inline int __davinci_direction(struct gpio_chip *chip, + unsigned offset, bool out, int value) +{ + struct davinci_gpio_controller *d = chip2controller(chip); + struct davinci_gpio_regs __iomem *g = d->regs; + unsigned long flags; + u32 temp; + u32 mask = 1 << offset; + + spin_lock_irqsave(&d->lock, flags); + temp = __raw_readl(&g->dir); + if (out) { + temp &= ~mask; + __raw_writel(mask, value ? &g->set_data : &g->clr_data); + } else { + temp |= mask; + } + __raw_writel(temp, &g->dir); + spin_unlock_irqrestore(&d->lock, flags); + + return 0; +} + +static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) +{ + return __davinci_direction(chip, offset, false, 0); +} + +static int +davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) +{ + return __davinci_direction(chip, offset, true, value); +} + +/* + * Read the pin's value (works even if it's set up as output); + * returns zero/nonzero. + * + * Note that changes are synched to the GPIO clock, so reading values back + * right after you've set them may give old values. + */ +static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_gpio_controller *d = chip2controller(chip); + struct davinci_gpio_regs __iomem *g = d->regs; + + return (1 << offset) & __raw_readl(&g->in_data); +} + +/* + * Assuming the pin is muxed as a gpio output, set its output value. + */ +static void +davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct davinci_gpio_controller *d = chip2controller(chip); + struct davinci_gpio_regs __iomem *g = d->regs; + + __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); +} + +static int __init davinci_gpio_setup(void) +{ + int i, base; + unsigned ngpio; + struct davinci_soc_info *soc_info = &davinci_soc_info; + struct davinci_gpio_regs *regs; + + if (soc_info->gpio_type != GPIO_TYPE_DAVINCI) + return 0; + + /* + * The gpio banks conceptually expose a segmented bitmap, + * and "ngpio" is one more than the largest zero-based + * bit index that's valid. + */ + ngpio = soc_info->gpio_num; + if (ngpio == 0) { + pr_err("GPIO setup: how many GPIOs?\n"); + return -EINVAL; + } + + if (WARN_ON(DAVINCI_N_GPIO < ngpio)) + ngpio = DAVINCI_N_GPIO; + + gpio_base = ioremap(soc_info->gpio_base, SZ_4K); + if (WARN_ON(!gpio_base)) + return -ENOMEM; + + for (i = 0, base = 0; base < ngpio; i++, base += 32) { + chips[i].chip.label = "DaVinci"; + + chips[i].chip.direction_input = davinci_direction_in; + chips[i].chip.get = davinci_gpio_get; + chips[i].chip.direction_output = davinci_direction_out; + chips[i].chip.set = davinci_gpio_set; + + chips[i].chip.base = base; + chips[i].chip.ngpio = ngpio - base; + if (chips[i].chip.ngpio > 32) + chips[i].chip.ngpio = 32; + + spin_lock_init(&chips[i].lock); + + regs = gpio2regs(base); + chips[i].regs = regs; + chips[i].set_data = ®s->set_data; + chips[i].clr_data = ®s->clr_data; + chips[i].in_data = ®s->in_data; + + gpiochip_add(&chips[i].chip); + } + + soc_info->gpio_ctlrs = chips; + soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); + + davinci_gpio_irq_setup(); + return 0; +} +pure_initcall(davinci_gpio_setup); + +/*--------------------------------------------------------------------------*/ +/* + * We expect irqs will normally be set up as input pins, but they can also be + * used as output pins ... which is convenient for testing. + * + * NOTE: The first few GPIOs also have direct INTC hookups in addition + * to their GPIOBNK0 irq, with a bit less overhead. + * + * All those INTC hookups (direct, plus several IRQ banks) can also + * serve as EDMA event triggers. + */ + +static void gpio_irq_disable(struct irq_data *d) +{ + struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); + u32 mask = (u32) irq_data_get_irq_handler_data(d); + + __raw_writel(mask, &g->clr_falling); + __raw_writel(mask, &g->clr_rising); +} + +static void gpio_irq_enable(struct irq_data *d) +{ + struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); + u32 mask = (u32) irq_data_get_irq_handler_data(d); + unsigned status = irqd_get_trigger_type(d); + + status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; + if (!status) + status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; + + if (status & IRQ_TYPE_EDGE_FALLING) + __raw_writel(mask, &g->set_falling); + if (status & IRQ_TYPE_EDGE_RISING) + __raw_writel(mask, &g->set_rising); +} + +static int gpio_irq_type(struct irq_data *d, unsigned trigger) +{ + struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); + u32 mask = (u32) irq_data_get_irq_handler_data(d); + + if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + return -EINVAL; + + return 0; +} + +static struct irq_chip gpio_irqchip = { + .name = "GPIO", + .irq_enable = gpio_irq_enable, + .irq_disable = gpio_irq_disable, + .irq_set_type = gpio_irq_type, + .flags = IRQCHIP_SET_TYPE_MASKED, +}; + +static void +gpio_irq_handler(unsigned irq, struct irq_desc *desc) +{ + struct davinci_gpio_regs __iomem *g; + u32 mask = 0xffff; + struct davinci_gpio_controller *d; + + d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc); + g = (struct davinci_gpio_regs __iomem *)d->regs; + + /* we only care about one bank */ + if (irq & 1) + mask <<= 16; + + /* temporarily mask (level sensitive) parent IRQ */ + desc->irq_data.chip->irq_mask(&desc->irq_data); + desc->irq_data.chip->irq_ack(&desc->irq_data); + while (1) { + u32 status; + int n; + int res; + + /* ack any irqs */ + status = __raw_readl(&g->intstat) & mask; + if (!status) + break; + __raw_writel(status, &g->intstat); + + /* now demux them to the right lowlevel handler */ + n = d->irq_base; + if (irq & 1) { + n += 16; + status >>= 16; + } + + while (status) { + res = ffs(status); + n += res; + generic_handle_irq(n - 1); + status >>= res; + } + } + desc->irq_data.chip->irq_unmask(&desc->irq_data); + /* now it may re-trigger */ +} + +static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_gpio_controller *d = chip2controller(chip); + + if (d->irq_base >= 0) + return d->irq_base + offset; + else + return -ENODEV; +} + +static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_soc_info *soc_info = &davinci_soc_info; + + /* NOTE: we assume for now that only irqs in the first gpio_chip + * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). + */ + if (offset < soc_info->gpio_unbanked) + return soc_info->gpio_irq + offset; + else + return -ENODEV; +} + +static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger) +{ + struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); + u32 mask = (u32) irq_data_get_irq_handler_data(d); + + if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + return -EINVAL; + + __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) + ? &g->set_falling : &g->clr_falling); + __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) + ? &g->set_rising : &g->clr_rising); + + return 0; +} + +/* + * NOTE: for suspend/resume, probably best to make a platform_device with + * suspend_late/resume_resume calls hooking into results of the set_wake() + * calls ... so if no gpios are wakeup events the clock can be disabled, + * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0 + * (dm6446) can be set appropriately for GPIOV33 pins. + */ + +static int __init davinci_gpio_irq_setup(void) +{ + unsigned gpio, irq, bank; + struct clk *clk; + u32 binten = 0; + unsigned ngpio, bank_irq; + struct davinci_soc_info *soc_info = &davinci_soc_info; + struct davinci_gpio_regs __iomem *g; + + ngpio = soc_info->gpio_num; + + bank_irq = soc_info->gpio_irq; + if (bank_irq == 0) { + printk(KERN_ERR "Don't know first GPIO bank IRQ.\n"); + return -EINVAL; + } + + clk = clk_get(NULL, "gpio"); + if (IS_ERR(clk)) { + printk(KERN_ERR "Error %ld getting gpio clock?\n", + PTR_ERR(clk)); + return PTR_ERR(clk); + } + clk_enable(clk); + + /* Arrange gpio_to_irq() support, handling either direct IRQs or + * banked IRQs. Having GPIOs in the first GPIO bank use direct + * IRQs, while the others use banked IRQs, would need some setup + * tweaks to recognize hardware which can do that. + */ + for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { + chips[bank].chip.to_irq = gpio_to_irq_banked; + chips[bank].irq_base = soc_info->gpio_unbanked + ? -EINVAL + : (soc_info->intc_irq_num + gpio); + } + + /* + * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO + * controller only handling trigger modes. We currently assume no + * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. + */ + if (soc_info->gpio_unbanked) { + static struct irq_chip gpio_irqchip_unbanked; + + /* pass "bank 0" GPIO IRQs to AINTC */ + chips[0].chip.to_irq = gpio_to_irq_unbanked; + binten = BIT(0); + + /* AINTC handles mask/unmask; GPIO handles triggering */ + irq = bank_irq; + gpio_irqchip_unbanked = *irq_get_chip(irq); + gpio_irqchip_unbanked.name = "GPIO-AINTC"; + gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked; + + /* default trigger: both edges */ + g = gpio2regs(0); + __raw_writel(~0, &g->set_falling); + __raw_writel(~0, &g->set_rising); + + /* set the direct IRQs up to use that irqchip */ + for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { + irq_set_chip(irq, &gpio_irqchip_unbanked); + irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); + irq_set_chip_data(irq, (__force void *)g); + irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); + } + + goto done; + } + + /* + * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we + * then chain through our own handler. + */ + for (gpio = 0, irq = gpio_to_irq(0), bank = 0; + gpio < ngpio; + bank++, bank_irq++) { + unsigned i; + + /* disabled by default, enabled only as needed */ + g = gpio2regs(gpio); + __raw_writel(~0, &g->clr_falling); + __raw_writel(~0, &g->clr_rising); + + /* set up all irqs in this bank */ + irq_set_chained_handler(bank_irq, gpio_irq_handler); + + /* + * Each chip handles 32 gpios, and each irq bank consists of 16 + * gpio irqs. Pass the irq bank's corresponding controller to + * the chained irq handler. + */ + irq_set_handler_data(bank_irq, &chips[gpio / 32]); + + for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { + irq_set_chip(irq, &gpio_irqchip); + irq_set_chip_data(irq, (__force void *)g); + irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); + irq_set_handler(irq, handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); + } + + binten |= BIT(bank); + } + +done: + /* BINTEN -- per-bank interrupt enable. genirq would also let these + * bits be set/cleared dynamically. + */ + __raw_writel(binten, gpio_base + 0x08); + + printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); + + return 0; +} -- cgit v1.2.3-59-g8ed1b From bd08d709c4a44089a9d87a3b402a54c1d6b8890b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:40:10 +0100 Subject: ARM: 7039/1: mach-davinci: move DaVinci TNET GPIO driver to GPIO subsystem As per example from the other ARM boards, push the DaVinci TNET GPIO driver down to the GPIO subsystem so it can be consolidated. Cc: Sekhar Nori Cc: Kevin Hilman Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-davinci/Makefile | 1 - arch/arm/mach-davinci/gpio-tnetv107x.c | 205 --------------------------------- drivers/gpio/Makefile | 1 + drivers/gpio/gpio-tnetv107x.c | 205 +++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+), 206 deletions(-) delete mode 100644 arch/arm/mach-davinci/gpio-tnetv107x.c create mode 100644 drivers/gpio/gpio-tnetv107x.c (limited to 'drivers/gpio') diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 8f3c8ee43ffa..495e31306fc0 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -17,7 +17,6 @@ obj-$(CONFIG_ARCH_DAVINCI_DM365) += dm365.o devices.o obj-$(CONFIG_ARCH_DAVINCI_DA830) += da830.o devices-da8xx.o obj-$(CONFIG_ARCH_DAVINCI_DA850) += da850.o devices-da8xx.o obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += tnetv107x.o devices-tnetv107x.o -obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o obj-$(CONFIG_AINTC) += irq.o obj-$(CONFIG_CP_INTC) += cp_intc.o diff --git a/arch/arm/mach-davinci/gpio-tnetv107x.c b/arch/arm/mach-davinci/gpio-tnetv107x.c deleted file mode 100644 index 3fa3e2867e19..000000000000 --- a/arch/arm/mach-davinci/gpio-tnetv107x.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Texas Instruments TNETV107X GPIO Controller - * - * Copyright (C) 2010 Texas Instruments - * - * 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include - -#include -#include - -struct tnetv107x_gpio_regs { - u32 idver; - u32 data_in[3]; - u32 data_out[3]; - u32 direction[3]; - u32 enable[3]; -}; - -#define gpio_reg_index(gpio) ((gpio) >> 5) -#define gpio_reg_bit(gpio) BIT((gpio) & 0x1f) - -#define gpio_reg_rmw(reg, mask, val) \ - __raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg)) - -#define gpio_reg_set_bit(reg, gpio) \ - gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio)) - -#define gpio_reg_clear_bit(reg, gpio) \ - gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0) - -#define gpio_reg_get_bit(reg, gpio) \ - (__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio)) - -#define chip2controller(chip) \ - container_of(chip, struct davinci_gpio_controller, chip) - -#define TNETV107X_GPIO_CTLRS DIV_ROUND_UP(TNETV107X_N_GPIO, 32) - -static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS]; - -static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - gpio_reg_set_bit(regs->enable, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); - - return 0; -} - -static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - gpio_reg_clear_bit(regs->enable, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); -} - -static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - gpio_reg_set_bit(regs->direction, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); - - return 0; -} - -static int tnetv107x_gpio_dir_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - if (value) - gpio_reg_set_bit(regs->data_out, gpio); - else - gpio_reg_clear_bit(regs->data_out, gpio); - - gpio_reg_clear_bit(regs->direction, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); - - return 0; -} - -static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - int ret; - - ret = gpio_reg_get_bit(regs->data_in, gpio); - - return ret ? 1 : 0; -} - -static void tnetv107x_gpio_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - if (value) - gpio_reg_set_bit(regs->data_out, gpio); - else - gpio_reg_clear_bit(regs->data_out, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); -} - -static int __init tnetv107x_gpio_setup(void) -{ - int i, base; - unsigned ngpio; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct tnetv107x_gpio_regs *regs; - struct davinci_gpio_controller *ctlr; - - if (soc_info->gpio_type != GPIO_TYPE_TNETV107X) - return 0; - - ngpio = soc_info->gpio_num; - if (ngpio == 0) { - pr_err("GPIO setup: how many GPIOs?\n"); - return -EINVAL; - } - - if (WARN_ON(TNETV107X_N_GPIO < ngpio)) - ngpio = TNETV107X_N_GPIO; - - regs = ioremap(soc_info->gpio_base, SZ_4K); - if (WARN_ON(!regs)) - return -EINVAL; - - for (i = 0, base = 0; base < ngpio; i++, base += 32) { - ctlr = &chips[i]; - - ctlr->chip.label = "tnetv107x"; - ctlr->chip.can_sleep = 0; - ctlr->chip.base = base; - ctlr->chip.ngpio = ngpio - base; - if (ctlr->chip.ngpio > 32) - ctlr->chip.ngpio = 32; - - ctlr->chip.request = tnetv107x_gpio_request; - ctlr->chip.free = tnetv107x_gpio_free; - ctlr->chip.direction_input = tnetv107x_gpio_dir_in; - ctlr->chip.get = tnetv107x_gpio_get; - ctlr->chip.direction_output = tnetv107x_gpio_dir_out; - ctlr->chip.set = tnetv107x_gpio_set; - - spin_lock_init(&ctlr->lock); - - ctlr->regs = regs; - ctlr->set_data = ®s->data_out[i]; - ctlr->clr_data = ®s->data_out[i]; - ctlr->in_data = ®s->data_in[i]; - - gpiochip_add(&ctlr->chip); - } - - soc_info->gpio_ctlrs = chips; - soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); - return 0; -} -pure_initcall(tnetv107x_gpio_setup); diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a26fffacdfa5..226982277330 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o +obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o diff --git a/drivers/gpio/gpio-tnetv107x.c b/drivers/gpio/gpio-tnetv107x.c new file mode 100644 index 000000000000..3fa3e2867e19 --- /dev/null +++ b/drivers/gpio/gpio-tnetv107x.c @@ -0,0 +1,205 @@ +/* + * Texas Instruments TNETV107X GPIO Controller + * + * Copyright (C) 2010 Texas Instruments + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include + +#include +#include + +struct tnetv107x_gpio_regs { + u32 idver; + u32 data_in[3]; + u32 data_out[3]; + u32 direction[3]; + u32 enable[3]; +}; + +#define gpio_reg_index(gpio) ((gpio) >> 5) +#define gpio_reg_bit(gpio) BIT((gpio) & 0x1f) + +#define gpio_reg_rmw(reg, mask, val) \ + __raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg)) + +#define gpio_reg_set_bit(reg, gpio) \ + gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio)) + +#define gpio_reg_clear_bit(reg, gpio) \ + gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0) + +#define gpio_reg_get_bit(reg, gpio) \ + (__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio)) + +#define chip2controller(chip) \ + container_of(chip, struct davinci_gpio_controller, chip) + +#define TNETV107X_GPIO_CTLRS DIV_ROUND_UP(TNETV107X_N_GPIO, 32) + +static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS]; + +static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_gpio_controller *ctlr = chip2controller(chip); + struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; + unsigned gpio = chip->base + offset; + unsigned long flags; + + spin_lock_irqsave(&ctlr->lock, flags); + + gpio_reg_set_bit(regs->enable, gpio); + + spin_unlock_irqrestore(&ctlr->lock, flags); + + return 0; +} + +static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_gpio_controller *ctlr = chip2controller(chip); + struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; + unsigned gpio = chip->base + offset; + unsigned long flags; + + spin_lock_irqsave(&ctlr->lock, flags); + + gpio_reg_clear_bit(regs->enable, gpio); + + spin_unlock_irqrestore(&ctlr->lock, flags); +} + +static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_gpio_controller *ctlr = chip2controller(chip); + struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; + unsigned gpio = chip->base + offset; + unsigned long flags; + + spin_lock_irqsave(&ctlr->lock, flags); + + gpio_reg_set_bit(regs->direction, gpio); + + spin_unlock_irqrestore(&ctlr->lock, flags); + + return 0; +} + +static int tnetv107x_gpio_dir_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct davinci_gpio_controller *ctlr = chip2controller(chip); + struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; + unsigned gpio = chip->base + offset; + unsigned long flags; + + spin_lock_irqsave(&ctlr->lock, flags); + + if (value) + gpio_reg_set_bit(regs->data_out, gpio); + else + gpio_reg_clear_bit(regs->data_out, gpio); + + gpio_reg_clear_bit(regs->direction, gpio); + + spin_unlock_irqrestore(&ctlr->lock, flags); + + return 0; +} + +static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_gpio_controller *ctlr = chip2controller(chip); + struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; + unsigned gpio = chip->base + offset; + int ret; + + ret = gpio_reg_get_bit(regs->data_in, gpio); + + return ret ? 1 : 0; +} + +static void tnetv107x_gpio_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct davinci_gpio_controller *ctlr = chip2controller(chip); + struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; + unsigned gpio = chip->base + offset; + unsigned long flags; + + spin_lock_irqsave(&ctlr->lock, flags); + + if (value) + gpio_reg_set_bit(regs->data_out, gpio); + else + gpio_reg_clear_bit(regs->data_out, gpio); + + spin_unlock_irqrestore(&ctlr->lock, flags); +} + +static int __init tnetv107x_gpio_setup(void) +{ + int i, base; + unsigned ngpio; + struct davinci_soc_info *soc_info = &davinci_soc_info; + struct tnetv107x_gpio_regs *regs; + struct davinci_gpio_controller *ctlr; + + if (soc_info->gpio_type != GPIO_TYPE_TNETV107X) + return 0; + + ngpio = soc_info->gpio_num; + if (ngpio == 0) { + pr_err("GPIO setup: how many GPIOs?\n"); + return -EINVAL; + } + + if (WARN_ON(TNETV107X_N_GPIO < ngpio)) + ngpio = TNETV107X_N_GPIO; + + regs = ioremap(soc_info->gpio_base, SZ_4K); + if (WARN_ON(!regs)) + return -EINVAL; + + for (i = 0, base = 0; base < ngpio; i++, base += 32) { + ctlr = &chips[i]; + + ctlr->chip.label = "tnetv107x"; + ctlr->chip.can_sleep = 0; + ctlr->chip.base = base; + ctlr->chip.ngpio = ngpio - base; + if (ctlr->chip.ngpio > 32) + ctlr->chip.ngpio = 32; + + ctlr->chip.request = tnetv107x_gpio_request; + ctlr->chip.free = tnetv107x_gpio_free; + ctlr->chip.direction_input = tnetv107x_gpio_dir_in; + ctlr->chip.get = tnetv107x_gpio_get; + ctlr->chip.direction_output = tnetv107x_gpio_dir_out; + ctlr->chip.set = tnetv107x_gpio_set; + + spin_lock_init(&ctlr->lock); + + ctlr->regs = regs; + ctlr->set_data = ®s->data_out[i]; + ctlr->clr_data = ®s->data_out[i]; + ctlr->in_data = ®s->data_in[i]; + + gpiochip_add(&ctlr->chip); + } + + soc_info->gpio_ctlrs = chips; + soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); + return 0; +} +pure_initcall(tnetv107x_gpio_setup); -- cgit v1.2.3-59-g8ed1b From 257af9f9725aa8a863b306659208a031135d59e7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:43:04 +0100 Subject: ARM: 7041/1: gpio-ep93xx: hookup the to_irq callback in the driver Remove the ep93xx machine specific dependencies for gpio_to_irq() by hooking up the callback in the driver and using __gpio_to_irq. Signed-off-by: H Hartley Sweeten Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ep93xx/include/mach/gpio.h | 9 +-------- drivers/gpio/gpio-ep93xx.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h index 071f676c6e09..76c68faca943 100644 --- a/arch/arm/mach-ep93xx/include/mach/gpio.h +++ b/arch/arm/mach-ep93xx/include/mach/gpio.h @@ -99,14 +99,7 @@ /* maximum value for irq capable line identifiers */ #define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) -/* - * Map GPIO A0..A7 (0..7) to irq 64..71, - * B0..B7 (7..15) to irq 72..79, and - * F0..F7 (16..24) to irq 80..87. - */ -#define gpio_to_irq(gpio) \ - (((gpio) <= EP93XX_GPIO_LINE_MAX_IRQ) ? (64 + (gpio)) : -EINVAL) - +#define gpio_to_irq __gpio_to_irq #define irq_to_gpio(irq) ((irq) - gpio_to_irq(0)) #endif diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 72fb9c665320..fbd6a6066777 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -307,6 +307,21 @@ static int ep93xx_gpio_set_debounce(struct gpio_chip *chip, return 0; } +/* + * Map GPIO A0..A7 (0..7) to irq 64..71, + * B0..B7 (7..15) to irq 72..79, and + * F0..F7 (16..24) to irq 80..87. + */ +static int ep93xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + + if (gpio > EP93XX_GPIO_LINE_MAX_IRQ) + return -EINVAL; + + return 64 + gpio; +} + static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev, void __iomem *mmio_base, struct ep93xx_gpio_bank *bank) { @@ -321,8 +336,10 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev, bgc->gc.label = bank->label; bgc->gc.base = bank->base; - if (bank->has_debounce) + if (bank->has_debounce) { bgc->gc.set_debounce = ep93xx_gpio_set_debounce; + bgc->gc.to_irq = ep93xx_gpio_to_irq; + } return gpiochip_add(&bgc->gc); } -- cgit v1.2.3-59-g8ed1b From f80cb526e301ab625dd04f6137f9995607348ce3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:44:45 +0100 Subject: ARM: 7044/1: mach-lpc32xx: move LPC32XX GPIO driver to GPIO subsystem As per example from the other ARM boards, push the LPC32XX GPIO driver down to the GPIO subsystem so it can be consolidated. Cc: Wolfram Sang Cc: Barry Song Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-lpc32xx/Makefile | 2 +- arch/arm/mach-lpc32xx/gpiolib.c | 446 ---------------------------------------- drivers/gpio/Makefile | 1 + drivers/gpio/gpio-lpc32xx.c | 445 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 447 insertions(+), 447 deletions(-) delete mode 100644 arch/arm/mach-lpc32xx/gpiolib.c create mode 100644 drivers/gpio/gpio-lpc32xx.c (limited to 'drivers/gpio') diff --git a/arch/arm/mach-lpc32xx/Makefile b/arch/arm/mach-lpc32xx/Makefile index a5fc5d0eeaeb..f5db805ab958 100644 --- a/arch/arm/mach-lpc32xx/Makefile +++ b/arch/arm/mach-lpc32xx/Makefile @@ -3,6 +3,6 @@ # obj-y := timer.o irq.o common.o serial.o clock.o -obj-y += gpiolib.o pm.o suspend.o +obj-y += pm.o suspend.o obj-y += phy3250.o diff --git a/arch/arm/mach-lpc32xx/gpiolib.c b/arch/arm/mach-lpc32xx/gpiolib.c deleted file mode 100644 index 69061ea8997a..000000000000 --- a/arch/arm/mach-lpc32xx/gpiolib.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * arch/arm/mach-lpc32xx/gpiolib.c - * - * Author: Kevin Wells - * - * Copyright (C) 2010 NXP Semiconductors - * - * 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. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include "common.h" - -#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) -#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) -#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008) -#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C) -#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010) -#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014) -#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018) -#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C) -#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020) -#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024) -#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028) -#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C) -#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030) -#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040) -#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044) -#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048) -#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C) -#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050) -#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054) -#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058) -#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060) -#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064) -#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068) -#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C) -#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070) -#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074) -#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078) - -#define GPIO012_PIN_TO_BIT(x) (1 << (x)) -#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25)) -#define GPO3_PIN_TO_BIT(x) (1 << (x)) -#define GPIO012_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) -#define GPIO3_PIN_IN_SHIFT(x) ((x) == 5 ? 24 : 10 + (x)) -#define GPIO3_PIN_IN_SEL(x, y) ((x) >> GPIO3_PIN_IN_SHIFT(y)) -#define GPIO3_PIN5_IN_SEL(x) (((x) >> 24) & 1) -#define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) - -struct gpio_regs { - void __iomem *inp_state; - void __iomem *outp_set; - void __iomem *outp_clr; - void __iomem *dir_set; - void __iomem *dir_clr; -}; - -/* - * GPIO names - */ -static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = { - "p0.0", "p0.1", "p0.2", "p0.3", - "p0.4", "p0.5", "p0.6", "p0.7" -}; - -static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = { - "p1.0", "p1.1", "p1.2", "p1.3", - "p1.4", "p1.5", "p1.6", "p1.7", - "p1.8", "p1.9", "p1.10", "p1.11", - "p1.12", "p1.13", "p1.14", "p1.15", - "p1.16", "p1.17", "p1.18", "p1.19", - "p1.20", "p1.21", "p1.22", "p1.23", -}; - -static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = { - "p2.0", "p2.1", "p2.2", "p2.3", - "p2.4", "p2.5", "p2.6", "p2.7", - "p2.8", "p2.9", "p2.10", "p2.11", - "p2.12" -}; - -static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = { - "gpi000", "gpio01", "gpio02", "gpio03", - "gpio04", "gpio05" -}; - -static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = { - "gpi00", "gpi01", "gpi02", "gpi03", - "gpi04", "gpi05", "gpi06", "gpi07", - "gpi08", "gpi09", NULL, NULL, - NULL, NULL, NULL, "gpi15", - "gpi16", "gpi17", "gpi18", "gpi19", - "gpi20", "gpi21", "gpi22", "gpi23", - "gpi24", "gpi25", "gpi26", "gpi27" -}; - -static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = { - "gpo00", "gpo01", "gpo02", "gpo03", - "gpo04", "gpo05", "gpo06", "gpo07", - "gpo08", "gpo09", "gpo10", "gpo11", - "gpo12", "gpo13", "gpo14", "gpo15", - "gpo16", "gpo17", "gpo18", "gpo19", - "gpo20", "gpo21", "gpo22", "gpo23" -}; - -static struct gpio_regs gpio_grp_regs_p0 = { - .inp_state = LPC32XX_GPIO_P0_INP_STATE, - .outp_set = LPC32XX_GPIO_P0_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P0_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P0_DIR_SET, - .dir_clr = LPC32XX_GPIO_P0_DIR_CLR, -}; - -static struct gpio_regs gpio_grp_regs_p1 = { - .inp_state = LPC32XX_GPIO_P1_INP_STATE, - .outp_set = LPC32XX_GPIO_P1_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P1_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P1_DIR_SET, - .dir_clr = LPC32XX_GPIO_P1_DIR_CLR, -}; - -static struct gpio_regs gpio_grp_regs_p2 = { - .inp_state = LPC32XX_GPIO_P2_INP_STATE, - .outp_set = LPC32XX_GPIO_P2_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P2_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P2_DIR_SET, - .dir_clr = LPC32XX_GPIO_P2_DIR_CLR, -}; - -static struct gpio_regs gpio_grp_regs_p3 = { - .inp_state = LPC32XX_GPIO_P3_INP_STATE, - .outp_set = LPC32XX_GPIO_P3_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P3_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P2_DIR_SET, - .dir_clr = LPC32XX_GPIO_P2_DIR_CLR, -}; - -struct lpc32xx_gpio_chip { - struct gpio_chip chip; - struct gpio_regs *gpio_grp; -}; - -static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio( - struct gpio_chip *gpc) -{ - return container_of(gpc, struct lpc32xx_gpio_chip, chip); -} - -static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group, - unsigned pin, int input) -{ - if (input) - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->dir_clr); - else - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->dir_set); -} - -static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group, - unsigned pin, int input) -{ - u32 u = GPIO3_PIN_TO_BIT(pin); - - if (input) - __raw_writel(u, group->gpio_grp->dir_clr); - else - __raw_writel(u, group->gpio_grp->dir_set); -} - -static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group, - unsigned pin, int high) -{ - if (high) - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->outp_set); - else - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->outp_clr); -} - -static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group, - unsigned pin, int high) -{ - u32 u = GPIO3_PIN_TO_BIT(pin); - - if (high) - __raw_writel(u, group->gpio_grp->outp_set); - else - __raw_writel(u, group->gpio_grp->outp_clr); -} - -static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group, - unsigned pin, int high) -{ - if (high) - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); - else - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); -} - -static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group, - unsigned pin) -{ - return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), - pin); -} - -static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, - unsigned pin) -{ - int state = __raw_readl(group->gpio_grp->inp_state); - - /* - * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped - * to bits 10..14, while GPIOP3-5 is mapped to bit 24. - */ - return GPIO3_PIN_IN_SEL(state, pin); -} - -static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, - unsigned pin) -{ - return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin); -} - -/* - * GENERIC_GPIO primitives. - */ -static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip, - unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p012(group, pin, 1); - - return 0; -} - -static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip, - unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p3(group, pin, 1); - - return 0; -} - -static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip, - unsigned pin) -{ - return 0; -} - -static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - return __get_gpio_state_p012(group, pin); -} - -static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - return __get_gpio_state_p3(group, pin); -} - -static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - return __get_gpi_state_p3(group, pin); -} - -static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p012(group, pin, 0); - - return 0; -} - -static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p3(group, pin, 0); - - return 0; -} - -static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin, - int value) -{ - return 0; -} - -static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_level_p012(group, pin, value); -} - -static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_level_p3(group, pin, value); -} - -static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpo_level_p3(group, pin, value); -} - -static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin) -{ - if (pin < chip->ngpio) - return 0; - - return -EINVAL; -} - -static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { - { - .chip = { - .label = "gpio_p0", - .direction_input = lpc32xx_gpio_dir_input_p012, - .get = lpc32xx_gpio_get_value_p012, - .direction_output = lpc32xx_gpio_dir_output_p012, - .set = lpc32xx_gpio_set_value_p012, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P0_GRP, - .ngpio = LPC32XX_GPIO_P0_MAX, - .names = gpio_p0_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p0, - }, - { - .chip = { - .label = "gpio_p1", - .direction_input = lpc32xx_gpio_dir_input_p012, - .get = lpc32xx_gpio_get_value_p012, - .direction_output = lpc32xx_gpio_dir_output_p012, - .set = lpc32xx_gpio_set_value_p012, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P1_GRP, - .ngpio = LPC32XX_GPIO_P1_MAX, - .names = gpio_p1_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p1, - }, - { - .chip = { - .label = "gpio_p2", - .direction_input = lpc32xx_gpio_dir_input_p012, - .get = lpc32xx_gpio_get_value_p012, - .direction_output = lpc32xx_gpio_dir_output_p012, - .set = lpc32xx_gpio_set_value_p012, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P2_GRP, - .ngpio = LPC32XX_GPIO_P2_MAX, - .names = gpio_p2_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p2, - }, - { - .chip = { - .label = "gpio_p3", - .direction_input = lpc32xx_gpio_dir_input_p3, - .get = lpc32xx_gpio_get_value_p3, - .direction_output = lpc32xx_gpio_dir_output_p3, - .set = lpc32xx_gpio_set_value_p3, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P3_GRP, - .ngpio = LPC32XX_GPIO_P3_MAX, - .names = gpio_p3_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p3, - }, - { - .chip = { - .label = "gpi_p3", - .direction_input = lpc32xx_gpio_dir_in_always, - .get = lpc32xx_gpi_get_value, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPI_P3_GRP, - .ngpio = LPC32XX_GPI_P3_MAX, - .names = gpi_p3_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p3, - }, - { - .chip = { - .label = "gpo_p3", - .direction_output = lpc32xx_gpio_dir_out_always, - .set = lpc32xx_gpo_set_value, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPO_P3_GRP, - .ngpio = LPC32XX_GPO_P3_MAX, - .names = gpo_p3_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p3, - }, -}; - -void __init lpc32xx_gpio_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) - gpiochip_add(&lpc32xx_gpiochip[i].chip); -} diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 226982277330..33e095bdb65c 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_MACH_KS8695) += gpio-ks8695.o obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o +obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c new file mode 100644 index 000000000000..b4e9d35a6fa6 --- /dev/null +++ b/drivers/gpio/gpio-lpc32xx.c @@ -0,0 +1,445 @@ +/* + * arch/arm/mach-lpc32xx/gpiolib.c + * + * Author: Kevin Wells + * + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) +#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) +#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008) +#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C) +#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010) +#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014) +#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018) +#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C) +#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020) +#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024) +#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028) +#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C) +#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030) +#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040) +#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044) +#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048) +#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C) +#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050) +#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054) +#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058) +#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060) +#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064) +#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068) +#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C) +#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070) +#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074) +#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078) + +#define GPIO012_PIN_TO_BIT(x) (1 << (x)) +#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25)) +#define GPO3_PIN_TO_BIT(x) (1 << (x)) +#define GPIO012_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) +#define GPIO3_PIN_IN_SHIFT(x) ((x) == 5 ? 24 : 10 + (x)) +#define GPIO3_PIN_IN_SEL(x, y) ((x) >> GPIO3_PIN_IN_SHIFT(y)) +#define GPIO3_PIN5_IN_SEL(x) (((x) >> 24) & 1) +#define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) + +struct gpio_regs { + void __iomem *inp_state; + void __iomem *outp_set; + void __iomem *outp_clr; + void __iomem *dir_set; + void __iomem *dir_clr; +}; + +/* + * GPIO names + */ +static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = { + "p0.0", "p0.1", "p0.2", "p0.3", + "p0.4", "p0.5", "p0.6", "p0.7" +}; + +static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = { + "p1.0", "p1.1", "p1.2", "p1.3", + "p1.4", "p1.5", "p1.6", "p1.7", + "p1.8", "p1.9", "p1.10", "p1.11", + "p1.12", "p1.13", "p1.14", "p1.15", + "p1.16", "p1.17", "p1.18", "p1.19", + "p1.20", "p1.21", "p1.22", "p1.23", +}; + +static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = { + "p2.0", "p2.1", "p2.2", "p2.3", + "p2.4", "p2.5", "p2.6", "p2.7", + "p2.8", "p2.9", "p2.10", "p2.11", + "p2.12" +}; + +static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = { + "gpi000", "gpio01", "gpio02", "gpio03", + "gpio04", "gpio05" +}; + +static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = { + "gpi00", "gpi01", "gpi02", "gpi03", + "gpi04", "gpi05", "gpi06", "gpi07", + "gpi08", "gpi09", NULL, NULL, + NULL, NULL, NULL, "gpi15", + "gpi16", "gpi17", "gpi18", "gpi19", + "gpi20", "gpi21", "gpi22", "gpi23", + "gpi24", "gpi25", "gpi26", "gpi27" +}; + +static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = { + "gpo00", "gpo01", "gpo02", "gpo03", + "gpo04", "gpo05", "gpo06", "gpo07", + "gpo08", "gpo09", "gpo10", "gpo11", + "gpo12", "gpo13", "gpo14", "gpo15", + "gpo16", "gpo17", "gpo18", "gpo19", + "gpo20", "gpo21", "gpo22", "gpo23" +}; + +static struct gpio_regs gpio_grp_regs_p0 = { + .inp_state = LPC32XX_GPIO_P0_INP_STATE, + .outp_set = LPC32XX_GPIO_P0_OUTP_SET, + .outp_clr = LPC32XX_GPIO_P0_OUTP_CLR, + .dir_set = LPC32XX_GPIO_P0_DIR_SET, + .dir_clr = LPC32XX_GPIO_P0_DIR_CLR, +}; + +static struct gpio_regs gpio_grp_regs_p1 = { + .inp_state = LPC32XX_GPIO_P1_INP_STATE, + .outp_set = LPC32XX_GPIO_P1_OUTP_SET, + .outp_clr = LPC32XX_GPIO_P1_OUTP_CLR, + .dir_set = LPC32XX_GPIO_P1_DIR_SET, + .dir_clr = LPC32XX_GPIO_P1_DIR_CLR, +}; + +static struct gpio_regs gpio_grp_regs_p2 = { + .inp_state = LPC32XX_GPIO_P2_INP_STATE, + .outp_set = LPC32XX_GPIO_P2_OUTP_SET, + .outp_clr = LPC32XX_GPIO_P2_OUTP_CLR, + .dir_set = LPC32XX_GPIO_P2_DIR_SET, + .dir_clr = LPC32XX_GPIO_P2_DIR_CLR, +}; + +static struct gpio_regs gpio_grp_regs_p3 = { + .inp_state = LPC32XX_GPIO_P3_INP_STATE, + .outp_set = LPC32XX_GPIO_P3_OUTP_SET, + .outp_clr = LPC32XX_GPIO_P3_OUTP_CLR, + .dir_set = LPC32XX_GPIO_P2_DIR_SET, + .dir_clr = LPC32XX_GPIO_P2_DIR_CLR, +}; + +struct lpc32xx_gpio_chip { + struct gpio_chip chip; + struct gpio_regs *gpio_grp; +}; + +static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio( + struct gpio_chip *gpc) +{ + return container_of(gpc, struct lpc32xx_gpio_chip, chip); +} + +static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group, + unsigned pin, int input) +{ + if (input) + __raw_writel(GPIO012_PIN_TO_BIT(pin), + group->gpio_grp->dir_clr); + else + __raw_writel(GPIO012_PIN_TO_BIT(pin), + group->gpio_grp->dir_set); +} + +static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group, + unsigned pin, int input) +{ + u32 u = GPIO3_PIN_TO_BIT(pin); + + if (input) + __raw_writel(u, group->gpio_grp->dir_clr); + else + __raw_writel(u, group->gpio_grp->dir_set); +} + +static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group, + unsigned pin, int high) +{ + if (high) + __raw_writel(GPIO012_PIN_TO_BIT(pin), + group->gpio_grp->outp_set); + else + __raw_writel(GPIO012_PIN_TO_BIT(pin), + group->gpio_grp->outp_clr); +} + +static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group, + unsigned pin, int high) +{ + u32 u = GPIO3_PIN_TO_BIT(pin); + + if (high) + __raw_writel(u, group->gpio_grp->outp_set); + else + __raw_writel(u, group->gpio_grp->outp_clr); +} + +static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group, + unsigned pin, int high) +{ + if (high) + __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); + else + __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); +} + +static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group, + unsigned pin) +{ + return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), + pin); +} + +static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, + unsigned pin) +{ + int state = __raw_readl(group->gpio_grp->inp_state); + + /* + * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped + * to bits 10..14, while GPIOP3-5 is mapped to bit 24. + */ + return GPIO3_PIN_IN_SEL(state, pin); +} + +static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, + unsigned pin) +{ + return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin); +} + +/* + * GENERIC_GPIO primitives. + */ +static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip, + unsigned pin) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpio_dir_p012(group, pin, 1); + + return 0; +} + +static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip, + unsigned pin) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpio_dir_p3(group, pin, 1); + + return 0; +} + +static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip, + unsigned pin) +{ + return 0; +} + +static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + return __get_gpio_state_p012(group, pin); +} + +static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + return __get_gpio_state_p3(group, pin); +} + +static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + return __get_gpi_state_p3(group, pin); +} + +static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, + int value) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpio_dir_p012(group, pin, 0); + + return 0; +} + +static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, + int value) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpio_dir_p3(group, pin, 0); + + return 0; +} + +static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin, + int value) +{ + return 0; +} + +static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin, + int value) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpio_level_p012(group, pin, value); +} + +static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin, + int value) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpio_level_p3(group, pin, value); +} + +static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin, + int value) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpo_level_p3(group, pin, value); +} + +static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin) +{ + if (pin < chip->ngpio) + return 0; + + return -EINVAL; +} + +static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { + { + .chip = { + .label = "gpio_p0", + .direction_input = lpc32xx_gpio_dir_input_p012, + .get = lpc32xx_gpio_get_value_p012, + .direction_output = lpc32xx_gpio_dir_output_p012, + .set = lpc32xx_gpio_set_value_p012, + .request = lpc32xx_gpio_request, + .base = LPC32XX_GPIO_P0_GRP, + .ngpio = LPC32XX_GPIO_P0_MAX, + .names = gpio_p0_names, + .can_sleep = 0, + }, + .gpio_grp = &gpio_grp_regs_p0, + }, + { + .chip = { + .label = "gpio_p1", + .direction_input = lpc32xx_gpio_dir_input_p012, + .get = lpc32xx_gpio_get_value_p012, + .direction_output = lpc32xx_gpio_dir_output_p012, + .set = lpc32xx_gpio_set_value_p012, + .request = lpc32xx_gpio_request, + .base = LPC32XX_GPIO_P1_GRP, + .ngpio = LPC32XX_GPIO_P1_MAX, + .names = gpio_p1_names, + .can_sleep = 0, + }, + .gpio_grp = &gpio_grp_regs_p1, + }, + { + .chip = { + .label = "gpio_p2", + .direction_input = lpc32xx_gpio_dir_input_p012, + .get = lpc32xx_gpio_get_value_p012, + .direction_output = lpc32xx_gpio_dir_output_p012, + .set = lpc32xx_gpio_set_value_p012, + .request = lpc32xx_gpio_request, + .base = LPC32XX_GPIO_P2_GRP, + .ngpio = LPC32XX_GPIO_P2_MAX, + .names = gpio_p2_names, + .can_sleep = 0, + }, + .gpio_grp = &gpio_grp_regs_p2, + }, + { + .chip = { + .label = "gpio_p3", + .direction_input = lpc32xx_gpio_dir_input_p3, + .get = lpc32xx_gpio_get_value_p3, + .direction_output = lpc32xx_gpio_dir_output_p3, + .set = lpc32xx_gpio_set_value_p3, + .request = lpc32xx_gpio_request, + .base = LPC32XX_GPIO_P3_GRP, + .ngpio = LPC32XX_GPIO_P3_MAX, + .names = gpio_p3_names, + .can_sleep = 0, + }, + .gpio_grp = &gpio_grp_regs_p3, + }, + { + .chip = { + .label = "gpi_p3", + .direction_input = lpc32xx_gpio_dir_in_always, + .get = lpc32xx_gpi_get_value, + .request = lpc32xx_gpio_request, + .base = LPC32XX_GPI_P3_GRP, + .ngpio = LPC32XX_GPI_P3_MAX, + .names = gpi_p3_names, + .can_sleep = 0, + }, + .gpio_grp = &gpio_grp_regs_p3, + }, + { + .chip = { + .label = "gpo_p3", + .direction_output = lpc32xx_gpio_dir_out_always, + .set = lpc32xx_gpo_set_value, + .request = lpc32xx_gpio_request, + .base = LPC32XX_GPO_P3_GRP, + .ngpio = LPC32XX_GPO_P3_MAX, + .names = gpo_p3_names, + .can_sleep = 0, + }, + .gpio_grp = &gpio_grp_regs_p3, + }, +}; + +void __init lpc32xx_gpio_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) + gpiochip_add(&lpc32xx_gpiochip[i].chip); +} -- cgit v1.2.3-59-g8ed1b From 9c587c05d715ca8461342c2cb3b4a67036b5c22b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:45:15 +0100 Subject: ARM: 7045/1: mach-lpc32xx: break out GPIO driver specifics The file is included from upper directories and deal with generic GPIO and gpiolib stuff. Break out the platform and driver specific defines and functions into its own header file. Cc: Wolfram Sang Cc: Barry Song Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h | 50 ++++++++++++++++++++++ arch/arm/mach-lpc32xx/include/mach/gpio.h | 52 ----------------------- arch/arm/mach-lpc32xx/phy3250.c | 1 + drivers/gpio/gpio-lpc32xx.c | 1 + 4 files changed, 52 insertions(+), 52 deletions(-) create mode 100644 arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h (limited to 'drivers/gpio') diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h b/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h new file mode 100644 index 000000000000..1816e22a3479 --- /dev/null +++ b/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h @@ -0,0 +1,50 @@ +/* + * Author: Kevin Wells + * + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +#ifndef __MACH_GPIO_LPC32XX_H +#define __MACH_GPIO_LPC32XX_H + +/* + * Note! + * Muxed GP pins need to be setup to the GP state in the board level + * code prior to using this driver. + * GPI pins : 28xP3 group + * GPO pins : 24xP3 group + * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group + */ + +#define LPC32XX_GPIO_P0_MAX 8 +#define LPC32XX_GPIO_P1_MAX 24 +#define LPC32XX_GPIO_P2_MAX 13 +#define LPC32XX_GPIO_P3_MAX 6 +#define LPC32XX_GPI_P3_MAX 28 +#define LPC32XX_GPO_P3_MAX 24 + +#define LPC32XX_GPIO_P0_GRP 0 +#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX) +#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX) +#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX) +#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX) +#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) + +/* + * A specific GPIO can be selected with this macro + * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5) + * See the LPC32x0 User's guide for GPIO group numbers + */ +#define LPC32XX_GPIO(x, y) ((x) + (y)) + +#endif /* __MACH_GPIO_LPC32XX_H */ diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio.h b/arch/arm/mach-lpc32xx/include/mach/gpio.h index 66d31f615eb9..e69de29bb2d1 100644 --- a/arch/arm/mach-lpc32xx/include/mach/gpio.h +++ b/arch/arm/mach-lpc32xx/include/mach/gpio.h @@ -1,52 +0,0 @@ -/* - * arch/arm/mach-lpc32xx/include/mach/gpio.h - * - * Author: Kevin Wells - * - * Copyright (C) 2010 NXP Semiconductors - * - * 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. - */ - -#ifndef __ASM_ARCH_GPIO_H -#define __ASM_ARCH_GPIO_H - -/* - * Note! - * Muxed GP pins need to be setup to the GP state in the board level - * code prior to using this driver. - * GPI pins : 28xP3 group - * GPO pins : 24xP3 group - * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group - */ - -#define LPC32XX_GPIO_P0_MAX 8 -#define LPC32XX_GPIO_P1_MAX 24 -#define LPC32XX_GPIO_P2_MAX 13 -#define LPC32XX_GPIO_P3_MAX 6 -#define LPC32XX_GPI_P3_MAX 28 -#define LPC32XX_GPO_P3_MAX 24 - -#define LPC32XX_GPIO_P0_GRP 0 -#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX) -#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX) -#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX) -#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX) -#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) - -/* - * A specific GPIO can be selected with this macro - * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5) - * See the LPC32x0 User's guide for GPIO group numbers - */ -#define LPC32XX_GPIO(x, y) ((x) + (y)) - -#endif diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 7993b096778e..c3a22fd736aa 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -37,6 +37,7 @@ #include #include +#include #include "common.h" /* diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index b4e9d35a6fa6..5b6948081f8f 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -24,6 +24,7 @@ #include #include +#include #define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) #define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) -- cgit v1.2.3-59-g8ed1b From 2428835fc6a579b68dde16d37e0b72ca29259c96 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 22 Aug 2011 08:49:07 +0100 Subject: ARM: 7049/1: mach-sa1100: move SA1100 GPIO driver to GPIO subsystem As per example from the other ARM boards, push the SA100 GPIO driver down to the GPIO subsystem so it can be consolidated. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/Makefile | 2 +- arch/arm/mach-sa1100/gpio.c | 64 ------------------------------------------- drivers/gpio/Makefile | 2 +- drivers/gpio/gpio-sa1100.c | 63 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 66 deletions(-) delete mode 100644 arch/arm/mach-sa1100/gpio.c create mode 100644 drivers/gpio/gpio-sa1100.c (limited to 'drivers/gpio') diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 41252d22e659..73a5c6431792 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := clock.o generic.o gpio.o irq.o dma.o time.o #nmi-oopser.o +obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-sa1100/gpio.c b/arch/arm/mach-sa1100/gpio.c deleted file mode 100644 index e547ed41ec6b..000000000000 --- a/arch/arm/mach-sa1100/gpio.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/gpio.c - * - * Generic SA-1100 GPIO handling - * - * 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 "generic.h" - -static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return GPLR & GPIO_GPIO(offset); -} - -static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - if (value) - GPSR = GPIO_GPIO(offset); - else - GPCR = GPIO_GPIO(offset); -} - -static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset) -{ - unsigned long flags; - - local_irq_save(flags); - GPDR &= ~GPIO_GPIO(offset); - local_irq_restore(flags); - return 0; -} - -static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value) -{ - unsigned long flags; - - local_irq_save(flags); - sa1100_gpio_set(chip, offset, value); - GPDR |= GPIO_GPIO(offset); - local_irq_restore(flags); - return 0; -} - -static struct gpio_chip sa1100_gpio_chip = { - .label = "gpio", - .direction_input = sa1100_direction_input, - .direction_output = sa1100_direction_output, - .set = sa1100_gpio_set, - .get = sa1100_gpio_get, - .base = 0, - .ngpio = GPIO_MAX + 1, -}; - -void __init sa1100_init_gpio(void) -{ - gpiochip_add(&sa1100_gpio_chip); -} diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 33e095bdb65c..84bc7389e367 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -45,7 +45,7 @@ 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_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c new file mode 100644 index 000000000000..b6c1f6d80649 --- /dev/null +++ b/drivers/gpio/gpio-sa1100.c @@ -0,0 +1,63 @@ +/* + * linux/arch/arm/mach-sa1100/gpio.c + * + * Generic SA-1100 GPIO handling + * + * 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 + +static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + return GPLR & GPIO_GPIO(offset); +} + +static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + if (value) + GPSR = GPIO_GPIO(offset); + else + GPCR = GPIO_GPIO(offset); +} + +static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset) +{ + unsigned long flags; + + local_irq_save(flags); + GPDR &= ~GPIO_GPIO(offset); + local_irq_restore(flags); + return 0; +} + +static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value) +{ + unsigned long flags; + + local_irq_save(flags); + sa1100_gpio_set(chip, offset, value); + GPDR |= GPIO_GPIO(offset); + local_irq_restore(flags); + return 0; +} + +static struct gpio_chip sa1100_gpio_chip = { + .label = "gpio", + .direction_input = sa1100_direction_input, + .direction_output = sa1100_direction_output, + .set = sa1100_gpio_set, + .get = sa1100_gpio_get, + .base = 0, + .ngpio = GPIO_MAX + 1, +}; + +void __init sa1100_init_gpio(void) +{ + gpiochip_add(&sa1100_gpio_chip); +} -- cgit v1.2.3-59-g8ed1b From 470080015c1f8bbd15ba1486d5c4bd8a3e7fa79a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 23 Aug 2011 00:39:55 +0100 Subject: ARM: 7052/1: gpio/tegra: Remove use of irq_to_gpio irq_to_gpio is being removed. Replace the only use of that API by the ARM Tegra sub-architecture. Signed-off-by: Stephen Warren Signed-off-by: Russell King --- drivers/gpio/gpio-tegra.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 747eb40e8afe..ecade29d79e8 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -331,6 +331,7 @@ static struct lock_class_key gpio_lock_class; static int __init tegra_gpio_init(void) { struct tegra_gpio_bank *bank; + int gpio; int i; int j; @@ -352,14 +353,17 @@ static int __init tegra_gpio_init(void) gpiochip_add(&tegra_gpio_chip); - for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { - bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; + for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) { + int irq = TEGRA_GPIO_TO_IRQ(gpio); + /* No validity check; all Tegra GPIOs are valid IRQs */ - irq_set_lockdep_class(i, &gpio_lock_class); - irq_set_chip_data(i, bank); - irq_set_chip_and_handler(i, &tegra_gpio_irq_chip, + bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; + + irq_set_lockdep_class(irq, &gpio_lock_class); + irq_set_chip_data(irq, bank); + irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip, handle_simple_irq); - set_irq_flags(i, IRQF_VALID); + set_irq_flags(irq, IRQF_VALID); } for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) { -- cgit v1.2.3-59-g8ed1b From 438a99c078b1bc3c9aebd92e7928f2477311d3e5 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 23 Aug 2011 00:39:56 +0100 Subject: ARM: 7053/1: gpio/tegra: Implement gpio_chip.to_irq Signed-off-by: Stephen Warren Signed-off-by: Russell King --- drivers/gpio/gpio-tegra.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index ecade29d79e8..df64536464f0 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -134,7 +134,10 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, return 0; } - +static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + return TEGRA_GPIO_TO_IRQ(offset); +} static struct gpio_chip tegra_gpio_chip = { .label = "tegra-gpio", @@ -142,6 +145,7 @@ static struct gpio_chip tegra_gpio_chip = { .get = tegra_gpio_get, .direction_output = tegra_gpio_direction_output, .set = tegra_gpio_set, + .to_irq = tegra_gpio_to_irq, .base = 0, .ngpio = TEGRA_NR_GPIOS, }; -- cgit v1.2.3-59-g8ed1b From 526a0dc771a5cac3224e26abd1f018976b967516 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 5 Sep 2011 03:29:04 +0100 Subject: ARM: 7074/1: gpio: davinci: eliminate unused variable warnings Since commit 5093aec872e5be7a55d8dd2b639e8a3818dc19db "arm: davinci: Cleanup irq chip code", the variable 'mask' and 'g' are not being used. This patch eliminate below unused variable warnings: CC drivers/gpio/gpio-davinci.o drivers/gpio/gpio-davinci.c: In function 'gpio_irq_type': drivers/gpio/gpio-davinci.c:234: warning: unused variable 'mask' drivers/gpio/gpio-davinci.c:233: warning: unused variable 'g' Signed-off-by: Axel Lin Signed-off-by: Russell King --- drivers/gpio/gpio-davinci.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index a8066e8edade..df0d59570a84 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -230,9 +230,6 @@ static void gpio_irq_enable(struct irq_data *d) static int gpio_irq_type(struct irq_data *d, unsigned trigger) { - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); - if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From cc890cd78acd7ab03442907d354b6af34e973cb3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Sep 2011 09:04:51 +0100 Subject: ARM: 7083/1: rewrite U300 GPIO to use gpiolib This rewrites the U300 GPIO so as to use gpiolib and struct gpio_chip instead of just generic GPIO, hiding all the platform specifics and passing in GPIO chip variant as platform data at runtime instead of the compiletime kludges. As a result is now empty for U300 and using just defaults. Cc: Grant Likely Cc: Debian kernel maintainers Cc: Arnaud Patard Reported-by: Ben Hutchings Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-u300/Kconfig | 1 + arch/arm/mach-u300/core.c | 31 +- arch/arm/mach-u300/include/mach/gpio-u300.h | 149 +--- arch/arm/mach-u300/include/mach/gpio.h | 47 -- arch/arm/mach-u300/include/mach/irqs.h | 25 +- drivers/gpio/Kconfig | 9 + drivers/gpio/gpio-u300.c | 1189 ++++++++++++++++----------- 8 files changed, 783 insertions(+), 669 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2c71a8f3535a..05589e85c180 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -836,6 +836,7 @@ config ARCH_U300 select CLKDEV_LOOKUP select HAVE_MACH_CLKDEV select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Support for ST-Ericsson U300 series mobile platforms. diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index 32a7b0f7e9f7..7b5c229dc7ea 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -6,6 +6,7 @@ comment "ST-Ericsson Mobile Platform Products" config MACH_U300 bool "U300" + select GPIO_U300 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections" diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 399c89f14dfb..fd435f44098b 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "clock.h" #include "mmc.h" @@ -239,7 +240,7 @@ static struct resource gpio_resources[] = { .end = IRQ_U300_GPIO_PORT2, .flags = IORESOURCE_IRQ, }, -#ifdef U300_COH901571_3 +#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335) { .name = "gpio3", .start = IRQ_U300_GPIO_PORT3, @@ -252,6 +253,7 @@ static struct resource gpio_resources[] = { .end = IRQ_U300_GPIO_PORT4, .flags = IORESOURCE_IRQ, }, +#endif #ifdef CONFIG_MACH_U300_BS335 { .name = "gpio5", @@ -266,7 +268,6 @@ static struct resource gpio_resources[] = { .flags = IORESOURCE_IRQ, }, #endif /* CONFIG_MACH_U300_BS335 */ -#endif /* U300_COH901571_3 */ }; static struct resource keypad_resources[] = { @@ -1556,11 +1557,35 @@ static struct platform_device i2c1_device = { .resource = i2c1_resources, }; +/* + * The different variants have a few different versions of the + * GPIO block, with different number of ports. + */ +static struct u300_gpio_platform u300_gpio_plat = { +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) + .variant = U300_GPIO_COH901335, + .ports = 3, +#endif +#ifdef CONFIG_MACH_U300_BS335 + .variant = U300_GPIO_COH901571_3_BS335, + .ports = 7, +#endif +#ifdef CONFIG_MACH_U300_BS365 + .variant = U300_GPIO_COH901571_3_BS365, + .ports = 5, +#endif + .gpio_base = 0, + .gpio_irq_base = IRQ_U300_GPIO_BASE, +}; + static struct platform_device gpio_device = { .name = "u300-gpio", .id = -1, .num_resources = ARRAY_SIZE(gpio_resources), .resource = gpio_resources, + .dev = { + .platform_data = &u300_gpio_plat, + }, }; static struct platform_device keypad_device = { @@ -1666,7 +1691,7 @@ void __init u300_init_irq(void) BUG_ON(IS_ERR(clk)); clk_enable(clk); - for (i = 0; i < NR_IRQS; i++) + for (i = 0; i < U300_VIC_IRQS_END; i++) set_bit(i, (unsigned long *) &mask[0]); vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]); vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]); diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.h index a6119062add9..0c2b2021951a 100644 --- a/arch/arm/mach-u300/include/mach/gpio-u300.h +++ b/arch/arm/mach-u300/include/mach/gpio-u300.h @@ -9,132 +9,6 @@ #ifndef __MACH_U300_GPIO_U300_H #define __MACH_U300_GPIO_U300_H -#include -#include -#include -#include - -/* Switch type depending on platform/chip variant */ -#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) -#define U300_COH901335 -#endif -#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335) -#define U300_COH901571_3 -#endif - -/* Get base address for regs here */ -#include "u300-regs.h" -/* IRQ numbers */ -#include "irqs.h" - -/* - * This is the GPIO block definitions. GPIO (General Purpose I/O) can be - * used for anything, and often is. The event/enable etc figures are for - * the lowermost pin (pin 0 on each port), shift this left to match your - * pin if you're gonna use these values. - */ -#ifdef U300_COH901335 -#define U300_GPIO_PORTX_SPACING (0x1C) -/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ -#define U300_GPIO_PXPDIR (0x00) -#define U300_GPIO_PXPDOR (0x00) -/* Port X Pin Config Register 32bit (R/W) */ -#define U300_GPIO_PXPCR (0x04) -#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) -#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) -#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) -/* Port X Interrupt Event Register 32bit (R/W) */ -#define U300_GPIO_PXIEV (0x08) -#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) -#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) -/* Port X Interrupt Enable Register 32bit (R/W) */ -#define U300_GPIO_PXIEN (0x0C) -#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) -/* Port X Interrupt Force Register 32bit (R/W) */ -#define U300_GPIO_PXIFR (0x10) -#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) -#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) -/* Port X Interrupt Config Register 32bit (R/W) */ -#define U300_GPIO_PXICR (0x14) -#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) -#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) -/* Port X Pull-up Enable Register 32bit (R/W) */ -#define U300_GPIO_PXPER (0x18) -#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) -/* Control Register 32bit (R/W) */ -#define U300_GPIO_CR (0x54) -#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) -/* three ports of 8 bits each = GPIO pins 0..23 */ -#define U300_GPIO_NUM_PORTS 3 -#define U300_GPIO_PINS_PER_PORT 8 -#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) -#endif - -#ifdef U300_COH901571_3 -/* - * Control Register 32bit (R/W) - * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores - * gives the number of GPIO pins. - * bit 8-2 (mask 0x000001FC) contains the core version ID. - */ -#define U300_GPIO_CR (0x00) -#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL) -#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) -#define U300_GPIO_PORTX_SPACING (0x30) -/* Port X Pin Data INPUT Register 32bit (R/W) */ -#define U300_GPIO_PXPDIR (0x04) -/* Port X Pin Data OUTPUT Register 32bit (R/W) */ -#define U300_GPIO_PXPDOR (0x08) -/* Port X Pin Config Register 32bit (R/W) */ -#define U300_GPIO_PXPCR (0x0C) -#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) -#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) -#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) -/* Port X Pull-up Enable Register 32bit (R/W) */ -#define U300_GPIO_PXPER (0x10) -#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) -/* Port X Interrupt Event Register 32bit (R/W) */ -#define U300_GPIO_PXIEV (0x14) -#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) -#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) -/* Port X Interrupt Enable Register 32bit (R/W) */ -#define U300_GPIO_PXIEN (0x18) -#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) -/* Port X Interrupt Force Register 32bit (R/W) */ -#define U300_GPIO_PXIFR (0x1C) -#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) -#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) -/* Port X Interrupt Config Register 32bit (R/W) */ -#define U300_GPIO_PXICR (0x20) -#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) -#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) -#ifdef CONFIG_MACH_U300_BS335 -/* seven ports of 8 bits each = GPIO pins 0..55 */ -#define U300_GPIO_NUM_PORTS 7 -#else -/* five ports of 8 bits each = GPIO pins 0..39 */ -#define U300_GPIO_NUM_PORTS 5 -#endif -#define U300_GPIO_PINS_PER_PORT 8 -#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) -#endif - /* * Individual pin assignments for the B26/S26. Notice that the * actual usage of these pins depends on the PAD MUX settings, that @@ -250,4 +124,27 @@ #endif +/** + * enum u300_gpio_variant - the type of U300 GPIO employed + */ +enum u300_gpio_variant { + U300_GPIO_COH901335, + U300_GPIO_COH901571_3_BS335, + U300_GPIO_COH901571_3_BS365, +}; + +/** + * struct u300_gpio_platform - U300 GPIO platform data + * @variant: IP block variant + * @ports: number of GPIO block ports + * @gpio_base: first GPIO number for this block (use a free range) + * @gpio_irq_base: first GPIO IRQ number for this block (use a free range) + */ +struct u300_gpio_platform { + enum u300_gpio_variant variant; + u8 ports; + int gpio_base; + int gpio_irq_base; +}; + #endif /* __MACH_U300_GPIO_U300_H */ diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h index 430a0544baff..e69de29bb2d1 100644 --- a/arch/arm/mach-u300/include/mach/gpio.h +++ b/arch/arm/mach-u300/include/mach/gpio.h @@ -1,47 +0,0 @@ -/* - * - * arch/arm/mach-u300/include/mach/gpio.h - * - * - * Copyright (C) 2007-2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * GPIO block resgister definitions and inline macros for - * U300 GPIO COH 901 335 or COH 901 571/3 - * Author: Linus Walleij - */ - -#ifndef __MACH_U300_GPIO_H -#define __MACH_U300_GPIO_H - -#define __ARM_GPIOLIB_COMPLEX - -/* These can be found in arch/arm/mach-u300/gpio.c */ -extern int gpio_is_valid(int number); -extern int gpio_request(unsigned gpio, const char *label); -extern void gpio_free(unsigned gpio); -extern int gpio_direction_input(unsigned gpio); -extern int gpio_direction_output(unsigned gpio, int value); -extern int gpio_register_callback(unsigned gpio, - int (*func)(void *arg), - void *); -extern int gpio_unregister_callback(unsigned gpio); -extern void enable_irq_on_gpio_pin(unsigned gpio, int edge); -extern void disable_irq_on_gpio_pin(unsigned gpio); -extern void gpio_pullup(unsigned gpio, int value); -extern int gpio_get_value(unsigned gpio); -extern void gpio_set_value(unsigned gpio, int value); - -#define gpio_get_value_cansleep gpio_get_value -#define gpio_set_value_cansleep gpio_set_value - -/* translates a pin number to a port number */ -#define PIN_TO_PORT(val) (val >> 3) - -/* wrappers to sleep-enable the previous two functions */ -static inline unsigned gpio_to_irq(unsigned gpio) -{ - return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0; -} -#define gpio_to_irq gpio_to_irq - -#endif /* __MACH_U300_GPIO_H */ diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h index 09b1b28fa8fd..d270fea32926 100644 --- a/arch/arm/mach-u300/include/mach/irqs.h +++ b/arch/arm/mach-u300/include/mach/irqs.h @@ -72,7 +72,7 @@ /* DB3150 and DB3200 have only 45 IRQs */ #if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) -#define U300_NR_IRQS 45 +#define U300_VIC_IRQS_END 45 #endif /* The DB3350-specific interrupt lines */ @@ -88,7 +88,7 @@ #define IRQ_U300_GPIO_PORT4 53 #define IRQ_U300_GPIO_PORT5 54 #define IRQ_U300_GPIO_PORT6 55 -#define U300_NR_IRQS 56 +#define U300_VIC_IRQS_END 56 #endif /* The DB3210-specific interrupt lines */ @@ -106,16 +106,25 @@ #define IRQ_U300_NFIF 45 #define IRQ_U300_NFIF2 46 #define IRQ_U300_SYSCON_PLL_LOCK 47 -#define U300_NR_IRQS 48 +#define U300_VIC_IRQS_END 48 #endif -#ifdef CONFIG_AB3550_CORE -#define IRQ_AB3550_BASE (U300_NR_IRQS) -#define IRQ_AB3550_END (IRQ_AB3550_BASE + 37) +/* Maximum 8*7 GPIO lines */ +#ifdef CONFIG_GPIO_U300 +#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END) +#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56) +#else +#define IRQ_U300_GPIO_END (U300_VIC_IRQS_END) +#endif -#define NR_IRQS (IRQ_AB3550_END + 1) +/* Optional AB3550 mixsig chip */ +#ifdef CONFIG_AB3550_CORE +#define IRQ_AB3550_BASE (IRQ_U300_GPIO_END) +#define IRQ_AB3550_END (IRQ_AB3550_BASE + 38) #else -#define NR_IRQS U300_NR_IRQS +#define IRQ_AB3550_END (IRQ_U300_GPIO_END) #endif +#define NR_IRQS (IRQ_AB3550_END) + #endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d539efd96d4b..4caa3d37bbde 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -178,6 +178,15 @@ config GPIO_SCH The Intel Tunnel Creek processor has 5 GPIOs powered by the core power rail and 9 from suspend power supply. +config GPIO_U300 + bool "ST-Ericsson U300 COH 901 335/571 GPIO" + depends on GPIOLIB && ARCH_U300 + help + Say yes here to support GPIO interface on ST-Ericsson U300. + The names of the two IP block variants supported are + COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 + ports of 8 GPIO pins each. + config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" depends on MFD_SUPPORT && PCI diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c index 92f2b8c06de1..4035778852b0 100644 --- a/drivers/gpio/gpio-u300.c +++ b/drivers/gpio/gpio-u300.c @@ -1,18 +1,17 @@ /* * U300 GPIO module. * - * Copyright (C) 2007-2009 ST-Ericsson AB + * Copyright (C) 2007-2011 ST-Ericsson AB * License terms: GNU General Public License (GPL) version 2 * 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) * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0) - * Notice that you also have inline macros in - * Author: Linus Walleij + * Author: Linus Walleij * Author: Jonas Aaberg - * */ #include +#include #include #include #include @@ -21,678 +20,898 @@ #include #include #include +#include +#include #include -/* Reference to GPIO block clock */ -static struct clk *clk; +/* + * Bias modes for U300 GPIOs + * + * GPIO_U300_CONFIG_BIAS_UNKNOWN: this bias mode is not known to us + * GPIO_U300_CONFIG_BIAS_FLOAT: no specific bias, the GPIO will float or state + * is not controlled by software + * GPIO_U300_CONFIG_BIAS_PULL_UP: the GPIO will be pulled up (usually with high + * impedance to VDD) + */ +#define GPIO_U300_CONFIG_BIAS_UNKNOWN 0x1000 +#define GPIO_U300_CONFIG_BIAS_FLOAT 0x1001 +#define GPIO_U300_CONFIG_BIAS_PULL_UP 0x1002 -/* Memory resource */ -static struct resource *memres; -static void __iomem *virtbase; -static struct device *gpiodev; +/* + * Drive modes for U300 GPIOs (output) + * + * GPIO_U300_CONFIG_DRIVE_PUSH_PULL: the GPIO will be driven actively high and + * low, this is the most typical case and is typically achieved with two + * active transistors on the output + * GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: the GPIO will be driven with open drain + * (open collector) which means it is usually wired with other output + * ports which are then pulled up with an external resistor + * GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: the GPIO will be driven with open drain + * (open emitter) which is the same as open drain mutatis mutandis but + * pulled to ground + */ +#define GPIO_U300_CONFIG_DRIVE_PUSH_PULL 0x2000 +#define GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN 0x2001 +#define GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE 0x2002 + +/* + * Register definitions for COH 901 335 variant + */ +#define U300_335_PORT_STRIDE (0x1C) +/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ +#define U300_335_PXPDIR (0x00) +#define U300_335_PXPDOR (0x00) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_335_PXPCR (0x04) +/* This register layout is the same in both blocks */ +#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) +#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) +#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) +/* Port X Interrupt Event Register 32bit (R/W) */ +#define U300_335_PXIEV (0x08) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_335_PXIEN (0x0C) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_335_PXIFR (0x10) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_335_PXICR (0x14) +/* This register layout is the same in both blocks */ +#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) +#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) +/* Port X Pull-up Enable Register 32bit (R/W) */ +#define U300_335_PXPER (0x18) +/* This register layout is the same in both blocks */ +#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) +/* Control Register 32bit (R/W) */ +#define U300_335_CR (0x54) +#define U300_335_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) + +/* + * Register definitions for COH 901 571 / 3 variant + */ +#define U300_571_PORT_STRIDE (0x30) +/* + * Control Register 32bit (R/W) + * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores + * gives the number of GPIO pins. + * bit 8-2 (mask 0x000001FC) contains the core version ID. + */ +#define U300_571_CR (0x00) +#define U300_571_CR_SYNC_SEL_ENABLE (0x00000002UL) +#define U300_571_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) +/* + * These registers have the same layout and function as the corresponding + * COH 901 335 registers, just at different offset. + */ +#define U300_571_PXPDIR (0x04) +#define U300_571_PXPDOR (0x08) +#define U300_571_PXPCR (0x0C) +#define U300_571_PXPER (0x10) +#define U300_571_PXIEV (0x14) +#define U300_571_PXIEN (0x18) +#define U300_571_PXIFR (0x1C) +#define U300_571_PXICR (0x20) + +/* 8 bits per port, no version has more than 7 ports */ +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * 7) + +struct u300_gpio { + struct gpio_chip chip; + struct list_head port_list; + struct clk *clk; + struct resource *memres; + void __iomem *base; + struct device *dev; + int irq_base; + u32 stride; + /* Register offsets */ + u32 pcr; + u32 dor; + u32 dir; + u32 per; + u32 icr; + u32 ien; + u32 iev; +}; struct u300_gpio_port { - const char *name; + struct list_head node; + struct u300_gpio *gpio; + char name[8]; int irq; int number; + u8 toggle_edge_mode; }; +/* + * Macro to expand to read a specific register found in the "gpio" + * struct. It requires the struct u300_gpio *gpio variable to exist in + * its context. It calculates the port offset from the given pin + * offset, muliplies by the port stride and adds the register offset + * so it provides a pointer to the desired register. + */ +#define U300_PIN_REG(pin, reg) \ + (gpio->base + (pin >> 3) * gpio->stride + gpio->reg) -static struct u300_gpio_port gpio_ports[] = { - { - .name = "gpio0", - .number = 0, - }, - { - .name = "gpio1", - .number = 1, - }, - { - .name = "gpio2", - .number = 2, - }, -#ifdef U300_COH901571_3 - { - .name = "gpio3", - .number = 3, - }, - { - .name = "gpio4", - .number = 4, - }, -#ifdef CONFIG_MACH_U300_BS335 - { - .name = "gpio5", - .number = 5, - }, - { - .name = "gpio6", - .number = 6, - }, -#endif -#endif +/* + * Provides a bitmask for a specific gpio pin inside an 8-bit GPIO + * register. + */ +#define U300_PIN_BIT(pin) \ + (1 << (pin & 0x07)) +struct u300_gpio_confdata { + u16 bias_mode; + bool output; + int outval; }; +/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */ +#define BS335_GPIO_NUM_PORTS 7 +/* BS365 has five ports of 8 bits each = GPIO pins 0..39 */ +#define BS365_GPIO_NUM_PORTS 5 -#ifdef U300_COH901571_3 +#define U300_FLOATING_INPUT { \ + .bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \ + .output = false, \ +} -/* Default input value */ -#define DEFAULT_OUTPUT_LOW 0 -#define DEFAULT_OUTPUT_HIGH 1 +#define U300_PULL_UP_INPUT { \ + .bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \ + .output = false, \ +} -/* GPIO Pull-Up status */ -#define DISABLE_PULL_UP 0 -#define ENABLE_PULL_UP 1 +#define U300_OUTPUT_LOW { \ + .output = true, \ + .outval = 0, \ +} -#define GPIO_NOT_USED 0 -#define GPIO_IN 1 -#define GPIO_OUT 2 +#define U300_OUTPUT_HIGH { \ + .output = true, \ + .outval = 1, \ +} -struct u300_gpio_configuration_data { - unsigned char pin_usage; - unsigned char default_output_value; - unsigned char pull_up; -}; /* Initial configuration */ -const struct u300_gpio_configuration_data -u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { -#ifdef CONFIG_MACH_U300_BS335 +static const struct __initdata u300_gpio_confdata +bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { /* Port 0, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_FLOATING_INPUT, + U300_OUTPUT_HIGH, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, }, /* Port 1, pins 0-7 */ { - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_FLOATING_INPUT, + U300_OUTPUT_HIGH, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, }, /* Port 2, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, }, /* Port 3, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_PULL_UP_INPUT, + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, }, /* Port 4, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, }, /* Port 5, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, }, /* Port 6, pind 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, } -#endif +}; -#ifdef CONFIG_MACH_U300_BS365 +static const struct __initdata u300_gpio_confdata +bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { /* Port 0, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_FLOATING_INPUT, }, /* Port 1, pins 0-7 */ { - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_OUTPUT_HIGH, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, }, /* Port 2, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + U300_FLOATING_INPUT, + U300_PULL_UP_INPUT, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, }, /* Port 3, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, }, /* Port 4, pins 0-7 */ { - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, /* These 4 pins doesn't exist on DB3210 */ - {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, - {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, } -#endif }; -#endif - -/* No users == we can power down GPIO */ -static int gpio_users; - -struct gpio_struct { - int (*callback)(void *); - void *data; - int users; -}; - -static struct gpio_struct gpio_pin[U300_GPIO_MAX]; - -/* - * Let drivers register callback in order to get notified when there is - * an interrupt on the gpio pin +/** + * to_u300_gpio() - get the pointer to u300_gpio + * @chip: the gpio chip member of the structure u300_gpio */ -int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data) +static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip) { - if (gpio_pin[gpio].callback) - dev_warn(gpiodev, "%s: WARNING: callback already " - "registered for gpio pin#%d\n", __func__, gpio); - gpio_pin[gpio].callback = func; - gpio_pin[gpio].data = data; - - return 0; + return container_of(chip, struct u300_gpio, chip); } -EXPORT_SYMBOL(gpio_register_callback); -int gpio_unregister_callback(unsigned gpio) +static int u300_gpio_get(struct gpio_chip *chip, unsigned offset) { - if (!gpio_pin[gpio].callback) - dev_warn(gpiodev, "%s: WARNING: callback already " - "unregistered for gpio pin#%d\n", __func__, gpio); - gpio_pin[gpio].callback = NULL; - gpio_pin[gpio].data = NULL; + struct u300_gpio *gpio = to_u300_gpio(chip); - return 0; + return readl(U300_PIN_REG(offset, dir)) & U300_PIN_BIT(offset); } -EXPORT_SYMBOL(gpio_unregister_callback); -/* Non-zero means valid */ -int gpio_is_valid(int number) +static void u300_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - if (number >= 0 && - number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT)) - return 1; - return 0; -} -EXPORT_SYMBOL(gpio_is_valid); + struct u300_gpio *gpio = to_u300_gpio(chip); + unsigned long flags; + u32 val; -int gpio_request(unsigned gpio, const char *label) -{ - if (gpio_pin[gpio].users) - return -EINVAL; - else - gpio_pin[gpio].users++; + local_irq_save(flags); - gpio_users++; + val = readl(U300_PIN_REG(offset, dor)); + if (value) + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, dor)); + else + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, dor)); - return 0; + local_irq_restore(flags); } -EXPORT_SYMBOL(gpio_request); -void gpio_free(unsigned gpio) +static int u300_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - gpio_users--; - gpio_pin[gpio].users--; - if (unlikely(gpio_pin[gpio].users < 0)) { - dev_warn(gpiodev, "warning: gpio#%d release mismatch\n", - gpio); - gpio_pin[gpio].users = 0; - } - - return; -} -EXPORT_SYMBOL(gpio_free); + struct u300_gpio *gpio = to_u300_gpio(chip); + unsigned long flags; + u32 val; -/* This returns zero or nonzero */ -int gpio_get_value(unsigned gpio) -{ - return readl(virtbase + U300_GPIO_PXPDIR + - PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07)); + local_irq_save(flags); + val = readl(U300_PIN_REG(offset, pcr)); + /* Mask out this pin, note 2 bits per setting */ + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + local_irq_restore(flags); + return 0; } -EXPORT_SYMBOL(gpio_get_value); -/* - * We hope that the compiler will optimize away the unused branch - * in case "value" is a constant - */ -void gpio_set_value(unsigned gpio, int value) +static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) { - u32 val; + struct u300_gpio *gpio = to_u300_gpio(chip); unsigned long flags; + u32 oldmode; + u32 val; local_irq_save(flags); - if (value) { - /* set */ - val = readl(virtbase + U300_GPIO_PXPDOR + - PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) - & (1 << (gpio & 0x07)); - writel(val | (1 << (gpio & 0x07)), virtbase + - U300_GPIO_PXPDOR + - PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); - } else { - /* clear */ - val = readl(virtbase + U300_GPIO_PXPDOR + - PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) - & (1 << (gpio & 0x07)); - writel(val & ~(1 << (gpio & 0x07)), virtbase + - U300_GPIO_PXPDOR + - PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); + val = readl(U300_PIN_REG(offset, pcr)); + /* + * Drive mode must be set by the special mode set function, set + * push/pull mode by default if no mode has been selected. + */ + oldmode = val & (U300_GPIO_PXPCR_PIN_MODE_MASK << + ((offset & 0x07) << 1)); + /* mode = 0 means input, else some mode is already set */ + if (oldmode == 0) { + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << + ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); } + u300_gpio_set(chip, offset, value); local_irq_restore(flags); + return 0; } -EXPORT_SYMBOL(gpio_set_value); -int gpio_direction_input(unsigned gpio) +static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { + struct u300_gpio *gpio = to_u300_gpio(chip); + int retirq = gpio->irq_base + offset; + + dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset, + retirq); + return retirq; +} + +static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, + u16 param, unsigned long *data) +{ + struct u300_gpio *gpio = to_u300_gpio(chip); unsigned long flags; u32 val; - if (gpio > U300_GPIO_MAX) - return -EINVAL; - local_irq_save(flags); - val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - /* Mask out this pin*/ - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1)); - /* This is not needed since it sets the bits to zero.*/ - /* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */ - writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); + switch (param) { + case GPIO_U300_CONFIG_BIAS_UNKNOWN: + case GPIO_U300_CONFIG_BIAS_FLOAT: + val = readl(U300_PIN_REG(offset, per)); + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); + break; + case GPIO_U300_CONFIG_BIAS_PULL_UP: + val = readl(U300_PIN_REG(offset, per)); + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); + break; + case GPIO_U300_CONFIG_DRIVE_PUSH_PULL: + val = readl(U300_PIN_REG(offset, pcr)); + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK + << ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + break; + case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: + val = readl(U300_PIN_REG(offset, pcr)); + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK + << ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + break; + case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: + val = readl(U300_PIN_REG(offset, pcr)); + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK + << ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + break; + default: + local_irq_restore(flags); + dev_err(gpio->dev, "illegal configuration requested\n"); + return -EINVAL; + } local_irq_restore(flags); return 0; } -EXPORT_SYMBOL(gpio_direction_input); -int gpio_direction_output(unsigned gpio, int value) +static struct gpio_chip u300_gpio_chip = { + .label = "u300-gpio-chip", + .owner = THIS_MODULE, + .get = u300_gpio_get, + .set = u300_gpio_set, + .direction_input = u300_gpio_direction_input, + .direction_output = u300_gpio_direction_output, + .to_irq = u300_gpio_to_irq, +}; + +static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset) { - unsigned long flags; u32 val; - if (gpio > U300_GPIO_MAX) - return -EINVAL; - - local_irq_save(flags); - val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - /* Mask out this pin */ - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1)); - /* - * FIXME: configure for push/pull, open drain or open source per pin - * in setup. The current driver will only support push/pull. - */ - val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL - << ((gpio & 0x07) << 1)); - writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - gpio_set_value(gpio, value); - local_irq_restore(flags); - return 0; + val = readl(U300_PIN_REG(offset, icr)); + /* Set mode depending on state */ + if (u300_gpio_get(&gpio->chip, offset)) { + /* High now, let's trigger on falling edge next then */ + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + dev_dbg(gpio->dev, "next IRQ on falling edge on pin %d\n", + offset); + } else { + /* Low now, let's trigger on rising edge next then */ + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + dev_dbg(gpio->dev, "next IRQ on rising edge on pin %d\n", + offset); + } } -EXPORT_SYMBOL(gpio_direction_output); -/* - * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0). - */ -void enable_irq_on_gpio_pin(unsigned gpio, int edge) +static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) { + struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = port->gpio; + int offset = d->irq - gpio->irq_base; u32 val; - unsigned long flags; - local_irq_save(flags); - val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - val |= (1 << (gpio & 0x07)); - writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - if (edge) - val |= (1 << (gpio & 0x07)); - else - val &= ~(1 << (gpio & 0x07)); - writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - local_irq_restore(flags); + if ((trigger & IRQF_TRIGGER_RISING) && + (trigger & IRQF_TRIGGER_FALLING)) { + /* + * The GPIO block can only trigger on falling OR rising edges, + * not both. So we need to toggle the mode whenever the pin + * goes from one state to the other with a special state flag + */ + dev_dbg(gpio->dev, + "trigger on both rising and falling edge on pin %d\n", + offset); + port->toggle_edge_mode |= U300_PIN_BIT(offset); + u300_toggle_trigger(gpio, offset); + } else if (trigger & IRQF_TRIGGER_RISING) { + dev_dbg(gpio->dev, "trigger on rising edge on pin %d\n", + offset); + val = readl(U300_PIN_REG(offset, icr)); + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + port->toggle_edge_mode &= ~U300_PIN_BIT(offset); + } else if (trigger & IRQF_TRIGGER_FALLING) { + dev_dbg(gpio->dev, "trigger on falling edge on pin %d\n", + offset); + val = readl(U300_PIN_REG(offset, icr)); + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + port->toggle_edge_mode &= ~U300_PIN_BIT(offset); + } + + return 0; } -EXPORT_SYMBOL(enable_irq_on_gpio_pin); -void disable_irq_on_gpio_pin(unsigned gpio) +static void u300_gpio_irq_enable(struct irq_data *d) { + struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = port->gpio; + int offset = d->irq - gpio->irq_base; u32 val; unsigned long flags; local_irq_save(flags); - val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - val &= ~(1 << (gpio & 0x07)); - writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); + val = readl(U300_PIN_REG(offset, ien)); + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); local_irq_restore(flags); } -EXPORT_SYMBOL(disable_irq_on_gpio_pin); -/* Enable (value == 0) or disable (value == 1) internal pullup */ -void gpio_pullup(unsigned gpio, int value) +static void u300_gpio_irq_disable(struct irq_data *d) { + struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = port->gpio; + int offset = d->irq - gpio->irq_base; u32 val; unsigned long flags; local_irq_save(flags); - if (value) { - val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER + - PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); - } else { - val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) * - U300_GPIO_PORTX_SPACING); - writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER + - PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); - } + val = readl(U300_PIN_REG(offset, ien)); + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); local_irq_restore(flags); } -EXPORT_SYMBOL(gpio_pullup); -static irqreturn_t gpio_irq_handler(int irq, void *dev_id) +static struct irq_chip u300_gpio_irqchip = { + .name = "u300-gpio-irqchip", + .irq_enable = u300_gpio_irq_enable, + .irq_disable = u300_gpio_irq_disable, + .irq_set_type = u300_gpio_irq_type, + +}; + +static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct u300_gpio_port *port = dev_id; - u32 val; - int pin; + struct u300_gpio_port *port = irq_get_handler_data(irq); + struct u300_gpio *gpio = port->gpio; + int pinoffset = port->number << 3; /* get the right stride */ + unsigned long val; + desc->irq_data.chip->irq_ack(&desc->irq_data); /* Read event register */ - val = readl(virtbase + U300_GPIO_PXIEV + port->number * - U300_GPIO_PORTX_SPACING); - /* Mask with enable register */ - val &= readl(virtbase + U300_GPIO_PXIEV + port->number * - U300_GPIO_PORTX_SPACING); + val = readl(U300_PIN_REG(pinoffset, iev)); /* Mask relevant bits */ - val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK; + val &= 0xFFU; /* 8 bits per port */ /* ACK IRQ (clear event) */ - writel(val, virtbase + U300_GPIO_PXIEV + port->number * - U300_GPIO_PORTX_SPACING); - /* Print message */ - while (val != 0) { - unsigned gpio; - - pin = __ffs(val); - /* mask off this pin */ - val &= ~(1 << pin); - gpio = (port->number << 3) + pin; - - if (gpio_pin[gpio].callback) - (void)gpio_pin[gpio].callback(gpio_pin[gpio].data); - else - dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n", - gpio); + writel(val, U300_PIN_REG(pinoffset, iev)); + + /* Call IRQ handler */ + if (val != 0) { + int irqoffset; + + for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { + int pin_irq = gpio->irq_base + (port->number << 3) + + irqoffset; + int offset = pinoffset + irqoffset; + + dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", + pin_irq, offset); + generic_handle_irq(pin_irq); + /* + * Triggering IRQ on both rising and falling edge + * needs mockery + */ + if (port->toggle_edge_mode & U300_PIN_BIT(offset)) + u300_toggle_trigger(gpio, offset); + } } - return IRQ_HANDLED; + + desc->irq_data.chip->irq_unmask(&desc->irq_data); } -static void gpio_set_initial_values(void) +static void __init u300_gpio_init_pin(struct u300_gpio *gpio, + int offset, + const struct u300_gpio_confdata *conf) { -#ifdef U300_COH901571_3 - int i, j; - unsigned long flags; - u32 val; + /* Set mode: input or output */ + if (conf->output) { + u300_gpio_direction_output(&gpio->chip, offset, conf->outval); - /* Write default values to all pins */ - for (i = 0; i < U300_GPIO_NUM_PORTS; i++) { - val = 0; - for (j = 0; j < 8; j++) - val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j; - local_irq_save(flags); - writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING); - local_irq_restore(flags); + /* Deactivate bias mode for output */ + u300_gpio_config(&gpio->chip, offset, + GPIO_U300_CONFIG_BIAS_FLOAT, + NULL); + + /* Set drive mode for output */ + u300_gpio_config(&gpio->chip, offset, + GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL); + + dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n", + offset, conf->outval); + } else { + u300_gpio_direction_input(&gpio->chip, offset); + + /* Always set output low on input pins */ + u300_gpio_set(&gpio->chip, offset, 0); + + /* Set bias mode for input */ + u300_gpio_config(&gpio->chip, offset, conf->bias_mode, NULL); + + dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n", + offset, conf->bias_mode); } +} - /* - * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED' - * to output and 'GPIO_IN' to input for each port. And initialize - * default value on outputs. - */ - for (i = 0; i < U300_GPIO_NUM_PORTS; i++) { - for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) { - local_irq_save(flags); - val = readl(virtbase + U300_GPIO_PXPCR + - i * U300_GPIO_PORTX_SPACING); - /* Mask out this pin */ - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1)); - - if (u300_gpio_config[i][j].pin_usage != GPIO_IN) - val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1)); - writel(val, virtbase + U300_GPIO_PXPCR + - i * U300_GPIO_PORTX_SPACING); - local_irq_restore(flags); +static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio, + struct u300_gpio_platform *plat) +{ + int i, j; + + /* Write default config and values to all pins */ + for (i = 0; i < plat->ports; i++) { + for (j = 0; j < 8; j++) { + const struct u300_gpio_confdata *conf; + int offset = (i*8) + j; + + if (plat->variant == U300_GPIO_COH901571_3_BS335) + conf = &bs335_gpio_config[i][j]; + else if (plat->variant == U300_GPIO_COH901571_3_BS365) + conf = &bs365_gpio_config[i][j]; + else + break; + + u300_gpio_init_pin(gpio, offset, conf); } } +} - /* Enable or disable the internal pull-ups in the GPIO ASIC block */ - for (i = 0; i < U300_GPIO_MAX; i++) { - val = 0; - for (j = 0; j < 8; j++) - val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j); - local_irq_save(flags); - writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING); - local_irq_restore(flags); +static inline void u300_gpio_free_ports(struct u300_gpio *gpio) +{ + struct u300_gpio_port *port; + struct list_head *p, *n; + + list_for_each_safe(p, n, &gpio->port_list) { + port = list_entry(p, struct u300_gpio_port, node); + list_del(&port->node); + free_irq(port->irq, port); + kfree(port); } -#endif } -static int __init gpio_probe(struct platform_device *pdev) +static int __init u300_gpio_probe(struct platform_device *pdev) { - u32 val; + struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev); + struct u300_gpio *gpio; int err = 0; + int portno; + u32 val; + u32 ifr; int i; - int num_irqs; - gpiodev = &pdev->dev; - memset(gpio_pin, 0, sizeof(gpio_pin)); + gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL); + if (gpio == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + gpio->chip = u300_gpio_chip; + gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT; + gpio->irq_base = plat->gpio_irq_base; + gpio->chip.dev = &pdev->dev; + gpio->chip.base = plat->gpio_base; + gpio->dev = &pdev->dev; /* Get GPIO clock */ - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - err = PTR_ERR(clk); - dev_err(gpiodev, "could not get GPIO clock\n"); + gpio->clk = clk_get(gpio->dev, NULL); + if (IS_ERR(gpio->clk)) { + err = PTR_ERR(gpio->clk); + dev_err(gpio->dev, "could not get GPIO clock\n"); goto err_no_clk; } - err = clk_enable(clk); + err = clk_enable(gpio->clk); if (err) { - dev_err(gpiodev, "could not enable GPIO clock\n"); + dev_err(gpio->dev, "could not enable GPIO clock\n"); goto err_no_clk_enable; } - memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!memres) + gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!gpio->memres) { + dev_err(gpio->dev, "could not get GPIO memory resource\n"); + err = -ENODEV; goto err_no_resource; + } - if (!request_mem_region(memres->start, resource_size(memres), + if (!request_mem_region(gpio->memres->start, + resource_size(gpio->memres), "GPIO Controller")) { err = -ENODEV; goto err_no_ioregion; } - virtbase = ioremap(memres->start, resource_size(memres)); - if (!virtbase) { + gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres)); + if (!gpio->base) { err = -ENOMEM; goto err_no_ioremap; } - dev_info(gpiodev, "remapped 0x%08x to %p\n", - memres->start, virtbase); - -#ifdef U300_COH901335 - dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n"); - /* Turn on the GPIO block */ - writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR); -#endif - -#ifdef U300_COH901571_3 - dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n"); - val = readl(virtbase + U300_GPIO_CR); - dev_info(gpiodev, "COH901571/3 block version: %d, " \ - "number of cores: %d\n", - ((val & 0x0000FE00) >> 9), - ((val & 0x000001FC) >> 2)); - writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR); -#endif - - gpio_set_initial_values(); - - for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) { - - gpio_ports[num_irqs].irq = - platform_get_irq_byname(pdev, - gpio_ports[num_irqs].name); - - err = request_irq(gpio_ports[num_irqs].irq, - gpio_irq_handler, IRQF_DISABLED, - gpio_ports[num_irqs].name, - &gpio_ports[num_irqs]); - if (err) { - dev_err(gpiodev, "cannot allocate IRQ for %s!\n", - gpio_ports[num_irqs].name); - goto err_no_irq; + + if (plat->variant == U300_GPIO_COH901335) { + dev_info(gpio->dev, + "initializing GPIO Controller COH 901 335\n"); + gpio->stride = U300_335_PORT_STRIDE; + gpio->pcr = U300_335_PXPCR; + gpio->dor = U300_335_PXPDOR; + gpio->dir = U300_335_PXPDIR; + gpio->per = U300_335_PXPER; + gpio->icr = U300_335_PXICR; + gpio->ien = U300_335_PXIEN; + gpio->iev = U300_335_PXIEV; + ifr = U300_335_PXIFR; + + /* Turn on the GPIO block */ + writel(U300_335_CR_BLOCK_CLOCK_ENABLE, + gpio->base + U300_335_CR); + } else if (plat->variant == U300_GPIO_COH901571_3_BS335 || + plat->variant == U300_GPIO_COH901571_3_BS365) { + dev_info(gpio->dev, + "initializing GPIO Controller COH 901 571/3\n"); + gpio->stride = U300_571_PORT_STRIDE; + gpio->pcr = U300_571_PXPCR; + gpio->dor = U300_571_PXPDOR; + gpio->dir = U300_571_PXPDIR; + gpio->per = U300_571_PXPER; + gpio->icr = U300_571_PXICR; + gpio->ien = U300_571_PXIEN; + gpio->iev = U300_571_PXIEV; + ifr = U300_571_PXIFR; + + val = readl(gpio->base + U300_571_CR); + dev_info(gpio->dev, "COH901571/3 block version: %d, " \ + "number of cores: %d totalling %d pins\n", + ((val & 0x000001FC) >> 2), + ((val & 0x0000FE00) >> 9), + ((val & 0x0000FE00) >> 9) * 8); + writel(U300_571_CR_BLOCK_CLKRQ_ENABLE, + gpio->base + U300_571_CR); + u300_gpio_init_coh901571(gpio, plat); + } else { + dev_err(gpio->dev, "unknown block variant\n"); + err = -ENODEV; + goto err_unknown_variant; + } + + /* Add each port with its IRQ separately */ + INIT_LIST_HEAD(&gpio->port_list); + for (portno = 0 ; portno < plat->ports; portno++) { + struct u300_gpio_port *port = + kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL); + + if (!port) { + dev_err(gpio->dev, "out of memory\n"); + err = -ENOMEM; + goto err_no_port; } - /* Turns off PortX_irq_force */ - writel(0x0, virtbase + U300_GPIO_PXIFR + - num_irqs * U300_GPIO_PORTX_SPACING); + + snprintf(port->name, 8, "gpio%d", portno); + port->number = portno; + port->gpio = gpio; + + port->irq = platform_get_irq_byname(pdev, + port->name); + + dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq, + port->name); + + irq_set_chained_handler(port->irq, u300_gpio_irq_handler); + irq_set_handler_data(port->irq, port); + + /* For each GPIO pin set the unique IRQ handler */ + for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { + int irqno = gpio->irq_base + (portno << 3) + i; + + dev_dbg(gpio->dev, "handler for IRQ %d on %s\n", + irqno, port->name); + irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, + handle_simple_irq); + set_irq_flags(irqno, IRQF_VALID); + irq_set_chip_data(irqno, port); + } + + /* Turns off irq force (test register) for this port */ + writel(0x0, gpio->base + portno * gpio->stride + ifr); + + list_add_tail(&port->node, &gpio->port_list); } + dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno); + + err = gpiochip_add(&gpio->chip); + if (err) { + dev_err(gpio->dev, "unable to add gpiochip: %d\n", err); + goto err_no_chip; + } + + platform_set_drvdata(pdev, gpio); return 0; - err_no_irq: - for (i = 0; i < num_irqs; i++) - free_irq(gpio_ports[i].irq, &gpio_ports[i]); - iounmap(virtbase); - err_no_ioremap: - release_mem_region(memres->start, resource_size(memres)); - err_no_ioregion: - err_no_resource: - clk_disable(clk); - err_no_clk_enable: - clk_put(clk); - err_no_clk: - dev_info(gpiodev, "module ERROR:%d\n", err); +err_no_chip: +err_no_port: + u300_gpio_free_ports(gpio); +err_unknown_variant: + iounmap(gpio->base); +err_no_ioremap: + release_mem_region(gpio->memres->start, resource_size(gpio->memres)); +err_no_ioregion: +err_no_resource: + clk_disable(gpio->clk); +err_no_clk_enable: + clk_put(gpio->clk); +err_no_clk: + kfree(gpio); + dev_info(&pdev->dev, "module ERROR:%d\n", err); return err; } -static int __exit gpio_remove(struct platform_device *pdev) +static int __exit u300_gpio_remove(struct platform_device *pdev) { - int i; + struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev); + struct u300_gpio *gpio = platform_get_drvdata(pdev); + int err; /* Turn off the GPIO block */ - writel(0x00000000U, virtbase + U300_GPIO_CR); - for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++) - free_irq(gpio_ports[i].irq, &gpio_ports[i]); - iounmap(virtbase); - release_mem_region(memres->start, resource_size(memres)); - clk_disable(clk); - clk_put(clk); + if (plat->variant == U300_GPIO_COH901335) + writel(0x00000000U, gpio->base + U300_335_CR); + if (plat->variant == U300_GPIO_COH901571_3_BS335 || + plat->variant == U300_GPIO_COH901571_3_BS365) + writel(0x00000000U, gpio->base + U300_571_CR); + + err = gpiochip_remove(&gpio->chip); + if (err < 0) { + dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err); + return err; + } + u300_gpio_free_ports(gpio); + iounmap(gpio->base); + release_mem_region(gpio->memres->start, + resource_size(gpio->memres)); + clk_disable(gpio->clk); + clk_put(gpio->clk); + platform_set_drvdata(pdev, NULL); + kfree(gpio); return 0; } -static struct platform_driver gpio_driver = { +static struct platform_driver u300_gpio_driver = { .driver = { .name = "u300-gpio", }, - .remove = __exit_p(gpio_remove), + .remove = __exit_p(u300_gpio_remove), }; static int __init u300_gpio_init(void) { - return platform_driver_probe(&gpio_driver, gpio_probe); + return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe); } static void __exit u300_gpio_exit(void) { - platform_driver_unregister(&gpio_driver); + platform_driver_unregister(&u300_gpio_driver); } arch_initcall(u300_gpio_init); module_exit(u300_gpio_exit); MODULE_AUTHOR("Linus Walleij "); - -#ifdef U300_COH901571_3 -MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver"); -#endif - -#ifdef U300_COH901335 -MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver"); -#endif - +MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From ea5abbd215b749b2ff14397a47a5e65741c67bf4 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 26 Sep 2011 19:00:02 +0100 Subject: ARM: 7101/1: arm/tegra: Replace with This will eventually allow to be deleted. This mirrors LinusW's recent equivalent work on various other ARM platforms. Signed-off-by: Stephen Warren Acked-by: Olof Johansson Signed-off-by: Russell King --- arch/arm/mach-tegra/board-harmony.h | 2 ++ arch/arm/mach-tegra/board-paz00.h | 2 ++ arch/arm/mach-tegra/board-seaboard.h | 2 ++ arch/arm/mach-tegra/board-trimslice.h | 2 ++ arch/arm/mach-tegra/include/mach/gpio-tegra.h | 39 +++++++++++++++++++++++++++ arch/arm/mach-tegra/include/mach/gpio.h | 39 --------------------------- arch/arm/mach-tegra/usb_phy.c | 1 + drivers/gpio/gpio-tegra.c | 1 + drivers/mmc/host/sdhci-tegra.c | 2 ++ 9 files changed, 51 insertions(+), 39 deletions(-) create mode 100644 arch/arm/mach-tegra/include/mach/gpio-tegra.h (limited to 'drivers/gpio') diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h index 280d203815a7..139d96c93843 100644 --- a/arch/arm/mach-tegra/board-harmony.h +++ b/arch/arm/mach-tegra/board-harmony.h @@ -17,6 +17,8 @@ #ifndef _MACH_TEGRA_BOARD_HARMONY_H #define _MACH_TEGRA_BOARD_HARMONY_H +#include + #define HARMONY_GPIO_TPS6586X(_x_) (TEGRA_NR_GPIOS + (_x_)) #define HARMONY_GPIO_WM8903(_x_) (HARMONY_GPIO_TPS6586X(4) + (_x_)) diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h index d4ff39ddaeb3..42ce8639b90c 100644 --- a/arch/arm/mach-tegra/board-paz00.h +++ b/arch/arm/mach-tegra/board-paz00.h @@ -17,6 +17,8 @@ #ifndef _MACH_TEGRA_BOARD_PAZ00_H #define _MACH_TEGRA_BOARD_PAZ00_H +#include + #define TEGRA_GPIO_SD1_CD TEGRA_GPIO_PV5 #define TEGRA_GPIO_SD1_WP TEGRA_GPIO_PH1 #define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PT3 diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h index d8415e1a8434..15b6c57361be 100644 --- a/arch/arm/mach-tegra/board-seaboard.h +++ b/arch/arm/mach-tegra/board-seaboard.h @@ -17,6 +17,8 @@ #ifndef _MACH_TEGRA_BOARD_SEABOARD_H #define _MACH_TEGRA_BOARD_SEABOARD_H +#include + #define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5 #define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1 #define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PI6 diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h index 7a7dee86b4da..50f128d87779 100644 --- a/arch/arm/mach-tegra/board-trimslice.h +++ b/arch/arm/mach-tegra/board-trimslice.h @@ -17,6 +17,8 @@ #ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H #define _MACH_TEGRA_BOARD_TRIMSLICE_H +#include + #define TRIMSLICE_GPIO_SD4_CD TEGRA_GPIO_PP1 /* mmc4 cd */ #define TRIMSLICE_GPIO_SD4_WP TEGRA_GPIO_PP2 /* mmc4 wp */ diff --git a/arch/arm/mach-tegra/include/mach/gpio-tegra.h b/arch/arm/mach-tegra/include/mach/gpio-tegra.h new file mode 100644 index 000000000000..87d37fdf5084 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/gpio-tegra.h @@ -0,0 +1,39 @@ +/* + * arch/arm/mach-tegra/include/mach/gpio.h + * + * Copyright (C) 2010 Google, Inc. + * + * Author: + * Erik Gilling + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __MACH_TEGRA_GPIO_TEGRA_H +#define __MACH_TEGRA_GPIO_TEGRA_H + +#include +#include + +#define TEGRA_NR_GPIOS INT_GPIO_NR + +#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio)) + +struct tegra_gpio_table { + int gpio; /* GPIO number */ + bool enable; /* Enable for GPIO at init? */ +}; + +void tegra_gpio_config(struct tegra_gpio_table *table, int num); +void tegra_gpio_enable(int gpio); +void tegra_gpio_disable(int gpio); + +#endif diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h index 7910d26e7133..e69de29bb2d1 100644 --- a/arch/arm/mach-tegra/include/mach/gpio.h +++ b/arch/arm/mach-tegra/include/mach/gpio.h @@ -1,39 +0,0 @@ -/* - * arch/arm/mach-tegra/include/mach/gpio.h - * - * Copyright (C) 2010 Google, Inc. - * - * Author: - * Erik Gilling - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#ifndef __MACH_TEGRA_GPIO_H -#define __MACH_TEGRA_GPIO_H - -#include -#include - -#define TEGRA_NR_GPIOS INT_GPIO_NR - -#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio)) - -struct tegra_gpio_table { - int gpio; /* GPIO number */ - bool enable; /* Enable for GPIO at init? */ -}; - -void tegra_gpio_config(struct tegra_gpio_table *table, int num); -void tegra_gpio_enable(int gpio); -void tegra_gpio_disable(int gpio); - -#endif diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 88081bb3ec52..37576a721aeb 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index df64536464f0..6b65207c8106 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -27,6 +27,7 @@ #include +#include #include #include diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index e9094f14659d..21b00cefae63 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -22,6 +22,8 @@ #include #include + +#include #include #include "sdhci-pltfm.h" -- cgit v1.2.3-59-g8ed1b From bd5f12a24766c1f299def0a78b008d4746f528f2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 22 Sep 2011 08:07:00 +0100 Subject: ARM: 7042/3: mach-ep93xx: break out GPIO driver specifics The file is included from upper directories and deal with generic GPIO and gpiolib stuff. Break out the platform and driver specific defines and functions into its own header file. Cc: Ryan Mallon Acked-by: Hartley Sweeten Acked-by: Grant Likely Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 1 + arch/arm/mach-ep93xx/edb93xx.c | 1 + arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h | 100 ++++++++++++++++++++++ arch/arm/mach-ep93xx/include/mach/gpio.h | 105 ------------------------ arch/arm/mach-ep93xx/simone.c | 2 +- arch/arm/mach-ep93xx/snappercl15.c | 2 +- drivers/gpio/gpio-ep93xx.c | 3 + 7 files changed, 107 insertions(+), 107 deletions(-) create mode 100644 arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h delete mode 100644 arch/arm/mach-ep93xx/include/mach/gpio.h (limited to 'drivers/gpio') diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index c60f081e930b..94c78bc66275 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index 9969bb115f60..3f320c6477bf 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h new file mode 100644 index 000000000000..8aff2ea35877 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h @@ -0,0 +1,100 @@ +/* Include file for the EP93XX GPIO controller machine specifics */ + +#ifndef __GPIO_EP93XX_H +#define __GPIO_EP93XX_H + +/* GPIO port A. */ +#define EP93XX_GPIO_LINE_A(x) ((x) + 0) +#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0) +#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1) +#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2) +#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3) +#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4) +#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5) +#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6) +#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7) + +/* GPIO port B. */ +#define EP93XX_GPIO_LINE_B(x) ((x) + 8) +#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0) +#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1) +#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2) +#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3) +#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4) +#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5) +#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6) +#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) + +/* GPIO port C. */ +#define EP93XX_GPIO_LINE_C(x) ((x) + 40) +#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) +#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) +#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) +#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3) +#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4) +#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5) +#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6) +#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7) + +/* GPIO port D. */ +#define EP93XX_GPIO_LINE_D(x) ((x) + 24) +#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0) +#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1) +#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2) +#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3) +#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4) +#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5) +#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6) +#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7) + +/* GPIO port E. */ +#define EP93XX_GPIO_LINE_E(x) ((x) + 32) +#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0) +#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1) +#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2) +#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3) +#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4) +#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5) +#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6) +#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) + +/* GPIO port F. */ +#define EP93XX_GPIO_LINE_F(x) ((x) + 16) +#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) +#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) +#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) +#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3) +#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4) +#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5) +#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6) +#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7) + +/* GPIO port G. */ +#define EP93XX_GPIO_LINE_G(x) ((x) + 48) +#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0) +#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1) +#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2) +#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3) +#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4) +#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5) +#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6) +#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7) + +/* GPIO port H. */ +#define EP93XX_GPIO_LINE_H(x) ((x) + 56) +#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0) +#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1) +#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2) +#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3) +#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4) +#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5) +#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) +#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) + +/* maximum value for gpio line identifiers */ +#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7) + +/* maximum value for irq capable line identifiers */ +#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) + +#endif /* __GPIO_EP93XX_H */ diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h deleted file mode 100644 index 76c68faca943..000000000000 --- a/arch/arm/mach-ep93xx/include/mach/gpio.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * arch/arm/mach-ep93xx/include/mach/gpio.h - */ - -#ifndef __ASM_ARCH_GPIO_H -#define __ASM_ARCH_GPIO_H - -/* GPIO port A. */ -#define EP93XX_GPIO_LINE_A(x) ((x) + 0) -#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0) -#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1) -#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2) -#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3) -#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4) -#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5) -#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6) -#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7) - -/* GPIO port B. */ -#define EP93XX_GPIO_LINE_B(x) ((x) + 8) -#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0) -#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1) -#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2) -#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3) -#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4) -#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5) -#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6) -#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) - -/* GPIO port C. */ -#define EP93XX_GPIO_LINE_C(x) ((x) + 40) -#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) -#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) -#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) -#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3) -#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4) -#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5) -#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6) -#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7) - -/* GPIO port D. */ -#define EP93XX_GPIO_LINE_D(x) ((x) + 24) -#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0) -#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1) -#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2) -#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3) -#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4) -#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5) -#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6) -#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7) - -/* GPIO port E. */ -#define EP93XX_GPIO_LINE_E(x) ((x) + 32) -#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0) -#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1) -#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2) -#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3) -#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4) -#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5) -#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6) -#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) - -/* GPIO port F. */ -#define EP93XX_GPIO_LINE_F(x) ((x) + 16) -#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) -#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) -#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) -#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3) -#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4) -#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5) -#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6) -#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7) - -/* GPIO port G. */ -#define EP93XX_GPIO_LINE_G(x) ((x) + 48) -#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0) -#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1) -#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2) -#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3) -#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4) -#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5) -#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6) -#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7) - -/* GPIO port H. */ -#define EP93XX_GPIO_LINE_H(x) ((x) + 56) -#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0) -#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1) -#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2) -#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3) -#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4) -#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5) -#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) -#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) - -/* maximum value for gpio line identifiers */ -#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7) - -/* maximum value for irq capable line identifiers */ -#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) - -#define gpio_to_irq __gpio_to_irq -#define irq_to_gpio(irq) ((irq) - gpio_to_irq(0)) - -#endif diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index 8392e95d7cea..1a472ff12cce 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -18,12 +18,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 2e9c614757e4..4f4b0b2c4c31 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include +#include #include #include diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index fbd6a6066777..7aafbb437339 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -23,6 +23,9 @@ #include #include +#include + +#define irq_to_gpio(irq) ((irq) - gpio_to_irq(0)) struct ep93xx_gpio { void __iomem *mmio_base; -- cgit v1.2.3-59-g8ed1b From 354bf8010ffea1ca5accd9fae26b7373df96bcb7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 28 Sep 2011 09:10:54 +0100 Subject: ARM: 7103/1: plat-pxa: move PXA GPIO driver to GPIO subsystem As per example from the other ARM boards, push the PXA GPIO driver down to the GPIO subsystem so it can be consolidated. Acked-by: Eric Miao Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/plat-pxa/Makefile | 1 - arch/arm/plat-pxa/gpio.c | 336 --------------------------------------------- drivers/gpio/Makefile | 1 + drivers/gpio/gpio-pxa.c | 336 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 337 insertions(+), 337 deletions(-) delete mode 100644 arch/arm/plat-pxa/gpio.c create mode 100644 drivers/gpio/gpio-pxa.c (limited to 'drivers/gpio') diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index 3aca5ba0f876..f302d048392d 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -4,7 +4,6 @@ obj-y := dma.o -obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_PXA3xx) += mfp.o obj-$(CONFIG_PXA95x) += mfp.o obj-$(CONFIG_ARCH_MMP) += mfp.o diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c deleted file mode 100644 index 5d6a86bfc68d..000000000000 --- a/arch/arm/plat-pxa/gpio.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * linux/arch/arm/plat-pxa/gpio.c - * - * Generic PXA GPIO handling - * - * Author: Nicolas Pitre - * Created: Jun 15, 2001 - * Copyright: MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include - -int pxa_last_gpio; - -struct pxa_gpio_chip { - struct gpio_chip chip; - void __iomem *regbase; - char label[10]; - - unsigned long irq_mask; - unsigned long irq_edge_rise; - unsigned long irq_edge_fall; - -#ifdef CONFIG_PM - unsigned long saved_gplr; - unsigned long saved_gpdr; - unsigned long saved_grer; - unsigned long saved_gfer; -#endif -}; - -static DEFINE_SPINLOCK(gpio_lock); -static struct pxa_gpio_chip *pxa_gpio_chips; - -#define for_each_gpio_chip(i, c) \ - for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) - -static inline void __iomem *gpio_chip_base(struct gpio_chip *c) -{ - return container_of(c, struct pxa_gpio_chip, chip)->regbase; -} - -static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio) -{ - return &pxa_gpio_chips[gpio_to_bank(gpio)]; -} - -static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - void __iomem *base = gpio_chip_base(chip); - uint32_t value, mask = 1 << offset; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - value = __raw_readl(base + GPDR_OFFSET); - if (__gpio_is_inverted(chip->base + offset)) - value |= mask; - else - value &= ~mask; - __raw_writel(value, base + GPDR_OFFSET); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} - -static int pxa_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - void __iomem *base = gpio_chip_base(chip); - uint32_t tmp, mask = 1 << offset; - unsigned long flags; - - __raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); - - spin_lock_irqsave(&gpio_lock, flags); - - tmp = __raw_readl(base + GPDR_OFFSET); - if (__gpio_is_inverted(chip->base + offset)) - tmp &= ~mask; - else - tmp |= mask; - __raw_writel(tmp, base + GPDR_OFFSET); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} - -static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); -} - -static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - __raw_writel(1 << offset, gpio_chip_base(chip) + - (value ? GPSR_OFFSET : GPCR_OFFSET)); -} - -static int __init pxa_init_gpio_chip(int gpio_end) -{ - int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; - struct pxa_gpio_chip *chips; - - chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL); - if (chips == NULL) { - pr_err("%s: failed to allocate GPIO chips\n", __func__); - return -ENOMEM; - } - - for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { - struct gpio_chip *c = &chips[i].chip; - - sprintf(chips[i].label, "gpio-%d", i); - chips[i].regbase = (void __iomem *)GPIO_BANK(i); - - c->base = gpio; - c->label = chips[i].label; - - c->direction_input = pxa_gpio_direction_input; - c->direction_output = pxa_gpio_direction_output; - c->get = pxa_gpio_get; - c->set = pxa_gpio_set; - - /* number of GPIOs on last bank may be less than 32 */ - c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; - gpiochip_add(c); - } - pxa_gpio_chips = chips; - return 0; -} - -/* Update only those GRERx and GFERx edge detection register bits if those - * bits are set in c->irq_mask - */ -static inline void update_edge_detect(struct pxa_gpio_chip *c) -{ - uint32_t grer, gfer; - - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask; - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask; - grer |= c->irq_edge_rise & c->irq_mask; - gfer |= c->irq_edge_fall & c->irq_mask; - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); -} - -static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) -{ - struct pxa_gpio_chip *c; - int gpio = irq_to_gpio(d->irq); - unsigned long gpdr, mask = GPIO_bit(gpio); - - c = gpio_to_pxachip(gpio); - - if (type == IRQ_TYPE_PROBE) { - /* Don't mess with enabled GPIOs using preconfigured edges or - * GPIOs set to alternate function or to output during probe - */ - if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio)) - return 0; - - if (__gpio_is_occupied(gpio)) - return 0; - - type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; - } - - gpdr = __raw_readl(c->regbase + GPDR_OFFSET); - - if (__gpio_is_inverted(gpio)) - __raw_writel(gpdr | mask, c->regbase + GPDR_OFFSET); - else - __raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET); - - if (type & IRQ_TYPE_EDGE_RISING) - c->irq_edge_rise |= mask; - else - c->irq_edge_rise &= ~mask; - - if (type & IRQ_TYPE_EDGE_FALLING) - c->irq_edge_fall |= mask; - else - c->irq_edge_fall &= ~mask; - - update_edge_detect(c); - - pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio, - ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""), - ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : "")); - return 0; -} - -static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) -{ - struct pxa_gpio_chip *c; - int loop, gpio, gpio_base, n; - unsigned long gedr; - - do { - loop = 0; - for_each_gpio_chip(gpio, c) { - gpio_base = c->chip.base; - - gedr = __raw_readl(c->regbase + GEDR_OFFSET); - gedr = gedr & c->irq_mask; - __raw_writel(gedr, c->regbase + GEDR_OFFSET); - - n = find_first_bit(&gedr, BITS_PER_LONG); - while (n < BITS_PER_LONG) { - loop = 1; - - generic_handle_irq(gpio_to_irq(gpio_base + n)); - n = find_next_bit(&gedr, BITS_PER_LONG, n + 1); - } - } - } while (loop); -} - -static void pxa_ack_muxed_gpio(struct irq_data *d) -{ - int gpio = irq_to_gpio(d->irq); - struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - - __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); -} - -static void pxa_mask_muxed_gpio(struct irq_data *d) -{ - int gpio = irq_to_gpio(d->irq); - struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - uint32_t grer, gfer; - - c->irq_mask &= ~GPIO_bit(gpio); - - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); -} - -static void pxa_unmask_muxed_gpio(struct irq_data *d) -{ - int gpio = irq_to_gpio(d->irq); - struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - - c->irq_mask |= GPIO_bit(gpio); - update_edge_detect(c); -} - -static struct irq_chip pxa_muxed_gpio_chip = { - .name = "GPIO", - .irq_ack = pxa_ack_muxed_gpio, - .irq_mask = pxa_mask_muxed_gpio, - .irq_unmask = pxa_unmask_muxed_gpio, - .irq_set_type = pxa_gpio_irq_type, -}; - -void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) -{ - struct pxa_gpio_chip *c; - int gpio, irq; - - pxa_last_gpio = end; - - /* Initialize GPIO chips */ - pxa_init_gpio_chip(end); - - /* clear all GPIO edge detects */ - for_each_gpio_chip(gpio, c) { - __raw_writel(0, c->regbase + GFER_OFFSET); - __raw_writel(0, c->regbase + GRER_OFFSET); - __raw_writel(~0,c->regbase + GEDR_OFFSET); - } - - for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { - irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, - handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } - - /* Install handler for GPIO>=2 edge detect interrupts */ - irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler); - pxa_muxed_gpio_chip.irq_set_wake = fn; -} - -#ifdef CONFIG_PM -static int pxa_gpio_suspend(void) -{ - struct pxa_gpio_chip *c; - int gpio; - - for_each_gpio_chip(gpio, c) { - c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET); - c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET); - c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET); - c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET); - - /* Clear GPIO transition detect bits */ - __raw_writel(0xffffffff, c->regbase + GEDR_OFFSET); - } - return 0; -} - -static void pxa_gpio_resume(void) -{ - struct pxa_gpio_chip *c; - int gpio; - - for_each_gpio_chip(gpio, c) { - /* restore level with set/clear */ - __raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET); - __raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET); - - __raw_writel(c->saved_grer, c->regbase + GRER_OFFSET); - __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); - __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); - } -} -#else -#define pxa_gpio_suspend NULL -#define pxa_gpio_resume NULL -#endif - -struct syscore_ops pxa_gpio_syscore_ops = { - .suspend = pxa_gpio_suspend, - .resume = pxa_gpio_resume, -}; diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 84bc7389e367..19c5d27b6d2e 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -40,6 +40,7 @@ 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_PLAT_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c new file mode 100644 index 000000000000..5d6a86bfc68d --- /dev/null +++ b/drivers/gpio/gpio-pxa.c @@ -0,0 +1,336 @@ +/* + * linux/arch/arm/plat-pxa/gpio.c + * + * Generic PXA GPIO handling + * + * Author: Nicolas Pitre + * Created: Jun 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +int pxa_last_gpio; + +struct pxa_gpio_chip { + struct gpio_chip chip; + void __iomem *regbase; + char label[10]; + + unsigned long irq_mask; + unsigned long irq_edge_rise; + unsigned long irq_edge_fall; + +#ifdef CONFIG_PM + unsigned long saved_gplr; + unsigned long saved_gpdr; + unsigned long saved_grer; + unsigned long saved_gfer; +#endif +}; + +static DEFINE_SPINLOCK(gpio_lock); +static struct pxa_gpio_chip *pxa_gpio_chips; + +#define for_each_gpio_chip(i, c) \ + for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) + +static inline void __iomem *gpio_chip_base(struct gpio_chip *c) +{ + return container_of(c, struct pxa_gpio_chip, chip)->regbase; +} + +static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio) +{ + return &pxa_gpio_chips[gpio_to_bank(gpio)]; +} + +static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + void __iomem *base = gpio_chip_base(chip); + uint32_t value, mask = 1 << offset; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + value = __raw_readl(base + GPDR_OFFSET); + if (__gpio_is_inverted(chip->base + offset)) + value |= mask; + else + value &= ~mask; + __raw_writel(value, base + GPDR_OFFSET); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} + +static int pxa_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + void __iomem *base = gpio_chip_base(chip); + uint32_t tmp, mask = 1 << offset; + unsigned long flags; + + __raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); + + spin_lock_irqsave(&gpio_lock, flags); + + tmp = __raw_readl(base + GPDR_OFFSET); + if (__gpio_is_inverted(chip->base + offset)) + tmp &= ~mask; + else + tmp |= mask; + __raw_writel(tmp, base + GPDR_OFFSET); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} + +static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); +} + +static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + __raw_writel(1 << offset, gpio_chip_base(chip) + + (value ? GPSR_OFFSET : GPCR_OFFSET)); +} + +static int __init pxa_init_gpio_chip(int gpio_end) +{ + int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; + struct pxa_gpio_chip *chips; + + chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL); + if (chips == NULL) { + pr_err("%s: failed to allocate GPIO chips\n", __func__); + return -ENOMEM; + } + + for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { + struct gpio_chip *c = &chips[i].chip; + + sprintf(chips[i].label, "gpio-%d", i); + chips[i].regbase = (void __iomem *)GPIO_BANK(i); + + c->base = gpio; + c->label = chips[i].label; + + c->direction_input = pxa_gpio_direction_input; + c->direction_output = pxa_gpio_direction_output; + c->get = pxa_gpio_get; + c->set = pxa_gpio_set; + + /* number of GPIOs on last bank may be less than 32 */ + c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; + gpiochip_add(c); + } + pxa_gpio_chips = chips; + return 0; +} + +/* Update only those GRERx and GFERx edge detection register bits if those + * bits are set in c->irq_mask + */ +static inline void update_edge_detect(struct pxa_gpio_chip *c) +{ + uint32_t grer, gfer; + + grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask; + gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask; + grer |= c->irq_edge_rise & c->irq_mask; + gfer |= c->irq_edge_fall & c->irq_mask; + __raw_writel(grer, c->regbase + GRER_OFFSET); + __raw_writel(gfer, c->regbase + GFER_OFFSET); +} + +static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) +{ + struct pxa_gpio_chip *c; + int gpio = irq_to_gpio(d->irq); + unsigned long gpdr, mask = GPIO_bit(gpio); + + c = gpio_to_pxachip(gpio); + + if (type == IRQ_TYPE_PROBE) { + /* Don't mess with enabled GPIOs using preconfigured edges or + * GPIOs set to alternate function or to output during probe + */ + if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio)) + return 0; + + if (__gpio_is_occupied(gpio)) + return 0; + + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + } + + gpdr = __raw_readl(c->regbase + GPDR_OFFSET); + + if (__gpio_is_inverted(gpio)) + __raw_writel(gpdr | mask, c->regbase + GPDR_OFFSET); + else + __raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET); + + if (type & IRQ_TYPE_EDGE_RISING) + c->irq_edge_rise |= mask; + else + c->irq_edge_rise &= ~mask; + + if (type & IRQ_TYPE_EDGE_FALLING) + c->irq_edge_fall |= mask; + else + c->irq_edge_fall &= ~mask; + + update_edge_detect(c); + + pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio, + ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""), + ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : "")); + return 0; +} + +static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) +{ + struct pxa_gpio_chip *c; + int loop, gpio, gpio_base, n; + unsigned long gedr; + + do { + loop = 0; + for_each_gpio_chip(gpio, c) { + gpio_base = c->chip.base; + + gedr = __raw_readl(c->regbase + GEDR_OFFSET); + gedr = gedr & c->irq_mask; + __raw_writel(gedr, c->regbase + GEDR_OFFSET); + + n = find_first_bit(&gedr, BITS_PER_LONG); + while (n < BITS_PER_LONG) { + loop = 1; + + generic_handle_irq(gpio_to_irq(gpio_base + n)); + n = find_next_bit(&gedr, BITS_PER_LONG, n + 1); + } + } + } while (loop); +} + +static void pxa_ack_muxed_gpio(struct irq_data *d) +{ + int gpio = irq_to_gpio(d->irq); + struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); + + __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); +} + +static void pxa_mask_muxed_gpio(struct irq_data *d) +{ + int gpio = irq_to_gpio(d->irq); + struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); + uint32_t grer, gfer; + + c->irq_mask &= ~GPIO_bit(gpio); + + grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); + gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); + __raw_writel(grer, c->regbase + GRER_OFFSET); + __raw_writel(gfer, c->regbase + GFER_OFFSET); +} + +static void pxa_unmask_muxed_gpio(struct irq_data *d) +{ + int gpio = irq_to_gpio(d->irq); + struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); + + c->irq_mask |= GPIO_bit(gpio); + update_edge_detect(c); +} + +static struct irq_chip pxa_muxed_gpio_chip = { + .name = "GPIO", + .irq_ack = pxa_ack_muxed_gpio, + .irq_mask = pxa_mask_muxed_gpio, + .irq_unmask = pxa_unmask_muxed_gpio, + .irq_set_type = pxa_gpio_irq_type, +}; + +void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) +{ + struct pxa_gpio_chip *c; + int gpio, irq; + + pxa_last_gpio = end; + + /* Initialize GPIO chips */ + pxa_init_gpio_chip(end); + + /* clear all GPIO edge detects */ + for_each_gpio_chip(gpio, c) { + __raw_writel(0, c->regbase + GFER_OFFSET); + __raw_writel(0, c->regbase + GRER_OFFSET); + __raw_writel(~0,c->regbase + GEDR_OFFSET); + } + + for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + + /* Install handler for GPIO>=2 edge detect interrupts */ + irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler); + pxa_muxed_gpio_chip.irq_set_wake = fn; +} + +#ifdef CONFIG_PM +static int pxa_gpio_suspend(void) +{ + struct pxa_gpio_chip *c; + int gpio; + + for_each_gpio_chip(gpio, c) { + c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET); + c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET); + c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET); + c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET); + + /* Clear GPIO transition detect bits */ + __raw_writel(0xffffffff, c->regbase + GEDR_OFFSET); + } + return 0; +} + +static void pxa_gpio_resume(void) +{ + struct pxa_gpio_chip *c; + int gpio; + + for_each_gpio_chip(gpio, c) { + /* restore level with set/clear */ + __raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET); + __raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET); + + __raw_writel(c->saved_grer, c->regbase + GRER_OFFSET); + __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); + __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); + } +} +#else +#define pxa_gpio_suspend NULL +#define pxa_gpio_resume NULL +#endif + +struct syscore_ops pxa_gpio_syscore_ops = { + .suspend = pxa_gpio_suspend, + .resume = pxa_gpio_resume, +}; -- cgit v1.2.3-59-g8ed1b From f55be1bf52aad524dc1bf556ae26c90262c87825 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 28 Sep 2011 09:11:30 +0100 Subject: ARM: 7104/1: plat-pxa: break out GPIO driver specifics The file is included from upper directories and deal with generic GPIO and gpiolib stuff. Break out the platform and driver specific defines and functions into its own header file. Cc: Eric Miao Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-mmp/aspenite.c | 1 + arch/arm/mach-mmp/brownstone.c | 1 - arch/arm/mach-mmp/gplugd.c | 2 +- arch/arm/mach-mmp/include/mach/gpio-pxa.h | 30 +++++++ arch/arm/mach-mmp/include/mach/gpio.h | 23 ----- arch/arm/mach-mmp/jasper.c | 1 - arch/arm/mach-mmp/mmp2.c | 2 +- arch/arm/mach-mmp/pxa168.c | 2 +- arch/arm/mach-mmp/pxa910.c | 2 +- arch/arm/mach-mmp/tavorevb.c | 1 + arch/arm/mach-pxa/cm-x255.c | 1 - arch/arm/mach-pxa/include/mach/gpio-pxa.h | 133 +++++++++++++++++++++++++++++ arch/arm/mach-pxa/include/mach/gpio.h | 110 +----------------------- arch/arm/mach-pxa/include/mach/littleton.h | 2 +- arch/arm/mach-pxa/irq.c | 2 +- arch/arm/mach-pxa/mfp-pxa2xx.c | 1 + arch/arm/mach-pxa/pxa25x.c | 1 + arch/arm/mach-pxa/pxa27x.c | 1 + arch/arm/mach-pxa/pxa3xx.c | 2 +- arch/arm/mach-pxa/pxa95x.c | 2 +- arch/arm/mach-pxa/saarb.c | 1 + arch/arm/plat-pxa/include/plat/gpio-pxa.h | 44 ++++++++++ arch/arm/plat-pxa/include/plat/gpio.h | 40 +-------- drivers/gpio/gpio-pxa.c | 2 + 24 files changed, 227 insertions(+), 180 deletions(-) create mode 100644 arch/arm/mach-mmp/include/mach/gpio-pxa.h create mode 100644 arch/arm/mach-pxa/include/mach/gpio-pxa.h create mode 100644 arch/arm/plat-pxa/include/plat/gpio-pxa.h (limited to 'drivers/gpio') diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index cf875189132e..833c3a2784aa 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index c79162a50f28..e411252e3d39 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index c070c24255f4..ef738deb20b5 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -9,11 +9,11 @@ */ #include +#include #include #include -#include #include #include #include diff --git a/arch/arm/mach-mmp/include/mach/gpio-pxa.h b/arch/arm/mach-mmp/include/mach/gpio-pxa.h new file mode 100644 index 000000000000..c017a983eced --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/gpio-pxa.h @@ -0,0 +1,30 @@ +#ifndef __ASM_MACH_GPIO_PXA_H +#define __ASM_MACH_GPIO_PXA_H + +#include +#include + +#define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000) + +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) +#define GPIO_REG(x) (*((volatile u32 *)(GPIO_REGS_VIRT + (x)))) + +#define NR_BUILTIN_GPIO IRQ_GPIO_NUM + +#define gpio_to_bank(gpio) ((gpio) >> 5) + +/* NOTE: these macros are defined here to make optimization of + * gpio_{get,set}_value() to work when 'gpio' is a constant. + * Usage of these macros otherwise is no longer recommended, + * use generic GPIO API whenever possible. + */ +#define GPIO_bit(gpio) (1 << ((gpio) & 0x1f)) + +#define GPLR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00) +#define GPDR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c) +#define GPSR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18) +#define GPCR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24) + +#include + +#endif /* __ASM_MACH_GPIO_PXA_H */ diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h index 7bfb827f3fe3..681262359d1c 100644 --- a/arch/arm/mach-mmp/include/mach/gpio.h +++ b/arch/arm/mach-mmp/include/mach/gpio.h @@ -1,36 +1,13 @@ #ifndef __ASM_MACH_GPIO_H #define __ASM_MACH_GPIO_H -#include -#include #include -#define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000) - -#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) -#define GPIO_REG(x) (*((volatile u32 *)(GPIO_REGS_VIRT + (x)))) - -#define NR_BUILTIN_GPIO IRQ_GPIO_NUM - -#define gpio_to_bank(gpio) ((gpio) >> 5) #define gpio_to_irq(gpio) (IRQ_GPIO_START + (gpio)) #define irq_to_gpio(irq) ((irq) - IRQ_GPIO_START) - #define __gpio_is_inverted(gpio) (0) #define __gpio_is_occupied(gpio) (0) -/* NOTE: these macros are defined here to make optimization of - * gpio_{get,set}_value() to work when 'gpio' is a constant. - * Usage of these macros otherwise is no longer recommended, - * use generic GPIO API whenever possible. - */ -#define GPIO_bit(gpio) (1 << ((gpio) & 0x1f)) - -#define GPLR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00) -#define GPDR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c) -#define GPSR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18) -#define GPCR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24) - #include #endif /* __ASM_MACH_GPIO_H */ diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c index 5d6421d63254..8bfac6612623 100644 --- a/arch/arm/mach-mmp/jasper.c +++ b/arch/arm/mach-mmp/jasper.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index 19358344a4a4..65d8689e40c9 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -9,7 +9,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include @@ -25,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 958155167807..50c1763911ff 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -7,7 +7,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include @@ -21,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c index c70b4dd359f6..4ebbfbba39fc 100644 --- a/arch/arm/mach-mmp/pxa910.c +++ b/arch/arm/mach-mmp/pxa910.c @@ -7,7 +7,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include @@ -20,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c index 143e52ede8ef..eb5be879fd8c 100644 --- a/arch/arm/mach-mmp/tavorevb.c +++ b/arch/arm/mach-mmp/tavorevb.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c index 93f59f877fc6..be751470d37b 100644 --- a/arch/arm/mach-pxa/cm-x255.c +++ b/arch/arm/mach-pxa/cm-x255.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-pxa/include/mach/gpio-pxa.h b/arch/arm/mach-pxa/include/mach/gpio-pxa.h new file mode 100644 index 000000000000..41b4c93a96c2 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/gpio-pxa.h @@ -0,0 +1,133 @@ +/* + * Written by Philipp Zabel + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __MACH_PXA_GPIO_PXA_H +#define __MACH_PXA_GPIO_PXA_H + +#include +#include + +#define GPIO_REGS_VIRT io_p2v(0x40E00000) + +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) +#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x))) + +/* GPIO Pin Level Registers */ +#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00) +#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00) +#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00) +#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00) + +/* GPIO Pin Direction Registers */ +#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c) +#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c) +#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c) +#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c) + +/* GPIO Pin Output Set Registers */ +#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18) +#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18) +#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18) +#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18) + +/* GPIO Pin Output Clear Registers */ +#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24) +#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24) +#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24) +#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24) + +/* GPIO Rising Edge Detect Registers */ +#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30) +#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30) +#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30) +#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30) + +/* GPIO Falling Edge Detect Registers */ +#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c) +#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c) +#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c) +#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c) + +/* GPIO Edge Detect Status Registers */ +#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48) +#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48) +#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48) +#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48) + +/* GPIO Alternate Function Select Registers */ +#define GAFR0_L GPIO_REG(0x0054) +#define GAFR0_U GPIO_REG(0x0058) +#define GAFR1_L GPIO_REG(0x005C) +#define GAFR1_U GPIO_REG(0x0060) +#define GAFR2_L GPIO_REG(0x0064) +#define GAFR2_U GPIO_REG(0x0068) +#define GAFR3_L GPIO_REG(0x006C) +#define GAFR3_U GPIO_REG(0x0070) + +/* More handy macros. The argument is a literal GPIO number. */ + +#define GPIO_bit(x) (1 << ((x) & 0x1f)) + +#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00) +#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c) +#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18) +#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24) +#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30) +#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c) +#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48) +#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2)) + + +#define NR_BUILTIN_GPIO PXA_GPIO_IRQ_NUM + +#define gpio_to_bank(gpio) ((gpio) >> 5) + +#ifdef CONFIG_CPU_PXA26x +/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, + * as well as their Alternate Function value being '1' for GPIO in GAFRx. + */ +static inline int __gpio_is_inverted(unsigned gpio) +{ + return cpu_is_pxa25x() && gpio > 85; +} +#else +static inline int __gpio_is_inverted(unsigned gpio) { return 0; } +#endif + +/* + * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate + * function of a GPIO, and GPDRx cannot be altered once configured. It + * is attributed as "occupied" here (I know this terminology isn't + * accurate, you are welcome to propose a better one :-) + */ +static inline int __gpio_is_occupied(unsigned gpio) +{ + if (cpu_is_pxa27x() || cpu_is_pxa25x()) { + int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; + int dir = GPDR(gpio) & GPIO_bit(gpio); + + if (__gpio_is_inverted(gpio)) + return af != 1 || dir == 0; + else + return af != 0 || dir != 0; + } else + return GPDR(gpio) & GPIO_bit(gpio); +} + +#include +#endif /* __MACH_PXA_GPIO_PXA_H */ diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index c4639502efca..004cade7bb13 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -24,84 +24,10 @@ #ifndef __ASM_ARCH_PXA_GPIO_H #define __ASM_ARCH_PXA_GPIO_H -#include -#include #include +/* The defines for the driver are needed for the accelerated accessors */ +#include "gpio-pxa.h" -#define GPIO_REGS_VIRT io_p2v(0x40E00000) - -#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) -#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x))) - -/* GPIO Pin Level Registers */ -#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00) -#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00) -#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00) -#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00) - -/* GPIO Pin Direction Registers */ -#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c) -#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c) -#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c) -#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c) - -/* GPIO Pin Output Set Registers */ -#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18) -#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18) -#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18) -#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18) - -/* GPIO Pin Output Clear Registers */ -#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24) -#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24) -#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24) -#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24) - -/* GPIO Rising Edge Detect Registers */ -#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30) -#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30) -#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30) -#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30) - -/* GPIO Falling Edge Detect Registers */ -#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c) -#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c) -#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c) -#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c) - -/* GPIO Edge Detect Status Registers */ -#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48) -#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48) -#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48) -#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48) - -/* GPIO Alternate Function Select Registers */ -#define GAFR0_L GPIO_REG(0x0054) -#define GAFR0_U GPIO_REG(0x0058) -#define GAFR1_L GPIO_REG(0x005C) -#define GAFR1_U GPIO_REG(0x0060) -#define GAFR2_L GPIO_REG(0x0064) -#define GAFR2_U GPIO_REG(0x0068) -#define GAFR3_L GPIO_REG(0x006C) -#define GAFR3_U GPIO_REG(0x0070) - -/* More handy macros. The argument is a literal GPIO number. */ - -#define GPIO_bit(x) (1 << ((x) & 0x1f)) - -#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00) -#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c) -#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18) -#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24) -#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30) -#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c) -#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48) -#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2)) - - -#define NR_BUILTIN_GPIO PXA_GPIO_IRQ_NUM - -#define gpio_to_bank(gpio) ((gpio) >> 5) #define gpio_to_irq(gpio) IRQ_GPIO(gpio) static inline int irq_to_gpio(unsigned int irq) @@ -118,37 +44,5 @@ static inline int irq_to_gpio(unsigned int irq) return -1; } -#ifdef CONFIG_CPU_PXA26x -/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, - * as well as their Alternate Function value being '1' for GPIO in GAFRx. - */ -static inline int __gpio_is_inverted(unsigned gpio) -{ - return cpu_is_pxa25x() && gpio > 85; -} -#else -static inline int __gpio_is_inverted(unsigned gpio) { return 0; } -#endif - -/* - * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate - * function of a GPIO, and GPDRx cannot be altered once configured. It - * is attributed as "occupied" here (I know this terminology isn't - * accurate, you are welcome to propose a better one :-) - */ -static inline int __gpio_is_occupied(unsigned gpio) -{ - if (cpu_is_pxa27x() || cpu_is_pxa25x()) { - int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; - int dir = GPDR(gpio) & GPIO_bit(gpio); - - if (__gpio_is_inverted(gpio)) - return af != 1 || dir == 0; - else - return af != 0 || dir != 0; - } else - return GPDR(gpio) & GPIO_bit(gpio); -} - #include #endif diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h index 1c585a79a1c1..b6238cbd8aea 100644 --- a/arch/arm/mach-pxa/include/mach/littleton.h +++ b/arch/arm/mach-pxa/include/mach/littleton.h @@ -1,7 +1,7 @@ #ifndef __ASM_ARCH_LITTLETON_H #define __ASM_ARCH_LITTLETON_H -#include +#include #define LITTLETON_ETH_PHYS 0x30000000 diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index dafb4bf6349e..d493a230addf 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -11,7 +11,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include @@ -21,6 +20,7 @@ #include #include +#include #include "generic.h" diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index b129527832cb..43a5f6861ca3 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -20,6 +20,7 @@ #include #include +#include #include "generic.h" diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 6bb3fa5d85ee..8746e1090b6e 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index d2cdcd6ead25..2bb5cf8ba6ec 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 3ab9e8471e60..f940a1345531 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -12,7 +12,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include @@ -26,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c index de25cebf78aa..51371b39d2a3 100644 --- a/arch/arm/mach-pxa/pxa95x.c +++ b/arch/arm/mach-pxa/pxa95x.c @@ -9,7 +9,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include @@ -21,6 +20,7 @@ #include #include +#include #include #include #include diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c index 87e9b757ef34..eb6a10d85b03 100644 --- a/arch/arm/mach-pxa/saarb.c +++ b/arch/arm/mach-pxa/saarb.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/plat-pxa/include/plat/gpio-pxa.h b/arch/arm/plat-pxa/include/plat/gpio-pxa.h new file mode 100644 index 000000000000..b6390beff323 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/gpio-pxa.h @@ -0,0 +1,44 @@ +#ifndef __PLAT_PXA_GPIO_H +#define __PLAT_PXA_GPIO_H + +struct irq_data; + +/* + * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with + * one set of registers. The register offsets are organized below: + * + * GPLR GPDR GPSR GPCR GRER GFER GEDR + * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 + * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C + * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 + * + * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 + * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C + * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 + * + * NOTE: + * BANK 3 is only available on PXA27x and later processors. + * BANK 4 and 5 are only available on PXA935 + */ + +#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 + +/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). + * Those cases currently cause holes in the GPIO number space, the + * actual number of the last GPIO is recorded by 'pxa_last_gpio'. + */ +extern int pxa_last_gpio; + +typedef int (*set_wake_t)(struct irq_data *d, unsigned int on); + +extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); + +#endif /* __PLAT_PXA_GPIO_H */ diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h index 6fc41db93e1c..258f77210b02 100644 --- a/arch/arm/plat-pxa/include/plat/gpio.h +++ b/arch/arm/plat-pxa/include/plat/gpio.h @@ -3,35 +3,8 @@ #define __ARM_GPIOLIB_COMPLEX -struct irq_data; - -/* - * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with - * one set of registers. The register offsets are organized below: - * - * GPLR GPDR GPSR GPCR GRER GFER GEDR - * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 - * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C - * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 - * - * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 - * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C - * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 - * - * NOTE: - * BANK 3 is only available on PXA27x and later processors. - * BANK 4 and 5 are only available on PXA935 - */ - -#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) - -#define GPLR_OFFSET 0x00 -#define GPDR_OFFSET 0x0C -#define GPSR_OFFSET 0x18 -#define GPCR_OFFSET 0x24 -#define GRER_OFFSET 0x30 -#define GFER_OFFSET 0x3C -#define GEDR_OFFSET 0x48 +/* The individual machine provides register offsets and NR_BUILTIN_GPIO */ +#include static inline int gpio_get_value(unsigned gpio) { @@ -54,13 +27,4 @@ static inline void gpio_set_value(unsigned gpio, int value) #define gpio_cansleep __gpio_cansleep -/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). - * Those cases currently cause holes in the GPIO number space, the - * actual number of the last GPIO is recorded by 'pxa_last_gpio'. - */ -extern int pxa_last_gpio; - -typedef int (*set_wake_t)(struct irq_data *d, unsigned int on); - -extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); #endif /* __PLAT_GPIO_H */ diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 5d6a86bfc68d..9052925c6fa2 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -18,6 +18,8 @@ #include #include +#include + int pxa_last_gpio; struct pxa_gpio_chip { -- cgit v1.2.3-59-g8ed1b