2 +++ b/arch/arm/plat-fa/gpio.c
5 + * Gpiochip and interrupt routines for Faraday FA526 based SoCs
7 + * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
8 + * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
10 + * Based on plat-mxc/gpio.c:
11 + * MXC GPIO supchip. (c) 2008 Daniel Mack <daniel@caiaq.de>
12 + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
14 + * This program is free software; you can redistribute it and/or modify
15 + * it under the terms of the GNU General Public License as published by
16 + * the Free Software Foundation; either version 2 of the License, or
17 + * (at your option) any later version.
20 +#include <linux/spinlock.h>
22 +#include <plat/gpio.h>
24 +#define GPIO_DATA_OUT 0x0
25 +#define GPIO_DATA_IN 0x4
27 +#define GPIO_DATA_SET 0x10
28 +#define GPIO_DATA_CLR 0x14
29 +#define GPIO_PULL_EN 0x18
30 +#define GPIO_PULL_TYPE 0x1C
31 +#define GPIO_INT_EN 0x20
32 +#define GPIO_INT_STAT 0x24
33 +#define GPIO_INT_MASK 0x2C
34 +#define GPIO_INT_CLR 0x30
35 +#define GPIO_INT_TYPE 0x34
36 +#define GPIO_INT_BOTH_EDGE 0x38
37 +#define GPIO_INT_LEVEL 0x3C
38 +#define GPIO_DEBOUNCE_EN 0x40
39 +#define GPIO_DEBOUNCE_PRESCALE 0x44
41 +#define GPIO_REGS_SIZE 0x48
43 +static DEFINE_SPINLOCK(fa_gpio_lock);
45 +static inline struct fa_gpio_chip *to_fgc(struct gpio_chip *chip)
47 + return container_of(chip, struct fa_gpio_chip, gpio_chip);
50 +static void _fa_gpio_irq_setenable(unsigned int irq, int enable)
52 + struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
53 + void __iomem *base = fgc->mem_base;
54 + unsigned int gpio = irq - fgc->irq_base;
57 + reg = __raw_readl(base + GPIO_INT_EN);
58 + reg = (reg & (~(1 << gpio))) | (!!enable << gpio);
59 + __raw_writel(reg, base + GPIO_INT_EN);
62 +static void fa_gpio_irq_ack(unsigned int irq)
64 + struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
65 + unsigned int gpio = irq - fgc->irq_base;
67 + __raw_writel(1 << gpio, fgc->mem_base + GPIO_INT_CLR);
70 +static void fa_gpio_irq_mask(unsigned int irq)
72 + _fa_gpio_irq_setenable(irq, 0);
75 +static void fa_gpio_irq_unmask(unsigned int irq)
77 + _fa_gpio_irq_setenable(irq, 1);
80 +static int fa_gpio_irq_set_type(unsigned int irq, unsigned int type)
82 + struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
83 + void __iomem *base = fgc->mem_base;
84 + unsigned int gpio = irq - fgc->irq_base;
85 + unsigned int gpio_mask = 1 << gpio;
86 + unsigned int reg_both, reg_level, reg_type;
88 + reg_type = __raw_readl(base + GPIO_INT_TYPE);
89 + reg_level = __raw_readl(base + GPIO_INT_LEVEL);
90 + reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);
93 + case IRQ_TYPE_EDGE_BOTH:
94 + reg_type &= ~gpio_mask;
95 + reg_both |= gpio_mask;
97 + case IRQ_TYPE_EDGE_RISING:
98 + reg_type &= ~gpio_mask;
99 + reg_both &= ~gpio_mask;
100 + reg_level &= ~gpio_mask;
102 + case IRQ_TYPE_EDGE_FALLING:
103 + reg_type &= ~gpio_mask;
104 + reg_both &= ~gpio_mask;
105 + reg_level |= gpio_mask;
107 + case IRQ_TYPE_LEVEL_HIGH:
108 + reg_type |= gpio_mask;
109 + reg_level &= ~gpio_mask;
111 + case IRQ_TYPE_LEVEL_LOW:
112 + reg_type |= gpio_mask;
113 + reg_level |= gpio_mask;
119 + __raw_writel(reg_type, base + GPIO_INT_TYPE);
120 + __raw_writel(reg_level, base + GPIO_INT_LEVEL);
121 + __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
123 + fa_gpio_irq_ack(irq);
128 +static void fa_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
130 + struct fa_gpio_data *data = get_irq_data(irq);
133 + for (chip = 0; chip < data->nchips; chip++) {
134 + struct fa_gpio_chip *fgc = &data->chips[chip];
135 + unsigned int status;
138 + status = __raw_readl(fgc->mem_base + GPIO_INT_STAT);
139 + for (i = fgc->irq_base; status != 0; status >>= 1, i++) {
140 + if ((status & 1) == 0)
143 + BUG_ON(!(irq_desc[i].handle_irq));
144 + irq_desc[i].handle_irq(i, &irq_desc[i]);
149 +static struct irq_chip fa_gpio_irq_chip = {
151 + .ack = fa_gpio_irq_ack,
152 + .mask = fa_gpio_irq_mask,
153 + .unmask = fa_gpio_irq_unmask,
154 + .set_type = fa_gpio_irq_set_type,
157 +static void _fa_gpio_set_direction(struct fa_gpio_chip *fgc, unsigned offset,
162 + reg = __raw_readl(fgc->mem_base + GPIO_DIR);
164 + reg |= 1 << offset;
166 + reg &= ~(1 << offset);
167 + __raw_writel(reg, fgc->mem_base + GPIO_DIR);
170 +static void _fa_gpio_set(struct fa_gpio_chip *fgc, unsigned offset, int value)
173 + __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_SET);
175 + __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_CLR);
178 +static void fa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
180 + struct fa_gpio_chip *fgc = to_fgc(chip);
182 + _fa_gpio_set(fgc, offset, value);
185 +static int fa_gpio_get(struct gpio_chip *chip, unsigned offset)
187 + struct fa_gpio_chip *fgc = to_fgc(chip);
189 + return (__raw_readl(fgc->mem_base + GPIO_DATA_IN) >> offset) & 1;
192 +static int fa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
194 + struct fa_gpio_chip *fgc = to_fgc(chip);
195 + unsigned long flags;
197 + spin_lock_irqsave(&fa_gpio_lock, flags);
199 + _fa_gpio_set_direction(fgc, offset, 0);
201 + spin_unlock_irqrestore(&fa_gpio_lock, flags);
206 +static int fa_gpio_direction_output(struct gpio_chip *chip,
210 + struct fa_gpio_chip *fgc = to_fgc(chip);
211 + unsigned long flags;
213 + spin_lock_irqsave(&fa_gpio_lock, flags);
215 + _fa_gpio_set(fgc, offset, value);
216 + _fa_gpio_set_direction(fgc, offset, 1);
218 + spin_unlock_irqrestore(&fa_gpio_lock, flags);
223 +static int fa_gpio_init_chip(struct fa_gpio_chip *fgc)
225 + void __iomem *mem_base;
229 + mem_base = ioremap(fgc->map_base, GPIO_REGS_SIZE);
233 + fgc->mem_base = mem_base;
235 + fgc->gpio_chip.direction_input = fa_gpio_direction_input;
236 + fgc->gpio_chip.direction_output = fa_gpio_direction_output;
237 + fgc->gpio_chip.get = fa_gpio_get;
238 + fgc->gpio_chip.set = fa_gpio_set;
240 + /* disable, unmask and clear all interrupts */
241 + __raw_writel(0x0, mem_base + GPIO_INT_EN);
242 + __raw_writel(0x0, mem_base + GPIO_INT_MASK);
243 + __raw_writel(~0x0, mem_base + GPIO_INT_CLR);
245 + for (i = fgc->irq_base;
246 + i < fgc->irq_base + fgc->gpio_chip.ngpio; i++) {
247 + set_irq_chip(i, &fa_gpio_irq_chip);
248 + set_irq_chip_data(i, fgc);
249 + set_irq_handler(i, handle_edge_irq);
250 + set_irq_flags(i, IRQF_VALID);
253 + err = gpiochip_add(&fgc->gpio_chip);
260 + iounmap(fgc->mem_base);
264 +void __init fa_gpio_init(struct fa_gpio_data *data)
268 + for (i = 0; i < data->nchips; i++) {
271 + err = fa_gpio_init_chip(&data->chips[i]);
272 + if (WARN(err, "GPIO init failed\n"))
276 + set_irq_chained_handler(data->irq, fa_gpio_irq_handler);
277 + set_irq_data(data->irq, data);
280 +++ b/arch/arm/plat-fa/include/plat/gpio.h
283 + * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
285 + * This file is free software; you can redistribute it and/or modify
286 + * it under the terms of the GNU General Public License, Version 2, as
287 + * published by the Free Software Foundation.
293 +#include <linux/init.h>
294 +#include <linux/gpio.h>
295 +#include <linux/irq.h>
296 +#include <linux/io.h>
298 +struct fa_gpio_chip {
299 + struct gpio_chip gpio_chip;
300 + unsigned int map_base;
301 + unsigned int irq_base;
303 + void __iomem *mem_base;
306 +struct fa_gpio_data {
307 + struct fa_gpio_chip *chips;
308 + unsigned int nchips;
312 +void __init fa_gpio_init(struct fa_gpio_data *data);
314 +#endif /* _FA_GPIO_H */
315 --- a/arch/arm/plat-fa/Kconfig
316 +++ b/arch/arm/plat-fa/Kconfig
326 --- a/arch/arm/plat-fa/Makefile
327 +++ b/arch/arm/plat-fa/Makefile
332 +obj-$(CONFIG_PLAT_FA_GPIO) += gpio.o
333 obj-$(CONFIG_PLAT_FA_TIME) += time.o