aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2006-09-26 02:32:13 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 11:48:54 -0400
commit5f97f7f9400de47ae837170bb274e90ad3934386 (patch)
tree514451e6dc6b46253293a00035d375e77b1c65ed /arch/avr32/mach-at32ap
parent53e62d3aaa60590d4a69b4e07c29f448b5151047 (diff)
[PATCH] avr32 architecture
This adds support for the Atmel AVR32 architecture as well as the AT32AP7000 CPU and the AT32STK1000 development board. AVR32 is a new high-performance 32-bit RISC microprocessor core, designed for cost-sensitive embedded applications, with particular emphasis on low power consumption and high code density. The AVR32 architecture is not binary compatible with earlier 8-bit AVR architectures. The AVR32 architecture, including the instruction set, is described by the AVR32 Architecture Manual, available from http://www.atmel.com/dyn/resources/prod_documents/doc32000.pdf The Atmel AT32AP7000 is the first CPU implementing the AVR32 architecture. It features a 7-stage pipeline, 16KB instruction and data caches and a full Memory Management Unit. It also comes with a large set of integrated peripherals, many of which are shared with the AT91 ARM-based controllers from Atmel. Full data sheet is available from http://www.atmel.com/dyn/resources/prod_documents/doc32003.pdf while the CPU core implementation including caches and MMU is documented by the AVR32 AP Technical Reference, available from http://www.atmel.com/dyn/resources/prod_documents/doc32001.pdf Information about the AT32STK1000 development board can be found at http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3918 including a BSP CD image with an earlier version of this patch, development tools (binaries and source/patches) and a root filesystem image suitable for booting from SD card. Alternatively, there's a preliminary "getting started" guide available at http://avr32linux.org/twiki/bin/view/Main/GettingStarted which provides links to the sources and patches you will need in order to set up a cross-compiling environment for avr32-linux. This patch, as well as the other patches included with the BSP and the toolchain patches, is actively supported by Atmel Corporation. [dmccr@us.ibm.com: Fix more pxx_page macro locations] [bunk@stusta.de: fix `make defconfig'] Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Dave McCracken <dmccr@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/avr32/mach-at32ap')
-rw-r--r--arch/avr32/mach-at32ap/Makefile2
-rw-r--r--arch/avr32/mach-at32ap/at32ap.c90
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c866
-rw-r--r--arch/avr32/mach-at32ap/clock.c148
-rw-r--r--arch/avr32/mach-at32ap/clock.h30
-rw-r--r--arch/avr32/mach-at32ap/extint.c171
-rw-r--r--arch/avr32/mach-at32ap/intc.c133
-rw-r--r--arch/avr32/mach-at32ap/intc.h327
-rw-r--r--arch/avr32/mach-at32ap/pio.c118
-rw-r--r--arch/avr32/mach-at32ap/pio.h178
-rw-r--r--arch/avr32/mach-at32ap/sm.c289
-rw-r--r--arch/avr32/mach-at32ap/sm.h240
12 files changed, 2592 insertions, 0 deletions
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
new file mode 100644
index 000000000000..4b10853eb614
--- /dev/null
+++ b/arch/avr32/mach-at32ap/Makefile
@@ -0,0 +1,2 @@
1obj-y += at32ap.o clock.o pio.o intc.o extint.o
2obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
diff --git a/arch/avr32/mach-at32ap/at32ap.c b/arch/avr32/mach-at32ap/at32ap.c
new file mode 100644
index 000000000000..f7cedf5aabea
--- /dev/null
+++ b/arch/avr32/mach-at32ap/at32ap.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright (C) 2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/err.h>
11#include <linux/init.h>
12#include <linux/platform_device.h>
13
14#include <asm/io.h>
15
16#include <asm/arch/init.h>
17#include <asm/arch/sm.h>
18
19struct at32_sm system_manager;
20
21static int __init at32_sm_init(void)
22{
23 struct resource *regs;
24 struct at32_sm *sm = &system_manager;
25 int ret = -ENXIO;
26
27 regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
28 if (!regs)
29 goto fail;
30
31 spin_lock_init(&sm->lock);
32 sm->pdev = &at32_sm_device;
33
34 ret = -ENOMEM;
35 sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
36 if (!sm->regs)
37 goto fail;
38
39 return 0;
40
41fail:
42 printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
43 return ret;
44}
45
46void __init setup_platform(void)
47{
48 at32_sm_init();
49 at32_clock_init();
50 at32_portmux_init();
51
52 /* FIXME: This doesn't belong here */
53 at32_setup_serial_console(1);
54}
55
56static int __init pdc_probe(struct platform_device *pdev)
57{
58 struct clk *pclk, *hclk;
59
60 pclk = clk_get(&pdev->dev, "pclk");
61 if (IS_ERR(pclk)) {
62 dev_err(&pdev->dev, "no pclk defined\n");
63 return PTR_ERR(pclk);
64 }
65 hclk = clk_get(&pdev->dev, "hclk");
66 if (IS_ERR(hclk)) {
67 dev_err(&pdev->dev, "no hclk defined\n");
68 clk_put(pclk);
69 return PTR_ERR(hclk);
70 }
71
72 clk_enable(pclk);
73 clk_enable(hclk);
74
75 dev_info(&pdev->dev, "Atmel Peripheral DMA Controller enabled\n");
76 return 0;
77}
78
79static struct platform_driver pdc_driver = {
80 .probe = pdc_probe,
81 .driver = {
82 .name = "pdc",
83 },
84};
85
86static int __init pdc_init(void)
87{
88 return platform_driver_register(&pdc_driver);
89}
90arch_initcall(pdc_init);
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
new file mode 100644
index 000000000000..e8c6893a1c23
--- /dev/null
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -0,0 +1,866 @@
1/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/clk.h>
9#include <linux/init.h>
10#include <linux/platform_device.h>
11
12#include <asm/io.h>
13
14#include <asm/arch/board.h>
15#include <asm/arch/portmux.h>
16#include <asm/arch/sm.h>
17
18#include "clock.h"
19#include "pio.h"
20#include "sm.h"
21
22#define PBMEM(base) \
23 { \
24 .start = base, \
25 .end = base + 0x3ff, \
26 .flags = IORESOURCE_MEM, \
27 }
28#define IRQ(num) \
29 { \
30 .start = num, \
31 .end = num, \
32 .flags = IORESOURCE_IRQ, \
33 }
34#define NAMED_IRQ(num, _name) \
35 { \
36 .start = num, \
37 .end = num, \
38 .name = _name, \
39 .flags = IORESOURCE_IRQ, \
40 }
41
42#define DEFINE_DEV(_name, _id) \
43static struct platform_device _name##_id##_device = { \
44 .name = #_name, \
45 .id = _id, \
46 .resource = _name##_id##_resource, \
47 .num_resources = ARRAY_SIZE(_name##_id##_resource), \
48}
49#define DEFINE_DEV_DATA(_name, _id) \
50static struct platform_device _name##_id##_device = { \
51 .name = #_name, \
52 .id = _id, \
53 .dev = { \
54 .platform_data = &_name##_id##_data, \
55 }, \
56 .resource = _name##_id##_resource, \
57 .num_resources = ARRAY_SIZE(_name##_id##_resource), \
58}
59
60#define DEV_CLK(_name, devname, bus, _index) \
61static struct clk devname##_##_name = { \
62 .name = #_name, \
63 .dev = &devname##_device.dev, \
64 .parent = &bus##_clk, \
65 .mode = bus##_clk_mode, \
66 .get_rate = bus##_clk_get_rate, \
67 .index = _index, \
68}
69
70enum {
71 PIOA,
72 PIOB,
73 PIOC,
74 PIOD,
75};
76
77enum {
78 FUNC_A,
79 FUNC_B,
80};
81
82unsigned long at32ap7000_osc_rates[3] = {
83 [0] = 32768,
84 /* FIXME: these are ATSTK1002-specific */
85 [1] = 20000000,
86 [2] = 12000000,
87};
88
89static unsigned long osc_get_rate(struct clk *clk)
90{
91 return at32ap7000_osc_rates[clk->index];
92}
93
94static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
95{
96 unsigned long div, mul, rate;
97
98 if (!(control & SM_BIT(PLLEN)))
99 return 0;
100
101 div = SM_BFEXT(PLLDIV, control) + 1;
102 mul = SM_BFEXT(PLLMUL, control) + 1;
103
104 rate = clk->parent->get_rate(clk->parent);
105 rate = (rate + div / 2) / div;
106 rate *= mul;
107
108 return rate;
109}
110
111static unsigned long pll0_get_rate(struct clk *clk)
112{
113 u32 control;
114
115 control = sm_readl(&system_manager, PM_PLL0);
116
117 return pll_get_rate(clk, control);
118}
119
120static unsigned long pll1_get_rate(struct clk *clk)
121{
122 u32 control;
123
124 control = sm_readl(&system_manager, PM_PLL1);
125
126 return pll_get_rate(clk, control);
127}
128
129/*
130 * The AT32AP7000 has five primary clock sources: One 32kHz
131 * oscillator, two crystal oscillators and two PLLs.
132 */
133static struct clk osc32k = {
134 .name = "osc32k",
135 .get_rate = osc_get_rate,
136 .users = 1,
137 .index = 0,
138};
139static struct clk osc0 = {
140 .name = "osc0",
141 .get_rate = osc_get_rate,
142 .users = 1,
143 .index = 1,
144};
145static struct clk osc1 = {
146 .name = "osc1",
147 .get_rate = osc_get_rate,
148 .index = 2,
149};
150static struct clk pll0 = {
151 .name = "pll0",
152 .get_rate = pll0_get_rate,
153 .parent = &osc0,
154};
155static struct clk pll1 = {
156 .name = "pll1",
157 .get_rate = pll1_get_rate,
158 .parent = &osc0,
159};
160
161/*
162 * The main clock can be either osc0 or pll0. The boot loader may
163 * have chosen one for us, so we don't really know which one until we
164 * have a look at the SM.
165 */
166static struct clk *main_clock;
167
168/*
169 * Synchronous clocks are generated from the main clock. The clocks
170 * must satisfy the constraint
171 * fCPU >= fHSB >= fPB
172 * i.e. each clock must not be faster than its parent.
173 */
174static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift)
175{
176 return main_clock->get_rate(main_clock) >> shift;
177};
178
179static void cpu_clk_mode(struct clk *clk, int enabled)
180{
181 struct at32_sm *sm = &system_manager;
182 unsigned long flags;
183 u32 mask;
184
185 spin_lock_irqsave(&sm->lock, flags);
186 mask = sm_readl(sm, PM_CPU_MASK);
187 if (enabled)
188 mask |= 1 << clk->index;
189 else
190 mask &= ~(1 << clk->index);
191 sm_writel(sm, PM_CPU_MASK, mask);
192 spin_unlock_irqrestore(&sm->lock, flags);
193}
194
195static unsigned long cpu_clk_get_rate(struct clk *clk)
196{
197 unsigned long cksel, shift = 0;
198
199 cksel = sm_readl(&system_manager, PM_CKSEL);
200 if (cksel & SM_BIT(CPUDIV))
201 shift = SM_BFEXT(CPUSEL, cksel) + 1;
202
203 return bus_clk_get_rate(clk, shift);
204}
205
206static void hsb_clk_mode(struct clk *clk, int enabled)
207{
208 struct at32_sm *sm = &system_manager;
209 unsigned long flags;
210 u32 mask;
211
212 spin_lock_irqsave(&sm->lock, flags);
213 mask = sm_readl(sm, PM_HSB_MASK);
214 if (enabled)
215 mask |= 1 << clk->index;
216 else
217 mask &= ~(1 << clk->index);
218 sm_writel(sm, PM_HSB_MASK, mask);
219 spin_unlock_irqrestore(&sm->lock, flags);
220}
221
222static unsigned long hsb_clk_get_rate(struct clk *clk)
223{
224 unsigned long cksel, shift = 0;
225
226 cksel = sm_readl(&system_manager, PM_CKSEL);
227 if (cksel & SM_BIT(HSBDIV))
228 shift = SM_BFEXT(HSBSEL, cksel) + 1;
229
230 return bus_clk_get_rate(clk, shift);
231}
232
233static void pba_clk_mode(struct clk *clk, int enabled)
234{
235 struct at32_sm *sm = &system_manager;
236 unsigned long flags;
237 u32 mask;
238
239 spin_lock_irqsave(&sm->lock, flags);
240 mask = sm_readl(sm, PM_PBA_MASK);
241 if (enabled)
242 mask |= 1 << clk->index;
243 else
244 mask &= ~(1 << clk->index);
245 sm_writel(sm, PM_PBA_MASK, mask);
246 spin_unlock_irqrestore(&sm->lock, flags);
247}
248
249static unsigned long pba_clk_get_rate(struct clk *clk)
250{
251 unsigned long cksel, shift = 0;
252
253 cksel = sm_readl(&system_manager, PM_CKSEL);
254 if (cksel & SM_BIT(PBADIV))
255 shift = SM_BFEXT(PBASEL, cksel) + 1;
256
257 return bus_clk_get_rate(clk, shift);
258}
259
260static void pbb_clk_mode(struct clk *clk, int enabled)
261{
262 struct at32_sm *sm = &system_manager;
263 unsigned long flags;
264 u32 mask;
265
266 spin_lock_irqsave(&sm->lock, flags);
267 mask = sm_readl(sm, PM_PBB_MASK);
268 if (enabled)
269 mask |= 1 << clk->index;
270 else
271 mask &= ~(1 << clk->index);
272 sm_writel(sm, PM_PBB_MASK, mask);
273 spin_unlock_irqrestore(&sm->lock, flags);
274}
275
276static unsigned long pbb_clk_get_rate(struct clk *clk)
277{
278 unsigned long cksel, shift = 0;
279
280 cksel = sm_readl(&system_manager, PM_CKSEL);
281 if (cksel & SM_BIT(PBBDIV))
282 shift = SM_BFEXT(PBBSEL, cksel) + 1;
283
284 return bus_clk_get_rate(clk, shift);
285}
286
287static struct clk cpu_clk = {
288 .name = "cpu",
289 .get_rate = cpu_clk_get_rate,
290 .users = 1,
291};
292static struct clk hsb_clk = {
293 .name = "hsb",
294 .parent = &cpu_clk,
295 .get_rate = hsb_clk_get_rate,
296};
297static struct clk pba_clk = {
298 .name = "pba",
299 .parent = &hsb_clk,
300 .mode = hsb_clk_mode,
301 .get_rate = pba_clk_get_rate,
302 .index = 1,
303};
304static struct clk pbb_clk = {
305 .name = "pbb",
306 .parent = &hsb_clk,
307 .mode = hsb_clk_mode,
308 .get_rate = pbb_clk_get_rate,
309 .users = 1,
310 .index = 2,
311};
312
313/* --------------------------------------------------------------------
314 * Generic Clock operations
315 * -------------------------------------------------------------------- */
316
317static void genclk_mode(struct clk *clk, int enabled)
318{
319 u32 control;
320
321 BUG_ON(clk->index > 7);
322
323 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
324 if (enabled)
325 control |= SM_BIT(CEN);
326 else
327 control &= ~SM_BIT(CEN);
328 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
329}
330
331static unsigned long genclk_get_rate(struct clk *clk)
332{
333 u32 control;
334 unsigned long div = 1;
335
336 BUG_ON(clk->index > 7);
337
338 if (!clk->parent)
339 return 0;
340
341 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
342 if (control & SM_BIT(DIVEN))
343 div = 2 * (SM_BFEXT(DIV, control) + 1);
344
345 return clk->parent->get_rate(clk->parent) / div;
346}
347
348static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
349{
350 u32 control;
351 unsigned long parent_rate, actual_rate, div;
352
353 BUG_ON(clk->index > 7);
354
355 if (!clk->parent)
356 return 0;
357
358 parent_rate = clk->parent->get_rate(clk->parent);
359 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
360
361 if (rate > 3 * parent_rate / 4) {
362 actual_rate = parent_rate;
363 control &= ~SM_BIT(DIVEN);
364 } else {
365 div = (parent_rate + rate) / (2 * rate) - 1;
366 control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN);
367 actual_rate = parent_rate / (2 * (div + 1));
368 }
369
370 printk("clk %s: new rate %lu (actual rate %lu)\n",
371 clk->name, rate, actual_rate);
372
373 if (apply)
374 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index,
375 control);
376
377 return actual_rate;
378}
379
380int genclk_set_parent(struct clk *clk, struct clk *parent)
381{
382 u32 control;
383
384 BUG_ON(clk->index > 7);
385
386 printk("clk %s: new parent %s (was %s)\n",
387 clk->name, parent->name,
388 clk->parent ? clk->parent->name : "(null)");
389
390 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
391
392 if (parent == &osc1 || parent == &pll1)
393 control |= SM_BIT(OSCSEL);
394 else if (parent == &osc0 || parent == &pll0)
395 control &= ~SM_BIT(OSCSEL);
396 else
397 return -EINVAL;
398
399 if (parent == &pll0 || parent == &pll1)
400 control |= SM_BIT(PLLSEL);
401 else
402 control &= ~SM_BIT(PLLSEL);
403
404 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
405 clk->parent = parent;
406
407 return 0;
408}
409
410/* --------------------------------------------------------------------
411 * System peripherals
412 * -------------------------------------------------------------------- */
413static struct resource sm_resource[] = {
414 PBMEM(0xfff00000),
415 NAMED_IRQ(19, "eim"),
416 NAMED_IRQ(20, "pm"),
417 NAMED_IRQ(21, "rtc"),
418};
419struct platform_device at32_sm_device = {
420 .name = "sm",
421 .id = 0,
422 .resource = sm_resource,
423 .num_resources = ARRAY_SIZE(sm_resource),
424};
425DEV_CLK(pclk, at32_sm, pbb, 0);
426
427static struct resource intc0_resource[] = {
428 PBMEM(0xfff00400),
429};
430struct platform_device at32_intc0_device = {
431 .name = "intc",
432 .id = 0,
433 .resource = intc0_resource,
434 .num_resources = ARRAY_SIZE(intc0_resource),
435};
436DEV_CLK(pclk, at32_intc0, pbb, 1);
437
438static struct clk ebi_clk = {
439 .name = "ebi",
440 .parent = &hsb_clk,
441 .mode = hsb_clk_mode,
442 .get_rate = hsb_clk_get_rate,
443 .users = 1,
444};
445static struct clk hramc_clk = {
446 .name = "hramc",
447 .parent = &hsb_clk,
448 .mode = hsb_clk_mode,
449 .get_rate = hsb_clk_get_rate,
450 .users = 1,
451};
452
453static struct platform_device pdc_device = {
454 .name = "pdc",
455 .id = 0,
456};
457DEV_CLK(hclk, pdc, hsb, 4);
458DEV_CLK(pclk, pdc, pba, 16);
459
460static struct clk pico_clk = {
461 .name = "pico",
462 .parent = &cpu_clk,
463 .mode = cpu_clk_mode,
464 .get_rate = cpu_clk_get_rate,
465 .users = 1,
466};
467
468/* --------------------------------------------------------------------
469 * PIO
470 * -------------------------------------------------------------------- */
471
472static struct resource pio0_resource[] = {
473 PBMEM(0xffe02800),
474 IRQ(13),
475};
476DEFINE_DEV(pio, 0);
477DEV_CLK(mck, pio0, pba, 10);
478
479static struct resource pio1_resource[] = {
480 PBMEM(0xffe02c00),
481 IRQ(14),
482};
483DEFINE_DEV(pio, 1);
484DEV_CLK(mck, pio1, pba, 11);
485
486static struct resource pio2_resource[] = {
487 PBMEM(0xffe03000),
488 IRQ(15),
489};
490DEFINE_DEV(pio, 2);
491DEV_CLK(mck, pio2, pba, 12);
492
493static struct resource pio3_resource[] = {
494 PBMEM(0xffe03400),
495 IRQ(16),
496};
497DEFINE_DEV(pio, 3);
498DEV_CLK(mck, pio3, pba, 13);
499
500void __init at32_add_system_devices(void)
501{
502 system_manager.eim_first_irq = NR_INTERNAL_IRQS;
503
504 platform_device_register(&at32_sm_device);
505 platform_device_register(&at32_intc0_device);
506 platform_device_register(&pdc_device);
507
508 platform_device_register(&pio0_device);
509 platform_device_register(&pio1_device);
510 platform_device_register(&pio2_device);
511 platform_device_register(&pio3_device);
512}
513
514/* --------------------------------------------------------------------
515 * USART
516 * -------------------------------------------------------------------- */
517
518static struct resource usart0_resource[] = {
519 PBMEM(0xffe00c00),
520 IRQ(7),
521};
522DEFINE_DEV(usart, 0);
523DEV_CLK(usart, usart0, pba, 4);
524
525static struct resource usart1_resource[] = {
526 PBMEM(0xffe01000),
527 IRQ(7),
528};
529DEFINE_DEV(usart, 1);
530DEV_CLK(usart, usart1, pba, 4);
531
532static struct resource usart2_resource[] = {
533 PBMEM(0xffe01400),
534 IRQ(8),
535};
536DEFINE_DEV(usart, 2);
537DEV_CLK(usart, usart2, pba, 5);
538
539static struct resource usart3_resource[] = {
540 PBMEM(0xffe01800),
541 IRQ(9),
542};
543DEFINE_DEV(usart, 3);
544DEV_CLK(usart, usart3, pba, 6);
545
546static inline void configure_usart0_pins(void)
547{
548 portmux_set_func(PIOA, 8, FUNC_B); /* RXD */
549 portmux_set_func(PIOA, 9, FUNC_B); /* TXD */
550}
551
552static inline void configure_usart1_pins(void)
553{
554 portmux_set_func(PIOA, 17, FUNC_A); /* RXD */
555 portmux_set_func(PIOA, 18, FUNC_A); /* TXD */
556}
557
558static inline void configure_usart2_pins(void)
559{
560 portmux_set_func(PIOB, 26, FUNC_B); /* RXD */
561 portmux_set_func(PIOB, 27, FUNC_B); /* TXD */
562}
563
564static inline void configure_usart3_pins(void)
565{
566 portmux_set_func(PIOB, 18, FUNC_B); /* RXD */
567 portmux_set_func(PIOB, 17, FUNC_B); /* TXD */
568}
569
570static struct platform_device *setup_usart(unsigned int id)
571{
572 struct platform_device *pdev;
573
574 switch (id) {
575 case 0:
576 pdev = &usart0_device;
577 configure_usart0_pins();
578 break;
579 case 1:
580 pdev = &usart1_device;
581 configure_usart1_pins();
582 break;
583 case 2:
584 pdev = &usart2_device;
585 configure_usart2_pins();
586 break;
587 case 3:
588 pdev = &usart3_device;
589 configure_usart3_pins();
590 break;
591 default:
592 pdev = NULL;
593 break;
594 }
595
596 return pdev;
597}
598
599struct platform_device *__init at32_add_device_usart(unsigned int id)
600{
601 struct platform_device *pdev;
602
603 pdev = setup_usart(id);
604 if (pdev)
605 platform_device_register(pdev);
606
607 return pdev;
608}
609
610struct platform_device *at91_default_console_device;
611
612void __init at32_setup_serial_console(unsigned int usart_id)
613{
614 at91_default_console_device = setup_usart(usart_id);
615}
616
617/* --------------------------------------------------------------------
618 * Ethernet
619 * -------------------------------------------------------------------- */
620
621static struct eth_platform_data macb0_data;
622static struct resource macb0_resource[] = {
623 PBMEM(0xfff01800),
624 IRQ(25),
625};
626DEFINE_DEV_DATA(macb, 0);
627DEV_CLK(hclk, macb0, hsb, 8);
628DEV_CLK(pclk, macb0, pbb, 6);
629
630struct platform_device *__init
631at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
632{
633 struct platform_device *pdev;
634
635 switch (id) {
636 case 0:
637 pdev = &macb0_device;
638
639 portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */
640 portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */
641 portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */
642 portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */
643 portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */
644 portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */
645 portmux_set_func(PIOC, 13, FUNC_A); /* RXER */
646 portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */
647 portmux_set_func(PIOC, 16, FUNC_A); /* MDC */
648 portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */
649
650 if (!data->is_rmii) {
651 portmux_set_func(PIOC, 0, FUNC_A); /* COL */
652 portmux_set_func(PIOC, 1, FUNC_A); /* CRS */
653 portmux_set_func(PIOC, 2, FUNC_A); /* TXER */
654 portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */
655 portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */
656 portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */
657 portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */
658 portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */
659 portmux_set_func(PIOC, 18, FUNC_A); /* SPD */
660 }
661 break;
662
663 default:
664 return NULL;
665 }
666
667 memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data));
668 platform_device_register(pdev);
669
670 return pdev;
671}
672
673/* --------------------------------------------------------------------
674 * SPI
675 * -------------------------------------------------------------------- */
676static struct resource spi0_resource[] = {
677 PBMEM(0xffe00000),
678 IRQ(3),
679};
680DEFINE_DEV(spi, 0);
681DEV_CLK(mck, spi0, pba, 0);
682
683struct platform_device *__init at32_add_device_spi(unsigned int id)
684{
685 struct platform_device *pdev;
686
687 switch (id) {
688 case 0:
689 pdev = &spi0_device;
690 portmux_set_func(PIOA, 0, FUNC_A); /* MISO */
691 portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */
692 portmux_set_func(PIOA, 2, FUNC_A); /* SCK */
693 portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */
694 portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */
695 portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */
696 break;
697
698 default:
699 return NULL;
700 }
701
702 platform_device_register(pdev);
703 return pdev;
704}
705
706/* --------------------------------------------------------------------
707 * LCDC
708 * -------------------------------------------------------------------- */
709static struct lcdc_platform_data lcdc0_data;
710static struct resource lcdc0_resource[] = {
711 {
712 .start = 0xff000000,
713 .end = 0xff000fff,
714 .flags = IORESOURCE_MEM,
715 },
716 IRQ(1),
717};
718DEFINE_DEV_DATA(lcdc, 0);
719DEV_CLK(hclk, lcdc0, hsb, 7);
720static struct clk lcdc0_pixclk = {
721 .name = "pixclk",
722 .dev = &lcdc0_device.dev,
723 .mode = genclk_mode,
724 .get_rate = genclk_get_rate,
725 .set_rate = genclk_set_rate,
726 .set_parent = genclk_set_parent,
727 .index = 7,
728};
729
730struct platform_device *__init
731at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
732{
733 struct platform_device *pdev;
734
735 switch (id) {
736 case 0:
737 pdev = &lcdc0_device;
738 portmux_set_func(PIOC, 19, FUNC_A); /* CC */
739 portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */
740 portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */
741 portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */
742 portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */
743 portmux_set_func(PIOC, 24, FUNC_A); /* MODE */
744 portmux_set_func(PIOC, 25, FUNC_A); /* PWR */
745 portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */
746 portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */
747 portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */
748 portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */
749 portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */
750 portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */
751 portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */
752 portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */
753 portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */
754 portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */
755 portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */
756 portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */
757 portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */
758 portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */
759 portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */
760 portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */
761 portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */
762 portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */
763 portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */
764 portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */
765 portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */
766 portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */
767 portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */
768 portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */
769
770 clk_set_parent(&lcdc0_pixclk, &pll0);
771 clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
772 break;
773
774 default:
775 return NULL;
776 }
777
778 memcpy(pdev->dev.platform_data, data,
779 sizeof(struct lcdc_platform_data));
780
781 platform_device_register(pdev);
782 return pdev;
783}
784
785struct clk *at32_clock_list[] = {
786 &osc32k,
787 &osc0,
788 &osc1,
789 &pll0,
790 &pll1,
791 &cpu_clk,
792 &hsb_clk,
793 &pba_clk,
794 &pbb_clk,
795 &at32_sm_pclk,
796 &at32_intc0_pclk,
797 &ebi_clk,
798 &hramc_clk,
799 &pdc_hclk,
800 &pdc_pclk,
801 &pico_clk,
802 &pio0_mck,
803 &pio1_mck,
804 &pio2_mck,
805 &pio3_mck,
806 &usart0_usart,
807 &usart1_usart,
808 &usart2_usart,
809 &usart3_usart,
810 &macb0_hclk,
811 &macb0_pclk,
812 &spi0_mck,
813 &lcdc0_hclk,
814 &lcdc0_pixclk,
815};
816unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
817
818void __init at32_portmux_init(void)
819{
820 at32_init_pio(&pio0_device);
821 at32_init_pio(&pio1_device);
822 at32_init_pio(&pio2_device);
823 at32_init_pio(&pio3_device);
824}
825
826void __init at32_clock_init(void)
827{
828 struct at32_sm *sm = &system_manager;
829 u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
830 int i;
831
832 if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL))
833 main_clock = &pll0;
834 else
835 main_clock = &osc0;
836
837 if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC))
838 pll0.parent = &osc1;
839 if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
840 pll1.parent = &osc1;
841
842 /*
843 * Turn on all clocks that have at least one user already, and
844 * turn off everything else. We only do this for module
845 * clocks, and even though it isn't particularly pretty to
846 * check the address of the mode function, it should do the
847 * trick...
848 */
849 for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) {
850 struct clk *clk = at32_clock_list[i];
851
852 if (clk->mode == &cpu_clk_mode)
853 cpu_mask |= 1 << clk->index;
854 else if (clk->mode == &hsb_clk_mode)
855 hsb_mask |= 1 << clk->index;
856 else if (clk->mode == &pba_clk_mode)
857 pba_mask |= 1 << clk->index;
858 else if (clk->mode == &pbb_clk_mode)
859 pbb_mask |= 1 << clk->index;
860 }
861
862 sm_writel(sm, PM_CPU_MASK, cpu_mask);
863 sm_writel(sm, PM_HSB_MASK, hsb_mask);
864 sm_writel(sm, PM_PBA_MASK, pba_mask);
865 sm_writel(sm, PM_PBB_MASK, pbb_mask);
866}
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
new file mode 100644
index 000000000000..3d0d1097389f
--- /dev/null
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -0,0 +1,148 @@
1/*
2 * Clock management for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * Based on arch/arm/mach-at91rm9200/clock.c
7 * Copyright (C) 2005 David Brownell
8 * Copyright (C) 2005 Ivan Kokshaysky
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/clk.h>
15#include <linux/err.h>
16#include <linux/device.h>
17#include <linux/string.h>
18
19#include "clock.h"
20
21static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
22
23struct clk *clk_get(struct device *dev, const char *id)
24{
25 int i;
26
27 for (i = 0; i < at32_nr_clocks; i++) {
28 struct clk *clk = at32_clock_list[i];
29
30 if (clk->dev == dev && strcmp(id, clk->name) == 0)
31 return clk;
32 }
33
34 return ERR_PTR(-ENOENT);
35}
36EXPORT_SYMBOL(clk_get);
37
38void clk_put(struct clk *clk)
39{
40 /* clocks are static for now, we can't free them */
41}
42EXPORT_SYMBOL(clk_put);
43
44static void __clk_enable(struct clk *clk)
45{
46 if (clk->parent)
47 __clk_enable(clk->parent);
48 if (clk->users++ == 0 && clk->mode)
49 clk->mode(clk, 1);
50}
51
52int clk_enable(struct clk *clk)
53{
54 unsigned long flags;
55
56 spin_lock_irqsave(&clk_lock, flags);
57 __clk_enable(clk);
58 spin_unlock_irqrestore(&clk_lock, flags);
59
60 return 0;
61}
62EXPORT_SYMBOL(clk_enable);
63
64static void __clk_disable(struct clk *clk)
65{
66 BUG_ON(clk->users == 0);
67
68 if (--clk->users == 0 && clk->mode)
69 clk->mode(clk, 0);
70 if (clk->parent)
71 __clk_disable(clk->parent);
72}
73
74void clk_disable(struct clk *clk)
75{
76 unsigned long flags;
77
78 spin_lock_irqsave(&clk_lock, flags);
79 __clk_disable(clk);
80 spin_unlock_irqrestore(&clk_lock, flags);
81}
82EXPORT_SYMBOL(clk_disable);
83
84unsigned long clk_get_rate(struct clk *clk)
85{
86 unsigned long flags;
87 unsigned long rate;
88
89 spin_lock_irqsave(&clk_lock, flags);
90 rate = clk->get_rate(clk);
91 spin_unlock_irqrestore(&clk_lock, flags);
92
93 return rate;
94}
95EXPORT_SYMBOL(clk_get_rate);
96
97long clk_round_rate(struct clk *clk, unsigned long rate)
98{
99 unsigned long flags, actual_rate;
100
101 if (!clk->set_rate)
102 return -ENOSYS;
103
104 spin_lock_irqsave(&clk_lock, flags);
105 actual_rate = clk->set_rate(clk, rate, 0);
106 spin_unlock_irqrestore(&clk_lock, flags);
107
108 return actual_rate;
109}
110EXPORT_SYMBOL(clk_round_rate);
111
112int clk_set_rate(struct clk *clk, unsigned long rate)
113{
114 unsigned long flags;
115 long ret;
116
117 if (!clk->set_rate)
118 return -ENOSYS;
119
120 spin_lock_irqsave(&clk_lock, flags);
121 ret = clk->set_rate(clk, rate, 1);
122 spin_unlock_irqrestore(&clk_lock, flags);
123
124 return (ret < 0) ? ret : 0;
125}
126EXPORT_SYMBOL(clk_set_rate);
127
128int clk_set_parent(struct clk *clk, struct clk *parent)
129{
130 unsigned long flags;
131 int ret;
132
133 if (!clk->set_parent)
134 return -ENOSYS;
135
136 spin_lock_irqsave(&clk_lock, flags);
137 ret = clk->set_parent(clk, parent);
138 spin_unlock_irqrestore(&clk_lock, flags);
139
140 return ret;
141}
142EXPORT_SYMBOL(clk_set_parent);
143
144struct clk *clk_get_parent(struct clk *clk)
145{
146 return clk->parent;
147}
148EXPORT_SYMBOL(clk_get_parent);
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
new file mode 100644
index 000000000000..f953f044ba4d
--- /dev/null
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -0,0 +1,30 @@
1/*
2 * Clock management for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * Based on arch/arm/mach-at91rm9200/clock.c
7 * Copyright (C) 2005 David Brownell
8 * Copyright (C) 2005 Ivan Kokshaysky
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/clk.h>
15
16struct clk {
17 const char *name; /* Clock name/function */
18 struct device *dev; /* Device the clock is used by */
19 struct clk *parent; /* Parent clock, if any */
20 void (*mode)(struct clk *clk, int enabled);
21 unsigned long (*get_rate)(struct clk *clk);
22 long (*set_rate)(struct clk *clk, unsigned long rate,
23 int apply);
24 int (*set_parent)(struct clk *clk, struct clk *parent);
25 u16 users; /* Enabled if non-zero */
26 u16 index; /* Sibling index */
27};
28
29extern struct clk *at32_clock_list[];
30extern unsigned int at32_nr_clocks;
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
new file mode 100644
index 000000000000..7da9c5f7a0eb
--- /dev/null
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -0,0 +1,171 @@
1/*
2 * External interrupt handling for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/errno.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/irq.h>
15#include <linux/platform_device.h>
16#include <linux/random.h>
17
18#include <asm/io.h>
19
20#include <asm/arch/sm.h>
21
22#include "sm.h"
23
24static void eim_ack_irq(unsigned int irq)
25{
26 struct at32_sm *sm = get_irq_chip_data(irq);
27 sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
28}
29
30static void eim_mask_irq(unsigned int irq)
31{
32 struct at32_sm *sm = get_irq_chip_data(irq);
33 sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
34}
35
36static void eim_mask_ack_irq(unsigned int irq)
37{
38 struct at32_sm *sm = get_irq_chip_data(irq);
39 sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
40 sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
41}
42
43static void eim_unmask_irq(unsigned int irq)
44{
45 struct at32_sm *sm = get_irq_chip_data(irq);
46 sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq));
47}
48
49static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
50{
51 struct at32_sm *sm = get_irq_chip_data(irq);
52 unsigned int i = irq - sm->eim_first_irq;
53 u32 mode, edge, level;
54 unsigned long flags;
55 int ret = 0;
56
57 flow_type &= IRQ_TYPE_SENSE_MASK;
58
59 spin_lock_irqsave(&sm->lock, flags);
60
61 mode = sm_readl(sm, EIM_MODE);
62 edge = sm_readl(sm, EIM_EDGE);
63 level = sm_readl(sm, EIM_LEVEL);
64
65 switch (flow_type) {
66 case IRQ_TYPE_LEVEL_LOW:
67 mode |= 1 << i;
68 level &= ~(1 << i);
69 break;
70 case IRQ_TYPE_LEVEL_HIGH:
71 mode |= 1 << i;
72 level |= 1 << i;
73 break;
74 case IRQ_TYPE_EDGE_RISING:
75 mode &= ~(1 << i);
76 edge |= 1 << i;
77 break;
78 case IRQ_TYPE_EDGE_FALLING:
79 mode &= ~(1 << i);
80 edge &= ~(1 << i);
81 break;
82 default:
83 ret = -EINVAL;
84 break;
85 }
86
87 sm_writel(sm, EIM_MODE, mode);
88 sm_writel(sm, EIM_EDGE, edge);
89 sm_writel(sm, EIM_LEVEL, level);
90
91 spin_unlock_irqrestore(&sm->lock, flags);
92
93 return ret;
94}
95
96struct irq_chip eim_chip = {
97 .name = "eim",
98 .ack = eim_ack_irq,
99 .mask = eim_mask_irq,
100 .mask_ack = eim_mask_ack_irq,
101 .unmask = eim_unmask_irq,
102 .set_type = eim_set_irq_type,
103};
104
105static void demux_eim_irq(unsigned int irq, struct irq_desc *desc,
106 struct pt_regs *regs)
107{
108 struct at32_sm *sm = desc->handler_data;
109 struct irq_desc *ext_desc;
110 unsigned long status, pending;
111 unsigned int i, ext_irq;
112
113 spin_lock(&sm->lock);
114
115 status = sm_readl(sm, EIM_ISR);
116 pending = status & sm_readl(sm, EIM_IMR);
117
118 while (pending) {
119 i = fls(pending) - 1;
120 pending &= ~(1 << i);
121
122 ext_irq = i + sm->eim_first_irq;
123 ext_desc = irq_desc + ext_irq;
124 ext_desc->handle_irq(ext_irq, ext_desc, regs);
125 }
126
127 spin_unlock(&sm->lock);
128}
129
130static int __init eim_init(void)
131{
132 struct at32_sm *sm = &system_manager;
133 unsigned int i;
134 unsigned int nr_irqs;
135 unsigned int int_irq;
136 u32 pattern;
137
138 /*
139 * The EIM is really the same module as SM, so register
140 * mapping, etc. has been taken care of already.
141 */
142
143 /*
144 * Find out how many interrupt lines that are actually
145 * implemented in hardware.
146 */
147 sm_writel(sm, EIM_IDR, ~0UL);
148 sm_writel(sm, EIM_MODE, ~0UL);
149 pattern = sm_readl(sm, EIM_MODE);
150 nr_irqs = fls(pattern);
151
152 sm->eim_chip = &eim_chip;
153
154 for (i = 0; i < nr_irqs; i++) {
155 set_irq_chip(sm->eim_first_irq + i, &eim_chip);
156 set_irq_chip_data(sm->eim_first_irq + i, sm);
157 }
158
159 int_irq = platform_get_irq_byname(sm->pdev, "eim");
160
161 set_irq_chained_handler(int_irq, demux_eim_irq);
162 set_irq_data(int_irq, sm);
163
164 printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n",
165 sm->regs, int_irq);
166 printk("EIM: Handling %u external IRQs, starting with IRQ %u\n",
167 nr_irqs, sm->eim_first_irq);
168
169 return 0;
170}
171arch_initcall(eim_init);
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
new file mode 100644
index 000000000000..74f8c9f2f03d
--- /dev/null
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -0,0 +1,133 @@
1/*
2 * Copyright (C) 2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/err.h>
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/irq.h>
14#include <linux/platform_device.h>
15
16#include <asm/io.h>
17
18#include "intc.h"
19
20struct intc {
21 void __iomem *regs;
22 struct irq_chip chip;
23};
24
25extern struct platform_device at32_intc0_device;
26
27/*
28 * TODO: We may be able to implement mask/unmask by setting IxM flags
29 * in the status register.
30 */
31static void intc_mask_irq(unsigned int irq)
32{
33
34}
35
36static void intc_unmask_irq(unsigned int irq)
37{
38
39}
40
41static struct intc intc0 = {
42 .chip = {
43 .name = "intc",
44 .mask = intc_mask_irq,
45 .unmask = intc_unmask_irq,
46 },
47};
48
49/*
50 * All interrupts go via intc at some point.
51 */
52asmlinkage void do_IRQ(int level, struct pt_regs *regs)
53{
54 struct irq_desc *desc;
55 unsigned int irq;
56 unsigned long status_reg;
57
58 local_irq_disable();
59
60 irq_enter();
61
62 irq = intc_readl(&intc0, INTCAUSE0 - 4 * level);
63 desc = irq_desc + irq;
64 desc->handle_irq(irq, desc, regs);
65
66 /*
67 * Clear all interrupt level masks so that we may handle
68 * interrupts during softirq processing. If this is a nested
69 * interrupt, interrupts must stay globally disabled until we
70 * return.
71 */
72 status_reg = sysreg_read(SR);
73 status_reg &= ~(SYSREG_BIT(I0M) | SYSREG_BIT(I1M)
74 | SYSREG_BIT(I2M) | SYSREG_BIT(I3M));
75 sysreg_write(SR, status_reg);
76
77 irq_exit();
78}
79
80void __init init_IRQ(void)
81{
82 extern void _evba(void);
83 extern void irq_level0(void);
84 struct resource *regs;
85 struct clk *pclk;
86 unsigned int i;
87 u32 offset, readback;
88
89 regs = platform_get_resource(&at32_intc0_device, IORESOURCE_MEM, 0);
90 if (!regs) {
91 printk(KERN_EMERG "intc: no mmio resource defined\n");
92 goto fail;
93 }
94 pclk = clk_get(&at32_intc0_device.dev, "pclk");
95 if (IS_ERR(pclk)) {
96 printk(KERN_EMERG "intc: no clock defined\n");
97 goto fail;
98 }
99
100 clk_enable(pclk);
101
102 intc0.regs = ioremap(regs->start, regs->end - regs->start + 1);
103 if (!intc0.regs) {
104 printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n",
105 (unsigned long)regs->start);
106 goto fail;
107 }
108
109 /*
110 * Initialize all interrupts to level 0 (lowest priority). The
111 * priority level may be changed by calling
112 * irq_set_priority().
113 *
114 */
115 offset = (unsigned long)&irq_level0 - (unsigned long)&_evba;
116 for (i = 0; i < NR_INTERNAL_IRQS; i++) {
117 intc_writel(&intc0, INTPR0 + 4 * i, offset);
118 readback = intc_readl(&intc0, INTPR0 + 4 * i);
119 if (readback == offset)
120 set_irq_chip_and_handler(i, &intc0.chip,
121 handle_simple_irq);
122 }
123
124 /* Unmask all interrupt levels */
125 sysreg_write(SR, (sysreg_read(SR)
126 & ~(SR_I3M | SR_I2M | SR_I1M | SR_I0M)));
127
128 return;
129
130fail:
131 panic("Interrupt controller initialization failed!\n");
132}
133
diff --git a/arch/avr32/mach-at32ap/intc.h b/arch/avr32/mach-at32ap/intc.h
new file mode 100644
index 000000000000..d289ca2fff13
--- /dev/null
+++ b/arch/avr32/mach-at32ap/intc.h
@@ -0,0 +1,327 @@
1/*
2 * Automatically generated by gen-header.xsl
3 */
4#ifndef __ASM_AVR32_PERIHP_INTC_H__
5#define __ASM_AVR32_PERIHP_INTC_H__
6
7#define INTC_NUM_INT_GRPS 33
8
9#define INTC_INTPR0 0x0
10# define INTC_INTPR0_INTLEV_OFFSET 30
11# define INTC_INTPR0_INTLEV_SIZE 2
12# define INTC_INTPR0_OFFSET_OFFSET 0
13# define INTC_INTPR0_OFFSET_SIZE 24
14#define INTC_INTREQ0 0x100
15# define INTC_INTREQ0_IREQUEST0_OFFSET 0
16# define INTC_INTREQ0_IREQUEST0_SIZE 1
17# define INTC_INTREQ0_IREQUEST1_OFFSET 1
18# define INTC_INTREQ0_IREQUEST1_SIZE 1
19#define INTC_INTPR1 0x4
20# define INTC_INTPR1_INTLEV_OFFSET 30
21# define INTC_INTPR1_INTLEV_SIZE 2
22# define INTC_INTPR1_OFFSET_OFFSET 0
23# define INTC_INTPR1_OFFSET_SIZE 24
24#define INTC_INTREQ1 0x104
25# define INTC_INTREQ1_IREQUEST32_OFFSET 0
26# define INTC_INTREQ1_IREQUEST32_SIZE 1
27# define INTC_INTREQ1_IREQUEST33_OFFSET 1
28# define INTC_INTREQ1_IREQUEST33_SIZE 1
29# define INTC_INTREQ1_IREQUEST34_OFFSET 2
30# define INTC_INTREQ1_IREQUEST34_SIZE 1
31# define INTC_INTREQ1_IREQUEST35_OFFSET 3
32# define INTC_INTREQ1_IREQUEST35_SIZE 1
33# define INTC_INTREQ1_IREQUEST36_OFFSET 4
34# define INTC_INTREQ1_IREQUEST36_SIZE 1
35# define INTC_INTREQ1_IREQUEST37_OFFSET 5
36# define INTC_INTREQ1_IREQUEST37_SIZE 1
37#define INTC_INTPR2 0x8
38# define INTC_INTPR2_INTLEV_OFFSET 30
39# define INTC_INTPR2_INTLEV_SIZE 2
40# define INTC_INTPR2_OFFSET_OFFSET 0
41# define INTC_INTPR2_OFFSET_SIZE 24
42#define INTC_INTREQ2 0x108
43# define INTC_INTREQ2_IREQUEST64_OFFSET 0
44# define INTC_INTREQ2_IREQUEST64_SIZE 1
45# define INTC_INTREQ2_IREQUEST65_OFFSET 1
46# define INTC_INTREQ2_IREQUEST65_SIZE 1
47# define INTC_INTREQ2_IREQUEST66_OFFSET 2
48# define INTC_INTREQ2_IREQUEST66_SIZE 1
49# define INTC_INTREQ2_IREQUEST67_OFFSET 3
50# define INTC_INTREQ2_IREQUEST67_SIZE 1
51# define INTC_INTREQ2_IREQUEST68_OFFSET 4
52# define INTC_INTREQ2_IREQUEST68_SIZE 1
53#define INTC_INTPR3 0xc
54# define INTC_INTPR3_INTLEV_OFFSET 30
55# define INTC_INTPR3_INTLEV_SIZE 2
56# define INTC_INTPR3_OFFSET_OFFSET 0
57# define INTC_INTPR3_OFFSET_SIZE 24
58#define INTC_INTREQ3 0x10c
59# define INTC_INTREQ3_IREQUEST96_OFFSET 0
60# define INTC_INTREQ3_IREQUEST96_SIZE 1
61#define INTC_INTPR4 0x10
62# define INTC_INTPR4_INTLEV_OFFSET 30
63# define INTC_INTPR4_INTLEV_SIZE 2
64# define INTC_INTPR4_OFFSET_OFFSET 0
65# define INTC_INTPR4_OFFSET_SIZE 24
66#define INTC_INTREQ4 0x110
67# define INTC_INTREQ4_IREQUEST128_OFFSET 0
68# define INTC_INTREQ4_IREQUEST128_SIZE 1
69#define INTC_INTPR5 0x14
70# define INTC_INTPR5_INTLEV_OFFSET 30
71# define INTC_INTPR5_INTLEV_SIZE 2
72# define INTC_INTPR5_OFFSET_OFFSET 0
73# define INTC_INTPR5_OFFSET_SIZE 24
74#define INTC_INTREQ5 0x114
75# define INTC_INTREQ5_IREQUEST160_OFFSET 0
76# define INTC_INTREQ5_IREQUEST160_SIZE 1
77#define INTC_INTPR6 0x18
78# define INTC_INTPR6_INTLEV_OFFSET 30
79# define INTC_INTPR6_INTLEV_SIZE 2
80# define INTC_INTPR6_OFFSET_OFFSET 0
81# define INTC_INTPR6_OFFSET_SIZE 24
82#define INTC_INTREQ6 0x118
83# define INTC_INTREQ6_IREQUEST192_OFFSET 0
84# define INTC_INTREQ6_IREQUEST192_SIZE 1
85#define INTC_INTPR7 0x1c
86# define INTC_INTPR7_INTLEV_OFFSET 30
87# define INTC_INTPR7_INTLEV_SIZE 2
88# define INTC_INTPR7_OFFSET_OFFSET 0
89# define INTC_INTPR7_OFFSET_SIZE 24
90#define INTC_INTREQ7 0x11c
91# define INTC_INTREQ7_IREQUEST224_OFFSET 0
92# define INTC_INTREQ7_IREQUEST224_SIZE 1
93#define INTC_INTPR8 0x20
94# define INTC_INTPR8_INTLEV_OFFSET 30
95# define INTC_INTPR8_INTLEV_SIZE 2
96# define INTC_INTPR8_OFFSET_OFFSET 0
97# define INTC_INTPR8_OFFSET_SIZE 24
98#define INTC_INTREQ8 0x120
99# define INTC_INTREQ8_IREQUEST256_OFFSET 0
100# define INTC_INTREQ8_IREQUEST256_SIZE 1
101#define INTC_INTPR9 0x24
102# define INTC_INTPR9_INTLEV_OFFSET 30
103# define INTC_INTPR9_INTLEV_SIZE 2
104# define INTC_INTPR9_OFFSET_OFFSET 0
105# define INTC_INTPR9_OFFSET_SIZE 24
106#define INTC_INTREQ9 0x124
107# define INTC_INTREQ9_IREQUEST288_OFFSET 0
108# define INTC_INTREQ9_IREQUEST288_SIZE 1
109#define INTC_INTPR10 0x28
110# define INTC_INTPR10_INTLEV_OFFSET 30
111# define INTC_INTPR10_INTLEV_SIZE 2
112# define INTC_INTPR10_OFFSET_OFFSET 0
113# define INTC_INTPR10_OFFSET_SIZE 24
114#define INTC_INTREQ10 0x128
115# define INTC_INTREQ10_IREQUEST320_OFFSET 0
116# define INTC_INTREQ10_IREQUEST320_SIZE 1
117#define INTC_INTPR11 0x2c
118# define INTC_INTPR11_INTLEV_OFFSET 30
119# define INTC_INTPR11_INTLEV_SIZE 2
120# define INTC_INTPR11_OFFSET_OFFSET 0
121# define INTC_INTPR11_OFFSET_SIZE 24
122#define INTC_INTREQ11 0x12c
123# define INTC_INTREQ11_IREQUEST352_OFFSET 0
124# define INTC_INTREQ11_IREQUEST352_SIZE 1
125#define INTC_INTPR12 0x30
126# define INTC_INTPR12_INTLEV_OFFSET 30
127# define INTC_INTPR12_INTLEV_SIZE 2
128# define INTC_INTPR12_OFFSET_OFFSET 0
129# define INTC_INTPR12_OFFSET_SIZE 24
130#define INTC_INTREQ12 0x130
131# define INTC_INTREQ12_IREQUEST384_OFFSET 0
132# define INTC_INTREQ12_IREQUEST384_SIZE 1
133#define INTC_INTPR13 0x34
134# define INTC_INTPR13_INTLEV_OFFSET 30
135# define INTC_INTPR13_INTLEV_SIZE 2
136# define INTC_INTPR13_OFFSET_OFFSET 0
137# define INTC_INTPR13_OFFSET_SIZE 24
138#define INTC_INTREQ13 0x134
139# define INTC_INTREQ13_IREQUEST416_OFFSET 0
140# define INTC_INTREQ13_IREQUEST416_SIZE 1
141#define INTC_INTPR14 0x38
142# define INTC_INTPR14_INTLEV_OFFSET 30
143# define INTC_INTPR14_INTLEV_SIZE 2
144# define INTC_INTPR14_OFFSET_OFFSET 0
145# define INTC_INTPR14_OFFSET_SIZE 24
146#define INTC_INTREQ14 0x138
147# define INTC_INTREQ14_IREQUEST448_OFFSET 0
148# define INTC_INTREQ14_IREQUEST448_SIZE 1
149#define INTC_INTPR15 0x3c
150# define INTC_INTPR15_INTLEV_OFFSET 30
151# define INTC_INTPR15_INTLEV_SIZE 2
152# define INTC_INTPR15_OFFSET_OFFSET 0
153# define INTC_INTPR15_OFFSET_SIZE 24
154#define INTC_INTREQ15 0x13c
155# define INTC_INTREQ15_IREQUEST480_OFFSET 0
156# define INTC_INTREQ15_IREQUEST480_SIZE 1
157#define INTC_INTPR16 0x40
158# define INTC_INTPR16_INTLEV_OFFSET 30
159# define INTC_INTPR16_INTLEV_SIZE 2
160# define INTC_INTPR16_OFFSET_OFFSET 0
161# define INTC_INTPR16_OFFSET_SIZE 24
162#define INTC_INTREQ16 0x140
163# define INTC_INTREQ16_IREQUEST512_OFFSET 0
164# define INTC_INTREQ16_IREQUEST512_SIZE 1
165#define INTC_INTPR17 0x44
166# define INTC_INTPR17_INTLEV_OFFSET 30
167# define INTC_INTPR17_INTLEV_SIZE 2
168# define INTC_INTPR17_OFFSET_OFFSET 0
169# define INTC_INTPR17_OFFSET_SIZE 24
170#define INTC_INTREQ17 0x144
171# define INTC_INTREQ17_IREQUEST544_OFFSET 0
172# define INTC_INTREQ17_IREQUEST544_SIZE 1
173#define INTC_INTPR18 0x48
174# define INTC_INTPR18_INTLEV_OFFSET 30
175# define INTC_INTPR18_INTLEV_SIZE 2
176# define INTC_INTPR18_OFFSET_OFFSET 0
177# define INTC_INTPR18_OFFSET_SIZE 24
178#define INTC_INTREQ18 0x148
179# define INTC_INTREQ18_IREQUEST576_OFFSET 0
180# define INTC_INTREQ18_IREQUEST576_SIZE 1
181#define INTC_INTPR19 0x4c
182# define INTC_INTPR19_INTLEV_OFFSET 30
183# define INTC_INTPR19_INTLEV_SIZE 2
184# define INTC_INTPR19_OFFSET_OFFSET 0
185# define INTC_INTPR19_OFFSET_SIZE 24
186#define INTC_INTREQ19 0x14c
187# define INTC_INTREQ19_IREQUEST608_OFFSET 0
188# define INTC_INTREQ19_IREQUEST608_SIZE 1
189# define INTC_INTREQ19_IREQUEST609_OFFSET 1
190# define INTC_INTREQ19_IREQUEST609_SIZE 1
191# define INTC_INTREQ19_IREQUEST610_OFFSET 2
192# define INTC_INTREQ19_IREQUEST610_SIZE 1
193# define INTC_INTREQ19_IREQUEST611_OFFSET 3
194# define INTC_INTREQ19_IREQUEST611_SIZE 1
195#define INTC_INTPR20 0x50
196# define INTC_INTPR20_INTLEV_OFFSET 30
197# define INTC_INTPR20_INTLEV_SIZE 2
198# define INTC_INTPR20_OFFSET_OFFSET 0
199# define INTC_INTPR20_OFFSET_SIZE 24
200#define INTC_INTREQ20 0x150
201# define INTC_INTREQ20_IREQUEST640_OFFSET 0
202# define INTC_INTREQ20_IREQUEST640_SIZE 1
203#define INTC_INTPR21 0x54
204# define INTC_INTPR21_INTLEV_OFFSET 30
205# define INTC_INTPR21_INTLEV_SIZE 2
206# define INTC_INTPR21_OFFSET_OFFSET 0
207# define INTC_INTPR21_OFFSET_SIZE 24
208#define INTC_INTREQ21 0x154
209# define INTC_INTREQ21_IREQUEST672_OFFSET 0
210# define INTC_INTREQ21_IREQUEST672_SIZE 1
211#define INTC_INTPR22 0x58
212# define INTC_INTPR22_INTLEV_OFFSET 30
213# define INTC_INTPR22_INTLEV_SIZE 2
214# define INTC_INTPR22_OFFSET_OFFSET 0
215# define INTC_INTPR22_OFFSET_SIZE 24
216#define INTC_INTREQ22 0x158
217# define INTC_INTREQ22_IREQUEST704_OFFSET 0
218# define INTC_INTREQ22_IREQUEST704_SIZE 1
219# define INTC_INTREQ22_IREQUEST705_OFFSET 1
220# define INTC_INTREQ22_IREQUEST705_SIZE 1
221# define INTC_INTREQ22_IREQUEST706_OFFSET 2
222# define INTC_INTREQ22_IREQUEST706_SIZE 1
223#define INTC_INTPR23 0x5c
224# define INTC_INTPR23_INTLEV_OFFSET 30
225# define INTC_INTPR23_INTLEV_SIZE 2
226# define INTC_INTPR23_OFFSET_OFFSET 0
227# define INTC_INTPR23_OFFSET_SIZE 24
228#define INTC_INTREQ23 0x15c
229# define INTC_INTREQ23_IREQUEST736_OFFSET 0
230# define INTC_INTREQ23_IREQUEST736_SIZE 1
231# define INTC_INTREQ23_IREQUEST737_OFFSET 1
232# define INTC_INTREQ23_IREQUEST737_SIZE 1
233# define INTC_INTREQ23_IREQUEST738_OFFSET 2
234# define INTC_INTREQ23_IREQUEST738_SIZE 1
235#define INTC_INTPR24 0x60
236# define INTC_INTPR24_INTLEV_OFFSET 30
237# define INTC_INTPR24_INTLEV_SIZE 2
238# define INTC_INTPR24_OFFSET_OFFSET 0
239# define INTC_INTPR24_OFFSET_SIZE 24
240#define INTC_INTREQ24 0x160
241# define INTC_INTREQ24_IREQUEST768_OFFSET 0
242# define INTC_INTREQ24_IREQUEST768_SIZE 1
243#define INTC_INTPR25 0x64
244# define INTC_INTPR25_INTLEV_OFFSET 30
245# define INTC_INTPR25_INTLEV_SIZE 2
246# define INTC_INTPR25_OFFSET_OFFSET 0
247# define INTC_INTPR25_OFFSET_SIZE 24
248#define INTC_INTREQ25 0x164
249# define INTC_INTREQ25_IREQUEST800_OFFSET 0
250# define INTC_INTREQ25_IREQUEST800_SIZE 1
251#define INTC_INTPR26 0x68
252# define INTC_INTPR26_INTLEV_OFFSET 30
253# define INTC_INTPR26_INTLEV_SIZE 2
254# define INTC_INTPR26_OFFSET_OFFSET 0
255# define INTC_INTPR26_OFFSET_SIZE 24
256#define INTC_INTREQ26 0x168
257# define INTC_INTREQ26_IREQUEST832_OFFSET 0
258# define INTC_INTREQ26_IREQUEST832_SIZE 1
259#define INTC_INTPR27 0x6c
260# define INTC_INTPR27_INTLEV_OFFSET 30
261# define INTC_INTPR27_INTLEV_SIZE 2
262# define INTC_INTPR27_OFFSET_OFFSET 0
263# define INTC_INTPR27_OFFSET_SIZE 24
264#define INTC_INTREQ27 0x16c
265# define INTC_INTREQ27_IREQUEST864_OFFSET 0
266# define INTC_INTREQ27_IREQUEST864_SIZE 1
267#define INTC_INTPR28 0x70
268# define INTC_INTPR28_INTLEV_OFFSET 30
269# define INTC_INTPR28_INTLEV_SIZE 2
270# define INTC_INTPR28_OFFSET_OFFSET 0
271# define INTC_INTPR28_OFFSET_SIZE 24
272#define INTC_INTREQ28 0x170
273# define INTC_INTREQ28_IREQUEST896_OFFSET 0
274# define INTC_INTREQ28_IREQUEST896_SIZE 1
275#define INTC_INTPR29 0x74
276# define INTC_INTPR29_INTLEV_OFFSET 30
277# define INTC_INTPR29_INTLEV_SIZE 2
278# define INTC_INTPR29_OFFSET_OFFSET 0
279# define INTC_INTPR29_OFFSET_SIZE 24
280#define INTC_INTREQ29 0x174
281# define INTC_INTREQ29_IREQUEST928_OFFSET 0
282# define INTC_INTREQ29_IREQUEST928_SIZE 1
283#define INTC_INTPR30 0x78
284# define INTC_INTPR30_INTLEV_OFFSET 30
285# define INTC_INTPR30_INTLEV_SIZE 2
286# define INTC_INTPR30_OFFSET_OFFSET 0
287# define INTC_INTPR30_OFFSET_SIZE 24
288#define INTC_INTREQ30 0x178
289# define INTC_INTREQ30_IREQUEST960_OFFSET 0
290# define INTC_INTREQ30_IREQUEST960_SIZE 1
291#define INTC_INTPR31 0x7c
292# define INTC_INTPR31_INTLEV_OFFSET 30
293# define INTC_INTPR31_INTLEV_SIZE 2
294# define INTC_INTPR31_OFFSET_OFFSET 0
295# define INTC_INTPR31_OFFSET_SIZE 24
296#define INTC_INTREQ31 0x17c
297# define INTC_INTREQ31_IREQUEST992_OFFSET 0
298# define INTC_INTREQ31_IREQUEST992_SIZE 1
299#define INTC_INTPR32 0x80
300# define INTC_INTPR32_INTLEV_OFFSET 30
301# define INTC_INTPR32_INTLEV_SIZE 2
302# define INTC_INTPR32_OFFSET_OFFSET 0
303# define INTC_INTPR32_OFFSET_SIZE 24
304#define INTC_INTREQ32 0x180
305# define INTC_INTREQ32_IREQUEST1024_OFFSET 0
306# define INTC_INTREQ32_IREQUEST1024_SIZE 1
307#define INTC_INTCAUSE0 0x20c
308# define INTC_INTCAUSE0_CAUSEGRP_OFFSET 0
309# define INTC_INTCAUSE0_CAUSEGRP_SIZE 6
310#define INTC_INTCAUSE1 0x208
311# define INTC_INTCAUSE1_CAUSEGRP_OFFSET 0
312# define INTC_INTCAUSE1_CAUSEGRP_SIZE 6
313#define INTC_INTCAUSE2 0x204
314# define INTC_INTCAUSE2_CAUSEGRP_OFFSET 0
315# define INTC_INTCAUSE2_CAUSEGRP_SIZE 6
316#define INTC_INTCAUSE3 0x200
317# define INTC_INTCAUSE3_CAUSEGRP_OFFSET 0
318# define INTC_INTCAUSE3_CAUSEGRP_SIZE 6
319
320#define INTC_BIT(name) (1 << INTC_##name##_OFFSET)
321#define INTC_MKBF(name, value) (((value) & ((1 << INTC_##name##_SIZE) - 1)) << INTC_##name##_OFFSET)
322#define INTC_GETBF(name, value) (((value) >> INTC_##name##_OFFSET) & ((1 << INTC_##name##_SIZE) - 1))
323
324#define intc_readl(port,reg) readl((port)->regs + INTC_##reg)
325#define intc_writel(port,reg,value) writel((value), (port)->regs + INTC_##reg)
326
327#endif /* __ASM_AVR32_PERIHP_INTC_H__ */
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
new file mode 100644
index 000000000000..d3aabfca8598
--- /dev/null
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -0,0 +1,118 @@
1/*
2 * Atmel PIO2 Port Multiplexer support
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/clk.h>
12#include <linux/debugfs.h>
13#include <linux/fs.h>
14#include <linux/platform_device.h>
15
16#include <asm/io.h>
17
18#include <asm/arch/portmux.h>
19
20#include "pio.h"
21
22#define MAX_NR_PIO_DEVICES 8
23
24struct pio_device {
25 void __iomem *regs;
26 const struct platform_device *pdev;
27 struct clk *clk;
28 u32 alloc_mask;
29 char name[32];
30};
31
32static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
33
34void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
35 unsigned int function_id)
36{
37 struct pio_device *pio;
38 u32 mask = 1 << pin_id;
39
40 BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
41
42 pio = &pio_dev[portmux_id];
43
44 if (function_id)
45 pio_writel(pio, BSR, mask);
46 else
47 pio_writel(pio, ASR, mask);
48 pio_writel(pio, PDR, mask);
49}
50
51static int __init pio_probe(struct platform_device *pdev)
52{
53 struct pio_device *pio = NULL;
54
55 BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
56 pio = &pio_dev[pdev->id];
57 BUG_ON(!pio->regs);
58
59 /* TODO: Interrupts */
60
61 platform_set_drvdata(pdev, pio);
62
63 printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n",
64 pio->name, pio->regs, platform_get_irq(pdev, 0));
65
66 return 0;
67}
68
69static struct platform_driver pio_driver = {
70 .probe = pio_probe,
71 .driver = {
72 .name = "pio",
73 },
74};
75
76static int __init pio_init(void)
77{
78 return platform_driver_register(&pio_driver);
79}
80subsys_initcall(pio_init);
81
82void __init at32_init_pio(struct platform_device *pdev)
83{
84 struct resource *regs;
85 struct pio_device *pio;
86
87 if (pdev->id > MAX_NR_PIO_DEVICES) {
88 dev_err(&pdev->dev, "only %d PIO devices supported\n",
89 MAX_NR_PIO_DEVICES);
90 return;
91 }
92
93 pio = &pio_dev[pdev->id];
94 snprintf(pio->name, sizeof(pio->name), "pio%d", pdev->id);
95
96 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
97 if (!regs) {
98 dev_err(&pdev->dev, "no mmio resource defined\n");
99 return;
100 }
101
102 pio->clk = clk_get(&pdev->dev, "mck");
103 if (IS_ERR(pio->clk))
104 /*
105 * This is a fatal error, but if we continue we might
106 * be so lucky that we manage to initialize the
107 * console and display this message...
108 */
109 dev_err(&pdev->dev, "no mck clock defined\n");
110 else
111 clk_enable(pio->clk);
112
113 pio->pdev = pdev;
114 pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
115
116 pio_writel(pio, ODR, ~0UL);
117 pio_writel(pio, PER, ~0UL);
118}
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
new file mode 100644
index 000000000000..cfea12351599
--- /dev/null
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -0,0 +1,178 @@
1/*
2 * Atmel PIO2 Port Multiplexer support
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#ifndef __ARCH_AVR32_AT32AP_PIO_H__
11#define __ARCH_AVR32_AT32AP_PIO_H__
12
13/* PIO register offsets */
14#define PIO_PER 0x0000
15#define PIO_PDR 0x0004
16#define PIO_PSR 0x0008
17#define PIO_OER 0x0010
18#define PIO_ODR 0x0014
19#define PIO_OSR 0x0018
20#define PIO_IFER 0x0020
21#define PIO_IFDR 0x0024
22#define PIO_ISFR 0x0028
23#define PIO_SODR 0x0030
24#define PIO_CODR 0x0034
25#define PIO_ODSR 0x0038
26#define PIO_PDSR 0x003c
27#define PIO_IER 0x0040
28#define PIO_IDR 0x0044
29#define PIO_IMR 0x0048
30#define PIO_ISR 0x004c
31#define PIO_MDER 0x0050
32#define PIO_MDDR 0x0054
33#define PIO_MDSR 0x0058
34#define PIO_PUDR 0x0060
35#define PIO_PUER 0x0064
36#define PIO_PUSR 0x0068
37#define PIO_ASR 0x0070
38#define PIO_BSR 0x0074
39#define PIO_ABSR 0x0078
40#define PIO_OWER 0x00a0
41#define PIO_OWDR 0x00a4
42#define PIO_OWSR 0x00a8
43
44/* Bitfields in PER */
45
46/* Bitfields in PDR */
47
48/* Bitfields in PSR */
49
50/* Bitfields in OER */
51
52/* Bitfields in ODR */
53
54/* Bitfields in OSR */
55
56/* Bitfields in IFER */
57
58/* Bitfields in IFDR */
59
60/* Bitfields in ISFR */
61
62/* Bitfields in SODR */
63
64/* Bitfields in CODR */
65
66/* Bitfields in ODSR */
67
68/* Bitfields in PDSR */
69
70/* Bitfields in IER */
71
72/* Bitfields in IDR */
73
74/* Bitfields in IMR */
75
76/* Bitfields in ISR */
77
78/* Bitfields in MDER */
79
80/* Bitfields in MDDR */
81
82/* Bitfields in MDSR */
83
84/* Bitfields in PUDR */
85
86/* Bitfields in PUER */
87
88/* Bitfields in PUSR */
89
90/* Bitfields in ASR */
91
92/* Bitfields in BSR */
93
94/* Bitfields in ABSR */
95#define PIO_P0_OFFSET 0
96#define PIO_P0_SIZE 1
97#define PIO_P1_OFFSET 1
98#define PIO_P1_SIZE 1
99#define PIO_P2_OFFSET 2
100#define PIO_P2_SIZE 1
101#define PIO_P3_OFFSET 3
102#define PIO_P3_SIZE 1
103#define PIO_P4_OFFSET 4
104#define PIO_P4_SIZE 1
105#define PIO_P5_OFFSET 5
106#define PIO_P5_SIZE 1
107#define PIO_P6_OFFSET 6
108#define PIO_P6_SIZE 1
109#define PIO_P7_OFFSET 7
110#define PIO_P7_SIZE 1
111#define PIO_P8_OFFSET 8
112#define PIO_P8_SIZE 1
113#define PIO_P9_OFFSET 9
114#define PIO_P9_SIZE 1
115#define PIO_P10_OFFSET 10
116#define PIO_P10_SIZE 1
117#define PIO_P11_OFFSET 11
118#define PIO_P11_SIZE 1
119#define PIO_P12_OFFSET 12
120#define PIO_P12_SIZE 1
121#define PIO_P13_OFFSET 13
122#define PIO_P13_SIZE 1
123#define PIO_P14_OFFSET 14
124#define PIO_P14_SIZE 1
125#define PIO_P15_OFFSET 15
126#define PIO_P15_SIZE 1
127#define PIO_P16_OFFSET 16
128#define PIO_P16_SIZE 1
129#define PIO_P17_OFFSET 17
130#define PIO_P17_SIZE 1
131#define PIO_P18_OFFSET 18
132#define PIO_P18_SIZE 1
133#define PIO_P19_OFFSET 19
134#define PIO_P19_SIZE 1
135#define PIO_P20_OFFSET 20
136#define PIO_P20_SIZE 1
137#define PIO_P21_OFFSET 21
138#define PIO_P21_SIZE 1
139#define PIO_P22_OFFSET 22
140#define PIO_P22_SIZE 1
141#define PIO_P23_OFFSET 23
142#define PIO_P23_SIZE 1
143#define PIO_P24_OFFSET 24
144#define PIO_P24_SIZE 1
145#define PIO_P25_OFFSET 25
146#define PIO_P25_SIZE 1
147#define PIO_P26_OFFSET 26
148#define PIO_P26_SIZE 1
149#define PIO_P27_OFFSET 27
150#define PIO_P27_SIZE 1
151#define PIO_P28_OFFSET 28
152#define PIO_P28_SIZE 1
153#define PIO_P29_OFFSET 29
154#define PIO_P29_SIZE 1
155#define PIO_P30_OFFSET 30
156#define PIO_P30_SIZE 1
157#define PIO_P31_OFFSET 31
158#define PIO_P31_SIZE 1
159
160/* Bitfields in OWER */
161
162/* Bitfields in OWDR */
163
164/* Bitfields in OWSR */
165
166/* Bit manipulation macros */
167#define PIO_BIT(name) (1 << PIO_##name##_OFFSET)
168#define PIO_BF(name,value) (((value) & ((1 << PIO_##name##_SIZE) - 1)) << PIO_##name##_OFFSET)
169#define PIO_BFEXT(name,value) (((value) >> PIO_##name##_OFFSET) & ((1 << PIO_##name##_SIZE) - 1))
170#define PIO_BFINS(name,value,old) (((old) & ~(((1 << PIO_##name##_SIZE) - 1) << PIO_##name##_OFFSET)) | PIO_BF(name,value))
171
172/* Register access macros */
173#define pio_readl(port,reg) readl((port)->regs + PIO_##reg)
174#define pio_writel(port,reg,value) writel((value), (port)->regs + PIO_##reg)
175
176void at32_init_pio(struct platform_device *pdev);
177
178#endif /* __ARCH_AVR32_AT32AP_PIO_H__ */
diff --git a/arch/avr32/mach-at32ap/sm.c b/arch/avr32/mach-at32ap/sm.c
new file mode 100644
index 000000000000..03306eb0345e
--- /dev/null
+++ b/arch/avr32/mach-at32ap/sm.c
@@ -0,0 +1,289 @@
1/*
2 * System Manager driver for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/errno.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/platform_device.h>
16#include <linux/random.h>
17#include <linux/spinlock.h>
18
19#include <asm/intc.h>
20#include <asm/io.h>
21#include <asm/irq.h>
22
23#include <asm/arch/sm.h>
24
25#include "sm.h"
26
27#define SM_EIM_IRQ_RESOURCE 1
28#define SM_PM_IRQ_RESOURCE 2
29#define SM_RTC_IRQ_RESOURCE 3
30
31#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
32
33struct at32_sm system_manager;
34
35int __init at32_sm_init(void)
36{
37 struct resource *regs;
38 struct at32_sm *sm = &system_manager;
39 int ret = -ENXIO;
40
41 regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
42 if (!regs)
43 goto fail;
44
45 spin_lock_init(&sm->lock);
46 sm->pdev = &at32_sm_device;
47
48 ret = -ENOMEM;
49 sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
50 if (!sm->regs)
51 goto fail;
52
53 return 0;
54
55fail:
56 printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
57 return ret;
58}
59
60/*
61 * External Interrupt Module (EIM).
62 *
63 * EIM gets level- or edge-triggered interrupts of either polarity
64 * from the outside and converts it to active-high level-triggered
65 * interrupts that the internal interrupt controller can handle. EIM
66 * also provides masking/unmasking of interrupts, as well as
67 * acknowledging of edge-triggered interrupts.
68 */
69
70static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
71 struct pt_regs *regs)
72{
73 printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
74 disable_irq(irq);
75 return IRQ_NONE;
76}
77
78static struct irqaction eim_spurious_action = {
79 .handler = spurious_eim_interrupt,
80};
81
82static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
83{
84 struct irq_controller * irqc = dev_id;
85 struct at32_sm *sm = to_eim(irqc);
86 unsigned long pending;
87
88 /*
89 * No need to disable interrupts globally. The interrupt
90 * level relevant to this group must be masked all the time,
91 * so we know that this particular EIM instance will not be
92 * re-entered.
93 */
94 spin_lock(&sm->lock);
95
96 pending = intc_get_pending(sm->irqc.irq_group);
97 if (unlikely(!pending)) {
98 printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
99 sm->irqc.irq_group);
100 goto unlock;
101 }
102
103 do {
104 struct irqaction *action;
105 unsigned int i;
106
107 i = fls(pending) - 1;
108 pending &= ~(1 << i);
109 action = sm->action[i];
110
111 /* Acknowledge the interrupt */
112 sm_writel(sm, EIM_ICR, 1 << i);
113
114 spin_unlock(&sm->lock);
115
116 if (action->flags & SA_INTERRUPT)
117 local_irq_disable();
118 action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
119 local_irq_enable();
120 spin_lock(&sm->lock);
121 if (action->flags & SA_SAMPLE_RANDOM)
122 add_interrupt_randomness(sm->irqc.first_irq + i);
123 } while (pending);
124
125unlock:
126 spin_unlock(&sm->lock);
127 return IRQ_HANDLED;
128}
129
130static void eim_mask(struct irq_controller *irqc, unsigned int irq)
131{
132 struct at32_sm *sm = to_eim(irqc);
133 unsigned int i;
134
135 i = irq - sm->irqc.first_irq;
136 sm_writel(sm, EIM_IDR, 1 << i);
137}
138
139static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
140{
141 struct at32_sm *sm = to_eim(irqc);
142 unsigned int i;
143
144 i = irq - sm->irqc.first_irq;
145 sm_writel(sm, EIM_IER, 1 << i);
146}
147
148static int eim_setup(struct irq_controller *irqc, unsigned int irq,
149 struct irqaction *action)
150{
151 struct at32_sm *sm = to_eim(irqc);
152 sm->action[irq - sm->irqc.first_irq] = action;
153 /* Acknowledge earlier interrupts */
154 sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
155 eim_unmask(irqc, irq);
156 return 0;
157}
158
159static void eim_free(struct irq_controller *irqc, unsigned int irq,
160 void *dev)
161{
162 struct at32_sm *sm = to_eim(irqc);
163 eim_mask(irqc, irq);
164 sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
165}
166
167static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
168 unsigned int type)
169{
170 struct at32_sm *sm = to_eim(irqc);
171 unsigned long flags;
172 u32 value, pattern;
173
174 spin_lock_irqsave(&sm->lock, flags);
175
176 pattern = 1 << (irq - sm->irqc.first_irq);
177
178 value = sm_readl(sm, EIM_MODE);
179 if (type & IRQ_TYPE_LEVEL)
180 value |= pattern;
181 else
182 value &= ~pattern;
183 sm_writel(sm, EIM_MODE, value);
184 value = sm_readl(sm, EIM_EDGE);
185 if (type & IRQ_EDGE_RISING)
186 value |= pattern;
187 else
188 value &= ~pattern;
189 sm_writel(sm, EIM_EDGE, value);
190 value = sm_readl(sm, EIM_LEVEL);
191 if (type & IRQ_LEVEL_HIGH)
192 value |= pattern;
193 else
194 value &= ~pattern;
195 sm_writel(sm, EIM_LEVEL, value);
196
197 spin_unlock_irqrestore(&sm->lock, flags);
198
199 return 0;
200}
201
202static unsigned int eim_get_type(struct irq_controller *irqc,
203 unsigned int irq)
204{
205 struct at32_sm *sm = to_eim(irqc);
206 unsigned long flags;
207 unsigned int type = 0;
208 u32 mode, edge, level, pattern;
209
210 pattern = 1 << (irq - sm->irqc.first_irq);
211
212 spin_lock_irqsave(&sm->lock, flags);
213 mode = sm_readl(sm, EIM_MODE);
214 edge = sm_readl(sm, EIM_EDGE);
215 level = sm_readl(sm, EIM_LEVEL);
216 spin_unlock_irqrestore(&sm->lock, flags);
217
218 if (mode & pattern)
219 type |= IRQ_TYPE_LEVEL;
220 if (edge & pattern)
221 type |= IRQ_EDGE_RISING;
222 if (level & pattern)
223 type |= IRQ_LEVEL_HIGH;
224
225 return type;
226}
227
228static struct irq_controller_class eim_irq_class = {
229 .typename = "EIM",
230 .handle = eim_handle_irq,
231 .setup = eim_setup,
232 .free = eim_free,
233 .mask = eim_mask,
234 .unmask = eim_unmask,
235 .set_type = eim_set_type,
236 .get_type = eim_get_type,
237};
238
239static int __init eim_init(void)
240{
241 struct at32_sm *sm = &system_manager;
242 unsigned int i;
243 u32 pattern;
244 int ret;
245
246 /*
247 * The EIM is really the same module as SM, so register
248 * mapping, etc. has been taken care of already.
249 */
250
251 /*
252 * Find out how many interrupt lines that are actually
253 * implemented in hardware.
254 */
255 sm_writel(sm, EIM_IDR, ~0UL);
256 sm_writel(sm, EIM_MODE, ~0UL);
257 pattern = sm_readl(sm, EIM_MODE);
258 sm->irqc.nr_irqs = fls(pattern);
259
260 ret = -ENOMEM;
261 sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
262 GFP_KERNEL);
263 if (!sm->action)
264 goto out;
265
266 for (i = 0; i < sm->irqc.nr_irqs; i++)
267 sm->action[i] = &eim_spurious_action;
268
269 spin_lock_init(&sm->lock);
270 sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
271 sm->irqc.class = &eim_irq_class;
272
273 ret = intc_register_controller(&sm->irqc);
274 if (ret < 0)
275 goto out_free_actions;
276
277 printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
278 sm->regs, sm->irqc.irq_group);
279 printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
280 sm->irqc.nr_irqs, sm->irqc.first_irq);
281
282 return 0;
283
284out_free_actions:
285 kfree(sm->action);
286out:
287 return ret;
288}
289arch_initcall(eim_init);
diff --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h
new file mode 100644
index 000000000000..27565822ae2a
--- /dev/null
+++ b/arch/avr32/mach-at32ap/sm.h
@@ -0,0 +1,240 @@
1/*
2 * Register definitions for SM
3 *
4 * System Manager
5 */
6#ifndef __ASM_AVR32_SM_H__
7#define __ASM_AVR32_SM_H__
8
9/* SM register offsets */
10#define SM_PM_MCCTRL 0x0000
11#define SM_PM_CKSEL 0x0004
12#define SM_PM_CPU_MASK 0x0008
13#define SM_PM_HSB_MASK 0x000c
14#define SM_PM_PBA_MASK 0x0010
15#define SM_PM_PBB_MASK 0x0014
16#define SM_PM_PLL0 0x0020
17#define SM_PM_PLL1 0x0024
18#define SM_PM_VCTRL 0x0030
19#define SM_PM_VMREF 0x0034
20#define SM_PM_VMV 0x0038
21#define SM_PM_IER 0x0040
22#define SM_PM_IDR 0x0044
23#define SM_PM_IMR 0x0048
24#define SM_PM_ISR 0x004c
25#define SM_PM_ICR 0x0050
26#define SM_PM_GCCTRL 0x0060
27#define SM_RTC_CTRL 0x0080
28#define SM_RTC_VAL 0x0084
29#define SM_RTC_TOP 0x0088
30#define SM_RTC_IER 0x0090
31#define SM_RTC_IDR 0x0094
32#define SM_RTC_IMR 0x0098
33#define SM_RTC_ISR 0x009c
34#define SM_RTC_ICR 0x00a0
35#define SM_WDT_CTRL 0x00b0
36#define SM_WDT_CLR 0x00b4
37#define SM_WDT_EXT 0x00b8
38#define SM_RC_RCAUSE 0x00c0
39#define SM_EIM_IER 0x0100
40#define SM_EIM_IDR 0x0104
41#define SM_EIM_IMR 0x0108
42#define SM_EIM_ISR 0x010c
43#define SM_EIM_ICR 0x0110
44#define SM_EIM_MODE 0x0114
45#define SM_EIM_EDGE 0x0118
46#define SM_EIM_LEVEL 0x011c
47#define SM_EIM_TEST 0x0120
48#define SM_EIM_NMIC 0x0124
49
50/* Bitfields in PM_MCCTRL */
51
52/* Bitfields in PM_CKSEL */
53#define SM_CPUSEL_OFFSET 0
54#define SM_CPUSEL_SIZE 3
55#define SM_CPUDIV_OFFSET 7
56#define SM_CPUDIV_SIZE 1
57#define SM_HSBSEL_OFFSET 8
58#define SM_HSBSEL_SIZE 3
59#define SM_HSBDIV_OFFSET 15
60#define SM_HSBDIV_SIZE 1
61#define SM_PBASEL_OFFSET 16
62#define SM_PBASEL_SIZE 3
63#define SM_PBADIV_OFFSET 23
64#define SM_PBADIV_SIZE 1
65#define SM_PBBSEL_OFFSET 24
66#define SM_PBBSEL_SIZE 3
67#define SM_PBBDIV_OFFSET 31
68#define SM_PBBDIV_SIZE 1
69
70/* Bitfields in PM_CPU_MASK */
71
72/* Bitfields in PM_HSB_MASK */
73
74/* Bitfields in PM_PBA_MASK */
75
76/* Bitfields in PM_PBB_MASK */
77
78/* Bitfields in PM_PLL0 */
79#define SM_PLLEN_OFFSET 0
80#define SM_PLLEN_SIZE 1
81#define SM_PLLOSC_OFFSET 1
82#define SM_PLLOSC_SIZE 1
83#define SM_PLLOPT_OFFSET 2
84#define SM_PLLOPT_SIZE 3
85#define SM_PLLDIV_OFFSET 8
86#define SM_PLLDIV_SIZE 8
87#define SM_PLLMUL_OFFSET 16
88#define SM_PLLMUL_SIZE 8
89#define SM_PLLCOUNT_OFFSET 24
90#define SM_PLLCOUNT_SIZE 6
91#define SM_PLLTEST_OFFSET 31
92#define SM_PLLTEST_SIZE 1
93
94/* Bitfields in PM_PLL1 */
95
96/* Bitfields in PM_VCTRL */
97#define SM_VAUTO_OFFSET 0
98#define SM_VAUTO_SIZE 1
99#define SM_PM_VCTRL_VAL_OFFSET 8
100#define SM_PM_VCTRL_VAL_SIZE 7
101
102/* Bitfields in PM_VMREF */
103#define SM_REFSEL_OFFSET 0
104#define SM_REFSEL_SIZE 4
105
106/* Bitfields in PM_VMV */
107#define SM_PM_VMV_VAL_OFFSET 0
108#define SM_PM_VMV_VAL_SIZE 8
109
110/* Bitfields in PM_IER */
111
112/* Bitfields in PM_IDR */
113
114/* Bitfields in PM_IMR */
115
116/* Bitfields in PM_ISR */
117
118/* Bitfields in PM_ICR */
119#define SM_LOCK0_OFFSET 0
120#define SM_LOCK0_SIZE 1
121#define SM_LOCK1_OFFSET 1
122#define SM_LOCK1_SIZE 1
123#define SM_WAKE_OFFSET 2
124#define SM_WAKE_SIZE 1
125#define SM_VOK_OFFSET 3
126#define SM_VOK_SIZE 1
127#define SM_VMRDY_OFFSET 4
128#define SM_VMRDY_SIZE 1
129#define SM_CKRDY_OFFSET 5
130#define SM_CKRDY_SIZE 1
131
132/* Bitfields in PM_GCCTRL */
133#define SM_OSCSEL_OFFSET 0
134#define SM_OSCSEL_SIZE 1
135#define SM_PLLSEL_OFFSET 1
136#define SM_PLLSEL_SIZE 1
137#define SM_CEN_OFFSET 2
138#define SM_CEN_SIZE 1
139#define SM_CPC_OFFSET 3
140#define SM_CPC_SIZE 1
141#define SM_DIVEN_OFFSET 4
142#define SM_DIVEN_SIZE 1
143#define SM_DIV_OFFSET 8
144#define SM_DIV_SIZE 8
145
146/* Bitfields in RTC_CTRL */
147#define SM_PCLR_OFFSET 1
148#define SM_PCLR_SIZE 1
149#define SM_TOPEN_OFFSET 2
150#define SM_TOPEN_SIZE 1
151#define SM_CLKEN_OFFSET 3
152#define SM_CLKEN_SIZE 1
153#define SM_PSEL_OFFSET 8
154#define SM_PSEL_SIZE 16
155
156/* Bitfields in RTC_VAL */
157#define SM_RTC_VAL_VAL_OFFSET 0
158#define SM_RTC_VAL_VAL_SIZE 31
159
160/* Bitfields in RTC_TOP */
161#define SM_RTC_TOP_VAL_OFFSET 0
162#define SM_RTC_TOP_VAL_SIZE 32
163
164/* Bitfields in RTC_IER */
165
166/* Bitfields in RTC_IDR */
167
168/* Bitfields in RTC_IMR */
169
170/* Bitfields in RTC_ISR */
171
172/* Bitfields in RTC_ICR */
173#define SM_TOPI_OFFSET 0
174#define SM_TOPI_SIZE 1
175
176/* Bitfields in WDT_CTRL */
177#define SM_KEY_OFFSET 24
178#define SM_KEY_SIZE 8
179
180/* Bitfields in WDT_CLR */
181
182/* Bitfields in WDT_EXT */
183
184/* Bitfields in RC_RCAUSE */
185#define SM_POR_OFFSET 0
186#define SM_POR_SIZE 1
187#define SM_BOD_OFFSET 1
188#define SM_BOD_SIZE 1
189#define SM_EXT_OFFSET 2
190#define SM_EXT_SIZE 1
191#define SM_WDT_OFFSET 3
192#define SM_WDT_SIZE 1
193#define SM_NTAE_OFFSET 4
194#define SM_NTAE_SIZE 1
195#define SM_SERP_OFFSET 5
196#define SM_SERP_SIZE 1
197
198/* Bitfields in EIM_IER */
199
200/* Bitfields in EIM_IDR */
201
202/* Bitfields in EIM_IMR */
203
204/* Bitfields in EIM_ISR */
205
206/* Bitfields in EIM_ICR */
207
208/* Bitfields in EIM_MODE */
209
210/* Bitfields in EIM_EDGE */
211#define SM_INT0_OFFSET 0
212#define SM_INT0_SIZE 1
213#define SM_INT1_OFFSET 1
214#define SM_INT1_SIZE 1
215#define SM_INT2_OFFSET 2
216#define SM_INT2_SIZE 1
217#define SM_INT3_OFFSET 3
218#define SM_INT3_SIZE 1
219
220/* Bitfields in EIM_LEVEL */
221
222/* Bitfields in EIM_TEST */
223#define SM_TESTEN_OFFSET 31
224#define SM_TESTEN_SIZE 1
225
226/* Bitfields in EIM_NMIC */
227#define SM_EN_OFFSET 0
228#define SM_EN_SIZE 1
229
230/* Bit manipulation macros */
231#define SM_BIT(name) (1 << SM_##name##_OFFSET)
232#define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET)
233#define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1))
234#define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value))
235
236/* Register access macros */
237#define sm_readl(port,reg) readl((port)->regs + SM_##reg)
238#define sm_writel(port,reg,value) writel((value), (port)->regs + SM_##reg)
239
240#endif /* __ASM_AVR32_SM_H__ */