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