• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/mach-s5pc100/
1/*
2 * arch/arm/plat-s5pc100/gpiolib.c
3 *
4 *  Copyright 2009 Samsung Electronics Co
5 *  Kyungmin Park <kyungmin.park@samsung.com>
6 *
7 * S5PC100 - GPIOlib support
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/irq.h>
16#include <linux/io.h>
17#include <linux/gpio.h>
18
19#include <mach/map.h>
20#include <mach/regs-gpio.h>
21
22#include <plat/gpio-core.h>
23#include <plat/gpio-cfg.h>
24#include <plat/gpio-cfg-helpers.h>
25
26/* S5PC100 GPIO bank summary:
27 *
28 * Bank	GPIOs	Style	INT Type
29 * A0	8	4Bit	GPIO_INT0
30 * A1	5	4Bit	GPIO_INT1
31 * B	8	4Bit	GPIO_INT2
32 * C	5	4Bit	GPIO_INT3
33 * D	7	4Bit	GPIO_INT4
34 * E0	8	4Bit	GPIO_INT5
35 * E1	6	4Bit	GPIO_INT6
36 * F0	8	4Bit	GPIO_INT7
37 * F1	8	4Bit	GPIO_INT8
38 * F2	8	4Bit	GPIO_INT9
39 * F3	4	4Bit	GPIO_INT10
40 * G0	8	4Bit	GPIO_INT11
41 * G1	3	4Bit	GPIO_INT12
42 * G2	7	4Bit	GPIO_INT13
43 * G3	7	4Bit	GPIO_INT14
44 * H0	8	4Bit	WKUP_INT
45 * H1	8	4Bit	WKUP_INT
46 * H2	8	4Bit	WKUP_INT
47 * H3	8	4Bit	WKUP_INT
48 * I	8	4Bit	GPIO_INT15
49 * J0	8	4Bit	GPIO_INT16
50 * J1	5	4Bit	GPIO_INT17
51 * J2	8	4Bit	GPIO_INT18
52 * J3	8	4Bit	GPIO_INT19
53 * J4	4	4Bit	GPIO_INT20
54 * K0	8	4Bit	None
55 * K1	6	4Bit	None
56 * K2	8	4Bit	None
57 * K3	8	4Bit	None
58 * L0	8	4Bit	None
59 * L1	8	4Bit	None
60 * L2	8	4Bit	None
61 * L3	8	4Bit	None
62 */
63
64static int s5pc100_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
65{
66	return S3C_IRQ_GPIO(chip->base + offset);
67}
68
69static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset)
70{
71	int base;
72
73	base = chip->base - S5PC100_GPH0(0);
74	if (base == 0)
75		return IRQ_EINT(offset);
76	base = chip->base - S5PC100_GPH1(0);
77	if (base == 0)
78		return IRQ_EINT(8 + offset);
79	base = chip->base - S5PC100_GPH2(0);
80	if (base == 0)
81		return IRQ_EINT(16 + offset);
82	base = chip->base - S5PC100_GPH3(0);
83	if (base == 0)
84		return IRQ_EINT(24 + offset);
85	return -EINVAL;
86}
87
88static struct s3c_gpio_cfg gpio_cfg = {
89	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
90	.set_pull	= s3c_gpio_setpull_updown,
91	.get_pull	= s3c_gpio_getpull_updown,
92};
93
94static struct s3c_gpio_cfg gpio_cfg_eint = {
95	.cfg_eint	= 0xf,
96	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
97	.set_pull	= s3c_gpio_setpull_updown,
98	.get_pull	= s3c_gpio_getpull_updown,
99};
100
101static struct s3c_gpio_cfg gpio_cfg_noint = {
102	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
103	.set_pull	= s3c_gpio_setpull_updown,
104	.get_pull	= s3c_gpio_getpull_updown,
105};
106
107static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
108	{
109		.base	= S5PC100_GPA0_BASE,
110		.config	= &gpio_cfg,
111		.chip	= {
112			.base	= S5PC100_GPA0(0),
113			.ngpio	= S5PC100_GPIO_A0_NR,
114			.label	= "GPA0",
115		},
116	}, {
117		.base	= S5PC100_GPA1_BASE,
118		.config	= &gpio_cfg,
119		.chip	= {
120			.base	= S5PC100_GPA1(0),
121			.ngpio	= S5PC100_GPIO_A1_NR,
122			.label	= "GPA1",
123		},
124	}, {
125		.base	= S5PC100_GPB_BASE,
126		.config	= &gpio_cfg,
127		.chip	= {
128			.base	= S5PC100_GPB(0),
129			.ngpio	= S5PC100_GPIO_B_NR,
130			.label	= "GPB",
131		},
132	}, {
133		.base	= S5PC100_GPC_BASE,
134		.config	= &gpio_cfg,
135		.chip	= {
136			.base	= S5PC100_GPC(0),
137			.ngpio	= S5PC100_GPIO_C_NR,
138			.label	= "GPC",
139		},
140	}, {
141		.base	= S5PC100_GPD_BASE,
142		.config	= &gpio_cfg,
143		.chip	= {
144			.base	= S5PC100_GPD(0),
145			.ngpio	= S5PC100_GPIO_D_NR,
146			.label	= "GPD",
147		},
148	}, {
149		.base	= S5PC100_GPE0_BASE,
150		.config	= &gpio_cfg,
151		.chip	= {
152			.base	= S5PC100_GPE0(0),
153			.ngpio	= S5PC100_GPIO_E0_NR,
154			.label	= "GPE0",
155		},
156	}, {
157		.base	= S5PC100_GPE1_BASE,
158		.config	= &gpio_cfg,
159		.chip	= {
160			.base	= S5PC100_GPE1(0),
161			.ngpio	= S5PC100_GPIO_E1_NR,
162			.label	= "GPE1",
163		},
164	}, {
165		.base	= S5PC100_GPF0_BASE,
166		.config	= &gpio_cfg,
167		.chip	= {
168			.base	= S5PC100_GPF0(0),
169			.ngpio	= S5PC100_GPIO_F0_NR,
170			.label	= "GPF0",
171		},
172	}, {
173		.base	= S5PC100_GPF1_BASE,
174		.config	= &gpio_cfg,
175		.chip	= {
176			.base	= S5PC100_GPF1(0),
177			.ngpio	= S5PC100_GPIO_F1_NR,
178			.label	= "GPF1",
179		},
180	}, {
181		.base	= S5PC100_GPF2_BASE,
182		.config	= &gpio_cfg,
183		.chip	= {
184			.base	= S5PC100_GPF2(0),
185			.ngpio	= S5PC100_GPIO_F2_NR,
186			.label	= "GPF2",
187		},
188	}, {
189		.base	= S5PC100_GPF3_BASE,
190		.config	= &gpio_cfg,
191		.chip	= {
192			.base	= S5PC100_GPF3(0),
193			.ngpio	= S5PC100_GPIO_F3_NR,
194			.label	= "GPF3",
195		},
196	}, {
197		.base	= S5PC100_GPG0_BASE,
198		.config	= &gpio_cfg,
199		.chip	= {
200			.base	= S5PC100_GPG0(0),
201			.ngpio	= S5PC100_GPIO_G0_NR,
202			.label	= "GPG0",
203		},
204	}, {
205		.base	= S5PC100_GPG1_BASE,
206		.config	= &gpio_cfg,
207		.chip	= {
208			.base	= S5PC100_GPG1(0),
209			.ngpio	= S5PC100_GPIO_G1_NR,
210			.label	= "GPG1",
211		},
212	}, {
213		.base	= S5PC100_GPG2_BASE,
214		.config	= &gpio_cfg,
215		.chip	= {
216			.base	= S5PC100_GPG2(0),
217			.ngpio	= S5PC100_GPIO_G2_NR,
218			.label	= "GPG2",
219		},
220	}, {
221		.base	= S5PC100_GPG3_BASE,
222		.config	= &gpio_cfg,
223		.chip	= {
224			.base	= S5PC100_GPG3(0),
225			.ngpio	= S5PC100_GPIO_G3_NR,
226			.label	= "GPG3",
227		},
228	}, {
229		.base	= S5PC100_GPH0_BASE,
230		.config	= &gpio_cfg_eint,
231		.chip	= {
232			.base	= S5PC100_GPH0(0),
233			.ngpio	= S5PC100_GPIO_H0_NR,
234			.label	= "GPH0",
235		},
236	}, {
237		.base	= S5PC100_GPH1_BASE,
238		.config	= &gpio_cfg_eint,
239		.chip	= {
240			.base	= S5PC100_GPH1(0),
241			.ngpio	= S5PC100_GPIO_H1_NR,
242			.label	= "GPH1",
243		},
244	}, {
245		.base	= S5PC100_GPH2_BASE,
246		.config	= &gpio_cfg_eint,
247		.chip	= {
248			.base	= S5PC100_GPH2(0),
249			.ngpio	= S5PC100_GPIO_H2_NR,
250			.label	= "GPH2",
251		},
252	}, {
253		.base	= S5PC100_GPH3_BASE,
254		.config	= &gpio_cfg_eint,
255		.chip	= {
256			.base	= S5PC100_GPH3(0),
257			.ngpio	= S5PC100_GPIO_H3_NR,
258			.label	= "GPH3",
259		},
260	}, {
261		.base	= S5PC100_GPI_BASE,
262		.config	= &gpio_cfg,
263		.chip	= {
264			.base	= S5PC100_GPI(0),
265			.ngpio	= S5PC100_GPIO_I_NR,
266			.label	= "GPI",
267		},
268	}, {
269		.base	= S5PC100_GPJ0_BASE,
270		.config	= &gpio_cfg,
271		.chip	= {
272			.base	= S5PC100_GPJ0(0),
273			.ngpio	= S5PC100_GPIO_J0_NR,
274			.label	= "GPJ0",
275		},
276	}, {
277		.base	= S5PC100_GPJ1_BASE,
278		.config	= &gpio_cfg,
279		.chip	= {
280			.base	= S5PC100_GPJ1(0),
281			.ngpio	= S5PC100_GPIO_J1_NR,
282			.label	= "GPJ1",
283		},
284	}, {
285		.base	= S5PC100_GPJ2_BASE,
286		.config	= &gpio_cfg,
287		.chip	= {
288			.base	= S5PC100_GPJ2(0),
289			.ngpio	= S5PC100_GPIO_J2_NR,
290			.label	= "GPJ2",
291		},
292	}, {
293		.base	= S5PC100_GPJ3_BASE,
294		.config	= &gpio_cfg,
295		.chip	= {
296			.base	= S5PC100_GPJ3(0),
297			.ngpio	= S5PC100_GPIO_J3_NR,
298			.label	= "GPJ3",
299		},
300	}, {
301		.base	= S5PC100_GPJ4_BASE,
302		.config	= &gpio_cfg,
303		.chip	= {
304			.base	= S5PC100_GPJ4(0),
305			.ngpio	= S5PC100_GPIO_J4_NR,
306			.label	= "GPJ4",
307		},
308	}, {
309		.base	= S5PC100_GPK0_BASE,
310		.config	= &gpio_cfg_noint,
311		.chip	= {
312			.base	= S5PC100_GPK0(0),
313			.ngpio	= S5PC100_GPIO_K0_NR,
314			.label	= "GPK0",
315		},
316	}, {
317		.base	= S5PC100_GPK1_BASE,
318		.config	= &gpio_cfg_noint,
319		.chip	= {
320			.base	= S5PC100_GPK1(0),
321			.ngpio	= S5PC100_GPIO_K1_NR,
322			.label	= "GPK1",
323		},
324	}, {
325		.base	= S5PC100_GPK2_BASE,
326		.config	= &gpio_cfg_noint,
327		.chip	= {
328			.base	= S5PC100_GPK2(0),
329			.ngpio	= S5PC100_GPIO_K2_NR,
330			.label	= "GPK2",
331		},
332	}, {
333		.base	= S5PC100_GPK3_BASE,
334		.config	= &gpio_cfg_noint,
335		.chip	= {
336			.base	= S5PC100_GPK3(0),
337			.ngpio	= S5PC100_GPIO_K3_NR,
338			.label	= "GPK3",
339		},
340	}, {
341		.base	= S5PC100_GPL0_BASE,
342		.config	= &gpio_cfg_noint,
343		.chip	= {
344			.base	= S5PC100_GPL0(0),
345			.ngpio	= S5PC100_GPIO_L0_NR,
346			.label	= "GPL0",
347		},
348	}, {
349		.base	= S5PC100_GPL1_BASE,
350		.config	= &gpio_cfg_noint,
351		.chip	= {
352			.base	= S5PC100_GPL1(0),
353			.ngpio	= S5PC100_GPIO_L1_NR,
354			.label	= "GPL1",
355		},
356	}, {
357		.base	= S5PC100_GPL2_BASE,
358		.config	= &gpio_cfg_noint,
359		.chip	= {
360			.base	= S5PC100_GPL2(0),
361			.ngpio	= S5PC100_GPIO_L2_NR,
362			.label	= "GPL2",
363		},
364	}, {
365		.base	= S5PC100_GPL3_BASE,
366		.config	= &gpio_cfg_noint,
367		.chip	= {
368			.base	= S5PC100_GPL3(0),
369			.ngpio	= S5PC100_GPIO_L3_NR,
370			.label	= "GPL3",
371		},
372	}, {
373		.base	= S5PC100_GPL4_BASE,
374		.config	= &gpio_cfg_noint,
375		.chip	= {
376			.base	= S5PC100_GPL4(0),
377			.ngpio	= S5PC100_GPIO_L4_NR,
378			.label	= "GPL4",
379		},
380	},
381};
382
383extern struct irq_chip s5pc100_gpioint;
384extern void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc);
385
386static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip)
387{
388	/* Interrupt */
389	if (chip->config == &gpio_cfg) {
390		int i, irq;
391
392		chip->chip.to_irq = s5pc100_gpiolib_to_irq;
393
394		for (i = 0;  i < chip->chip.ngpio; i++) {
395			irq = S3C_IRQ_GPIO_BASE + chip->chip.base + i;
396			set_irq_chip(irq, &s5pc100_gpioint);
397			set_irq_data(irq, &chip->chip);
398			set_irq_handler(irq, handle_level_irq);
399			set_irq_flags(irq, IRQF_VALID);
400		}
401	} else if (chip->config == &gpio_cfg_eint) {
402		chip->chip.to_irq = s5pc100_gpiolib_to_eint;
403	}
404}
405
406static __init int s5pc100_gpiolib_init(void)
407{
408	struct s3c_gpio_chip *chip;
409	int nr_chips;
410
411	chip = s5pc100_gpio_chips;
412	nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
413
414	for (; nr_chips > 0; nr_chips--, chip++)
415		s5pc100_gpiolib_link(chip);
416
417	samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips,
418				       ARRAY_SIZE(s5pc100_gpio_chips));
419
420	/* Interrupt */
421	set_irq_chained_handler(IRQ_GPIOINT, s5pc100_irq_gpioint_handler);
422
423	return 0;
424}
425core_initcall(s5pc100_gpiolib_init);
426