aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-lpc32xx
diff options
context:
space:
mode:
authorKevin Wells <wellsk40@gmail.com>2010-02-26 18:53:41 -0500
committerKevin Wells <wellsk40@gmail.com>2010-07-27 06:08:09 -0400
commitc4a0208fff6cba5c7e22166ad7209322eab16bb3 (patch)
tree93d8b760390dff993865e6453ceee1c56339fec6 /arch/arm/mach-lpc32xx
parentb9cc4bf6656d5f349c283e6ac267b852b7a2e42e (diff)
ARM: LPC32XX: GPIO, timer, and IRQ drivers
Common drivers for the LPC32XX used on all platforms Signed-off-by: Kevin Wells <wellsk40@gmail.com> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-lpc32xx')
-rw-r--r--arch/arm/mach-lpc32xx/gpiolib.c446
-rw-r--r--arch/arm/mach-lpc32xx/irq.c432
-rw-r--r--arch/arm/mach-lpc32xx/timer.c182
3 files changed, 1060 insertions, 0 deletions
diff --git a/arch/arm/mach-lpc32xx/gpiolib.c b/arch/arm/mach-lpc32xx/gpiolib.c
new file mode 100644
index 000000000000..69061ea8997a
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/gpiolib.c
@@ -0,0 +1,446 @@
1/*
2 * arch/arm/mach-lpc32xx/gpiolib.c
3 *
4 * Author: Kevin Wells <kevin.wells@nxp.com>
5 *
6 * Copyright (C) 2010 NXP Semiconductors
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/io.h>
22#include <linux/errno.h>
23#include <linux/gpio.h>
24
25#include <mach/hardware.h>
26#include <mach/platform.h>
27#include "common.h"
28
29#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000)
30#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004)
31#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008)
32#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C)
33#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010)
34#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014)
35#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018)
36#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C)
37#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020)
38#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024)
39#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028)
40#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C)
41#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030)
42#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040)
43#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044)
44#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048)
45#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C)
46#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050)
47#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054)
48#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058)
49#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060)
50#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064)
51#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068)
52#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C)
53#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070)
54#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074)
55#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078)
56
57#define GPIO012_PIN_TO_BIT(x) (1 << (x))
58#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25))
59#define GPO3_PIN_TO_BIT(x) (1 << (x))
60#define GPIO012_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)
61#define GPIO3_PIN_IN_SHIFT(x) ((x) == 5 ? 24 : 10 + (x))
62#define GPIO3_PIN_IN_SEL(x, y) ((x) >> GPIO3_PIN_IN_SHIFT(y))
63#define GPIO3_PIN5_IN_SEL(x) (((x) >> 24) & 1)
64#define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)
65
66struct gpio_regs {
67 void __iomem *inp_state;
68 void __iomem *outp_set;
69 void __iomem *outp_clr;
70 void __iomem *dir_set;
71 void __iomem *dir_clr;
72};
73
74/*
75 * GPIO names
76 */
77static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
78 "p0.0", "p0.1", "p0.2", "p0.3",
79 "p0.4", "p0.5", "p0.6", "p0.7"
80};
81
82static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
83 "p1.0", "p1.1", "p1.2", "p1.3",
84 "p1.4", "p1.5", "p1.6", "p1.7",
85 "p1.8", "p1.9", "p1.10", "p1.11",
86 "p1.12", "p1.13", "p1.14", "p1.15",
87 "p1.16", "p1.17", "p1.18", "p1.19",
88 "p1.20", "p1.21", "p1.22", "p1.23",
89};
90
91static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
92 "p2.0", "p2.1", "p2.2", "p2.3",
93 "p2.4", "p2.5", "p2.6", "p2.7",
94 "p2.8", "p2.9", "p2.10", "p2.11",
95 "p2.12"
96};
97
98static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
99 "gpi000", "gpio01", "gpio02", "gpio03",
100 "gpio04", "gpio05"
101};
102
103static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
104 "gpi00", "gpi01", "gpi02", "gpi03",
105 "gpi04", "gpi05", "gpi06", "gpi07",
106 "gpi08", "gpi09", NULL, NULL,
107 NULL, NULL, NULL, "gpi15",
108 "gpi16", "gpi17", "gpi18", "gpi19",
109 "gpi20", "gpi21", "gpi22", "gpi23",
110 "gpi24", "gpi25", "gpi26", "gpi27"
111};
112
113static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
114 "gpo00", "gpo01", "gpo02", "gpo03",
115 "gpo04", "gpo05", "gpo06", "gpo07",
116 "gpo08", "gpo09", "gpo10", "gpo11",
117 "gpo12", "gpo13", "gpo14", "gpo15",
118 "gpo16", "gpo17", "gpo18", "gpo19",
119 "gpo20", "gpo21", "gpo22", "gpo23"
120};
121
122static struct gpio_regs gpio_grp_regs_p0 = {
123 .inp_state = LPC32XX_GPIO_P0_INP_STATE,
124 .outp_set = LPC32XX_GPIO_P0_OUTP_SET,
125 .outp_clr = LPC32XX_GPIO_P0_OUTP_CLR,
126 .dir_set = LPC32XX_GPIO_P0_DIR_SET,
127 .dir_clr = LPC32XX_GPIO_P0_DIR_CLR,
128};
129
130static struct gpio_regs gpio_grp_regs_p1 = {
131 .inp_state = LPC32XX_GPIO_P1_INP_STATE,
132 .outp_set = LPC32XX_GPIO_P1_OUTP_SET,
133 .outp_clr = LPC32XX_GPIO_P1_OUTP_CLR,
134 .dir_set = LPC32XX_GPIO_P1_DIR_SET,
135 .dir_clr = LPC32XX_GPIO_P1_DIR_CLR,
136};
137
138static struct gpio_regs gpio_grp_regs_p2 = {
139 .inp_state = LPC32XX_GPIO_P2_INP_STATE,
140 .outp_set = LPC32XX_GPIO_P2_OUTP_SET,
141 .outp_clr = LPC32XX_GPIO_P2_OUTP_CLR,
142 .dir_set = LPC32XX_GPIO_P2_DIR_SET,
143 .dir_clr = LPC32XX_GPIO_P2_DIR_CLR,
144};
145
146static struct gpio_regs gpio_grp_regs_p3 = {
147 .inp_state = LPC32XX_GPIO_P3_INP_STATE,
148 .outp_set = LPC32XX_GPIO_P3_OUTP_SET,
149 .outp_clr = LPC32XX_GPIO_P3_OUTP_CLR,
150 .dir_set = LPC32XX_GPIO_P2_DIR_SET,
151 .dir_clr = LPC32XX_GPIO_P2_DIR_CLR,
152};
153
154struct lpc32xx_gpio_chip {
155 struct gpio_chip chip;
156 struct gpio_regs *gpio_grp;
157};
158
159static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
160 struct gpio_chip *gpc)
161{
162 return container_of(gpc, struct lpc32xx_gpio_chip, chip);
163}
164
165static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
166 unsigned pin, int input)
167{
168 if (input)
169 __raw_writel(GPIO012_PIN_TO_BIT(pin),
170 group->gpio_grp->dir_clr);
171 else
172 __raw_writel(GPIO012_PIN_TO_BIT(pin),
173 group->gpio_grp->dir_set);
174}
175
176static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
177 unsigned pin, int input)
178{
179 u32 u = GPIO3_PIN_TO_BIT(pin);
180
181 if (input)
182 __raw_writel(u, group->gpio_grp->dir_clr);
183 else
184 __raw_writel(u, group->gpio_grp->dir_set);
185}
186
187static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
188 unsigned pin, int high)
189{
190 if (high)
191 __raw_writel(GPIO012_PIN_TO_BIT(pin),
192 group->gpio_grp->outp_set);
193 else
194 __raw_writel(GPIO012_PIN_TO_BIT(pin),
195 group->gpio_grp->outp_clr);
196}
197
198static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
199 unsigned pin, int high)
200{
201 u32 u = GPIO3_PIN_TO_BIT(pin);
202
203 if (high)
204 __raw_writel(u, group->gpio_grp->outp_set);
205 else
206 __raw_writel(u, group->gpio_grp->outp_clr);
207}
208
209static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
210 unsigned pin, int high)
211{
212 if (high)
213 __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
214 else
215 __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
216}
217
218static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
219 unsigned pin)
220{
221 return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
222 pin);
223}
224
225static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
226 unsigned pin)
227{
228 int state = __raw_readl(group->gpio_grp->inp_state);
229
230 /*
231 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
232 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
233 */
234 return GPIO3_PIN_IN_SEL(state, pin);
235}
236
237static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
238 unsigned pin)
239{
240 return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
241}
242
243/*
244 * GENERIC_GPIO primitives.
245 */
246static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
247 unsigned pin)
248{
249 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
250
251 __set_gpio_dir_p012(group, pin, 1);
252
253 return 0;
254}
255
256static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
257 unsigned pin)
258{
259 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
260
261 __set_gpio_dir_p3(group, pin, 1);
262
263 return 0;
264}
265
266static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
267 unsigned pin)
268{
269 return 0;
270}
271
272static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
273{
274 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
275
276 return __get_gpio_state_p012(group, pin);
277}
278
279static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
280{
281 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
282
283 return __get_gpio_state_p3(group, pin);
284}
285
286static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
287{
288 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
289
290 return __get_gpi_state_p3(group, pin);
291}
292
293static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
294 int value)
295{
296 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
297
298 __set_gpio_dir_p012(group, pin, 0);
299
300 return 0;
301}
302
303static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
304 int value)
305{
306 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
307
308 __set_gpio_dir_p3(group, pin, 0);
309
310 return 0;
311}
312
313static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
314 int value)
315{
316 return 0;
317}
318
319static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
320 int value)
321{
322 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
323
324 __set_gpio_level_p012(group, pin, value);
325}
326
327static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
328 int value)
329{
330 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
331
332 __set_gpio_level_p3(group, pin, value);
333}
334
335static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
336 int value)
337{
338 struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
339
340 __set_gpo_level_p3(group, pin, value);
341}
342
343static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
344{
345 if (pin < chip->ngpio)
346 return 0;
347
348 return -EINVAL;
349}
350
351static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
352 {
353 .chip = {
354 .label = "gpio_p0",
355 .direction_input = lpc32xx_gpio_dir_input_p012,
356 .get = lpc32xx_gpio_get_value_p012,
357 .direction_output = lpc32xx_gpio_dir_output_p012,
358 .set = lpc32xx_gpio_set_value_p012,
359 .request = lpc32xx_gpio_request,
360 .base = LPC32XX_GPIO_P0_GRP,
361 .ngpio = LPC32XX_GPIO_P0_MAX,
362 .names = gpio_p0_names,
363 .can_sleep = 0,
364 },
365 .gpio_grp = &gpio_grp_regs_p0,
366 },
367 {
368 .chip = {
369 .label = "gpio_p1",
370 .direction_input = lpc32xx_gpio_dir_input_p012,
371 .get = lpc32xx_gpio_get_value_p012,
372 .direction_output = lpc32xx_gpio_dir_output_p012,
373 .set = lpc32xx_gpio_set_value_p012,
374 .request = lpc32xx_gpio_request,
375 .base = LPC32XX_GPIO_P1_GRP,
376 .ngpio = LPC32XX_GPIO_P1_MAX,
377 .names = gpio_p1_names,
378 .can_sleep = 0,
379 },
380 .gpio_grp = &gpio_grp_regs_p1,
381 },
382 {
383 .chip = {
384 .label = "gpio_p2",
385 .direction_input = lpc32xx_gpio_dir_input_p012,
386 .get = lpc32xx_gpio_get_value_p012,
387 .direction_output = lpc32xx_gpio_dir_output_p012,
388 .set = lpc32xx_gpio_set_value_p012,
389 .request = lpc32xx_gpio_request,
390 .base = LPC32XX_GPIO_P2_GRP,
391 .ngpio = LPC32XX_GPIO_P2_MAX,
392 .names = gpio_p2_names,
393 .can_sleep = 0,
394 },
395 .gpio_grp = &gpio_grp_regs_p2,
396 },
397 {
398 .chip = {
399 .label = "gpio_p3",
400 .direction_input = lpc32xx_gpio_dir_input_p3,
401 .get = lpc32xx_gpio_get_value_p3,
402 .direction_output = lpc32xx_gpio_dir_output_p3,
403 .set = lpc32xx_gpio_set_value_p3,
404 .request = lpc32xx_gpio_request,
405 .base = LPC32XX_GPIO_P3_GRP,
406 .ngpio = LPC32XX_GPIO_P3_MAX,
407 .names = gpio_p3_names,
408 .can_sleep = 0,
409 },
410 .gpio_grp = &gpio_grp_regs_p3,
411 },
412 {
413 .chip = {
414 .label = "gpi_p3",
415 .direction_input = lpc32xx_gpio_dir_in_always,
416 .get = lpc32xx_gpi_get_value,
417 .request = lpc32xx_gpio_request,
418 .base = LPC32XX_GPI_P3_GRP,
419 .ngpio = LPC32XX_GPI_P3_MAX,
420 .names = gpi_p3_names,
421 .can_sleep = 0,
422 },
423 .gpio_grp = &gpio_grp_regs_p3,
424 },
425 {
426 .chip = {
427 .label = "gpo_p3",
428 .direction_output = lpc32xx_gpio_dir_out_always,
429 .set = lpc32xx_gpo_set_value,
430 .request = lpc32xx_gpio_request,
431 .base = LPC32XX_GPO_P3_GRP,
432 .ngpio = LPC32XX_GPO_P3_MAX,
433 .names = gpo_p3_names,
434 .can_sleep = 0,
435 },
436 .gpio_grp = &gpio_grp_regs_p3,
437 },
438};
439
440void __init lpc32xx_gpio_init(void)
441{
442 int i;
443
444 for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
445 gpiochip_add(&lpc32xx_gpiochip[i].chip);
446}
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
new file mode 100644
index 000000000000..bd0df26c415b
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/irq.c
@@ -0,0 +1,432 @@
1/*
2 * arch/arm/mach-lpc32xx/irq.c
3 *
4 * Author: Kevin Wells <kevin.wells@nxp.com>
5 *
6 * Copyright (C) 2010 NXP Semiconductors
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/kernel.h>
20#include <linux/types.h>
21#include <linux/interrupt.h>
22#include <linux/irq.h>
23#include <linux/err.h>
24#include <linux/io.h>
25
26#include <mach/irqs.h>
27#include <mach/hardware.h>
28#include <mach/platform.h>
29#include "common.h"
30
31/*
32 * Default value representing the Activation polarity of all internal
33 * interrupt sources
34 */
35#define MIC_APR_DEFAULT 0x3FF0EFE0
36#define SIC1_APR_DEFAULT 0xFBD27186
37#define SIC2_APR_DEFAULT 0x801810C0
38
39/*
40 * Default value representing the Activation Type of all internal
41 * interrupt sources. All are level sensitive.
42 */
43#define MIC_ATR_DEFAULT 0x00000000
44#define SIC1_ATR_DEFAULT 0x00026000
45#define SIC2_ATR_DEFAULT 0x00000000
46
47struct lpc32xx_event_group_regs {
48 void __iomem *enab_reg;
49 void __iomem *edge_reg;
50 void __iomem *maskstat_reg;
51 void __iomem *rawstat_reg;
52};
53
54static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = {
55 .enab_reg = LPC32XX_CLKPWR_INT_ER,
56 .edge_reg = LPC32XX_CLKPWR_INT_AP,
57 .maskstat_reg = LPC32XX_CLKPWR_INT_SR,
58 .rawstat_reg = LPC32XX_CLKPWR_INT_RS,
59};
60
61static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = {
62 .enab_reg = LPC32XX_CLKPWR_PIN_ER,
63 .edge_reg = LPC32XX_CLKPWR_PIN_AP,
64 .maskstat_reg = LPC32XX_CLKPWR_PIN_SR,
65 .rawstat_reg = LPC32XX_CLKPWR_PIN_RS,
66};
67
68struct lpc32xx_event_info {
69 const struct lpc32xx_event_group_regs *event_group;
70 u32 mask;
71};
72
73/*
74 * Maps an IRQ number to and event mask and register
75 */
76static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
77 [IRQ_LPC32XX_GPI_08] = {
78 .event_group = &lpc32xx_event_pin_regs,
79 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
80 },
81 [IRQ_LPC32XX_GPI_09] = {
82 .event_group = &lpc32xx_event_pin_regs,
83 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT,
84 },
85 [IRQ_LPC32XX_GPI_19] = {
86 .event_group = &lpc32xx_event_pin_regs,
87 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT,
88 },
89 [IRQ_LPC32XX_GPI_07] = {
90 .event_group = &lpc32xx_event_pin_regs,
91 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT,
92 },
93 [IRQ_LPC32XX_GPI_00] = {
94 .event_group = &lpc32xx_event_pin_regs,
95 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT,
96 },
97 [IRQ_LPC32XX_GPI_01] = {
98 .event_group = &lpc32xx_event_pin_regs,
99 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT,
100 },
101 [IRQ_LPC32XX_GPI_02] = {
102 .event_group = &lpc32xx_event_pin_regs,
103 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT,
104 },
105 [IRQ_LPC32XX_GPI_03] = {
106 .event_group = &lpc32xx_event_pin_regs,
107 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT,
108 },
109 [IRQ_LPC32XX_GPI_04] = {
110 .event_group = &lpc32xx_event_pin_regs,
111 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT,
112 },
113 [IRQ_LPC32XX_GPI_05] = {
114 .event_group = &lpc32xx_event_pin_regs,
115 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT,
116 },
117 [IRQ_LPC32XX_GPI_06] = {
118 .event_group = &lpc32xx_event_pin_regs,
119 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
120 },
121 [IRQ_LPC32XX_GPIO_00] = {
122 .event_group = &lpc32xx_event_int_regs,
123 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
124 },
125 [IRQ_LPC32XX_GPIO_01] = {
126 .event_group = &lpc32xx_event_int_regs,
127 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
128 },
129 [IRQ_LPC32XX_GPIO_02] = {
130 .event_group = &lpc32xx_event_int_regs,
131 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
132 },
133 [IRQ_LPC32XX_GPIO_03] = {
134 .event_group = &lpc32xx_event_int_regs,
135 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
136 },
137 [IRQ_LPC32XX_GPIO_04] = {
138 .event_group = &lpc32xx_event_int_regs,
139 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
140 },
141 [IRQ_LPC32XX_GPIO_05] = {
142 .event_group = &lpc32xx_event_int_regs,
143 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
144 },
145 [IRQ_LPC32XX_KEY] = {
146 .event_group = &lpc32xx_event_int_regs,
147 .mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
148 },
149 [IRQ_LPC32XX_USB_OTG_ATX] = {
150 .event_group = &lpc32xx_event_int_regs,
151 .mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
152 },
153 [IRQ_LPC32XX_USB_HOST] = {
154 .event_group = &lpc32xx_event_int_regs,
155 .mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
156 },
157 [IRQ_LPC32XX_RTC] = {
158 .event_group = &lpc32xx_event_int_regs,
159 .mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
160 },
161 [IRQ_LPC32XX_MSTIMER] = {
162 .event_group = &lpc32xx_event_int_regs,
163 .mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
164 },
165 [IRQ_LPC32XX_TS_AUX] = {
166 .event_group = &lpc32xx_event_int_regs,
167 .mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
168 },
169 [IRQ_LPC32XX_TS_P] = {
170 .event_group = &lpc32xx_event_int_regs,
171 .mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
172 },
173 [IRQ_LPC32XX_TS_IRQ] = {
174 .event_group = &lpc32xx_event_int_regs,
175 .mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
176 },
177};
178
179static void get_controller(unsigned int irq, unsigned int *base,
180 unsigned int *irqbit)
181{
182 if (irq < 32) {
183 *base = LPC32XX_MIC_BASE;
184 *irqbit = 1 << irq;
185 } else if (irq < 64) {
186 *base = LPC32XX_SIC1_BASE;
187 *irqbit = 1 << (irq - 32);
188 } else {
189 *base = LPC32XX_SIC2_BASE;
190 *irqbit = 1 << (irq - 64);
191 }
192}
193
194static void lpc32xx_mask_irq(unsigned int irq)
195{
196 unsigned int reg, ctrl, mask;
197
198 get_controller(irq, &ctrl, &mask);
199
200 reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
201 __raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
202}
203
204static void lpc32xx_unmask_irq(unsigned int irq)
205{
206 unsigned int reg, ctrl, mask;
207
208 get_controller(irq, &ctrl, &mask);
209
210 reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
211 __raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
212}
213
214static void lpc32xx_ack_irq(unsigned int irq)
215{
216 unsigned int ctrl, mask;
217
218 get_controller(irq, &ctrl, &mask);
219
220 __raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
221
222 /* Also need to clear pending wake event */
223 if (lpc32xx_events[irq].mask != 0)
224 __raw_writel(lpc32xx_events[irq].mask,
225 lpc32xx_events[irq].event_group->rawstat_reg);
226}
227
228static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
229 int use_edge)
230{
231 unsigned int reg, ctrl, mask;
232
233 get_controller(irq, &ctrl, &mask);
234
235 /* Activation level, high or low */
236 reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
237 if (use_high_level)
238 reg |= mask;
239 else
240 reg &= ~mask;
241 __raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
242
243 /* Activation type, edge or level */
244 reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
245 if (use_edge)
246 reg |= mask;
247 else
248 reg &= ~mask;
249 __raw_writel(reg, LPC32XX_INTC_ACT_TYPE(ctrl));
250
251 /* Use same polarity for the wake events */
252 if (lpc32xx_events[irq].mask != 0) {
253 reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
254
255 if (use_high_level)
256 reg |= lpc32xx_events[irq].mask;
257 else
258 reg &= ~lpc32xx_events[irq].mask;
259
260 __raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
261 }
262}
263
264static int lpc32xx_set_irq_type(unsigned int irq, unsigned int type)
265{
266 switch (type) {
267 case IRQ_TYPE_EDGE_RISING:
268 /* Rising edge sensitive */
269 __lpc32xx_set_irq_type(irq, 1, 1);
270 break;
271
272 case IRQ_TYPE_EDGE_FALLING:
273 /* Falling edge sensitive */
274 __lpc32xx_set_irq_type(irq, 0, 1);
275 break;
276
277 case IRQ_TYPE_LEVEL_LOW:
278 /* Low level sensitive */
279 __lpc32xx_set_irq_type(irq, 0, 0);
280 break;
281
282 case IRQ_TYPE_LEVEL_HIGH:
283 /* High level sensitive */
284 __lpc32xx_set_irq_type(irq, 1, 0);
285 break;
286
287 /* Other modes are not supported */
288 default:
289 return -EINVAL;
290 }
291
292 /* Ok to use the level handler for all types */
293 set_irq_handler(irq, handle_level_irq);
294
295 return 0;
296}
297
298static int lpc32xx_irq_wake(unsigned int irqno, unsigned int state)
299{
300 unsigned long eventreg;
301
302 if (lpc32xx_events[irqno].mask != 0) {
303 eventreg = __raw_readl(lpc32xx_events[irqno].
304 event_group->enab_reg);
305
306 if (state)
307 eventreg |= lpc32xx_events[irqno].mask;
308 else
309 eventreg &= ~lpc32xx_events[irqno].mask;
310
311 __raw_writel(eventreg,
312 lpc32xx_events[irqno].event_group->enab_reg);
313
314 return 0;
315 }
316
317 /* Clear event */
318 __raw_writel(lpc32xx_events[irqno].mask,
319 lpc32xx_events[irqno].event_group->rawstat_reg);
320
321 return -ENODEV;
322}
323
324static void __init lpc32xx_set_default_mappings(unsigned int apr,
325 unsigned int atr, unsigned int offset)
326{
327 unsigned int i;
328
329 /* Set activation levels for each interrupt */
330 i = 0;
331 while (i < 32) {
332 __lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
333 ((atr >> i) & 0x1));
334 i++;
335 }
336}
337
338static struct irq_chip lpc32xx_irq_chip = {
339 .ack = lpc32xx_ack_irq,
340 .mask = lpc32xx_mask_irq,
341 .unmask = lpc32xx_unmask_irq,
342 .set_type = lpc32xx_set_irq_type,
343 .set_wake = lpc32xx_irq_wake
344};
345
346static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
347{
348 unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
349
350 while (ints != 0) {
351 int irqno = fls(ints) - 1;
352
353 ints &= ~(1 << irqno);
354
355 generic_handle_irq(LPC32XX_SIC1_IRQ(irqno));
356 }
357}
358
359static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
360{
361 unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
362
363 while (ints != 0) {
364 int irqno = fls(ints) - 1;
365
366 ints &= ~(1 << irqno);
367
368 generic_handle_irq(LPC32XX_SIC2_IRQ(irqno));
369 }
370}
371
372void __init lpc32xx_init_irq(void)
373{
374 unsigned int i;
375
376 /* Setup MIC */
377 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
378 __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
379 __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
380
381 /* Setup SIC1 */
382 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
383 __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
384 __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
385
386 /* Setup SIC2 */
387 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
388 __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
389 __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
390
391 /* Configure supported IRQ's */
392 for (i = 0; i < NR_IRQS; i++) {
393 set_irq_chip(i, &lpc32xx_irq_chip);
394 set_irq_handler(i, handle_level_irq);
395 set_irq_flags(i, IRQF_VALID);
396 }
397
398 /* Set default mappings */
399 lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
400 lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
401 lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
402
403 /* mask all interrupts except SUBIRQ */
404 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
405 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
406 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
407
408 /* MIC SUBIRQx interrupts will route handling to the chain handlers */
409 set_irq_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
410 set_irq_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
411
412 /* Initially disable all wake events */
413 __raw_writel(0, LPC32XX_CLKPWR_P01_ER);
414 __raw_writel(0, LPC32XX_CLKPWR_INT_ER);
415 __raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
416
417 /*
418 * Default wake activation polarities, all pin sources are low edge
419 * triggered
420 */
421 __raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
422 LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
423 LPC32XX_CLKPWR_INTSRC_RTC_BIT,
424 LPC32XX_CLKPWR_INT_AP);
425 __raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
426
427 /* Clear latched wake event states */
428 __raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
429 LPC32XX_CLKPWR_PIN_RS);
430 __raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
431 LPC32XX_CLKPWR_INT_RS);
432}
diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c
new file mode 100644
index 000000000000..630dd4a74b26
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/timer.c
@@ -0,0 +1,182 @@
1/*
2 * arch/arm/mach-lpc32xx/timer.c
3 *
4 * Author: Kevin Wells <kevin.wells@nxp.com>
5 *
6 * Copyright (C) 2009 - 2010 NXP Semiconductors
7 * Copyright (C) 2009 Fontys University of Applied Sciences, Eindhoven
8 * Ed Schouten <e.schouten@fontys.nl>
9 * Laurens Timmermans <l.timmermans@fontys.nl>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
22#include <linux/interrupt.h>
23#include <linux/irq.h>
24#include <linux/time.h>
25#include <linux/err.h>
26#include <linux/clockchips.h>
27
28#include <asm/mach/time.h>
29
30#include <mach/hardware.h>
31#include <mach/platform.h>
32#include "common.h"
33
34static cycle_t lpc32xx_clksrc_read(struct clocksource *cs)
35{
36 return (cycle_t)__raw_readl(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE));
37}
38
39static struct clocksource lpc32xx_clksrc = {
40 .name = "lpc32xx_clksrc",
41 .shift = 24,
42 .rating = 300,
43 .read = lpc32xx_clksrc_read,
44 .mask = CLOCKSOURCE_MASK(32),
45 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
46};
47
48static int lpc32xx_clkevt_next_event(unsigned long delta,
49 struct clock_event_device *dev)
50{
51 __raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
52 LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
53 __raw_writel(delta, LCP32XX_TIMER_PR(LPC32XX_TIMER0_BASE));
54 __raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
55 LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
56
57 return 0;
58}
59
60static void lpc32xx_clkevt_mode(enum clock_event_mode mode,
61 struct clock_event_device *dev)
62{
63 switch (mode) {
64 case CLOCK_EVT_MODE_PERIODIC:
65 WARN_ON(1);
66 break;
67
68 case CLOCK_EVT_MODE_ONESHOT:
69 case CLOCK_EVT_MODE_SHUTDOWN:
70 /*
71 * Disable the timer. When using oneshot, we must also
72 * disable the timer to wait for the first call to
73 * set_next_event().
74 */
75 __raw_writel(0, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
76 break;
77
78 case CLOCK_EVT_MODE_UNUSED:
79 case CLOCK_EVT_MODE_RESUME:
80 break;
81 }
82}
83
84static struct clock_event_device lpc32xx_clkevt = {
85 .name = "lpc32xx_clkevt",
86 .features = CLOCK_EVT_FEAT_ONESHOT,
87 .shift = 32,
88 .rating = 300,
89 .set_next_event = lpc32xx_clkevt_next_event,
90 .set_mode = lpc32xx_clkevt_mode,
91};
92
93static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id)
94{
95 struct clock_event_device *evt = &lpc32xx_clkevt;
96
97 /* Clear match */
98 __raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
99 LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
100
101 evt->event_handler(evt);
102
103 return IRQ_HANDLED;
104}
105
106static struct irqaction lpc32xx_timer_irq = {
107 .name = "LPC32XX Timer Tick",
108 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
109 .handler = lpc32xx_timer_interrupt,
110};
111
112/*
113 * The clock management driver isn't initialized at this point, so the
114 * clocks need to be enabled here manually and then tagged as used in
115 * the clock driver initialization
116 */
117static void __init lpc32xx_timer_init(void)
118{
119 u32 clkrate, pllreg;
120
121 /* Enable timer clock */
122 __raw_writel(LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN |
123 LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
124 LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1);
125
126 /*
127 * The clock driver isn't initialized at this point. So determine if
128 * the SYSCLK is driven from the PLL397 or main oscillator and then use
129 * it to compute the PLL frequency and the PCLK divider to get the base
130 * timer rates. This rate is needed to compute the tick rate.
131 */
132 if (clk_is_sysclk_mainosc() != 0)
133 clkrate = LPC32XX_MAIN_OSC_FREQ;
134 else
135 clkrate = 397 * LPC32XX_CLOCK_OSC_FREQ;
136
137 /* Get ARM HCLKPLL register and convert it into a frequency */
138 pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
139 clkrate = clk_get_pllrate_from_reg(clkrate, pllreg);
140
141 /* Get PCLK divider and divide ARM PLL clock by it to get timer rate */
142 clkrate = clkrate / clk_get_pclk_div();
143
144 /* Initial timer setup */
145 __raw_writel(0, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
146 __raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
147 LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
148 __raw_writel(1, LCP32XX_TIMER_MR0(LPC32XX_TIMER0_BASE));
149 __raw_writel(LCP32XX_TIMER_CNTR_MCR_MTCH(0) |
150 LCP32XX_TIMER_CNTR_MCR_STOP(0) |
151 LCP32XX_TIMER_CNTR_MCR_RESET(0),
152 LCP32XX_TIMER_MCR(LPC32XX_TIMER0_BASE));
153
154 /* Setup tick interrupt */
155 setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq);
156
157 /* Setup the clockevent structure. */
158 lpc32xx_clkevt.mult = div_sc(clkrate, NSEC_PER_SEC,
159 lpc32xx_clkevt.shift);
160 lpc32xx_clkevt.max_delta_ns = clockevent_delta2ns(-1,
161 &lpc32xx_clkevt);
162 lpc32xx_clkevt.min_delta_ns = clockevent_delta2ns(1,
163 &lpc32xx_clkevt) + 1;
164 lpc32xx_clkevt.cpumask = cpumask_of(0);
165 clockevents_register_device(&lpc32xx_clkevt);
166
167 /* Use timer1 as clock source. */
168 __raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
169 LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
170 __raw_writel(0, LCP32XX_TIMER_PR(LPC32XX_TIMER1_BASE));
171 __raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
172 __raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
173 LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
174 lpc32xx_clksrc.mult = clocksource_hz2mult(clkrate,
175 lpc32xx_clksrc.shift);
176 clocksource_register(&lpc32xx_clksrc);
177}
178
179struct sys_timer lpc32xx_timer = {
180 .init = &lpc32xx_timer_init,
181};
182