diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-10-29 10:28:07 -0400 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2008-01-25 02:31:41 -0500 |
commit | 438ff3f3cc33833206a48492e9d6674e4e82bed8 (patch) | |
tree | 5159b43453c6a86949798af889d3cb0200818b74 /arch/avr32/mach-at32ap/at32ap700x.c | |
parent | 281ef58ccf62eaa6c4e4b7e4c0a3ee6b52e84e5b (diff) |
[AVR32] Add support for AT32AP7001 and AT32AP7002
These are derivatives of the AT32AP7000 chip, which means that most of
the code stays the same. Rename a few files, functions, definitions
and config symbols to reflect that they apply to all AP700x chips, and
exclude some platform devices from chips where they aren't present.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32/mach-at32ap/at32ap700x.c')
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 1742 |
1 files changed, 1742 insertions, 0 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c new file mode 100644 index 000000000000..9386e1f82fb8 --- /dev/null +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
@@ -0,0 +1,1742 @@ | |||
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/fb.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/dma-mapping.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | |||
15 | #include <asm/io.h> | ||
16 | |||
17 | #include <asm/arch/at32ap700x.h> | ||
18 | #include <asm/arch/board.h> | ||
19 | #include <asm/arch/portmux.h> | ||
20 | |||
21 | #include <video/atmel_lcdc.h> | ||
22 | |||
23 | #include "clock.h" | ||
24 | #include "hmatrix.h" | ||
25 | #include "pio.h" | ||
26 | #include "pm.h" | ||
27 | |||
28 | |||
29 | #define PBMEM(base) \ | ||
30 | { \ | ||
31 | .start = base, \ | ||
32 | .end = base + 0x3ff, \ | ||
33 | .flags = IORESOURCE_MEM, \ | ||
34 | } | ||
35 | #define IRQ(num) \ | ||
36 | { \ | ||
37 | .start = num, \ | ||
38 | .end = num, \ | ||
39 | .flags = IORESOURCE_IRQ, \ | ||
40 | } | ||
41 | #define NAMED_IRQ(num, _name) \ | ||
42 | { \ | ||
43 | .start = num, \ | ||
44 | .end = num, \ | ||
45 | .name = _name, \ | ||
46 | .flags = IORESOURCE_IRQ, \ | ||
47 | } | ||
48 | |||
49 | /* REVISIT these assume *every* device supports DMA, but several | ||
50 | * don't ... tc, smc, pio, rtc, watchdog, pwm, ps2, and more. | ||
51 | */ | ||
52 | #define DEFINE_DEV(_name, _id) \ | ||
53 | static u64 _name##_id##_dma_mask = DMA_32BIT_MASK; \ | ||
54 | static struct platform_device _name##_id##_device = { \ | ||
55 | .name = #_name, \ | ||
56 | .id = _id, \ | ||
57 | .dev = { \ | ||
58 | .dma_mask = &_name##_id##_dma_mask, \ | ||
59 | .coherent_dma_mask = DMA_32BIT_MASK, \ | ||
60 | }, \ | ||
61 | .resource = _name##_id##_resource, \ | ||
62 | .num_resources = ARRAY_SIZE(_name##_id##_resource), \ | ||
63 | } | ||
64 | #define DEFINE_DEV_DATA(_name, _id) \ | ||
65 | static u64 _name##_id##_dma_mask = DMA_32BIT_MASK; \ | ||
66 | static struct platform_device _name##_id##_device = { \ | ||
67 | .name = #_name, \ | ||
68 | .id = _id, \ | ||
69 | .dev = { \ | ||
70 | .dma_mask = &_name##_id##_dma_mask, \ | ||
71 | .platform_data = &_name##_id##_data, \ | ||
72 | .coherent_dma_mask = DMA_32BIT_MASK, \ | ||
73 | }, \ | ||
74 | .resource = _name##_id##_resource, \ | ||
75 | .num_resources = ARRAY_SIZE(_name##_id##_resource), \ | ||
76 | } | ||
77 | |||
78 | #define select_peripheral(pin, periph, flags) \ | ||
79 | at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags) | ||
80 | |||
81 | #define DEV_CLK(_name, devname, bus, _index) \ | ||
82 | static struct clk devname##_##_name = { \ | ||
83 | .name = #_name, \ | ||
84 | .dev = &devname##_device.dev, \ | ||
85 | .parent = &bus##_clk, \ | ||
86 | .mode = bus##_clk_mode, \ | ||
87 | .get_rate = bus##_clk_get_rate, \ | ||
88 | .index = _index, \ | ||
89 | } | ||
90 | |||
91 | static DEFINE_SPINLOCK(pm_lock); | ||
92 | |||
93 | unsigned long at32ap7000_osc_rates[3] = { | ||
94 | [0] = 32768, | ||
95 | /* FIXME: these are ATSTK1002-specific */ | ||
96 | [1] = 20000000, | ||
97 | [2] = 12000000, | ||
98 | }; | ||
99 | |||
100 | static unsigned long osc_get_rate(struct clk *clk) | ||
101 | { | ||
102 | return at32ap7000_osc_rates[clk->index]; | ||
103 | } | ||
104 | |||
105 | static unsigned long pll_get_rate(struct clk *clk, unsigned long control) | ||
106 | { | ||
107 | unsigned long div, mul, rate; | ||
108 | |||
109 | if (!(control & PM_BIT(PLLEN))) | ||
110 | return 0; | ||
111 | |||
112 | div = PM_BFEXT(PLLDIV, control) + 1; | ||
113 | mul = PM_BFEXT(PLLMUL, control) + 1; | ||
114 | |||
115 | rate = clk->parent->get_rate(clk->parent); | ||
116 | rate = (rate + div / 2) / div; | ||
117 | rate *= mul; | ||
118 | |||
119 | return rate; | ||
120 | } | ||
121 | |||
122 | static unsigned long pll0_get_rate(struct clk *clk) | ||
123 | { | ||
124 | u32 control; | ||
125 | |||
126 | control = pm_readl(PLL0); | ||
127 | |||
128 | return pll_get_rate(clk, control); | ||
129 | } | ||
130 | |||
131 | static unsigned long pll1_get_rate(struct clk *clk) | ||
132 | { | ||
133 | u32 control; | ||
134 | |||
135 | control = pm_readl(PLL1); | ||
136 | |||
137 | return pll_get_rate(clk, control); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * The AT32AP7000 has five primary clock sources: One 32kHz | ||
142 | * oscillator, two crystal oscillators and two PLLs. | ||
143 | */ | ||
144 | static struct clk osc32k = { | ||
145 | .name = "osc32k", | ||
146 | .get_rate = osc_get_rate, | ||
147 | .users = 1, | ||
148 | .index = 0, | ||
149 | }; | ||
150 | static struct clk osc0 = { | ||
151 | .name = "osc0", | ||
152 | .get_rate = osc_get_rate, | ||
153 | .users = 1, | ||
154 | .index = 1, | ||
155 | }; | ||
156 | static struct clk osc1 = { | ||
157 | .name = "osc1", | ||
158 | .get_rate = osc_get_rate, | ||
159 | .index = 2, | ||
160 | }; | ||
161 | static struct clk pll0 = { | ||
162 | .name = "pll0", | ||
163 | .get_rate = pll0_get_rate, | ||
164 | .parent = &osc0, | ||
165 | }; | ||
166 | static struct clk pll1 = { | ||
167 | .name = "pll1", | ||
168 | .get_rate = pll1_get_rate, | ||
169 | .parent = &osc0, | ||
170 | }; | ||
171 | |||
172 | /* | ||
173 | * The main clock can be either osc0 or pll0. The boot loader may | ||
174 | * have chosen one for us, so we don't really know which one until we | ||
175 | * have a look at the SM. | ||
176 | */ | ||
177 | static struct clk *main_clock; | ||
178 | |||
179 | /* | ||
180 | * Synchronous clocks are generated from the main clock. The clocks | ||
181 | * must satisfy the constraint | ||
182 | * fCPU >= fHSB >= fPB | ||
183 | * i.e. each clock must not be faster than its parent. | ||
184 | */ | ||
185 | static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) | ||
186 | { | ||
187 | return main_clock->get_rate(main_clock) >> shift; | ||
188 | }; | ||
189 | |||
190 | static void cpu_clk_mode(struct clk *clk, int enabled) | ||
191 | { | ||
192 | unsigned long flags; | ||
193 | u32 mask; | ||
194 | |||
195 | spin_lock_irqsave(&pm_lock, flags); | ||
196 | mask = pm_readl(CPU_MASK); | ||
197 | if (enabled) | ||
198 | mask |= 1 << clk->index; | ||
199 | else | ||
200 | mask &= ~(1 << clk->index); | ||
201 | pm_writel(CPU_MASK, mask); | ||
202 | spin_unlock_irqrestore(&pm_lock, flags); | ||
203 | } | ||
204 | |||
205 | static unsigned long cpu_clk_get_rate(struct clk *clk) | ||
206 | { | ||
207 | unsigned long cksel, shift = 0; | ||
208 | |||
209 | cksel = pm_readl(CKSEL); | ||
210 | if (cksel & PM_BIT(CPUDIV)) | ||
211 | shift = PM_BFEXT(CPUSEL, cksel) + 1; | ||
212 | |||
213 | return bus_clk_get_rate(clk, shift); | ||
214 | } | ||
215 | |||
216 | static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply) | ||
217 | { | ||
218 | u32 control; | ||
219 | unsigned long parent_rate, child_div, actual_rate, div; | ||
220 | |||
221 | parent_rate = clk->parent->get_rate(clk->parent); | ||
222 | control = pm_readl(CKSEL); | ||
223 | |||
224 | if (control & PM_BIT(HSBDIV)) | ||
225 | child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1); | ||
226 | else | ||
227 | child_div = 1; | ||
228 | |||
229 | if (rate > 3 * (parent_rate / 4) || child_div == 1) { | ||
230 | actual_rate = parent_rate; | ||
231 | control &= ~PM_BIT(CPUDIV); | ||
232 | } else { | ||
233 | unsigned int cpusel; | ||
234 | div = (parent_rate + rate / 2) / rate; | ||
235 | if (div > child_div) | ||
236 | div = child_div; | ||
237 | cpusel = (div > 1) ? (fls(div) - 2) : 0; | ||
238 | control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control); | ||
239 | actual_rate = parent_rate / (1 << (cpusel + 1)); | ||
240 | } | ||
241 | |||
242 | pr_debug("clk %s: new rate %lu (actual rate %lu)\n", | ||
243 | clk->name, rate, actual_rate); | ||
244 | |||
245 | if (apply) | ||
246 | pm_writel(CKSEL, control); | ||
247 | |||
248 | return actual_rate; | ||
249 | } | ||
250 | |||
251 | static void hsb_clk_mode(struct clk *clk, int enabled) | ||
252 | { | ||
253 | unsigned long flags; | ||
254 | u32 mask; | ||
255 | |||
256 | spin_lock_irqsave(&pm_lock, flags); | ||
257 | mask = pm_readl(HSB_MASK); | ||
258 | if (enabled) | ||
259 | mask |= 1 << clk->index; | ||
260 | else | ||
261 | mask &= ~(1 << clk->index); | ||
262 | pm_writel(HSB_MASK, mask); | ||
263 | spin_unlock_irqrestore(&pm_lock, flags); | ||
264 | } | ||
265 | |||
266 | static unsigned long hsb_clk_get_rate(struct clk *clk) | ||
267 | { | ||
268 | unsigned long cksel, shift = 0; | ||
269 | |||
270 | cksel = pm_readl(CKSEL); | ||
271 | if (cksel & PM_BIT(HSBDIV)) | ||
272 | shift = PM_BFEXT(HSBSEL, cksel) + 1; | ||
273 | |||
274 | return bus_clk_get_rate(clk, shift); | ||
275 | } | ||
276 | |||
277 | static void pba_clk_mode(struct clk *clk, int enabled) | ||
278 | { | ||
279 | unsigned long flags; | ||
280 | u32 mask; | ||
281 | |||
282 | spin_lock_irqsave(&pm_lock, flags); | ||
283 | mask = pm_readl(PBA_MASK); | ||
284 | if (enabled) | ||
285 | mask |= 1 << clk->index; | ||
286 | else | ||
287 | mask &= ~(1 << clk->index); | ||
288 | pm_writel(PBA_MASK, mask); | ||
289 | spin_unlock_irqrestore(&pm_lock, flags); | ||
290 | } | ||
291 | |||
292 | static unsigned long pba_clk_get_rate(struct clk *clk) | ||
293 | { | ||
294 | unsigned long cksel, shift = 0; | ||
295 | |||
296 | cksel = pm_readl(CKSEL); | ||
297 | if (cksel & PM_BIT(PBADIV)) | ||
298 | shift = PM_BFEXT(PBASEL, cksel) + 1; | ||
299 | |||
300 | return bus_clk_get_rate(clk, shift); | ||
301 | } | ||
302 | |||
303 | static void pbb_clk_mode(struct clk *clk, int enabled) | ||
304 | { | ||
305 | unsigned long flags; | ||
306 | u32 mask; | ||
307 | |||
308 | spin_lock_irqsave(&pm_lock, flags); | ||
309 | mask = pm_readl(PBB_MASK); | ||
310 | if (enabled) | ||
311 | mask |= 1 << clk->index; | ||
312 | else | ||
313 | mask &= ~(1 << clk->index); | ||
314 | pm_writel(PBB_MASK, mask); | ||
315 | spin_unlock_irqrestore(&pm_lock, flags); | ||
316 | } | ||
317 | |||
318 | static unsigned long pbb_clk_get_rate(struct clk *clk) | ||
319 | { | ||
320 | unsigned long cksel, shift = 0; | ||
321 | |||
322 | cksel = pm_readl(CKSEL); | ||
323 | if (cksel & PM_BIT(PBBDIV)) | ||
324 | shift = PM_BFEXT(PBBSEL, cksel) + 1; | ||
325 | |||
326 | return bus_clk_get_rate(clk, shift); | ||
327 | } | ||
328 | |||
329 | static struct clk cpu_clk = { | ||
330 | .name = "cpu", | ||
331 | .get_rate = cpu_clk_get_rate, | ||
332 | .set_rate = cpu_clk_set_rate, | ||
333 | .users = 1, | ||
334 | }; | ||
335 | static struct clk hsb_clk = { | ||
336 | .name = "hsb", | ||
337 | .parent = &cpu_clk, | ||
338 | .get_rate = hsb_clk_get_rate, | ||
339 | }; | ||
340 | static struct clk pba_clk = { | ||
341 | .name = "pba", | ||
342 | .parent = &hsb_clk, | ||
343 | .mode = hsb_clk_mode, | ||
344 | .get_rate = pba_clk_get_rate, | ||
345 | .index = 1, | ||
346 | }; | ||
347 | static struct clk pbb_clk = { | ||
348 | .name = "pbb", | ||
349 | .parent = &hsb_clk, | ||
350 | .mode = hsb_clk_mode, | ||
351 | .get_rate = pbb_clk_get_rate, | ||
352 | .users = 1, | ||
353 | .index = 2, | ||
354 | }; | ||
355 | |||
356 | /* -------------------------------------------------------------------- | ||
357 | * Generic Clock operations | ||
358 | * -------------------------------------------------------------------- */ | ||
359 | |||
360 | static void genclk_mode(struct clk *clk, int enabled) | ||
361 | { | ||
362 | u32 control; | ||
363 | |||
364 | control = pm_readl(GCCTRL(clk->index)); | ||
365 | if (enabled) | ||
366 | control |= PM_BIT(CEN); | ||
367 | else | ||
368 | control &= ~PM_BIT(CEN); | ||
369 | pm_writel(GCCTRL(clk->index), control); | ||
370 | } | ||
371 | |||
372 | static unsigned long genclk_get_rate(struct clk *clk) | ||
373 | { | ||
374 | u32 control; | ||
375 | unsigned long div = 1; | ||
376 | |||
377 | control = pm_readl(GCCTRL(clk->index)); | ||
378 | if (control & PM_BIT(DIVEN)) | ||
379 | div = 2 * (PM_BFEXT(DIV, control) + 1); | ||
380 | |||
381 | return clk->parent->get_rate(clk->parent) / div; | ||
382 | } | ||
383 | |||
384 | static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply) | ||
385 | { | ||
386 | u32 control; | ||
387 | unsigned long parent_rate, actual_rate, div; | ||
388 | |||
389 | parent_rate = clk->parent->get_rate(clk->parent); | ||
390 | control = pm_readl(GCCTRL(clk->index)); | ||
391 | |||
392 | if (rate > 3 * parent_rate / 4) { | ||
393 | actual_rate = parent_rate; | ||
394 | control &= ~PM_BIT(DIVEN); | ||
395 | } else { | ||
396 | div = (parent_rate + rate) / (2 * rate) - 1; | ||
397 | control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN); | ||
398 | actual_rate = parent_rate / (2 * (div + 1)); | ||
399 | } | ||
400 | |||
401 | dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n", | ||
402 | clk->name, rate, actual_rate); | ||
403 | |||
404 | if (apply) | ||
405 | pm_writel(GCCTRL(clk->index), control); | ||
406 | |||
407 | return actual_rate; | ||
408 | } | ||
409 | |||
410 | int genclk_set_parent(struct clk *clk, struct clk *parent) | ||
411 | { | ||
412 | u32 control; | ||
413 | |||
414 | dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n", | ||
415 | clk->name, parent->name, clk->parent->name); | ||
416 | |||
417 | control = pm_readl(GCCTRL(clk->index)); | ||
418 | |||
419 | if (parent == &osc1 || parent == &pll1) | ||
420 | control |= PM_BIT(OSCSEL); | ||
421 | else if (parent == &osc0 || parent == &pll0) | ||
422 | control &= ~PM_BIT(OSCSEL); | ||
423 | else | ||
424 | return -EINVAL; | ||
425 | |||
426 | if (parent == &pll0 || parent == &pll1) | ||
427 | control |= PM_BIT(PLLSEL); | ||
428 | else | ||
429 | control &= ~PM_BIT(PLLSEL); | ||
430 | |||
431 | pm_writel(GCCTRL(clk->index), control); | ||
432 | clk->parent = parent; | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static void __init genclk_init_parent(struct clk *clk) | ||
438 | { | ||
439 | u32 control; | ||
440 | struct clk *parent; | ||
441 | |||
442 | BUG_ON(clk->index > 7); | ||
443 | |||
444 | control = pm_readl(GCCTRL(clk->index)); | ||
445 | if (control & PM_BIT(OSCSEL)) | ||
446 | parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1; | ||
447 | else | ||
448 | parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0; | ||
449 | |||
450 | clk->parent = parent; | ||
451 | } | ||
452 | |||
453 | /* -------------------------------------------------------------------- | ||
454 | * System peripherals | ||
455 | * -------------------------------------------------------------------- */ | ||
456 | static struct resource at32_pm0_resource[] = { | ||
457 | { | ||
458 | .start = 0xfff00000, | ||
459 | .end = 0xfff0007f, | ||
460 | .flags = IORESOURCE_MEM, | ||
461 | }, | ||
462 | IRQ(20), | ||
463 | }; | ||
464 | |||
465 | static struct resource at32ap700x_rtc0_resource[] = { | ||
466 | { | ||
467 | .start = 0xfff00080, | ||
468 | .end = 0xfff000af, | ||
469 | .flags = IORESOURCE_MEM, | ||
470 | }, | ||
471 | IRQ(21), | ||
472 | }; | ||
473 | |||
474 | static struct resource at32_wdt0_resource[] = { | ||
475 | { | ||
476 | .start = 0xfff000b0, | ||
477 | .end = 0xfff000cf, | ||
478 | .flags = IORESOURCE_MEM, | ||
479 | }, | ||
480 | }; | ||
481 | |||
482 | static struct resource at32_eic0_resource[] = { | ||
483 | { | ||
484 | .start = 0xfff00100, | ||
485 | .end = 0xfff0013f, | ||
486 | .flags = IORESOURCE_MEM, | ||
487 | }, | ||
488 | IRQ(19), | ||
489 | }; | ||
490 | |||
491 | DEFINE_DEV(at32_pm, 0); | ||
492 | DEFINE_DEV(at32ap700x_rtc, 0); | ||
493 | DEFINE_DEV(at32_wdt, 0); | ||
494 | DEFINE_DEV(at32_eic, 0); | ||
495 | |||
496 | /* | ||
497 | * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this | ||
498 | * is always running. | ||
499 | */ | ||
500 | static struct clk at32_pm_pclk = { | ||
501 | .name = "pclk", | ||
502 | .dev = &at32_pm0_device.dev, | ||
503 | .parent = &pbb_clk, | ||
504 | .mode = pbb_clk_mode, | ||
505 | .get_rate = pbb_clk_get_rate, | ||
506 | .users = 1, | ||
507 | .index = 0, | ||
508 | }; | ||
509 | |||
510 | static struct resource intc0_resource[] = { | ||
511 | PBMEM(0xfff00400), | ||
512 | }; | ||
513 | struct platform_device at32_intc0_device = { | ||
514 | .name = "intc", | ||
515 | .id = 0, | ||
516 | .resource = intc0_resource, | ||
517 | .num_resources = ARRAY_SIZE(intc0_resource), | ||
518 | }; | ||
519 | DEV_CLK(pclk, at32_intc0, pbb, 1); | ||
520 | |||
521 | static struct clk ebi_clk = { | ||
522 | .name = "ebi", | ||
523 | .parent = &hsb_clk, | ||
524 | .mode = hsb_clk_mode, | ||
525 | .get_rate = hsb_clk_get_rate, | ||
526 | .users = 1, | ||
527 | }; | ||
528 | static struct clk hramc_clk = { | ||
529 | .name = "hramc", | ||
530 | .parent = &hsb_clk, | ||
531 | .mode = hsb_clk_mode, | ||
532 | .get_rate = hsb_clk_get_rate, | ||
533 | .users = 1, | ||
534 | .index = 3, | ||
535 | }; | ||
536 | |||
537 | static struct resource smc0_resource[] = { | ||
538 | PBMEM(0xfff03400), | ||
539 | }; | ||
540 | DEFINE_DEV(smc, 0); | ||
541 | DEV_CLK(pclk, smc0, pbb, 13); | ||
542 | DEV_CLK(mck, smc0, hsb, 0); | ||
543 | |||
544 | static struct platform_device pdc_device = { | ||
545 | .name = "pdc", | ||
546 | .id = 0, | ||
547 | }; | ||
548 | DEV_CLK(hclk, pdc, hsb, 4); | ||
549 | DEV_CLK(pclk, pdc, pba, 16); | ||
550 | |||
551 | static struct clk pico_clk = { | ||
552 | .name = "pico", | ||
553 | .parent = &cpu_clk, | ||
554 | .mode = cpu_clk_mode, | ||
555 | .get_rate = cpu_clk_get_rate, | ||
556 | .users = 1, | ||
557 | }; | ||
558 | |||
559 | static struct resource dmaca0_resource[] = { | ||
560 | { | ||
561 | .start = 0xff200000, | ||
562 | .end = 0xff20ffff, | ||
563 | .flags = IORESOURCE_MEM, | ||
564 | }, | ||
565 | IRQ(2), | ||
566 | }; | ||
567 | DEFINE_DEV(dmaca, 0); | ||
568 | DEV_CLK(hclk, dmaca0, hsb, 10); | ||
569 | |||
570 | /* -------------------------------------------------------------------- | ||
571 | * HMATRIX | ||
572 | * -------------------------------------------------------------------- */ | ||
573 | |||
574 | static struct clk hmatrix_clk = { | ||
575 | .name = "hmatrix_clk", | ||
576 | .parent = &pbb_clk, | ||
577 | .mode = pbb_clk_mode, | ||
578 | .get_rate = pbb_clk_get_rate, | ||
579 | .index = 2, | ||
580 | .users = 1, | ||
581 | }; | ||
582 | #define HMATRIX_BASE ((void __iomem *)0xfff00800) | ||
583 | |||
584 | #define hmatrix_readl(reg) \ | ||
585 | __raw_readl((HMATRIX_BASE) + HMATRIX_##reg) | ||
586 | #define hmatrix_writel(reg,value) \ | ||
587 | __raw_writel((value), (HMATRIX_BASE) + HMATRIX_##reg) | ||
588 | |||
589 | /* | ||
590 | * Set bits in the HMATRIX Special Function Register (SFR) used by the | ||
591 | * External Bus Interface (EBI). This can be used to enable special | ||
592 | * features like CompactFlash support, NAND Flash support, etc. on | ||
593 | * certain chipselects. | ||
594 | */ | ||
595 | static inline void set_ebi_sfr_bits(u32 mask) | ||
596 | { | ||
597 | u32 sfr; | ||
598 | |||
599 | clk_enable(&hmatrix_clk); | ||
600 | sfr = hmatrix_readl(SFR4); | ||
601 | sfr |= mask; | ||
602 | hmatrix_writel(SFR4, sfr); | ||
603 | clk_disable(&hmatrix_clk); | ||
604 | } | ||
605 | |||
606 | /* -------------------------------------------------------------------- | ||
607 | * System Timer/Counter (TC) | ||
608 | * -------------------------------------------------------------------- */ | ||
609 | static struct resource at32_systc0_resource[] = { | ||
610 | PBMEM(0xfff00c00), | ||
611 | IRQ(22), | ||
612 | }; | ||
613 | struct platform_device at32_systc0_device = { | ||
614 | .name = "systc", | ||
615 | .id = 0, | ||
616 | .resource = at32_systc0_resource, | ||
617 | .num_resources = ARRAY_SIZE(at32_systc0_resource), | ||
618 | }; | ||
619 | DEV_CLK(pclk, at32_systc0, pbb, 3); | ||
620 | |||
621 | /* -------------------------------------------------------------------- | ||
622 | * PIO | ||
623 | * -------------------------------------------------------------------- */ | ||
624 | |||
625 | static struct resource pio0_resource[] = { | ||
626 | PBMEM(0xffe02800), | ||
627 | IRQ(13), | ||
628 | }; | ||
629 | DEFINE_DEV(pio, 0); | ||
630 | DEV_CLK(mck, pio0, pba, 10); | ||
631 | |||
632 | static struct resource pio1_resource[] = { | ||
633 | PBMEM(0xffe02c00), | ||
634 | IRQ(14), | ||
635 | }; | ||
636 | DEFINE_DEV(pio, 1); | ||
637 | DEV_CLK(mck, pio1, pba, 11); | ||
638 | |||
639 | static struct resource pio2_resource[] = { | ||
640 | PBMEM(0xffe03000), | ||
641 | IRQ(15), | ||
642 | }; | ||
643 | DEFINE_DEV(pio, 2); | ||
644 | DEV_CLK(mck, pio2, pba, 12); | ||
645 | |||
646 | static struct resource pio3_resource[] = { | ||
647 | PBMEM(0xffe03400), | ||
648 | IRQ(16), | ||
649 | }; | ||
650 | DEFINE_DEV(pio, 3); | ||
651 | DEV_CLK(mck, pio3, pba, 13); | ||
652 | |||
653 | static struct resource pio4_resource[] = { | ||
654 | PBMEM(0xffe03800), | ||
655 | IRQ(17), | ||
656 | }; | ||
657 | DEFINE_DEV(pio, 4); | ||
658 | DEV_CLK(mck, pio4, pba, 14); | ||
659 | |||
660 | void __init at32_add_system_devices(void) | ||
661 | { | ||
662 | platform_device_register(&at32_pm0_device); | ||
663 | platform_device_register(&at32_intc0_device); | ||
664 | platform_device_register(&at32ap700x_rtc0_device); | ||
665 | platform_device_register(&at32_wdt0_device); | ||
666 | platform_device_register(&at32_eic0_device); | ||
667 | platform_device_register(&smc0_device); | ||
668 | platform_device_register(&pdc_device); | ||
669 | platform_device_register(&dmaca0_device); | ||
670 | |||
671 | platform_device_register(&at32_systc0_device); | ||
672 | |||
673 | platform_device_register(&pio0_device); | ||
674 | platform_device_register(&pio1_device); | ||
675 | platform_device_register(&pio2_device); | ||
676 | platform_device_register(&pio3_device); | ||
677 | platform_device_register(&pio4_device); | ||
678 | } | ||
679 | |||
680 | /* -------------------------------------------------------------------- | ||
681 | * USART | ||
682 | * -------------------------------------------------------------------- */ | ||
683 | |||
684 | static struct atmel_uart_data atmel_usart0_data = { | ||
685 | .use_dma_tx = 1, | ||
686 | .use_dma_rx = 1, | ||
687 | }; | ||
688 | static struct resource atmel_usart0_resource[] = { | ||
689 | PBMEM(0xffe00c00), | ||
690 | IRQ(6), | ||
691 | }; | ||
692 | DEFINE_DEV_DATA(atmel_usart, 0); | ||
693 | DEV_CLK(usart, atmel_usart0, pba, 3); | ||
694 | |||
695 | static struct atmel_uart_data atmel_usart1_data = { | ||
696 | .use_dma_tx = 1, | ||
697 | .use_dma_rx = 1, | ||
698 | }; | ||
699 | static struct resource atmel_usart1_resource[] = { | ||
700 | PBMEM(0xffe01000), | ||
701 | IRQ(7), | ||
702 | }; | ||
703 | DEFINE_DEV_DATA(atmel_usart, 1); | ||
704 | DEV_CLK(usart, atmel_usart1, pba, 4); | ||
705 | |||
706 | static struct atmel_uart_data atmel_usart2_data = { | ||
707 | .use_dma_tx = 1, | ||
708 | .use_dma_rx = 1, | ||
709 | }; | ||
710 | static struct resource atmel_usart2_resource[] = { | ||
711 | PBMEM(0xffe01400), | ||
712 | IRQ(8), | ||
713 | }; | ||
714 | DEFINE_DEV_DATA(atmel_usart, 2); | ||
715 | DEV_CLK(usart, atmel_usart2, pba, 5); | ||
716 | |||
717 | static struct atmel_uart_data atmel_usart3_data = { | ||
718 | .use_dma_tx = 1, | ||
719 | .use_dma_rx = 1, | ||
720 | }; | ||
721 | static struct resource atmel_usart3_resource[] = { | ||
722 | PBMEM(0xffe01800), | ||
723 | IRQ(9), | ||
724 | }; | ||
725 | DEFINE_DEV_DATA(atmel_usart, 3); | ||
726 | DEV_CLK(usart, atmel_usart3, pba, 6); | ||
727 | |||
728 | static inline void configure_usart0_pins(void) | ||
729 | { | ||
730 | select_peripheral(PA(8), PERIPH_B, 0); /* RXD */ | ||
731 | select_peripheral(PA(9), PERIPH_B, 0); /* TXD */ | ||
732 | } | ||
733 | |||
734 | static inline void configure_usart1_pins(void) | ||
735 | { | ||
736 | select_peripheral(PA(17), PERIPH_A, 0); /* RXD */ | ||
737 | select_peripheral(PA(18), PERIPH_A, 0); /* TXD */ | ||
738 | } | ||
739 | |||
740 | static inline void configure_usart2_pins(void) | ||
741 | { | ||
742 | select_peripheral(PB(26), PERIPH_B, 0); /* RXD */ | ||
743 | select_peripheral(PB(27), PERIPH_B, 0); /* TXD */ | ||
744 | } | ||
745 | |||
746 | static inline void configure_usart3_pins(void) | ||
747 | { | ||
748 | select_peripheral(PB(18), PERIPH_B, 0); /* RXD */ | ||
749 | select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ | ||
750 | } | ||
751 | |||
752 | static struct platform_device *__initdata at32_usarts[4]; | ||
753 | |||
754 | void __init at32_map_usart(unsigned int hw_id, unsigned int line) | ||
755 | { | ||
756 | struct platform_device *pdev; | ||
757 | |||
758 | switch (hw_id) { | ||
759 | case 0: | ||
760 | pdev = &atmel_usart0_device; | ||
761 | configure_usart0_pins(); | ||
762 | break; | ||
763 | case 1: | ||
764 | pdev = &atmel_usart1_device; | ||
765 | configure_usart1_pins(); | ||
766 | break; | ||
767 | case 2: | ||
768 | pdev = &atmel_usart2_device; | ||
769 | configure_usart2_pins(); | ||
770 | break; | ||
771 | case 3: | ||
772 | pdev = &atmel_usart3_device; | ||
773 | configure_usart3_pins(); | ||
774 | break; | ||
775 | default: | ||
776 | return; | ||
777 | } | ||
778 | |||
779 | if (PXSEG(pdev->resource[0].start) == P4SEG) { | ||
780 | /* Addresses in the P4 segment are permanently mapped 1:1 */ | ||
781 | struct atmel_uart_data *data = pdev->dev.platform_data; | ||
782 | data->regs = (void __iomem *)pdev->resource[0].start; | ||
783 | } | ||
784 | |||
785 | pdev->id = line; | ||
786 | at32_usarts[line] = pdev; | ||
787 | } | ||
788 | |||
789 | struct platform_device *__init at32_add_device_usart(unsigned int id) | ||
790 | { | ||
791 | platform_device_register(at32_usarts[id]); | ||
792 | return at32_usarts[id]; | ||
793 | } | ||
794 | |||
795 | struct platform_device *atmel_default_console_device; | ||
796 | |||
797 | void __init at32_setup_serial_console(unsigned int usart_id) | ||
798 | { | ||
799 | atmel_default_console_device = at32_usarts[usart_id]; | ||
800 | } | ||
801 | |||
802 | /* -------------------------------------------------------------------- | ||
803 | * Ethernet | ||
804 | * -------------------------------------------------------------------- */ | ||
805 | |||
806 | #ifdef CONFIG_CPU_AT32AP7000 | ||
807 | static struct eth_platform_data macb0_data; | ||
808 | static struct resource macb0_resource[] = { | ||
809 | PBMEM(0xfff01800), | ||
810 | IRQ(25), | ||
811 | }; | ||
812 | DEFINE_DEV_DATA(macb, 0); | ||
813 | DEV_CLK(hclk, macb0, hsb, 8); | ||
814 | DEV_CLK(pclk, macb0, pbb, 6); | ||
815 | |||
816 | static struct eth_platform_data macb1_data; | ||
817 | static struct resource macb1_resource[] = { | ||
818 | PBMEM(0xfff01c00), | ||
819 | IRQ(26), | ||
820 | }; | ||
821 | DEFINE_DEV_DATA(macb, 1); | ||
822 | DEV_CLK(hclk, macb1, hsb, 9); | ||
823 | DEV_CLK(pclk, macb1, pbb, 7); | ||
824 | |||
825 | struct platform_device *__init | ||
826 | at32_add_device_eth(unsigned int id, struct eth_platform_data *data) | ||
827 | { | ||
828 | struct platform_device *pdev; | ||
829 | |||
830 | switch (id) { | ||
831 | case 0: | ||
832 | pdev = &macb0_device; | ||
833 | |||
834 | select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */ | ||
835 | select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */ | ||
836 | select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */ | ||
837 | select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */ | ||
838 | select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */ | ||
839 | select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */ | ||
840 | select_peripheral(PC(13), PERIPH_A, 0); /* RXER */ | ||
841 | select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */ | ||
842 | select_peripheral(PC(16), PERIPH_A, 0); /* MDC */ | ||
843 | select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */ | ||
844 | |||
845 | if (!data->is_rmii) { | ||
846 | select_peripheral(PC(0), PERIPH_A, 0); /* COL */ | ||
847 | select_peripheral(PC(1), PERIPH_A, 0); /* CRS */ | ||
848 | select_peripheral(PC(2), PERIPH_A, 0); /* TXER */ | ||
849 | select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */ | ||
850 | select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */ | ||
851 | select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */ | ||
852 | select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */ | ||
853 | select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */ | ||
854 | select_peripheral(PC(18), PERIPH_A, 0); /* SPD */ | ||
855 | } | ||
856 | break; | ||
857 | |||
858 | case 1: | ||
859 | pdev = &macb1_device; | ||
860 | |||
861 | select_peripheral(PD(13), PERIPH_B, 0); /* TXD0 */ | ||
862 | select_peripheral(PD(14), PERIPH_B, 0); /* TXD1 */ | ||
863 | select_peripheral(PD(11), PERIPH_B, 0); /* TXEN */ | ||
864 | select_peripheral(PD(12), PERIPH_B, 0); /* TXCK */ | ||
865 | select_peripheral(PD(10), PERIPH_B, 0); /* RXD0 */ | ||
866 | select_peripheral(PD(6), PERIPH_B, 0); /* RXD1 */ | ||
867 | select_peripheral(PD(5), PERIPH_B, 0); /* RXER */ | ||
868 | select_peripheral(PD(4), PERIPH_B, 0); /* RXDV */ | ||
869 | select_peripheral(PD(3), PERIPH_B, 0); /* MDC */ | ||
870 | select_peripheral(PD(2), PERIPH_B, 0); /* MDIO */ | ||
871 | |||
872 | if (!data->is_rmii) { | ||
873 | select_peripheral(PC(19), PERIPH_B, 0); /* COL */ | ||
874 | select_peripheral(PC(23), PERIPH_B, 0); /* CRS */ | ||
875 | select_peripheral(PC(26), PERIPH_B, 0); /* TXER */ | ||
876 | select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */ | ||
877 | select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */ | ||
878 | select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */ | ||
879 | select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */ | ||
880 | select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */ | ||
881 | select_peripheral(PD(15), PERIPH_B, 0); /* SPD */ | ||
882 | } | ||
883 | break; | ||
884 | |||
885 | default: | ||
886 | return NULL; | ||
887 | } | ||
888 | |||
889 | memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data)); | ||
890 | platform_device_register(pdev); | ||
891 | |||
892 | return pdev; | ||
893 | } | ||
894 | #endif | ||
895 | |||
896 | /* -------------------------------------------------------------------- | ||
897 | * SPI | ||
898 | * -------------------------------------------------------------------- */ | ||
899 | static struct resource atmel_spi0_resource[] = { | ||
900 | PBMEM(0xffe00000), | ||
901 | IRQ(3), | ||
902 | }; | ||
903 | DEFINE_DEV(atmel_spi, 0); | ||
904 | DEV_CLK(spi_clk, atmel_spi0, pba, 0); | ||
905 | |||
906 | static struct resource atmel_spi1_resource[] = { | ||
907 | PBMEM(0xffe00400), | ||
908 | IRQ(4), | ||
909 | }; | ||
910 | DEFINE_DEV(atmel_spi, 1); | ||
911 | DEV_CLK(spi_clk, atmel_spi1, pba, 1); | ||
912 | |||
913 | static void __init | ||
914 | at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, | ||
915 | unsigned int n, const u8 *pins) | ||
916 | { | ||
917 | unsigned int pin, mode; | ||
918 | |||
919 | for (; n; n--, b++) { | ||
920 | b->bus_num = bus_num; | ||
921 | if (b->chip_select >= 4) | ||
922 | continue; | ||
923 | pin = (unsigned)b->controller_data; | ||
924 | if (!pin) { | ||
925 | pin = pins[b->chip_select]; | ||
926 | b->controller_data = (void *)pin; | ||
927 | } | ||
928 | mode = AT32_GPIOF_OUTPUT; | ||
929 | if (!(b->mode & SPI_CS_HIGH)) | ||
930 | mode |= AT32_GPIOF_HIGH; | ||
931 | at32_select_gpio(pin, mode); | ||
932 | } | ||
933 | } | ||
934 | |||
935 | struct platform_device *__init | ||
936 | at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) | ||
937 | { | ||
938 | /* | ||
939 | * Manage the chipselects as GPIOs, normally using the same pins | ||
940 | * the SPI controller expects; but boards can use other pins. | ||
941 | */ | ||
942 | static u8 __initdata spi0_pins[] = | ||
943 | { GPIO_PIN_PA(3), GPIO_PIN_PA(4), | ||
944 | GPIO_PIN_PA(5), GPIO_PIN_PA(20), }; | ||
945 | static u8 __initdata spi1_pins[] = | ||
946 | { GPIO_PIN_PB(2), GPIO_PIN_PB(3), | ||
947 | GPIO_PIN_PB(4), GPIO_PIN_PA(27), }; | ||
948 | struct platform_device *pdev; | ||
949 | |||
950 | switch (id) { | ||
951 | case 0: | ||
952 | pdev = &atmel_spi0_device; | ||
953 | select_peripheral(PA(0), PERIPH_A, 0); /* MISO */ | ||
954 | select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ | ||
955 | select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ | ||
956 | at32_spi_setup_slaves(0, b, n, spi0_pins); | ||
957 | break; | ||
958 | |||
959 | case 1: | ||
960 | pdev = &atmel_spi1_device; | ||
961 | select_peripheral(PB(0), PERIPH_B, 0); /* MISO */ | ||
962 | select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ | ||
963 | select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ | ||
964 | at32_spi_setup_slaves(1, b, n, spi1_pins); | ||
965 | break; | ||
966 | |||
967 | default: | ||
968 | return NULL; | ||
969 | } | ||
970 | |||
971 | spi_register_board_info(b, n); | ||
972 | platform_device_register(pdev); | ||
973 | return pdev; | ||
974 | } | ||
975 | |||
976 | /* -------------------------------------------------------------------- | ||
977 | * TWI | ||
978 | * -------------------------------------------------------------------- */ | ||
979 | static struct resource atmel_twi0_resource[] __initdata = { | ||
980 | PBMEM(0xffe00800), | ||
981 | IRQ(5), | ||
982 | }; | ||
983 | static struct clk atmel_twi0_pclk = { | ||
984 | .name = "twi_pclk", | ||
985 | .parent = &pba_clk, | ||
986 | .mode = pba_clk_mode, | ||
987 | .get_rate = pba_clk_get_rate, | ||
988 | .index = 2, | ||
989 | }; | ||
990 | |||
991 | struct platform_device *__init at32_add_device_twi(unsigned int id) | ||
992 | { | ||
993 | struct platform_device *pdev; | ||
994 | |||
995 | if (id != 0) | ||
996 | return NULL; | ||
997 | |||
998 | pdev = platform_device_alloc("atmel_twi", id); | ||
999 | if (!pdev) | ||
1000 | return NULL; | ||
1001 | |||
1002 | if (platform_device_add_resources(pdev, atmel_twi0_resource, | ||
1003 | ARRAY_SIZE(atmel_twi0_resource))) | ||
1004 | goto err_add_resources; | ||
1005 | |||
1006 | select_peripheral(PA(6), PERIPH_A, 0); /* SDA */ | ||
1007 | select_peripheral(PA(7), PERIPH_A, 0); /* SDL */ | ||
1008 | |||
1009 | atmel_twi0_pclk.dev = &pdev->dev; | ||
1010 | |||
1011 | platform_device_add(pdev); | ||
1012 | return pdev; | ||
1013 | |||
1014 | err_add_resources: | ||
1015 | platform_device_put(pdev); | ||
1016 | return NULL; | ||
1017 | } | ||
1018 | |||
1019 | /* -------------------------------------------------------------------- | ||
1020 | * MMC | ||
1021 | * -------------------------------------------------------------------- */ | ||
1022 | static struct resource atmel_mci0_resource[] __initdata = { | ||
1023 | PBMEM(0xfff02400), | ||
1024 | IRQ(28), | ||
1025 | }; | ||
1026 | static struct clk atmel_mci0_pclk = { | ||
1027 | .name = "mci_clk", | ||
1028 | .parent = &pbb_clk, | ||
1029 | .mode = pbb_clk_mode, | ||
1030 | .get_rate = pbb_clk_get_rate, | ||
1031 | .index = 9, | ||
1032 | }; | ||
1033 | |||
1034 | struct platform_device *__init at32_add_device_mci(unsigned int id) | ||
1035 | { | ||
1036 | struct platform_device *pdev; | ||
1037 | |||
1038 | if (id != 0) | ||
1039 | return NULL; | ||
1040 | |||
1041 | pdev = platform_device_alloc("atmel_mci", id); | ||
1042 | if (!pdev) | ||
1043 | return NULL; | ||
1044 | |||
1045 | if (platform_device_add_resources(pdev, atmel_mci0_resource, | ||
1046 | ARRAY_SIZE(atmel_mci0_resource))) | ||
1047 | goto err_add_resources; | ||
1048 | |||
1049 | select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ | ||
1050 | select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ | ||
1051 | select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */ | ||
1052 | select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ | ||
1053 | select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ | ||
1054 | select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ | ||
1055 | |||
1056 | atmel_mci0_pclk.dev = &pdev->dev; | ||
1057 | |||
1058 | platform_device_add(pdev); | ||
1059 | return pdev; | ||
1060 | |||
1061 | err_add_resources: | ||
1062 | platform_device_put(pdev); | ||
1063 | return NULL; | ||
1064 | } | ||
1065 | |||
1066 | /* -------------------------------------------------------------------- | ||
1067 | * LCDC | ||
1068 | * -------------------------------------------------------------------- */ | ||
1069 | #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002) | ||
1070 | static struct atmel_lcdfb_info atmel_lcdfb0_data; | ||
1071 | static struct resource atmel_lcdfb0_resource[] = { | ||
1072 | { | ||
1073 | .start = 0xff000000, | ||
1074 | .end = 0xff000fff, | ||
1075 | .flags = IORESOURCE_MEM, | ||
1076 | }, | ||
1077 | IRQ(1), | ||
1078 | { | ||
1079 | /* Placeholder for pre-allocated fb memory */ | ||
1080 | .start = 0x00000000, | ||
1081 | .end = 0x00000000, | ||
1082 | .flags = 0, | ||
1083 | }, | ||
1084 | }; | ||
1085 | DEFINE_DEV_DATA(atmel_lcdfb, 0); | ||
1086 | DEV_CLK(hck1, atmel_lcdfb0, hsb, 7); | ||
1087 | static struct clk atmel_lcdfb0_pixclk = { | ||
1088 | .name = "lcdc_clk", | ||
1089 | .dev = &atmel_lcdfb0_device.dev, | ||
1090 | .mode = genclk_mode, | ||
1091 | .get_rate = genclk_get_rate, | ||
1092 | .set_rate = genclk_set_rate, | ||
1093 | .set_parent = genclk_set_parent, | ||
1094 | .index = 7, | ||
1095 | }; | ||
1096 | |||
1097 | struct platform_device *__init | ||
1098 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, | ||
1099 | unsigned long fbmem_start, unsigned long fbmem_len) | ||
1100 | { | ||
1101 | struct platform_device *pdev; | ||
1102 | struct atmel_lcdfb_info *info; | ||
1103 | struct fb_monspecs *monspecs; | ||
1104 | struct fb_videomode *modedb; | ||
1105 | unsigned int modedb_size; | ||
1106 | |||
1107 | /* | ||
1108 | * Do a deep copy of the fb data, monspecs and modedb. Make | ||
1109 | * sure all allocations are done before setting up the | ||
1110 | * portmux. | ||
1111 | */ | ||
1112 | monspecs = kmemdup(data->default_monspecs, | ||
1113 | sizeof(struct fb_monspecs), GFP_KERNEL); | ||
1114 | if (!monspecs) | ||
1115 | return NULL; | ||
1116 | |||
1117 | modedb_size = sizeof(struct fb_videomode) * monspecs->modedb_len; | ||
1118 | modedb = kmemdup(monspecs->modedb, modedb_size, GFP_KERNEL); | ||
1119 | if (!modedb) | ||
1120 | goto err_dup_modedb; | ||
1121 | monspecs->modedb = modedb; | ||
1122 | |||
1123 | switch (id) { | ||
1124 | case 0: | ||
1125 | pdev = &atmel_lcdfb0_device; | ||
1126 | select_peripheral(PC(19), PERIPH_A, 0); /* CC */ | ||
1127 | select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ | ||
1128 | select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ | ||
1129 | select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */ | ||
1130 | select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */ | ||
1131 | select_peripheral(PC(24), PERIPH_A, 0); /* MODE */ | ||
1132 | select_peripheral(PC(25), PERIPH_A, 0); /* PWR */ | ||
1133 | select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */ | ||
1134 | select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */ | ||
1135 | select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */ | ||
1136 | select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */ | ||
1137 | select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */ | ||
1138 | select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */ | ||
1139 | select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */ | ||
1140 | select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */ | ||
1141 | select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */ | ||
1142 | select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */ | ||
1143 | select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */ | ||
1144 | select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */ | ||
1145 | select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */ | ||
1146 | select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */ | ||
1147 | select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */ | ||
1148 | select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */ | ||
1149 | select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */ | ||
1150 | select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */ | ||
1151 | select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */ | ||
1152 | select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */ | ||
1153 | select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */ | ||
1154 | select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */ | ||
1155 | select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ | ||
1156 | select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ | ||
1157 | |||
1158 | clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); | ||
1159 | clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); | ||
1160 | break; | ||
1161 | |||
1162 | default: | ||
1163 | goto err_invalid_id; | ||
1164 | } | ||
1165 | |||
1166 | if (fbmem_len) { | ||
1167 | pdev->resource[2].start = fbmem_start; | ||
1168 | pdev->resource[2].end = fbmem_start + fbmem_len - 1; | ||
1169 | pdev->resource[2].flags = IORESOURCE_MEM; | ||
1170 | } | ||
1171 | |||
1172 | info = pdev->dev.platform_data; | ||
1173 | memcpy(info, data, sizeof(struct atmel_lcdfb_info)); | ||
1174 | info->default_monspecs = monspecs; | ||
1175 | |||
1176 | platform_device_register(pdev); | ||
1177 | return pdev; | ||
1178 | |||
1179 | err_invalid_id: | ||
1180 | kfree(modedb); | ||
1181 | err_dup_modedb: | ||
1182 | kfree(monspecs); | ||
1183 | return NULL; | ||
1184 | } | ||
1185 | #endif | ||
1186 | |||
1187 | /* -------------------------------------------------------------------- | ||
1188 | * SSC | ||
1189 | * -------------------------------------------------------------------- */ | ||
1190 | static struct resource ssc0_resource[] = { | ||
1191 | PBMEM(0xffe01c00), | ||
1192 | IRQ(10), | ||
1193 | }; | ||
1194 | DEFINE_DEV(ssc, 0); | ||
1195 | DEV_CLK(pclk, ssc0, pba, 7); | ||
1196 | |||
1197 | static struct resource ssc1_resource[] = { | ||
1198 | PBMEM(0xffe02000), | ||
1199 | IRQ(11), | ||
1200 | }; | ||
1201 | DEFINE_DEV(ssc, 1); | ||
1202 | DEV_CLK(pclk, ssc1, pba, 8); | ||
1203 | |||
1204 | static struct resource ssc2_resource[] = { | ||
1205 | PBMEM(0xffe02400), | ||
1206 | IRQ(12), | ||
1207 | }; | ||
1208 | DEFINE_DEV(ssc, 2); | ||
1209 | DEV_CLK(pclk, ssc2, pba, 9); | ||
1210 | |||
1211 | struct platform_device *__init | ||
1212 | at32_add_device_ssc(unsigned int id, unsigned int flags) | ||
1213 | { | ||
1214 | struct platform_device *pdev; | ||
1215 | |||
1216 | switch (id) { | ||
1217 | case 0: | ||
1218 | pdev = &ssc0_device; | ||
1219 | if (flags & ATMEL_SSC_RF) | ||
1220 | select_peripheral(PA(21), PERIPH_A, 0); /* RF */ | ||
1221 | if (flags & ATMEL_SSC_RK) | ||
1222 | select_peripheral(PA(22), PERIPH_A, 0); /* RK */ | ||
1223 | if (flags & ATMEL_SSC_TK) | ||
1224 | select_peripheral(PA(23), PERIPH_A, 0); /* TK */ | ||
1225 | if (flags & ATMEL_SSC_TF) | ||
1226 | select_peripheral(PA(24), PERIPH_A, 0); /* TF */ | ||
1227 | if (flags & ATMEL_SSC_TD) | ||
1228 | select_peripheral(PA(25), PERIPH_A, 0); /* TD */ | ||
1229 | if (flags & ATMEL_SSC_RD) | ||
1230 | select_peripheral(PA(26), PERIPH_A, 0); /* RD */ | ||
1231 | break; | ||
1232 | case 1: | ||
1233 | pdev = &ssc1_device; | ||
1234 | if (flags & ATMEL_SSC_RF) | ||
1235 | select_peripheral(PA(0), PERIPH_B, 0); /* RF */ | ||
1236 | if (flags & ATMEL_SSC_RK) | ||
1237 | select_peripheral(PA(1), PERIPH_B, 0); /* RK */ | ||
1238 | if (flags & ATMEL_SSC_TK) | ||
1239 | select_peripheral(PA(2), PERIPH_B, 0); /* TK */ | ||
1240 | if (flags & ATMEL_SSC_TF) | ||
1241 | select_peripheral(PA(3), PERIPH_B, 0); /* TF */ | ||
1242 | if (flags & ATMEL_SSC_TD) | ||
1243 | select_peripheral(PA(4), PERIPH_B, 0); /* TD */ | ||
1244 | if (flags & ATMEL_SSC_RD) | ||
1245 | select_peripheral(PA(5), PERIPH_B, 0); /* RD */ | ||
1246 | break; | ||
1247 | case 2: | ||
1248 | pdev = &ssc2_device; | ||
1249 | if (flags & ATMEL_SSC_TD) | ||
1250 | select_peripheral(PB(13), PERIPH_A, 0); /* TD */ | ||
1251 | if (flags & ATMEL_SSC_RD) | ||
1252 | select_peripheral(PB(14), PERIPH_A, 0); /* RD */ | ||
1253 | if (flags & ATMEL_SSC_TK) | ||
1254 | select_peripheral(PB(15), PERIPH_A, 0); /* TK */ | ||
1255 | if (flags & ATMEL_SSC_TF) | ||
1256 | select_peripheral(PB(16), PERIPH_A, 0); /* TF */ | ||
1257 | if (flags & ATMEL_SSC_RF) | ||
1258 | select_peripheral(PB(17), PERIPH_A, 0); /* RF */ | ||
1259 | if (flags & ATMEL_SSC_RK) | ||
1260 | select_peripheral(PB(18), PERIPH_A, 0); /* RK */ | ||
1261 | break; | ||
1262 | default: | ||
1263 | return NULL; | ||
1264 | } | ||
1265 | |||
1266 | platform_device_register(pdev); | ||
1267 | return pdev; | ||
1268 | } | ||
1269 | |||
1270 | /* -------------------------------------------------------------------- | ||
1271 | * USB Device Controller | ||
1272 | * -------------------------------------------------------------------- */ | ||
1273 | static struct resource usba0_resource[] __initdata = { | ||
1274 | { | ||
1275 | .start = 0xff300000, | ||
1276 | .end = 0xff3fffff, | ||
1277 | .flags = IORESOURCE_MEM, | ||
1278 | }, { | ||
1279 | .start = 0xfff03000, | ||
1280 | .end = 0xfff033ff, | ||
1281 | .flags = IORESOURCE_MEM, | ||
1282 | }, | ||
1283 | IRQ(31), | ||
1284 | }; | ||
1285 | static struct clk usba0_pclk = { | ||
1286 | .name = "pclk", | ||
1287 | .parent = &pbb_clk, | ||
1288 | .mode = pbb_clk_mode, | ||
1289 | .get_rate = pbb_clk_get_rate, | ||
1290 | .index = 12, | ||
1291 | }; | ||
1292 | static struct clk usba0_hclk = { | ||
1293 | .name = "hclk", | ||
1294 | .parent = &hsb_clk, | ||
1295 | .mode = hsb_clk_mode, | ||
1296 | .get_rate = hsb_clk_get_rate, | ||
1297 | .index = 6, | ||
1298 | }; | ||
1299 | |||
1300 | struct platform_device *__init | ||
1301 | at32_add_device_usba(unsigned int id, struct usba_platform_data *data) | ||
1302 | { | ||
1303 | struct platform_device *pdev; | ||
1304 | |||
1305 | if (id != 0) | ||
1306 | return NULL; | ||
1307 | |||
1308 | pdev = platform_device_alloc("atmel_usba_udc", 0); | ||
1309 | if (!pdev) | ||
1310 | return NULL; | ||
1311 | |||
1312 | if (platform_device_add_resources(pdev, usba0_resource, | ||
1313 | ARRAY_SIZE(usba0_resource))) | ||
1314 | goto out_free_pdev; | ||
1315 | |||
1316 | if (data) { | ||
1317 | if (platform_device_add_data(pdev, data, sizeof(*data))) | ||
1318 | goto out_free_pdev; | ||
1319 | |||
1320 | if (data->vbus_pin != GPIO_PIN_NONE) | ||
1321 | at32_select_gpio(data->vbus_pin, 0); | ||
1322 | } | ||
1323 | |||
1324 | usba0_pclk.dev = &pdev->dev; | ||
1325 | usba0_hclk.dev = &pdev->dev; | ||
1326 | |||
1327 | platform_device_add(pdev); | ||
1328 | |||
1329 | return pdev; | ||
1330 | |||
1331 | out_free_pdev: | ||
1332 | platform_device_put(pdev); | ||
1333 | return NULL; | ||
1334 | } | ||
1335 | |||
1336 | /* -------------------------------------------------------------------- | ||
1337 | * IDE / CompactFlash | ||
1338 | * -------------------------------------------------------------------- */ | ||
1339 | #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7001) | ||
1340 | static struct resource at32_smc_cs4_resource[] __initdata = { | ||
1341 | { | ||
1342 | .start = 0x04000000, | ||
1343 | .end = 0x07ffffff, | ||
1344 | .flags = IORESOURCE_MEM, | ||
1345 | }, | ||
1346 | IRQ(~0UL), /* Magic IRQ will be overridden */ | ||
1347 | }; | ||
1348 | static struct resource at32_smc_cs5_resource[] __initdata = { | ||
1349 | { | ||
1350 | .start = 0x20000000, | ||
1351 | .end = 0x23ffffff, | ||
1352 | .flags = IORESOURCE_MEM, | ||
1353 | }, | ||
1354 | IRQ(~0UL), /* Magic IRQ will be overridden */ | ||
1355 | }; | ||
1356 | |||
1357 | static int __init at32_init_ide_or_cf(struct platform_device *pdev, | ||
1358 | unsigned int cs, unsigned int extint) | ||
1359 | { | ||
1360 | static unsigned int extint_pin_map[4] __initdata = { | ||
1361 | GPIO_PIN_PB(25), | ||
1362 | GPIO_PIN_PB(26), | ||
1363 | GPIO_PIN_PB(27), | ||
1364 | GPIO_PIN_PB(28), | ||
1365 | }; | ||
1366 | static bool common_pins_initialized __initdata = false; | ||
1367 | unsigned int extint_pin; | ||
1368 | int ret; | ||
1369 | |||
1370 | if (extint >= ARRAY_SIZE(extint_pin_map)) | ||
1371 | return -EINVAL; | ||
1372 | extint_pin = extint_pin_map[extint]; | ||
1373 | |||
1374 | switch (cs) { | ||
1375 | case 4: | ||
1376 | ret = platform_device_add_resources(pdev, | ||
1377 | at32_smc_cs4_resource, | ||
1378 | ARRAY_SIZE(at32_smc_cs4_resource)); | ||
1379 | if (ret) | ||
1380 | return ret; | ||
1381 | |||
1382 | select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */ | ||
1383 | set_ebi_sfr_bits(HMATRIX_BIT(CS4A)); | ||
1384 | break; | ||
1385 | case 5: | ||
1386 | ret = platform_device_add_resources(pdev, | ||
1387 | at32_smc_cs5_resource, | ||
1388 | ARRAY_SIZE(at32_smc_cs5_resource)); | ||
1389 | if (ret) | ||
1390 | return ret; | ||
1391 | |||
1392 | select_peripheral(PE(22), PERIPH_A, 0); /* NCS5 -> OE_N */ | ||
1393 | set_ebi_sfr_bits(HMATRIX_BIT(CS5A)); | ||
1394 | break; | ||
1395 | default: | ||
1396 | return -EINVAL; | ||
1397 | } | ||
1398 | |||
1399 | if (!common_pins_initialized) { | ||
1400 | select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */ | ||
1401 | select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */ | ||
1402 | select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */ | ||
1403 | select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */ | ||
1404 | common_pins_initialized = true; | ||
1405 | } | ||
1406 | |||
1407 | at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); | ||
1408 | |||
1409 | pdev->resource[1].start = EIM_IRQ_BASE + extint; | ||
1410 | pdev->resource[1].end = pdev->resource[1].start; | ||
1411 | |||
1412 | return 0; | ||
1413 | } | ||
1414 | |||
1415 | struct platform_device *__init | ||
1416 | at32_add_device_ide(unsigned int id, unsigned int extint, | ||
1417 | struct ide_platform_data *data) | ||
1418 | { | ||
1419 | struct platform_device *pdev; | ||
1420 | |||
1421 | pdev = platform_device_alloc("at32_ide", id); | ||
1422 | if (!pdev) | ||
1423 | goto fail; | ||
1424 | |||
1425 | if (platform_device_add_data(pdev, data, | ||
1426 | sizeof(struct ide_platform_data))) | ||
1427 | goto fail; | ||
1428 | |||
1429 | if (at32_init_ide_or_cf(pdev, data->cs, extint)) | ||
1430 | goto fail; | ||
1431 | |||
1432 | platform_device_add(pdev); | ||
1433 | return pdev; | ||
1434 | |||
1435 | fail: | ||
1436 | platform_device_put(pdev); | ||
1437 | return NULL; | ||
1438 | } | ||
1439 | |||
1440 | struct platform_device *__init | ||
1441 | at32_add_device_cf(unsigned int id, unsigned int extint, | ||
1442 | struct cf_platform_data *data) | ||
1443 | { | ||
1444 | struct platform_device *pdev; | ||
1445 | |||
1446 | pdev = platform_device_alloc("at32_cf", id); | ||
1447 | if (!pdev) | ||
1448 | goto fail; | ||
1449 | |||
1450 | if (platform_device_add_data(pdev, data, | ||
1451 | sizeof(struct cf_platform_data))) | ||
1452 | goto fail; | ||
1453 | |||
1454 | if (at32_init_ide_or_cf(pdev, data->cs, extint)) | ||
1455 | goto fail; | ||
1456 | |||
1457 | if (data->detect_pin != GPIO_PIN_NONE) | ||
1458 | at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH); | ||
1459 | if (data->reset_pin != GPIO_PIN_NONE) | ||
1460 | at32_select_gpio(data->reset_pin, 0); | ||
1461 | if (data->vcc_pin != GPIO_PIN_NONE) | ||
1462 | at32_select_gpio(data->vcc_pin, 0); | ||
1463 | /* READY is used as extint, so we can't select it as gpio */ | ||
1464 | |||
1465 | platform_device_add(pdev); | ||
1466 | return pdev; | ||
1467 | |||
1468 | fail: | ||
1469 | platform_device_put(pdev); | ||
1470 | return NULL; | ||
1471 | } | ||
1472 | #endif | ||
1473 | |||
1474 | /* -------------------------------------------------------------------- | ||
1475 | * AC97C | ||
1476 | * -------------------------------------------------------------------- */ | ||
1477 | static struct resource atmel_ac97c0_resource[] __initdata = { | ||
1478 | PBMEM(0xfff02800), | ||
1479 | IRQ(29), | ||
1480 | }; | ||
1481 | static struct clk atmel_ac97c0_pclk = { | ||
1482 | .name = "pclk", | ||
1483 | .parent = &pbb_clk, | ||
1484 | .mode = pbb_clk_mode, | ||
1485 | .get_rate = pbb_clk_get_rate, | ||
1486 | .index = 10, | ||
1487 | }; | ||
1488 | |||
1489 | struct platform_device *__init at32_add_device_ac97c(unsigned int id) | ||
1490 | { | ||
1491 | struct platform_device *pdev; | ||
1492 | |||
1493 | if (id != 0) | ||
1494 | return NULL; | ||
1495 | |||
1496 | pdev = platform_device_alloc("atmel_ac97c", id); | ||
1497 | if (!pdev) | ||
1498 | return NULL; | ||
1499 | |||
1500 | if (platform_device_add_resources(pdev, atmel_ac97c0_resource, | ||
1501 | ARRAY_SIZE(atmel_ac97c0_resource))) | ||
1502 | goto err_add_resources; | ||
1503 | |||
1504 | select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */ | ||
1505 | select_peripheral(PB(21), PERIPH_B, 0); /* SDO */ | ||
1506 | select_peripheral(PB(22), PERIPH_B, 0); /* SDI */ | ||
1507 | select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */ | ||
1508 | |||
1509 | atmel_ac97c0_pclk.dev = &pdev->dev; | ||
1510 | |||
1511 | platform_device_add(pdev); | ||
1512 | return pdev; | ||
1513 | |||
1514 | err_add_resources: | ||
1515 | platform_device_put(pdev); | ||
1516 | return NULL; | ||
1517 | } | ||
1518 | |||
1519 | /* -------------------------------------------------------------------- | ||
1520 | * ABDAC | ||
1521 | * -------------------------------------------------------------------- */ | ||
1522 | static struct resource abdac0_resource[] __initdata = { | ||
1523 | PBMEM(0xfff02000), | ||
1524 | IRQ(27), | ||
1525 | }; | ||
1526 | static struct clk abdac0_pclk = { | ||
1527 | .name = "pclk", | ||
1528 | .parent = &pbb_clk, | ||
1529 | .mode = pbb_clk_mode, | ||
1530 | .get_rate = pbb_clk_get_rate, | ||
1531 | .index = 8, | ||
1532 | }; | ||
1533 | static struct clk abdac0_sample_clk = { | ||
1534 | .name = "sample_clk", | ||
1535 | .mode = genclk_mode, | ||
1536 | .get_rate = genclk_get_rate, | ||
1537 | .set_rate = genclk_set_rate, | ||
1538 | .set_parent = genclk_set_parent, | ||
1539 | .index = 6, | ||
1540 | }; | ||
1541 | |||
1542 | struct platform_device *__init at32_add_device_abdac(unsigned int id) | ||
1543 | { | ||
1544 | struct platform_device *pdev; | ||
1545 | |||
1546 | if (id != 0) | ||
1547 | return NULL; | ||
1548 | |||
1549 | pdev = platform_device_alloc("abdac", id); | ||
1550 | if (!pdev) | ||
1551 | return NULL; | ||
1552 | |||
1553 | if (platform_device_add_resources(pdev, abdac0_resource, | ||
1554 | ARRAY_SIZE(abdac0_resource))) | ||
1555 | goto err_add_resources; | ||
1556 | |||
1557 | select_peripheral(PB(20), PERIPH_A, 0); /* DATA1 */ | ||
1558 | select_peripheral(PB(21), PERIPH_A, 0); /* DATA0 */ | ||
1559 | select_peripheral(PB(22), PERIPH_A, 0); /* DATAN1 */ | ||
1560 | select_peripheral(PB(23), PERIPH_A, 0); /* DATAN0 */ | ||
1561 | |||
1562 | abdac0_pclk.dev = &pdev->dev; | ||
1563 | abdac0_sample_clk.dev = &pdev->dev; | ||
1564 | |||
1565 | platform_device_add(pdev); | ||
1566 | return pdev; | ||
1567 | |||
1568 | err_add_resources: | ||
1569 | platform_device_put(pdev); | ||
1570 | return NULL; | ||
1571 | } | ||
1572 | |||
1573 | /* -------------------------------------------------------------------- | ||
1574 | * GCLK | ||
1575 | * -------------------------------------------------------------------- */ | ||
1576 | static struct clk gclk0 = { | ||
1577 | .name = "gclk0", | ||
1578 | .mode = genclk_mode, | ||
1579 | .get_rate = genclk_get_rate, | ||
1580 | .set_rate = genclk_set_rate, | ||
1581 | .set_parent = genclk_set_parent, | ||
1582 | .index = 0, | ||
1583 | }; | ||
1584 | static struct clk gclk1 = { | ||
1585 | .name = "gclk1", | ||
1586 | .mode = genclk_mode, | ||
1587 | .get_rate = genclk_get_rate, | ||
1588 | .set_rate = genclk_set_rate, | ||
1589 | .set_parent = genclk_set_parent, | ||
1590 | .index = 1, | ||
1591 | }; | ||
1592 | static struct clk gclk2 = { | ||
1593 | .name = "gclk2", | ||
1594 | .mode = genclk_mode, | ||
1595 | .get_rate = genclk_get_rate, | ||
1596 | .set_rate = genclk_set_rate, | ||
1597 | .set_parent = genclk_set_parent, | ||
1598 | .index = 2, | ||
1599 | }; | ||
1600 | static struct clk gclk3 = { | ||
1601 | .name = "gclk3", | ||
1602 | .mode = genclk_mode, | ||
1603 | .get_rate = genclk_get_rate, | ||
1604 | .set_rate = genclk_set_rate, | ||
1605 | .set_parent = genclk_set_parent, | ||
1606 | .index = 3, | ||
1607 | }; | ||
1608 | static struct clk gclk4 = { | ||
1609 | .name = "gclk4", | ||
1610 | .mode = genclk_mode, | ||
1611 | .get_rate = genclk_get_rate, | ||
1612 | .set_rate = genclk_set_rate, | ||
1613 | .set_parent = genclk_set_parent, | ||
1614 | .index = 4, | ||
1615 | }; | ||
1616 | |||
1617 | struct clk *at32_clock_list[] = { | ||
1618 | &osc32k, | ||
1619 | &osc0, | ||
1620 | &osc1, | ||
1621 | &pll0, | ||
1622 | &pll1, | ||
1623 | &cpu_clk, | ||
1624 | &hsb_clk, | ||
1625 | &pba_clk, | ||
1626 | &pbb_clk, | ||
1627 | &at32_pm_pclk, | ||
1628 | &at32_intc0_pclk, | ||
1629 | &hmatrix_clk, | ||
1630 | &ebi_clk, | ||
1631 | &hramc_clk, | ||
1632 | &smc0_pclk, | ||
1633 | &smc0_mck, | ||
1634 | &pdc_hclk, | ||
1635 | &pdc_pclk, | ||
1636 | &dmaca0_hclk, | ||
1637 | &pico_clk, | ||
1638 | &pio0_mck, | ||
1639 | &pio1_mck, | ||
1640 | &pio2_mck, | ||
1641 | &pio3_mck, | ||
1642 | &pio4_mck, | ||
1643 | &at32_systc0_pclk, | ||
1644 | &atmel_usart0_usart, | ||
1645 | &atmel_usart1_usart, | ||
1646 | &atmel_usart2_usart, | ||
1647 | &atmel_usart3_usart, | ||
1648 | #if defined(CONFIG_CPU_AT32AP7000) | ||
1649 | &macb0_hclk, | ||
1650 | &macb0_pclk, | ||
1651 | &macb1_hclk, | ||
1652 | &macb1_pclk, | ||
1653 | #endif | ||
1654 | &atmel_spi0_spi_clk, | ||
1655 | &atmel_spi1_spi_clk, | ||
1656 | &atmel_twi0_pclk, | ||
1657 | &atmel_mci0_pclk, | ||
1658 | #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002) | ||
1659 | &atmel_lcdfb0_hck1, | ||
1660 | &atmel_lcdfb0_pixclk, | ||
1661 | #endif | ||
1662 | &ssc0_pclk, | ||
1663 | &ssc1_pclk, | ||
1664 | &ssc2_pclk, | ||
1665 | &usba0_hclk, | ||
1666 | &usba0_pclk, | ||
1667 | &atmel_ac97c0_pclk, | ||
1668 | &abdac0_pclk, | ||
1669 | &abdac0_sample_clk, | ||
1670 | &gclk0, | ||
1671 | &gclk1, | ||
1672 | &gclk2, | ||
1673 | &gclk3, | ||
1674 | &gclk4, | ||
1675 | }; | ||
1676 | unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); | ||
1677 | |||
1678 | void __init at32_portmux_init(void) | ||
1679 | { | ||
1680 | at32_init_pio(&pio0_device); | ||
1681 | at32_init_pio(&pio1_device); | ||
1682 | at32_init_pio(&pio2_device); | ||
1683 | at32_init_pio(&pio3_device); | ||
1684 | at32_init_pio(&pio4_device); | ||
1685 | } | ||
1686 | |||
1687 | void __init at32_clock_init(void) | ||
1688 | { | ||
1689 | u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; | ||
1690 | int i; | ||
1691 | |||
1692 | if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) { | ||
1693 | main_clock = &pll0; | ||
1694 | cpu_clk.parent = &pll0; | ||
1695 | } else { | ||
1696 | main_clock = &osc0; | ||
1697 | cpu_clk.parent = &osc0; | ||
1698 | } | ||
1699 | |||
1700 | if (pm_readl(PLL0) & PM_BIT(PLLOSC)) | ||
1701 | pll0.parent = &osc1; | ||
1702 | if (pm_readl(PLL1) & PM_BIT(PLLOSC)) | ||
1703 | pll1.parent = &osc1; | ||
1704 | |||
1705 | genclk_init_parent(&gclk0); | ||
1706 | genclk_init_parent(&gclk1); | ||
1707 | genclk_init_parent(&gclk2); | ||
1708 | genclk_init_parent(&gclk3); | ||
1709 | genclk_init_parent(&gclk4); | ||
1710 | #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002) | ||
1711 | genclk_init_parent(&atmel_lcdfb0_pixclk); | ||
1712 | #endif | ||
1713 | genclk_init_parent(&abdac0_sample_clk); | ||
1714 | |||
1715 | /* | ||
1716 | * Turn on all clocks that have at least one user already, and | ||
1717 | * turn off everything else. We only do this for module | ||
1718 | * clocks, and even though it isn't particularly pretty to | ||
1719 | * check the address of the mode function, it should do the | ||
1720 | * trick... | ||
1721 | */ | ||
1722 | for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) { | ||
1723 | struct clk *clk = at32_clock_list[i]; | ||
1724 | |||
1725 | if (clk->users == 0) | ||
1726 | continue; | ||
1727 | |||
1728 | if (clk->mode == &cpu_clk_mode) | ||
1729 | cpu_mask |= 1 << clk->index; | ||
1730 | else if (clk->mode == &hsb_clk_mode) | ||
1731 | hsb_mask |= 1 << clk->index; | ||
1732 | else if (clk->mode == &pba_clk_mode) | ||
1733 | pba_mask |= 1 << clk->index; | ||
1734 | else if (clk->mode == &pbb_clk_mode) | ||
1735 | pbb_mask |= 1 << clk->index; | ||
1736 | } | ||
1737 | |||
1738 | pm_writel(CPU_MASK, cpu_mask); | ||
1739 | pm_writel(HSB_MASK, hsb_mask); | ||
1740 | pm_writel(PBA_MASK, pba_mask); | ||
1741 | pm_writel(PBB_MASK, pbb_mask); | ||
1742 | } | ||