diff options
Diffstat (limited to 'target/linux/cns21xx/patches-3.7/005-arm-add-fa-gpio-driver.patch')
-rw-r--r-- | target/linux/cns21xx/patches-3.7/005-arm-add-fa-gpio-driver.patch | 343 |
1 files changed, 0 insertions, 343 deletions
diff --git a/target/linux/cns21xx/patches-3.7/005-arm-add-fa-gpio-driver.patch b/target/linux/cns21xx/patches-3.7/005-arm-add-fa-gpio-driver.patch deleted file mode 100644 index d7e8e88..0000000 --- a/target/linux/cns21xx/patches-3.7/005-arm-add-fa-gpio-driver.patch +++ /dev/null @@ -1,343 +0,0 @@ ---- /dev/null -+++ b/arch/arm/plat-fa/gpio.c -@@ -0,0 +1,283 @@ -+/* -+ * Gpiochip and interrupt routines for Faraday FA526 based SoCs -+ * -+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> -+ * Copyright (C) 2010-2012 Gabor Juhos <juhosg@openwrt.org> -+ * -+ * Based on plat-mxc/gpio.c: -+ * MXC GPIO supchip. (c) 2008 Daniel Mack <daniel@caiaq.de> -+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de -+ * -+ * 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 <linux/spinlock.h> -+ -+#include <plat/gpio.h> -+ -+#define GPIO_DATA_OUT 0x0 -+#define GPIO_DATA_IN 0x4 -+#define GPIO_DIR 0x8 -+#define GPIO_DATA_SET 0x10 -+#define GPIO_DATA_CLR 0x14 -+#define GPIO_PULL_EN 0x18 -+#define GPIO_PULL_TYPE 0x1C -+#define GPIO_INT_EN 0x20 -+#define GPIO_INT_STAT 0x24 -+#define GPIO_INT_MASK 0x2C -+#define GPIO_INT_CLR 0x30 -+#define GPIO_INT_TYPE 0x34 -+#define GPIO_INT_BOTH_EDGE 0x38 -+#define GPIO_INT_LEVEL 0x3C -+#define GPIO_DEBOUNCE_EN 0x40 -+#define GPIO_DEBOUNCE_PRESCALE 0x44 -+ -+#define GPIO_REGS_SIZE 0x48 -+ -+static DEFINE_SPINLOCK(fa_gpio_lock); -+ -+static inline struct fa_gpio_chip *to_fgc(struct gpio_chip *chip) -+{ -+ return container_of(chip, struct fa_gpio_chip, gpio_chip); -+} -+ -+static void _fa_gpio_irq_setenable(struct irq_data *d, int enable) -+{ -+ struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq); -+ void __iomem *base = fgc->mem_base; -+ unsigned int gpio = d->irq - fgc->irq_base; -+ unsigned int reg; -+ -+ reg = __raw_readl(base + GPIO_INT_EN); -+ reg = (reg & (~(1 << gpio))) | (!!enable << gpio); -+ __raw_writel(reg, base + GPIO_INT_EN); -+} -+ -+static void fa_gpio_irq_ack(struct irq_data *d) -+{ -+ struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq); -+ unsigned int gpio = d->irq - fgc->irq_base; -+ -+ __raw_writel(1 << gpio, fgc->mem_base + GPIO_INT_CLR); -+} -+ -+static void fa_gpio_irq_mask(struct irq_data *d) -+{ -+ _fa_gpio_irq_setenable(d, 0); -+} -+ -+static void fa_gpio_irq_unmask(struct irq_data *d) -+{ -+ _fa_gpio_irq_setenable(d, 1); -+} -+ -+static int fa_gpio_irq_set_type(struct irq_data *d, unsigned int type) -+{ -+ struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq); -+ void __iomem *base = fgc->mem_base; -+ unsigned int gpio = d->irq - fgc->irq_base; -+ unsigned int gpio_mask = 1 << gpio; -+ unsigned int reg_both, reg_level, reg_type; -+ -+ reg_type = __raw_readl(base + GPIO_INT_TYPE); -+ reg_level = __raw_readl(base + GPIO_INT_LEVEL); -+ reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE); -+ -+ switch (type) { -+ case IRQ_TYPE_EDGE_BOTH: -+ reg_type &= ~gpio_mask; -+ reg_both |= gpio_mask; -+ break; -+ case IRQ_TYPE_EDGE_RISING: -+ reg_type &= ~gpio_mask; -+ reg_both &= ~gpio_mask; -+ reg_level &= ~gpio_mask; -+ break; -+ case IRQ_TYPE_EDGE_FALLING: -+ reg_type &= ~gpio_mask; -+ reg_both &= ~gpio_mask; -+ reg_level |= gpio_mask; -+ break; -+ case IRQ_TYPE_LEVEL_HIGH: -+ reg_type |= gpio_mask; -+ reg_level &= ~gpio_mask; -+ break; -+ case IRQ_TYPE_LEVEL_LOW: -+ reg_type |= gpio_mask; -+ reg_level |= gpio_mask; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ __raw_writel(reg_type, base + GPIO_INT_TYPE); -+ __raw_writel(reg_level, base + GPIO_INT_LEVEL); -+ __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE); -+ -+ fa_gpio_irq_ack(d); -+ -+ return 0; -+} -+ -+static void fa_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -+{ -+ struct fa_gpio_data *data = irq_get_handler_data(irq); -+ unsigned int chip; -+ -+ for (chip = 0; chip < data->nchips; chip++) { -+ struct fa_gpio_chip *fgc = &data->chips[chip]; -+ unsigned int status; -+ unsigned int i; -+ -+ status = __raw_readl(fgc->mem_base + GPIO_INT_STAT); -+ for (i = fgc->irq_base; status != 0; status >>= 1, i++) { -+ if ((status & 1) == 0) -+ continue; -+ -+ BUG_ON(!(irq_desc[i].handle_irq)); -+ irq_desc[i].handle_irq(i, &irq_desc[i]); -+ } -+ } -+} -+ -+static struct irq_chip fa_gpio_irq_chip = { -+ .name = "GPIO", -+ .irq_ack = fa_gpio_irq_ack, -+ .irq_mask = fa_gpio_irq_mask, -+ .irq_unmask = fa_gpio_irq_unmask, -+ .irq_set_type = fa_gpio_irq_set_type, -+}; -+ -+static void _fa_gpio_set_direction(struct fa_gpio_chip *fgc, unsigned offset, -+ int is_output) -+{ -+ unsigned int reg; -+ -+ reg = __raw_readl(fgc->mem_base + GPIO_DIR); -+ if (is_output) -+ reg |= 1 << offset; -+ else -+ reg &= ~(1 << offset); -+ __raw_writel(reg, fgc->mem_base + GPIO_DIR); -+} -+ -+static void _fa_gpio_set(struct fa_gpio_chip *fgc, unsigned offset, int value) -+{ -+ if (value) -+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_SET); -+ else -+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_CLR); -+} -+ -+static void fa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -+{ -+ struct fa_gpio_chip *fgc = to_fgc(chip); -+ -+ _fa_gpio_set(fgc, offset, value); -+} -+ -+static int fa_gpio_get(struct gpio_chip *chip, unsigned offset) -+{ -+ struct fa_gpio_chip *fgc = to_fgc(chip); -+ -+ return (__raw_readl(fgc->mem_base + GPIO_DATA_IN) >> offset) & 1; -+} -+ -+static int fa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -+{ -+ struct fa_gpio_chip *fgc = to_fgc(chip); -+ -+ return fgc->irq_base + offset; -+} -+ -+static int fa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -+{ -+ struct fa_gpio_chip *fgc = to_fgc(chip); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&fa_gpio_lock, flags); -+ -+ _fa_gpio_set_direction(fgc, offset, 0); -+ -+ spin_unlock_irqrestore(&fa_gpio_lock, flags); -+ -+ return 0; -+} -+ -+static int fa_gpio_direction_output(struct gpio_chip *chip, -+ unsigned offset, -+ int value) -+{ -+ struct fa_gpio_chip *fgc = to_fgc(chip); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&fa_gpio_lock, flags); -+ -+ _fa_gpio_set(fgc, offset, value); -+ _fa_gpio_set_direction(fgc, offset, 1); -+ -+ spin_unlock_irqrestore(&fa_gpio_lock, flags); -+ -+ return 0; -+} -+ -+static int fa_gpio_init_chip(struct fa_gpio_chip *fgc) -+{ -+ void __iomem *mem_base; -+ unsigned int i; -+ int err; -+ -+ mem_base = ioremap(fgc->map_base, GPIO_REGS_SIZE); -+ if (!mem_base) -+ return -ENXIO; -+ -+ fgc->mem_base = mem_base; -+ -+ fgc->gpio_chip.direction_input = fa_gpio_direction_input; -+ fgc->gpio_chip.direction_output = fa_gpio_direction_output; -+ fgc->gpio_chip.get = fa_gpio_get; -+ fgc->gpio_chip.set = fa_gpio_set; -+ fgc->gpio_chip.to_irq = fa_gpio_to_irq; -+ -+ /* disable, unmask and clear all interrupts */ -+ __raw_writel(0x0, mem_base + GPIO_INT_EN); -+ __raw_writel(0x0, mem_base + GPIO_INT_MASK); -+ __raw_writel(~0x0, mem_base + GPIO_INT_CLR); -+ -+ for (i = fgc->irq_base; -+ i < fgc->irq_base + fgc->gpio_chip.ngpio; i++) { -+ irq_set_chip(i, &fa_gpio_irq_chip); -+ irq_set_chip_data(i, fgc); -+ irq_set_handler(i, handle_edge_irq); -+ set_irq_flags(i, IRQF_VALID); -+ } -+ -+ err = gpiochip_add(&fgc->gpio_chip); -+ if (err) -+ goto unmap; -+ -+ return 0; -+ -+ unmap: -+ iounmap(fgc->mem_base); -+ return err; -+} -+ -+void __init fa_gpio_init(struct fa_gpio_data *data) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < data->nchips; i++) { -+ int err; -+ -+ err = fa_gpio_init_chip(&data->chips[i]); -+ if (WARN(err, "GPIO init failed\n")) -+ return; -+ } -+ -+ irq_set_chained_handler(data->irq, fa_gpio_irq_handler); -+ irq_set_handler_data(data->irq, data); -+} ---- /dev/null -+++ b/arch/arm/plat-fa/include/plat/gpio.h -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (c) 2010-2012 Gabor Juhos <juhosg@openwrt.org> -+ * -+ * This file 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 _FA_GPIO_H -+#define _FA_GPIO_H -+ -+#include <linux/init.h> -+#include <linux/gpio.h> -+#include <linux/irq.h> -+#include <linux/io.h> -+ -+struct fa_gpio_chip { -+ struct gpio_chip gpio_chip; -+ unsigned int map_base; -+ unsigned int irq_base; -+ -+ void __iomem *mem_base; -+}; -+ -+struct fa_gpio_data { -+ struct fa_gpio_chip *chips; -+ unsigned int nchips; -+ unsigned int irq; -+}; -+ -+void __init fa_gpio_init(struct fa_gpio_data *data); -+ -+#endif /* _FA_GPIO_H */ ---- a/arch/arm/plat-fa/Kconfig -+++ b/arch/arm/plat-fa/Kconfig -@@ -1,5 +1,8 @@ - if PLAT_FA - -+config PLAT_FA_GPIO -+ def_bool n -+ - config PLAT_FA_TIME - def_bool n - ---- a/arch/arm/plat-fa/Makefile -+++ b/arch/arm/plat-fa/Makefile -@@ -4,6 +4,7 @@ - - obj-y := - -+obj-$(CONFIG_PLAT_FA_GPIO) += gpio.o - obj-$(CONFIG_PLAT_FA_TIME) += time.o - - obj-m := |