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 diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile index 7e3e816..853efd9 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 b3fdfe1..0000000 --- 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 9588948..27295cb 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 0000000..b3fdfe1 --- /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 v0.10.2