Root/target/linux/cns21xx/patches-3.3/005-arm-add-fa-gpio-driver.patch

1--- /dev/null
2+++ b/arch/arm/plat-fa/gpio.c
3@@ -0,0 +1,283 @@
4+/*
5+ * Gpiochip and interrupt routines for Faraday FA526 based SoCs
6+ *
7+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
8+ * Copyright (C) 2010-2012 Gabor Juhos <juhosg@openwrt.org>
9+ *
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
13+ *
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.
18+ */
19+
20+#include <linux/spinlock.h>
21+
22+#include <plat/gpio.h>
23+
24+#define GPIO_DATA_OUT 0x0
25+#define GPIO_DATA_IN 0x4
26+#define GPIO_DIR 0x8
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
40+
41+#define GPIO_REGS_SIZE 0x48
42+
43+static DEFINE_SPINLOCK(fa_gpio_lock);
44+
45+static inline struct fa_gpio_chip *to_fgc(struct gpio_chip *chip)
46+{
47+ return container_of(chip, struct fa_gpio_chip, gpio_chip);
48+}
49+
50+static void _fa_gpio_irq_setenable(struct irq_data *d, int enable)
51+{
52+ struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq);
53+ void __iomem *base = fgc->mem_base;
54+ unsigned int gpio = d->irq - fgc->irq_base;
55+ unsigned int reg;
56+
57+ reg = __raw_readl(base + GPIO_INT_EN);
58+ reg = (reg & (~(1 << gpio))) | (!!enable << gpio);
59+ __raw_writel(reg, base + GPIO_INT_EN);
60+}
61+
62+static void fa_gpio_irq_ack(struct irq_data *d)
63+{
64+ struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq);
65+ unsigned int gpio = d->irq - fgc->irq_base;
66+
67+ __raw_writel(1 << gpio, fgc->mem_base + GPIO_INT_CLR);
68+}
69+
70+static void fa_gpio_irq_mask(struct irq_data *d)
71+{
72+ _fa_gpio_irq_setenable(d, 0);
73+}
74+
75+static void fa_gpio_irq_unmask(struct irq_data *d)
76+{
77+ _fa_gpio_irq_setenable(d, 1);
78+}
79+
80+static int fa_gpio_irq_set_type(struct irq_data *d, unsigned int type)
81+{
82+ struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq);
83+ void __iomem *base = fgc->mem_base;
84+ unsigned int gpio = d->irq - fgc->irq_base;
85+ unsigned int gpio_mask = 1 << gpio;
86+ unsigned int reg_both, reg_level, reg_type;
87+
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);
91+
92+ switch (type) {
93+ case IRQ_TYPE_EDGE_BOTH:
94+ reg_type &= ~gpio_mask;
95+ reg_both |= gpio_mask;
96+ break;
97+ case IRQ_TYPE_EDGE_RISING:
98+ reg_type &= ~gpio_mask;
99+ reg_both &= ~gpio_mask;
100+ reg_level &= ~gpio_mask;
101+ break;
102+ case IRQ_TYPE_EDGE_FALLING:
103+ reg_type &= ~gpio_mask;
104+ reg_both &= ~gpio_mask;
105+ reg_level |= gpio_mask;
106+ break;
107+ case IRQ_TYPE_LEVEL_HIGH:
108+ reg_type |= gpio_mask;
109+ reg_level &= ~gpio_mask;
110+ break;
111+ case IRQ_TYPE_LEVEL_LOW:
112+ reg_type |= gpio_mask;
113+ reg_level |= gpio_mask;
114+ break;
115+ default:
116+ return -EINVAL;
117+ }
118+
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);
122+
123+ fa_gpio_irq_ack(d);
124+
125+ return 0;
126+}
127+
128+static void fa_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
129+{
130+ struct fa_gpio_data *data = irq_get_handler_data(irq);
131+ unsigned int chip;
132+
133+ for (chip = 0; chip < data->nchips; chip++) {
134+ struct fa_gpio_chip *fgc = &data->chips[chip];
135+ unsigned int status;
136+ unsigned int i;
137+
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)
141+ continue;
142+
143+ BUG_ON(!(irq_desc[i].handle_irq));
144+ irq_desc[i].handle_irq(i, &irq_desc[i]);
145+ }
146+ }
147+}
148+
149+static struct irq_chip fa_gpio_irq_chip = {
150+ .name = "GPIO",
151+ .irq_ack = fa_gpio_irq_ack,
152+ .irq_mask = fa_gpio_irq_mask,
153+ .irq_unmask = fa_gpio_irq_unmask,
154+ .irq_set_type = fa_gpio_irq_set_type,
155+};
156+
157+static void _fa_gpio_set_direction(struct fa_gpio_chip *fgc, unsigned offset,
158+ int is_output)
159+{
160+ unsigned int reg;
161+
162+ reg = __raw_readl(fgc->mem_base + GPIO_DIR);
163+ if (is_output)
164+ reg |= 1 << offset;
165+ else
166+ reg &= ~(1 << offset);
167+ __raw_writel(reg, fgc->mem_base + GPIO_DIR);
168+}
169+
170+static void _fa_gpio_set(struct fa_gpio_chip *fgc, unsigned offset, int value)
171+{
172+ if (value)
173+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_SET);
174+ else
175+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_CLR);
176+}
177+
178+static void fa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
179+{
180+ struct fa_gpio_chip *fgc = to_fgc(chip);
181+
182+ _fa_gpio_set(fgc, offset, value);
183+}
184+
185+static int fa_gpio_get(struct gpio_chip *chip, unsigned offset)
186+{
187+ struct fa_gpio_chip *fgc = to_fgc(chip);
188+
189+ return (__raw_readl(fgc->mem_base + GPIO_DATA_IN) >> offset) & 1;
190+}
191+
192+static int fa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
193+{
194+ struct fa_gpio_chip *fgc = to_fgc(chip);
195+
196+ return fgc->irq_base + offset;
197+}
198+
199+static int fa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
200+{
201+ struct fa_gpio_chip *fgc = to_fgc(chip);
202+ unsigned long flags;
203+
204+ spin_lock_irqsave(&fa_gpio_lock, flags);
205+
206+ _fa_gpio_set_direction(fgc, offset, 0);
207+
208+ spin_unlock_irqrestore(&fa_gpio_lock, flags);
209+
210+ return 0;
211+}
212+
213+static int fa_gpio_direction_output(struct gpio_chip *chip,
214+ unsigned offset,
215+ int value)
216+{
217+ struct fa_gpio_chip *fgc = to_fgc(chip);
218+ unsigned long flags;
219+
220+ spin_lock_irqsave(&fa_gpio_lock, flags);
221+
222+ _fa_gpio_set(fgc, offset, value);
223+ _fa_gpio_set_direction(fgc, offset, 1);
224+
225+ spin_unlock_irqrestore(&fa_gpio_lock, flags);
226+
227+ return 0;
228+}
229+
230+static int fa_gpio_init_chip(struct fa_gpio_chip *fgc)
231+{
232+ void __iomem *mem_base;
233+ unsigned int i;
234+ int err;
235+
236+ mem_base = ioremap(fgc->map_base, GPIO_REGS_SIZE);
237+ if (!mem_base)
238+ return -ENXIO;
239+
240+ fgc->mem_base = mem_base;
241+
242+ fgc->gpio_chip.direction_input = fa_gpio_direction_input;
243+ fgc->gpio_chip.direction_output = fa_gpio_direction_output;
244+ fgc->gpio_chip.get = fa_gpio_get;
245+ fgc->gpio_chip.set = fa_gpio_set;
246+ fgc->gpio_chip.to_irq = fa_gpio_to_irq;
247+
248+ /* disable, unmask and clear all interrupts */
249+ __raw_writel(0x0, mem_base + GPIO_INT_EN);
250+ __raw_writel(0x0, mem_base + GPIO_INT_MASK);
251+ __raw_writel(~0x0, mem_base + GPIO_INT_CLR);
252+
253+ for (i = fgc->irq_base;
254+ i < fgc->irq_base + fgc->gpio_chip.ngpio; i++) {
255+ irq_set_chip(i, &fa_gpio_irq_chip);
256+ irq_set_chip_data(i, fgc);
257+ irq_set_handler(i, handle_edge_irq);
258+ set_irq_flags(i, IRQF_VALID);
259+ }
260+
261+ err = gpiochip_add(&fgc->gpio_chip);
262+ if (err)
263+ goto unmap;
264+
265+ return 0;
266+
267+ unmap:
268+ iounmap(fgc->mem_base);
269+ return err;
270+}
271+
272+void __init fa_gpio_init(struct fa_gpio_data *data)
273+{
274+ unsigned int i;
275+
276+ for (i = 0; i < data->nchips; i++) {
277+ int err;
278+
279+ err = fa_gpio_init_chip(&data->chips[i]);
280+ if (WARN(err, "GPIO init failed\n"))
281+ return;
282+ }
283+
284+ irq_set_chained_handler(data->irq, fa_gpio_irq_handler);
285+ irq_set_handler_data(data->irq, data);
286+}
287--- /dev/null
288+++ b/arch/arm/plat-fa/include/plat/gpio.h
289@@ -0,0 +1,33 @@
290+/*
291+ * Copyright (c) 2010-2012 Gabor Juhos <juhosg@openwrt.org>
292+ *
293+ * This file is free software; you can redistribute it and/or modify
294+ * it under the terms of the GNU General Public License, Version 2, as
295+ * published by the Free Software Foundation.
296+ */
297+
298+#ifndef _FA_GPIO_H
299+#define _FA_GPIO_H
300+
301+#include <linux/init.h>
302+#include <linux/gpio.h>
303+#include <linux/irq.h>
304+#include <linux/io.h>
305+
306+struct fa_gpio_chip {
307+ struct gpio_chip gpio_chip;
308+ unsigned int map_base;
309+ unsigned int irq_base;
310+
311+ void __iomem *mem_base;
312+};
313+
314+struct fa_gpio_data {
315+ struct fa_gpio_chip *chips;
316+ unsigned int nchips;
317+ unsigned int irq;
318+};
319+
320+void __init fa_gpio_init(struct fa_gpio_data *data);
321+
322+#endif /* _FA_GPIO_H */
323--- a/arch/arm/plat-fa/Kconfig
324+++ b/arch/arm/plat-fa/Kconfig
325@@ -1,5 +1,8 @@
326 if PLAT_FA
327 
328+config PLAT_FA_GPIO
329+ def_bool n
330+
331 config PLAT_FA_TIME
332     def_bool n
333 
334--- a/arch/arm/plat-fa/Makefile
335+++ b/arch/arm/plat-fa/Makefile
336@@ -4,6 +4,7 @@
337 
338 obj-y :=
339 
340+obj-$(CONFIG_PLAT_FA_GPIO) += gpio.o
341 obj-$(CONFIG_PLAT_FA_TIME) += time.o
342 
343 obj-m :=
344

Archive Download this file



interactive