diff options
author | Florian Fainelli <florian@openwrt.org> | 2012-12-06 22:41:04 +0000 |
---|---|---|
committer | Florian Fainelli <florian@openwrt.org> | 2012-12-06 22:41:04 +0000 |
commit | 5d23ae4a89f2da38a6b436417ec24c9c60b8a857 (patch) | |
tree | e6ee6ad7b5fe7adb0491f95a3f6bc0e35a10bd4c | |
parent | 9efcb6346bbde19ccb05770abc0d44c167940419 (diff) | |
download | upstream-5d23ae4a89f2da38a6b436417ec24c9c60b8a857.tar.gz upstream-5d23ae4a89f2da38a6b436417ec24c9c60b8a857.tar.bz2 upstream-5d23ae4a89f2da38a6b436417ec24c9c60b8a857.zip |
[adm8668] add a gpiolib driver
Signed-off-by: Florian Fainelli <florian@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34564 3c298f89-4303-0410-b956-a3cf2f4a3e73
4 files changed, 143 insertions, 2 deletions
diff --git a/target/linux/adm8668/config-3.3 b/target/linux/adm8668/config-3.3 index 169245d1cc..e63f14053c 100644 --- a/target/linux/adm8668/config-3.3 +++ b/target/linux/adm8668/config-3.3 @@ -2,6 +2,7 @@ CONFIG_ADM8668=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y CONFIG_ARCH_DISCARD_MEMBLOCK=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARM_AMBA=y # CONFIG_ARM_SP805_WATCHDOG is not set @@ -31,8 +32,11 @@ CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y diff --git a/target/linux/adm8668/files/arch/mips/adm8668/gpio.c b/target/linux/adm8668/files/arch/mips/adm8668/gpio.c new file mode 100644 index 0000000000..fb39f7f588 --- /dev/null +++ b/target/linux/adm8668/files/arch/mips/adm8668/gpio.c @@ -0,0 +1,123 @@ +/* + * Infineon/ADMTek ADM8668 WildPass GPIO support + * + * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org> + * + * Licensed under the terms of GPLv2. + * + */ +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/io.h> + +#include <adm8668.h> + +#define GPIO_MASK 0x3f + +#define GPIO_IN_OFS 0 +#define GPIO_OUT_OFS 6 +#define GPIO_OE_OFS 12 + +struct adm8668_gpio_chip { + void __iomem *base; + struct gpio_chip chip; +}; + +static int adm8668_gpio_dir_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct adm8668_gpio_chip *c = + container_of(chip, struct adm8668_gpio_chip, chip); + u32 mask; + + /* clear input, set output enable and output value */ + mask = __raw_readl(c->base); + mask &= ~(1 << offset); + mask |= (1 << (offset + GPIO_OE_OFS)); + if (value) + mask |= (1 << (offset + GPIO_OUT_OFS)); + else + mask &= ~(1 << (offset + GPIO_OUT_OFS)); + __raw_writel(mask, c->base); + + return 0; +} + +static int adm8668_gpio_dir_in(struct gpio_chip *chip, + unsigned offset) +{ + struct adm8668_gpio_chip *c = + container_of(chip, struct adm8668_gpio_chip, chip); + u32 mask; + + mask = __raw_readl(c->base); + mask &= ~(((1 << (offset + GPIO_OE_OFS)) | (1 << (offset + GPIO_OUT_OFS)))); + mask |= (1 << offset); + __raw_writel(mask, c->base); + + return 0; +} + +static void adm8668_gpio_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct adm8668_gpio_chip *c = + container_of(chip, struct adm8668_gpio_chip, chip); + u32 mask; + + mask = __raw_readl(c->base); + if (value) + mask |= (1 << (offset + GPIO_OUT_OFS)); + else + mask &= ~(1 << (offset + GPIO_OUT_OFS)); + __raw_writel(mask, c->base); +} + +static int adm8668_gpio_get(struct gpio_chip *chip, + unsigned offset) +{ + struct adm8668_gpio_chip *c = + container_of(chip, struct adm8668_gpio_chip, chip); + u32 value; + + value = __raw_readl(c->base) & GPIO_MASK; + + return value & (1 << offset); +} + +static struct adm8668_gpio_chip adm8668_gpio_cpu = { + .base = (void __iomem *)KSEG1ADDR(ADM8668_CONFIG_BASE + CRGPIO_REG), + .chip = { + .label = "adm8668-cpu-gpio", + .direction_output = adm8668_gpio_dir_out, + .direction_input = adm8668_gpio_dir_in, + .set = adm8668_gpio_set, + .get = adm8668_gpio_get, + .ngpio = 6, + }, +}; + +static struct adm8668_gpio_chip adm8668_gpio_wlan = { + .base = (void __iomem *)KSEG1ADDR(ADM8668_WLAN_BASE + GPIO_REG), + .chip = { + .label = "adm8668-wlan-gpio", + .direction_output = adm8668_gpio_dir_out, + .direction_input = adm8668_gpio_dir_in, + .set = adm8668_gpio_set, + .get = adm8668_gpio_get, + .ngpio = 6, + .base = 6, + }, +}; + +static int __init adm8668_gpio_init(void) +{ + int ret; + + ret = gpiochip_add(&adm8668_gpio_cpu.chip); + if (ret) + return ret; + + return gpiochip_add(&adm8668_gpio_wlan.chip); +} +arch_initcall(adm8668_gpio_init); diff --git a/target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h b/target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h new file mode 100644 index 0000000000..b0473fc4b3 --- /dev/null +++ b/target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h @@ -0,0 +1,13 @@ +#ifndef __ADM8668_GPIO_H__ +#define __ADM8668_GPIO_H__ + +#define gpio_to_irq(gpio) -1 + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value + +#define gpio_cansleep __gpio_cansleep + +#include <asm-generic/gpio.h> + +#endif diff --git a/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch b/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch index 66be46c8d0..1d52bcf97d 100644 --- a/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch +++ b/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch @@ -10,7 +10,7 @@ include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -105,6 +105,25 @@ config BCM47XX +@@ -105,6 +105,26 @@ config BCM47XX help Support for BCM47XX based boards @@ -29,6 +29,7 @@ + select DMA_NONCOHERENT + select SWAP_IO_SPACE + select SYS_HAS_EARLY_PRINTK ++ select ARCH_REQUIRE_GPIOLIB + help + ADM8668 board support by neutronscott + Scott Nicholas <neutronscott@scottn.us> @@ -36,7 +37,7 @@ config BCM63XX bool "Broadcom BCM63XX based boards" select CEVT_R4K -@@ -813,6 +832,7 @@ config NLM_XLP_BOARD +@@ -813,6 +833,7 @@ config NLM_XLP_BOARD endchoice |