From: Atsushi Nemoto Date: Fri, 22 Jun 2007 14:21:55 +0000 (+0900) Subject: [MIPS] rbtx4938: Add generic GPIO support X-Git-Tag: v2.6.23-rc1~1153^2~21 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3896b05418b9b8548a678231db754206b3ebe56e;p=linux-2.6 [MIPS] rbtx4938: Add generic GPIO support GPIO 0..15 are for TX4938 PIO pins, GPIO 16..18 are for FPGA-driven chipselect signals for SPI devices. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 24661d60bc..823a6285c5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -660,6 +660,7 @@ config TOSHIBA_RBTX4938 select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_KGDB select GENERIC_HARDIRQS_NO__DO_IRQ + select GENERIC_GPIO help This Toshiba board is based on the TX4938 processor. Say Y here to support this machine type diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig index b0abd16fae..6e10c15cec 100644 --- a/arch/mips/configs/rbhma4500_defconfig +++ b/arch/mips/configs/rbhma4500_defconfig @@ -80,6 +80,7 @@ CONFIG_DMA_NONCOHERENT=y CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_GENERIC_ISA_DMA=y CONFIG_I8259=y +CONFIG_GENERIC_GPIO=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index f5d1ce739f..12b9f4f9c3 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef CONFIG_SERIAL_TXX9 #include @@ -1057,3 +1058,106 @@ static int __init rbtx4938_ne_init(void) return IS_ERR(dev) ? PTR_ERR(dev) : 0; } device_initcall(rbtx4938_ne_init); + +/* GPIO support */ + +static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock); + +static void rbtx4938_spi_gpio_set(unsigned gpio, int value) +{ + u8 val; + unsigned long flags; + gpio -= 16; + spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags); + val = *rbtx4938_spics_ptr; + if (value) + val |= 1 << gpio; + else + val &= ~(1 << gpio); + *rbtx4938_spics_ptr = val; + mmiowb(); + spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags); +} + +static int rbtx4938_spi_gpio_dir_out(unsigned gpio, int value) +{ + rbtx4938_spi_gpio_set(gpio, value); + return 0; +} + +static DEFINE_SPINLOCK(tx4938_gpio_lock); + +static int tx4938_gpio_get(unsigned gpio) +{ + return tx4938_pioptr->din & (1 << gpio); +} + +static void tx4938_gpio_set_raw(unsigned gpio, int value) +{ + u32 val; + val = tx4938_pioptr->dout; + if (value) + val |= 1 << gpio; + else + val &= ~(1 << gpio); + tx4938_pioptr->dout = val; +} + +static void tx4938_gpio_set(unsigned gpio, int value) +{ + unsigned long flags; + spin_lock_irqsave(&tx4938_gpio_lock, flags); + tx4938_gpio_set_raw(gpio, value); + mmiowb(); + spin_unlock_irqrestore(&tx4938_gpio_lock, flags); +} + +static int tx4938_gpio_dir_in(unsigned gpio) +{ + spin_lock_irq(&tx4938_gpio_lock); + tx4938_pioptr->dir &= ~(1 << gpio); + mmiowb(); + spin_unlock_irq(&tx4938_gpio_lock); + return 0; +} + +static int tx4938_gpio_dir_out(unsigned int gpio, int value) +{ + spin_lock_irq(&tx4938_gpio_lock); + tx4938_gpio_set_raw(gpio, value); + tx4938_pioptr->dir |= 1 << gpio; + mmiowb(); + spin_unlock_irq(&tx4938_gpio_lock); + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + if (gpio < 16) + return tx4938_gpio_dir_in(gpio); + return -EINVAL; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + if (gpio < 16) + return tx4938_gpio_dir_out(gpio, value); + if (gpio < 16 + 3) + return rbtx4938_spi_gpio_dir_out(gpio, value); + return -EINVAL; +} + +int gpio_get_value(unsigned gpio) +{ + if (gpio < 16) + return tx4938_gpio_get(gpio); + return 0; +} + +void gpio_set_value(unsigned gpio, int value) +{ + if (gpio < 16) + tx4938_gpio_set(gpio, value); + else + rbtx4938_spi_gpio_set(gpio, value); +}