diff options
author | luka <luka@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-11-06 11:16:41 +0000 |
---|---|---|
committer | luka <luka@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-11-06 11:16:41 +0000 |
commit | e0dd91dd954fe687d03ca14097740c209df64181 (patch) | |
tree | c33c664da49037a91a25597c2d522b2810428e8e /target/linux/cns3xxx/patches-3.3/470-gpio_irq.patch | |
parent | eb5c7edbb6c013045a935ddd4a319ee800f7e82d (diff) |
cns3xxx: use files directory
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34101 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/cns3xxx/patches-3.3/470-gpio_irq.patch')
-rw-r--r-- | target/linux/cns3xxx/patches-3.3/470-gpio_irq.patch | 407 |
1 files changed, 0 insertions, 407 deletions
diff --git a/target/linux/cns3xxx/patches-3.3/470-gpio_irq.patch b/target/linux/cns3xxx/patches-3.3/470-gpio_irq.patch index c5de35fe42..cb80d6419b 100644 --- a/target/linux/cns3xxx/patches-3.3/470-gpio_irq.patch +++ b/target/linux/cns3xxx/patches-3.3/470-gpio_irq.patch @@ -104,413 +104,6 @@ } /* used by entry-macro.S */ ---- /dev/null -+++ b/arch/arm/mach-cns3xxx/gpio.c -@@ -0,0 +1,277 @@ -+/* -+ * Copyright 2012 Gateworks Corporation -+ * Chris Lang <clang@gateworks.com> -+ * Tim Harvey <tharvey@gateworks.com> -+ * -+ * 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. -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/io.h> -+#include <linux/gpio.h> -+#include <linux/irq.h> -+ -+#include <asm/mach/irq.h> -+ -+/* -+ * Registers -+ */ -+#define GPIO_INPUT 0x04 -+#define GPIO_DIR 0x08 -+#define GPIO_SET 0x10 -+#define GPIO_CLEAR 0x14 -+#define GPIO_INTERRUPT_ENABLE 0x20 -+#define GPIO_INTERRUPT_RAW_STATUS 0x24 -+#define GPIO_INTERRUPT_MASKED_STATUS 0x28 -+#define GPIO_INTERRUPT_MASK 0x2C -+#define GPIO_INTERRUPT_CLEAR 0x30 -+#define GPIO_INTERRUPT_TRIGGER_METHOD 0x34 -+#define GPIO_INTERRUPT_TRIGGER_BOTH_EDGES 0x38 -+#define GPIO_INTERRUPT_TRIGGER_TYPE 0x3C -+ -+#define GPIO_INTERRUPT_TRIGGER_METHOD_EDGE 0 -+#define GPIO_INTERRUPT_TRIGGER_METHOD_LEVEL 1 -+#define GPIO_INTERRUPT_TRIGGER_EDGE_SINGLE 0 -+#define GPIO_INTERRUPT_TRIGGER_EDGE_BOTH 1 -+#define GPIO_INTERRUPT_TRIGGER_TYPE_RISING 0 -+#define GPIO_INTERRUPT_TRIGGER_TYPE_FALLING 1 -+#define GPIO_INTERRUPT_TRIGGER_TYPE_HIGH 0 -+#define GPIO_INTERRUPT_TRIGGER_TYPE_LOW 1 -+ -+struct cns3xxx_gpio_chip { -+ struct gpio_chip chip; -+ spinlock_t lock; -+ void __iomem *base; -+ int secondary_irq_base; -+}; -+ -+static struct cns3xxx_gpio_chip cns3xxx_gpio_chips[2]; -+static int cns3xxx_gpio_chip_count; -+ -+static inline void -+__set_direction(struct cns3xxx_gpio_chip *cchip, unsigned pin, int input) -+{ -+ u32 reg; -+ -+ reg = __raw_readl(cchip->base + GPIO_DIR); -+ if (input) -+ reg |= 1 << pin; -+ else -+ reg &= !(1 << pin); -+ __raw_writel(reg, cchip->base + GPIO_DIR); -+} -+ -+/* -+ * GENERIC_GPIO primatives -+ */ -+static int cns3xxx_gpio_direction_input(struct gpio_chip *chip, unsigned pin) -+{ -+ struct cns3xxx_gpio_chip *cchip = -+ container_of(chip, struct cns3xxx_gpio_chip, chip); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&cchip->lock, flags); -+ __set_direction(cchip, pin, 1); -+ spin_unlock_irqrestore(&cchip->lock, flags); -+ -+ return 0; -+} -+ -+static int cns3xxx_gpio_get(struct gpio_chip *chip, unsigned pin) -+{ -+ struct cns3xxx_gpio_chip *cchip = -+ container_of(chip, struct cns3xxx_gpio_chip, chip); -+ int val; -+ -+ val = ((__raw_readl(cchip->base + GPIO_INPUT) >> pin) & 0x1); -+ -+ return val; -+} -+ -+static int cns3xxx_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int level) -+{ -+ struct cns3xxx_gpio_chip *cchip = -+ container_of(chip, struct cns3xxx_gpio_chip, chip); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&cchip->lock, flags); -+ if (level) -+ __raw_writel(1 << pin, cchip->base + GPIO_SET); -+ else -+ __raw_writel(1 << pin, cchip->base + GPIO_CLEAR); -+ __set_direction(cchip, pin, 0); -+ spin_unlock_irqrestore(&cchip->lock, flags); -+ -+ return 0; -+} -+ -+static void cns3xxx_gpio_set(struct gpio_chip *chip, unsigned pin, -+ int level) -+{ -+ struct cns3xxx_gpio_chip *cchip = -+ container_of(chip, struct cns3xxx_gpio_chip, chip); -+ -+ if (level) -+ __raw_writel(1 << pin, cchip->base + GPIO_SET); -+ else -+ __raw_writel(1 << pin, cchip->base + GPIO_CLEAR); -+} -+ -+static int cns3xxx_gpio_to_irq(struct gpio_chip *chip, unsigned pin) -+{ -+ struct cns3xxx_gpio_chip *cchip = -+ container_of(chip, struct cns3xxx_gpio_chip, chip); -+ -+ return cchip->secondary_irq_base + pin; -+} -+ -+ -+/* -+ * IRQ support -+ */ -+ -+/* one interrupt per GPIO controller (GPIOA/GPIOB) -+ * this is called in task context, with IRQs enabled -+ */ -+static void cns3xxx_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -+{ -+ struct cns3xxx_gpio_chip *cchip = irq_get_handler_data(irq); -+ struct irq_chip *chip = irq_get_chip(irq); -+ struct irq_chip_generic *gc = irq_desc_get_chip_data(desc); -+ struct irq_chip_type *ct = gc->chip_types; -+ u16 i; -+ u32 reg; -+ -+ chained_irq_enter(chip, desc); /* mask and ack the base interrupt */ -+ -+ /* see which pin(s) triggered the interrupt */ -+ reg = __raw_readl(cchip->base + GPIO_INTERRUPT_RAW_STATUS); -+ for (i = 0; i < 32; i++) { -+ if (reg & (1 << i)) { -+ /* let the generic IRQ layer handle an interrupt */ -+ generic_handle_irq(cchip->secondary_irq_base + i); -+ } -+ } -+ -+ chained_irq_exit(chip, desc); /* unmask the base interrupt */ -+} -+ -+static int cns3xxx_gpio_irq_set_type(struct irq_data *d, u32 irqtype) -+{ -+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); -+ struct cns3xxx_gpio_chip *cchip = gc->private; -+ u32 gpio = d->irq - cchip->secondary_irq_base; -+ unsigned long flags; -+ u32 method, edges, type; -+ -+ spin_lock_irqsave(&cchip->lock, flags); -+ method = __raw_readl(cchip->base + GPIO_INTERRUPT_TRIGGER_METHOD); -+ edges = __raw_readl(cchip->base + GPIO_INTERRUPT_TRIGGER_BOTH_EDGES); -+ type = __raw_readl(cchip->base + GPIO_INTERRUPT_TRIGGER_TYPE); -+ method &= ~(1 << gpio); -+ edges &= ~(1 << gpio); -+ type &= ~(1 << gpio); -+ -+ switch(irqtype) { -+ case IRQ_TYPE_EDGE_RISING: -+ method |= (GPIO_INTERRUPT_TRIGGER_METHOD_EDGE << gpio); -+ edges |= (GPIO_INTERRUPT_TRIGGER_EDGE_SINGLE << gpio); -+ type |= (GPIO_INTERRUPT_TRIGGER_TYPE_RISING << gpio); -+ break; -+ case IRQ_TYPE_EDGE_FALLING: -+ method |= (GPIO_INTERRUPT_TRIGGER_METHOD_EDGE << gpio); -+ edges |= (GPIO_INTERRUPT_TRIGGER_EDGE_SINGLE << gpio); -+ type |= (GPIO_INTERRUPT_TRIGGER_TYPE_FALLING << gpio); -+ break; -+ case IRQ_TYPE_EDGE_BOTH: -+ method |= (GPIO_INTERRUPT_TRIGGER_METHOD_EDGE << gpio); -+ edges |= (GPIO_INTERRUPT_TRIGGER_EDGE_BOTH << gpio); -+ break; -+ case IRQ_TYPE_LEVEL_LOW: -+ method |= (GPIO_INTERRUPT_TRIGGER_METHOD_LEVEL << gpio); -+ type |= (GPIO_INTERRUPT_TRIGGER_TYPE_LOW << gpio); -+ break; -+ case IRQ_TYPE_LEVEL_HIGH: -+ method |= (GPIO_INTERRUPT_TRIGGER_METHOD_LEVEL << gpio); -+ type |= (GPIO_INTERRUPT_TRIGGER_TYPE_HIGH << gpio); -+ break; -+ default: -+ printk(KERN_WARNING "No irq type\n"); -+ spin_unlock_irqrestore(&cchip->lock, flags); -+ return -EINVAL; -+ } -+ -+ __raw_writel(method, cchip->base + GPIO_INTERRUPT_TRIGGER_METHOD); -+ __raw_writel(edges, cchip->base + GPIO_INTERRUPT_TRIGGER_BOTH_EDGES); -+ __raw_writel(type, cchip->base + GPIO_INTERRUPT_TRIGGER_TYPE); -+ spin_unlock_irqrestore(&cchip->lock, flags); -+ -+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) -+ __irq_set_handler_locked(d->irq, handle_level_irq); -+ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) -+ __irq_set_handler_locked(d->irq, handle_edge_irq); -+ -+ return 0; -+} -+ -+void __init cns3xxx_gpio_init(int gpio_base, int ngpio, -+ u32 base, int irq, int secondary_irq_base) -+{ -+ struct cns3xxx_gpio_chip *cchip; -+ struct irq_chip_generic *gc; -+ struct irq_chip_type *ct; -+ char gc_label[16]; -+ -+ if (cns3xxx_gpio_chip_count == ARRAY_SIZE(cns3xxx_gpio_chips)) -+ return; -+ -+ snprintf(gc_label, sizeof(gc_label), "cns3xxx_gpio%d", -+ cns3xxx_gpio_chip_count); -+ -+ cchip = cns3xxx_gpio_chips + cns3xxx_gpio_chip_count; -+ cchip->chip.label = kstrdup(gc_label, GFP_KERNEL); -+ cchip->chip.direction_input = cns3xxx_gpio_direction_input; -+ cchip->chip.get = cns3xxx_gpio_get; -+ cchip->chip.direction_output = cns3xxx_gpio_direction_output; -+ cchip->chip.set = cns3xxx_gpio_set; -+ cchip->chip.to_irq = cns3xxx_gpio_to_irq; -+ cchip->chip.base = gpio_base; -+ cchip->chip.ngpio = ngpio; -+ cchip->chip.can_sleep = 0; -+ spin_lock_init(&cchip->lock); -+ cchip->base = (void __iomem *)base; -+ cchip->secondary_irq_base = secondary_irq_base; -+ -+ BUG_ON(gpiochip_add(&cchip->chip) < 0); -+ cns3xxx_gpio_chip_count++; -+ -+ /* clear GPIO interrupts */ -+ __raw_writel(0xffff, cchip->base + GPIO_INTERRUPT_CLEAR); -+ -+ /* -+ * IRQ chip init -+ */ -+ gc = irq_alloc_generic_chip("cns3xxx_gpio_irq", 1, secondary_irq_base, -+ cchip->base, handle_edge_irq); -+ gc->private = cchip; -+ -+ ct = gc->chip_types; -+ ct->type = IRQ_TYPE_EDGE_FALLING; -+ ct->regs.ack = GPIO_INTERRUPT_CLEAR; -+ ct->regs.enable = GPIO_INTERRUPT_ENABLE; -+ ct->chip.irq_ack = irq_gc_ack_set_bit; -+ ct->chip.irq_enable = irq_gc_unmask_enable_reg; -+ ct->chip.irq_disable = irq_gc_mask_disable_reg; -+ ct->chip.irq_set_type = cns3xxx_gpio_irq_set_type; -+ ct->handler = handle_edge_irq; -+ -+ irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE, -+ IRQ_NOREQUEST, 0); -+ -+ irq_set_chained_handler(irq, cns3xxx_gpio_irq_handler); -+ irq_set_handler_data(irq, cchip); -+} ---- a/arch/arm/mach-cns3xxx/include/mach/gpio.h -+++ b/arch/arm/mach-cns3xxx/include/mach/gpio.h -@@ -1,98 +1,17 @@ - /* - * arch/arm/mach-cns3xxx/include/mach/gpio.h - * -- * CNS3xxx GPIO wrappers for arch-neutral GPIO calls -- * -- * Copyright 2011 Gateworks Corporation -- * Chris Lang <clang@gateworks.com> -- * -- * Based on IXP implementation by Milan Svoboda <msvoboda@ra.rockwell.com> -- * Based on PXA implementation by Philipp Zabel <philipp.zabel@gmail.com> -- * -- * 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. -- * -- * 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 -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. - * - */ -- - #ifndef __ASM_ARCH_CNS3XXX_GPIO_H - #define __ASM_ARCH_CNS3XXX_GPIO_H - - #include <linux/kernel.h> --#include <linux/io.h> --#include <mach/platform.h> --#include <asm-generic/gpio.h> /* cansleep wrappers */ -- --#define NR_BUILTIN_GPIO 64 -- --#define CNS3XXX_GPIO_IN 0x0 --#define CNS3XXX_GPIO_OUT 0x1 -- --#define CNS3XXX_GPIO_LO 0 --#define CNS3XXX_GPIO_HI 1 -- --#define CNS3XXX_GPIO_OUTPUT 0x00 --#define CNS3XXX_GPIO_INPUT 0x04 --#define CNS3XXX_GPIO_DIR 0x08 --#define CNS3XXX_GPIO_SET 0x10 --#define CNS3XXX_GPIO_CLEAR 0x14 -- --static inline void gpio_line_get(u8 line, int *value) --{ -- if (line < 32) -- *value = ((__raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> line) & 0x1); -- else -- *value = ((__raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> (line - 32)) & 0x1); --} -- --static inline void gpio_line_set(u8 line, int value) --{ -- if (line < 32) { -- if (value) -- __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_SET); -- else -- __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_CLEAR); -- } else { -- if (value) -- __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_SET); -- else -- __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_CLEAR); -- } --} -- --static inline int gpio_get_value(unsigned gpio) --{ -- if (gpio < NR_BUILTIN_GPIO) -- { -- int value; -- gpio_line_get(gpio, &value); -- return value; -- } -- else -- return __gpio_get_value(gpio); --} -- --static inline void gpio_set_value(unsigned gpio, int value) --{ -- if (gpio < NR_BUILTIN_GPIO) -- gpio_line_set(gpio, value); -- else -- __gpio_set_value(gpio, value); --} -- --#define gpio_cansleep __gpio_cansleep - --extern int gpio_to_irq(int gpio); --extern int irq_to_gpio(int gpio); -+extern void __init cns3xxx_gpio_init(int gpio_base, int ngpio, -+ u32 base, int irq, int secondary_irq_base); - - #endif ---- a/arch/arm/mach-cns3xxx/laguna.c -+++ b/arch/arm/mach-cns3xxx/laguna.c -@@ -45,6 +45,7 @@ - #include <mach/irqs.h> - #include <mach/platform.h> - #include <mach/pm.h> -+#include <mach/gpio.h> - #include <asm/hardware/gic.h> - #include "core.h" - #include "devices.h" -@@ -759,6 +760,10 @@ static int __init laguna_model_setup(voi - u8 pcie_bitmap = 0; - - printk("Running on Gateworks Laguna %s\n", laguna_info.model); -+ cns3xxx_gpio_init( 0, 32, CNS3XXX_GPIOA_BASE_VIRT, IRQ_CNS3XXX_GPIOA, -+ NR_IRQS_CNS3XXX); -+ cns3xxx_gpio_init(32, 32, CNS3XXX_GPIOB_BASE_VIRT, IRQ_CNS3XXX_GPIOB, -+ NR_IRQS_CNS3XXX + 32); - - if (strncmp(laguna_info.model, "GW", 2) == 0) { - if (laguna_info.config_bitmap & ETH0_LOAD) --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -366,7 +366,8 @@ config ARCH_CLPS711X |