diff options
Diffstat (limited to 'target/linux/adm8668/files/arch/mips')
-rw-r--r-- | target/linux/adm8668/files/arch/mips/adm8668/gpio.c | 123 | ||||
-rw-r--r-- | target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h | 13 |
2 files changed, 136 insertions, 0 deletions
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 000000000..fb39f7f58 --- /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 000000000..b0473fc4b --- /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 |