diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2006-09-26 02:32:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 11:48:54 -0400 |
commit | 5f97f7f9400de47ae837170bb274e90ad3934386 (patch) | |
tree | 514451e6dc6b46253293a00035d375e77b1c65ed /arch/avr32/mach-at32ap | |
parent | 53e62d3aaa60590d4a69b4e07c29f448b5151047 (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/Makefile | 2 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap.c | 90 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 866 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/clock.c | 148 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/clock.h | 30 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/extint.c | 171 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/intc.c | 133 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/intc.h | 327 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/pio.c | 118 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/pio.h | 178 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/sm.c | 289 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/sm.h | 240 |
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 @@ | |||
1 | obj-y += at32ap.o clock.o pio.o intc.o extint.o | ||
2 | obj-$(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 | |||
19 | struct at32_sm system_manager; | ||
20 | |||
21 | static 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 | |||
41 | fail: | ||
42 | printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | void __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 | |||
56 | static 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 | |||
79 | static struct platform_driver pdc_driver = { | ||
80 | .probe = pdc_probe, | ||
81 | .driver = { | ||
82 | .name = "pdc", | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static int __init pdc_init(void) | ||
87 | { | ||
88 | return platform_driver_register(&pdc_driver); | ||
89 | } | ||
90 | arch_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) \ | ||
43 | static 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) \ | ||
50 | static 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) \ | ||
61 | static 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 | |||
70 | enum { | ||
71 | PIOA, | ||
72 | PIOB, | ||
73 | PIOC, | ||
74 | PIOD, | ||
75 | }; | ||
76 | |||
77 | enum { | ||
78 | FUNC_A, | ||
79 | FUNC_B, | ||
80 | }; | ||
81 | |||
82 | unsigned long at32ap7000_osc_rates[3] = { | ||
83 | [0] = 32768, | ||
84 | /* FIXME: these are ATSTK1002-specific */ | ||
85 | [1] = 20000000, | ||
86 | [2] = 12000000, | ||
87 | }; | ||
88 | |||
89 | static unsigned long osc_get_rate(struct clk *clk) | ||
90 | { | ||
91 | return at32ap7000_osc_rates[clk->index]; | ||
92 | } | ||
93 | |||
94 | static 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 | |||
111 | static 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 | |||
120 | static 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 | */ | ||
133 | static struct clk osc32k = { | ||
134 | .name = "osc32k", | ||
135 | .get_rate = osc_get_rate, | ||
136 | .users = 1, | ||
137 | .index = 0, | ||
138 | }; | ||
139 | static struct clk osc0 = { | ||
140 | .name = "osc0", | ||
141 | .get_rate = osc_get_rate, | ||
142 | .users = 1, | ||
143 | .index = 1, | ||
144 | }; | ||
145 | static struct clk osc1 = { | ||
146 | .name = "osc1", | ||
147 | .get_rate = osc_get_rate, | ||
148 | .index = 2, | ||
149 | }; | ||
150 | static struct clk pll0 = { | ||
151 | .name = "pll0", | ||
152 | .get_rate = pll0_get_rate, | ||
153 | .parent = &osc0, | ||
154 | }; | ||
155 | static 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 | */ | ||
166 | static 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 | */ | ||
174 | static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) | ||
175 | { | ||
176 | return main_clock->get_rate(main_clock) >> shift; | ||
177 | }; | ||
178 | |||
179 | static 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 | |||
195 | static 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 | |||
206 | static 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 | |||
222 | static 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 | |||
233 | static 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 | |||
249 | static 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 | |||
260 | static 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 | |||
276 | static 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 | |||
287 | static struct clk cpu_clk = { | ||
288 | .name = "cpu", | ||
289 | .get_rate = cpu_clk_get_rate, | ||
290 | .users = 1, | ||
291 | }; | ||
292 | static struct clk hsb_clk = { | ||
293 | .name = "hsb", | ||
294 | .parent = &cpu_clk, | ||
295 | .get_rate = hsb_clk_get_rate, | ||
296 | }; | ||
297 | static 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 | }; | ||
304 | static 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 | |||
317 | static 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 | |||
331 | static 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 | |||
348 | static 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 | |||
380 | int 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 | * -------------------------------------------------------------------- */ | ||
413 | static struct resource sm_resource[] = { | ||
414 | PBMEM(0xfff00000), | ||
415 | NAMED_IRQ(19, "eim"), | ||
416 | NAMED_IRQ(20, "pm"), | ||
417 | NAMED_IRQ(21, "rtc"), | ||
418 | }; | ||
419 | struct platform_device at32_sm_device = { | ||
420 | .name = "sm", | ||
421 | .id = 0, | ||
422 | .resource = sm_resource, | ||
423 | .num_resources = ARRAY_SIZE(sm_resource), | ||
424 | }; | ||
425 | DEV_CLK(pclk, at32_sm, pbb, 0); | ||
426 | |||
427 | static struct resource intc0_resource[] = { | ||
428 | PBMEM(0xfff00400), | ||
429 | }; | ||
430 | struct platform_device at32_intc0_device = { | ||
431 | .name = "intc", | ||
432 | .id = 0, | ||
433 | .resource = intc0_resource, | ||
434 | .num_resources = ARRAY_SIZE(intc0_resource), | ||
435 | }; | ||
436 | DEV_CLK(pclk, at32_intc0, pbb, 1); | ||
437 | |||
438 | static 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 | }; | ||
445 | static 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 | |||
453 | static struct platform_device pdc_device = { | ||
454 | .name = "pdc", | ||
455 | .id = 0, | ||
456 | }; | ||
457 | DEV_CLK(hclk, pdc, hsb, 4); | ||
458 | DEV_CLK(pclk, pdc, pba, 16); | ||
459 | |||
460 | static 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 | |||
472 | static struct resource pio0_resource[] = { | ||
473 | PBMEM(0xffe02800), | ||
474 | IRQ(13), | ||
475 | }; | ||
476 | DEFINE_DEV(pio, 0); | ||
477 | DEV_CLK(mck, pio0, pba, 10); | ||
478 | |||
479 | static struct resource pio1_resource[] = { | ||
480 | PBMEM(0xffe02c00), | ||
481 | IRQ(14), | ||
482 | }; | ||
483 | DEFINE_DEV(pio, 1); | ||
484 | DEV_CLK(mck, pio1, pba, 11); | ||
485 | |||
486 | static struct resource pio2_resource[] = { | ||
487 | PBMEM(0xffe03000), | ||
488 | IRQ(15), | ||
489 | }; | ||
490 | DEFINE_DEV(pio, 2); | ||
491 | DEV_CLK(mck, pio2, pba, 12); | ||
492 | |||
493 | static struct resource pio3_resource[] = { | ||
494 | PBMEM(0xffe03400), | ||
495 | IRQ(16), | ||
496 | }; | ||
497 | DEFINE_DEV(pio, 3); | ||
498 | DEV_CLK(mck, pio3, pba, 13); | ||
499 | |||
500 | void __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 | |||
518 | static struct resource usart0_resource[] = { | ||
519 | PBMEM(0xffe00c00), | ||
520 | IRQ(7), | ||
521 | }; | ||
522 | DEFINE_DEV(usart, 0); | ||
523 | DEV_CLK(usart, usart0, pba, 4); | ||
524 | |||
525 | static struct resource usart1_resource[] = { | ||
526 | PBMEM(0xffe01000), | ||
527 | IRQ(7), | ||
528 | }; | ||
529 | DEFINE_DEV(usart, 1); | ||
530 | DEV_CLK(usart, usart1, pba, 4); | ||
531 | |||
532 | static struct resource usart2_resource[] = { | ||
533 | PBMEM(0xffe01400), | ||
534 | IRQ(8), | ||
535 | }; | ||
536 | DEFINE_DEV(usart, 2); | ||
537 | DEV_CLK(usart, usart2, pba, 5); | ||
538 | |||
539 | static struct resource usart3_resource[] = { | ||
540 | PBMEM(0xffe01800), | ||
541 | IRQ(9), | ||
542 | }; | ||
543 | DEFINE_DEV(usart, 3); | ||
544 | DEV_CLK(usart, usart3, pba, 6); | ||
545 | |||
546 | static 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 | |||
552 | static 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 | |||
558 | static 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 | |||
564 | static 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 | |||
570 | static 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 | |||
599 | struct 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 | |||
610 | struct platform_device *at91_default_console_device; | ||
611 | |||
612 | void __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 | |||
621 | static struct eth_platform_data macb0_data; | ||
622 | static struct resource macb0_resource[] = { | ||
623 | PBMEM(0xfff01800), | ||
624 | IRQ(25), | ||
625 | }; | ||
626 | DEFINE_DEV_DATA(macb, 0); | ||
627 | DEV_CLK(hclk, macb0, hsb, 8); | ||
628 | DEV_CLK(pclk, macb0, pbb, 6); | ||
629 | |||
630 | struct platform_device *__init | ||
631 | at32_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 | * -------------------------------------------------------------------- */ | ||
676 | static struct resource spi0_resource[] = { | ||
677 | PBMEM(0xffe00000), | ||
678 | IRQ(3), | ||
679 | }; | ||
680 | DEFINE_DEV(spi, 0); | ||
681 | DEV_CLK(mck, spi0, pba, 0); | ||
682 | |||
683 | struct 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 | * -------------------------------------------------------------------- */ | ||
709 | static struct lcdc_platform_data lcdc0_data; | ||
710 | static struct resource lcdc0_resource[] = { | ||
711 | { | ||
712 | .start = 0xff000000, | ||
713 | .end = 0xff000fff, | ||
714 | .flags = IORESOURCE_MEM, | ||
715 | }, | ||
716 | IRQ(1), | ||
717 | }; | ||
718 | DEFINE_DEV_DATA(lcdc, 0); | ||
719 | DEV_CLK(hclk, lcdc0, hsb, 7); | ||
720 | static 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 | |||
730 | struct platform_device *__init | ||
731 | at32_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 | |||
785 | struct 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 | }; | ||
816 | unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); | ||
817 | |||
818 | void __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 | |||
826 | void __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 | |||
21 | static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED; | ||
22 | |||
23 | struct 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 | } | ||
36 | EXPORT_SYMBOL(clk_get); | ||
37 | |||
38 | void clk_put(struct clk *clk) | ||
39 | { | ||
40 | /* clocks are static for now, we can't free them */ | ||
41 | } | ||
42 | EXPORT_SYMBOL(clk_put); | ||
43 | |||
44 | static 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 | |||
52 | int 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 | } | ||
62 | EXPORT_SYMBOL(clk_enable); | ||
63 | |||
64 | static 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 | |||
74 | void 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 | } | ||
82 | EXPORT_SYMBOL(clk_disable); | ||
83 | |||
84 | unsigned 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 | } | ||
95 | EXPORT_SYMBOL(clk_get_rate); | ||
96 | |||
97 | long 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 | } | ||
110 | EXPORT_SYMBOL(clk_round_rate); | ||
111 | |||
112 | int 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 | } | ||
126 | EXPORT_SYMBOL(clk_set_rate); | ||
127 | |||
128 | int 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 | } | ||
142 | EXPORT_SYMBOL(clk_set_parent); | ||
143 | |||
144 | struct clk *clk_get_parent(struct clk *clk) | ||
145 | { | ||
146 | return clk->parent; | ||
147 | } | ||
148 | EXPORT_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 | |||
16 | struct 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 | |||
29 | extern struct clk *at32_clock_list[]; | ||
30 | extern 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 | |||
24 | static 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 | |||
30 | static 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 | |||
36 | static 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 | |||
43 | static 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 | |||
49 | static 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 | |||
96 | struct 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 | |||
105 | static 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 | |||
130 | static 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 | } | ||
171 | arch_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 | |||
20 | struct intc { | ||
21 | void __iomem *regs; | ||
22 | struct irq_chip chip; | ||
23 | }; | ||
24 | |||
25 | extern 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 | */ | ||
31 | static void intc_mask_irq(unsigned int irq) | ||
32 | { | ||
33 | |||
34 | } | ||
35 | |||
36 | static void intc_unmask_irq(unsigned int irq) | ||
37 | { | ||
38 | |||
39 | } | ||
40 | |||
41 | static 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 | */ | ||
52 | asmlinkage 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 | |||
80 | void __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 | |||
130 | fail: | ||
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 | |||
24 | struct 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 | |||
32 | static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; | ||
33 | |||
34 | void 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 | |||
51 | static 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 | |||
69 | static struct platform_driver pio_driver = { | ||
70 | .probe = pio_probe, | ||
71 | .driver = { | ||
72 | .name = "pio", | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static int __init pio_init(void) | ||
77 | { | ||
78 | return platform_driver_register(&pio_driver); | ||
79 | } | ||
80 | subsys_initcall(pio_init); | ||
81 | |||
82 | void __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 | |||
176 | void 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 | |||
33 | struct at32_sm system_manager; | ||
34 | |||
35 | int __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 | |||
55 | fail: | ||
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 | |||
70 | static 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 | |||
78 | static struct irqaction eim_spurious_action = { | ||
79 | .handler = spurious_eim_interrupt, | ||
80 | }; | ||
81 | |||
82 | static 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 | |||
125 | unlock: | ||
126 | spin_unlock(&sm->lock); | ||
127 | return IRQ_HANDLED; | ||
128 | } | ||
129 | |||
130 | static 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 | |||
139 | static 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 | |||
148 | static 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 | |||
159 | static 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 | |||
167 | static 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 | |||
202 | static 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 | |||
228 | static 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 | |||
239 | static 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 | |||
284 | out_free_actions: | ||
285 | kfree(sm->action); | ||
286 | out: | ||
287 | return ret; | ||
288 | } | ||
289 | arch_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__ */ | ||