blob: 1bc6389b20b062a180976e563d61ac00f52a3b4b [file] [log] [blame]
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001/*
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>
Hans-Christian Egtvedt35bf50c2007-12-19 09:29:19 +01009#include <linux/delay.h>
Haavard Skinnemoen3bfb1d22008-07-08 11:59:42 -070010#include <linux/dw_dmac.h>
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +010011#include <linux/fb.h>
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070012#include <linux/init.h>
13#include <linux/platform_device.h>
David Brownell6b84bbf2007-06-22 19:17:57 -070014#include <linux/dma-mapping.h>
David Brownell3c26e172008-07-27 02:34:45 -070015#include <linux/gpio.h>
Haavard Skinnemoen41d8ca42007-02-16 13:56:11 +010016#include <linux/spi/spi.h>
Stelian Pop8d855312008-03-05 00:00:00 +010017#include <linux/usb/atmel_usba_udc.h>
Nicolas Ferrec42aa772008-11-20 15:59:12 +010018#include <linux/atmel-mci.h>
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070019
20#include <asm/io.h>
Haavard Skinnemoene7ba1762007-10-10 14:58:29 +020021#include <asm/irq.h>
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070022
Haavard Skinnemoen3663b732008-08-05 13:57:38 +020023#include <mach/at32ap700x.h>
24#include <mach/board.h>
Haavard Skinnemoenb47eb402008-07-31 15:56:36 +020025#include <mach/hmatrix.h>
Haavard Skinnemoen3663b732008-08-05 13:57:38 +020026#include <mach/portmux.h>
27#include <mach/sram.h>
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070028
Hans-Christian Egtvedt6b0c9352009-03-24 13:59:22 +010029#include <sound/atmel-abdac.h>
30
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +010031#include <video/atmel_lcdc.h>
32
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070033#include "clock.h"
34#include "pio.h"
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +020035#include "pm.h"
36
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070037
38#define PBMEM(base) \
39 { \
40 .start = base, \
41 .end = base + 0x3ff, \
42 .flags = IORESOURCE_MEM, \
43 }
44#define IRQ(num) \
45 { \
46 .start = num, \
47 .end = num, \
48 .flags = IORESOURCE_IRQ, \
49 }
50#define NAMED_IRQ(num, _name) \
51 { \
52 .start = num, \
53 .end = num, \
54 .name = _name, \
55 .flags = IORESOURCE_IRQ, \
56 }
57
David Brownell6b84bbf2007-06-22 19:17:57 -070058/* REVISIT these assume *every* device supports DMA, but several
59 * don't ... tc, smc, pio, rtc, watchdog, pwm, ps2, and more.
60 */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070061#define DEFINE_DEV(_name, _id) \
David Brownell6b84bbf2007-06-22 19:17:57 -070062static u64 _name##_id##_dma_mask = DMA_32BIT_MASK; \
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070063static struct platform_device _name##_id##_device = { \
64 .name = #_name, \
65 .id = _id, \
66 .dev = { \
David Brownell6b84bbf2007-06-22 19:17:57 -070067 .dma_mask = &_name##_id##_dma_mask, \
68 .coherent_dma_mask = DMA_32BIT_MASK, \
69 }, \
70 .resource = _name##_id##_resource, \
71 .num_resources = ARRAY_SIZE(_name##_id##_resource), \
72}
73#define DEFINE_DEV_DATA(_name, _id) \
74static u64 _name##_id##_dma_mask = DMA_32BIT_MASK; \
75static struct platform_device _name##_id##_device = { \
76 .name = #_name, \
77 .id = _id, \
78 .dev = { \
79 .dma_mask = &_name##_id##_dma_mask, \
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070080 .platform_data = &_name##_id##_data, \
David Brownell6b84bbf2007-06-22 19:17:57 -070081 .coherent_dma_mask = DMA_32BIT_MASK, \
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070082 }, \
83 .resource = _name##_id##_resource, \
84 .num_resources = ARRAY_SIZE(_name##_id##_resource), \
85}
86
Julien Maycaf18f12008-09-24 10:30:47 +020087#define select_peripheral(port, pin_mask, periph, flags) \
88 at32_select_periph(GPIO_##port##_BASE, pin_mask, \
89 GPIO_##periph, flags)
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010090
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070091#define DEV_CLK(_name, devname, bus, _index) \
92static struct clk devname##_##_name = { \
93 .name = #_name, \
94 .dev = &devname##_device.dev, \
95 .parent = &bus##_clk, \
96 .mode = bus##_clk_mode, \
97 .get_rate = bus##_clk_get_rate, \
98 .index = _index, \
99}
100
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200101static DEFINE_SPINLOCK(pm_lock);
102
Hans-Christian Egtvedt35bf50c2007-12-19 09:29:19 +0100103static struct clk osc0;
104static struct clk osc1;
105
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700106static unsigned long osc_get_rate(struct clk *clk)
107{
Alex60ed7952008-03-17 14:55:06 +0100108 return at32_board_osc_rates[clk->index];
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700109}
110
111static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
112{
113 unsigned long div, mul, rate;
114
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200115 div = PM_BFEXT(PLLDIV, control) + 1;
116 mul = PM_BFEXT(PLLMUL, control) + 1;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700117
118 rate = clk->parent->get_rate(clk->parent);
119 rate = (rate + div / 2) / div;
120 rate *= mul;
121
122 return rate;
123}
124
Hans-Christian Egtvedt35bf50c2007-12-19 09:29:19 +0100125static long pll_set_rate(struct clk *clk, unsigned long rate,
126 u32 *pll_ctrl)
127{
128 unsigned long mul;
129 unsigned long mul_best_fit = 0;
130 unsigned long div;
131 unsigned long div_min;
132 unsigned long div_max;
133 unsigned long div_best_fit = 0;
134 unsigned long base;
135 unsigned long pll_in;
136 unsigned long actual = 0;
137 unsigned long rate_error;
138 unsigned long rate_error_prev = ~0UL;
139 u32 ctrl;
140
141 /* Rate must be between 80 MHz and 200 Mhz. */
142 if (rate < 80000000UL || rate > 200000000UL)
143 return -EINVAL;
144
145 ctrl = PM_BF(PLLOPT, 4);
146 base = clk->parent->get_rate(clk->parent);
147
148 /* PLL input frequency must be between 6 MHz and 32 MHz. */
149 div_min = DIV_ROUND_UP(base, 32000000UL);
150 div_max = base / 6000000UL;
151
152 if (div_max < div_min)
153 return -EINVAL;
154
155 for (div = div_min; div <= div_max; div++) {
156 pll_in = (base + div / 2) / div;
157 mul = (rate + pll_in / 2) / pll_in;
158
159 if (mul == 0)
160 continue;
161
162 actual = pll_in * mul;
163 rate_error = abs(actual - rate);
164
165 if (rate_error < rate_error_prev) {
166 mul_best_fit = mul;
167 div_best_fit = div;
168 rate_error_prev = rate_error;
169 }
170
171 if (rate_error == 0)
172 break;
173 }
174
175 if (div_best_fit == 0)
176 return -EINVAL;
177
178 ctrl |= PM_BF(PLLMUL, mul_best_fit - 1);
179 ctrl |= PM_BF(PLLDIV, div_best_fit - 1);
180 ctrl |= PM_BF(PLLCOUNT, 16);
181
182 if (clk->parent == &osc1)
183 ctrl |= PM_BIT(PLLOSC);
184
185 *pll_ctrl = ctrl;
186
187 return actual;
188}
189
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700190static unsigned long pll0_get_rate(struct clk *clk)
191{
192 u32 control;
193
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200194 control = pm_readl(PLL0);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700195
196 return pll_get_rate(clk, control);
197}
198
Hans-Christian Egtvedt35bf50c2007-12-19 09:29:19 +0100199static void pll1_mode(struct clk *clk, int enabled)
200{
201 unsigned long timeout;
202 u32 status;
203 u32 ctrl;
204
205 ctrl = pm_readl(PLL1);
206
207 if (enabled) {
208 if (!PM_BFEXT(PLLMUL, ctrl) && !PM_BFEXT(PLLDIV, ctrl)) {
209 pr_debug("clk %s: failed to enable, rate not set\n",
210 clk->name);
211 return;
212 }
213
214 ctrl |= PM_BIT(PLLEN);
215 pm_writel(PLL1, ctrl);
216
217 /* Wait for PLL lock. */
218 for (timeout = 10000; timeout; timeout--) {
219 status = pm_readl(ISR);
220 if (status & PM_BIT(LOCK1))
221 break;
222 udelay(10);
223 }
224
225 if (!(status & PM_BIT(LOCK1)))
226 printk(KERN_ERR "clk %s: timeout waiting for lock\n",
227 clk->name);
228 } else {
229 ctrl &= ~PM_BIT(PLLEN);
230 pm_writel(PLL1, ctrl);
231 }
232}
233
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700234static unsigned long pll1_get_rate(struct clk *clk)
235{
236 u32 control;
237
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200238 control = pm_readl(PLL1);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700239
240 return pll_get_rate(clk, control);
241}
242
Hans-Christian Egtvedt35bf50c2007-12-19 09:29:19 +0100243static long pll1_set_rate(struct clk *clk, unsigned long rate, int apply)
244{
245 u32 ctrl = 0;
246 unsigned long actual_rate;
247
248 actual_rate = pll_set_rate(clk, rate, &ctrl);
249
250 if (apply) {
251 if (actual_rate != rate)
252 return -EINVAL;
253 if (clk->users > 0)
254 return -EBUSY;
255 pr_debug(KERN_INFO "clk %s: new rate %lu (actual rate %lu)\n",
256 clk->name, rate, actual_rate);
257 pm_writel(PLL1, ctrl);
258 }
259
260 return actual_rate;
261}
262
263static int pll1_set_parent(struct clk *clk, struct clk *parent)
264{
265 u32 ctrl;
266
267 if (clk->users > 0)
268 return -EBUSY;
269
270 ctrl = pm_readl(PLL1);
271 WARN_ON(ctrl & PM_BIT(PLLEN));
272
273 if (parent == &osc0)
274 ctrl &= ~PM_BIT(PLLOSC);
275 else if (parent == &osc1)
276 ctrl |= PM_BIT(PLLOSC);
277 else
278 return -EINVAL;
279
280 pm_writel(PLL1, ctrl);
281 clk->parent = parent;
282
283 return 0;
284}
285
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700286/*
287 * The AT32AP7000 has five primary clock sources: One 32kHz
288 * oscillator, two crystal oscillators and two PLLs.
289 */
290static struct clk osc32k = {
291 .name = "osc32k",
292 .get_rate = osc_get_rate,
293 .users = 1,
294 .index = 0,
295};
296static struct clk osc0 = {
297 .name = "osc0",
298 .get_rate = osc_get_rate,
299 .users = 1,
300 .index = 1,
301};
302static struct clk osc1 = {
303 .name = "osc1",
304 .get_rate = osc_get_rate,
305 .index = 2,
306};
307static struct clk pll0 = {
308 .name = "pll0",
309 .get_rate = pll0_get_rate,
310 .parent = &osc0,
311};
312static struct clk pll1 = {
313 .name = "pll1",
Hans-Christian Egtvedt35bf50c2007-12-19 09:29:19 +0100314 .mode = pll1_mode,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700315 .get_rate = pll1_get_rate,
Hans-Christian Egtvedt35bf50c2007-12-19 09:29:19 +0100316 .set_rate = pll1_set_rate,
317 .set_parent = pll1_set_parent,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700318 .parent = &osc0,
319};
320
321/*
322 * The main clock can be either osc0 or pll0. The boot loader may
323 * have chosen one for us, so we don't really know which one until we
324 * have a look at the SM.
325 */
326static struct clk *main_clock;
327
328/*
329 * Synchronous clocks are generated from the main clock. The clocks
330 * must satisfy the constraint
331 * fCPU >= fHSB >= fPB
332 * i.e. each clock must not be faster than its parent.
333 */
334static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift)
335{
336 return main_clock->get_rate(main_clock) >> shift;
337};
338
339static void cpu_clk_mode(struct clk *clk, int enabled)
340{
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700341 unsigned long flags;
342 u32 mask;
343
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200344 spin_lock_irqsave(&pm_lock, flags);
345 mask = pm_readl(CPU_MASK);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700346 if (enabled)
347 mask |= 1 << clk->index;
348 else
349 mask &= ~(1 << clk->index);
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200350 pm_writel(CPU_MASK, mask);
351 spin_unlock_irqrestore(&pm_lock, flags);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700352}
353
354static unsigned long cpu_clk_get_rate(struct clk *clk)
355{
356 unsigned long cksel, shift = 0;
357
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200358 cksel = pm_readl(CKSEL);
359 if (cksel & PM_BIT(CPUDIV))
360 shift = PM_BFEXT(CPUSEL, cksel) + 1;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700361
362 return bus_clk_get_rate(clk, shift);
363}
364
Hans-Christian Egtvedt9e58e182007-06-04 16:10:57 +0200365static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply)
366{
367 u32 control;
368 unsigned long parent_rate, child_div, actual_rate, div;
369
370 parent_rate = clk->parent->get_rate(clk->parent);
371 control = pm_readl(CKSEL);
372
373 if (control & PM_BIT(HSBDIV))
374 child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1);
375 else
376 child_div = 1;
377
378 if (rate > 3 * (parent_rate / 4) || child_div == 1) {
379 actual_rate = parent_rate;
380 control &= ~PM_BIT(CPUDIV);
381 } else {
382 unsigned int cpusel;
383 div = (parent_rate + rate / 2) / rate;
384 if (div > child_div)
385 div = child_div;
386 cpusel = (div > 1) ? (fls(div) - 2) : 0;
387 control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control);
388 actual_rate = parent_rate / (1 << (cpusel + 1));
389 }
390
391 pr_debug("clk %s: new rate %lu (actual rate %lu)\n",
392 clk->name, rate, actual_rate);
393
394 if (apply)
395 pm_writel(CKSEL, control);
396
397 return actual_rate;
398}
399
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700400static void hsb_clk_mode(struct clk *clk, int enabled)
401{
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700402 unsigned long flags;
403 u32 mask;
404
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200405 spin_lock_irqsave(&pm_lock, flags);
406 mask = pm_readl(HSB_MASK);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700407 if (enabled)
408 mask |= 1 << clk->index;
409 else
410 mask &= ~(1 << clk->index);
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200411 pm_writel(HSB_MASK, mask);
412 spin_unlock_irqrestore(&pm_lock, flags);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700413}
414
415static unsigned long hsb_clk_get_rate(struct clk *clk)
416{
417 unsigned long cksel, shift = 0;
418
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200419 cksel = pm_readl(CKSEL);
420 if (cksel & PM_BIT(HSBDIV))
421 shift = PM_BFEXT(HSBSEL, cksel) + 1;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700422
423 return bus_clk_get_rate(clk, shift);
424}
425
Alex Raimondidd5e1332008-12-09 16:17:13 +0100426void pba_clk_mode(struct clk *clk, int enabled)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700427{
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700428 unsigned long flags;
429 u32 mask;
430
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200431 spin_lock_irqsave(&pm_lock, flags);
432 mask = pm_readl(PBA_MASK);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700433 if (enabled)
434 mask |= 1 << clk->index;
435 else
436 mask &= ~(1 << clk->index);
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200437 pm_writel(PBA_MASK, mask);
438 spin_unlock_irqrestore(&pm_lock, flags);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700439}
440
Alex Raimondidd5e1332008-12-09 16:17:13 +0100441unsigned long pba_clk_get_rate(struct clk *clk)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700442{
443 unsigned long cksel, shift = 0;
444
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200445 cksel = pm_readl(CKSEL);
446 if (cksel & PM_BIT(PBADIV))
447 shift = PM_BFEXT(PBASEL, cksel) + 1;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700448
449 return bus_clk_get_rate(clk, shift);
450}
451
452static void pbb_clk_mode(struct clk *clk, int enabled)
453{
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700454 unsigned long flags;
455 u32 mask;
456
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200457 spin_lock_irqsave(&pm_lock, flags);
458 mask = pm_readl(PBB_MASK);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700459 if (enabled)
460 mask |= 1 << clk->index;
461 else
462 mask &= ~(1 << clk->index);
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200463 pm_writel(PBB_MASK, mask);
464 spin_unlock_irqrestore(&pm_lock, flags);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700465}
466
467static unsigned long pbb_clk_get_rate(struct clk *clk)
468{
469 unsigned long cksel, shift = 0;
470
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200471 cksel = pm_readl(CKSEL);
472 if (cksel & PM_BIT(PBBDIV))
473 shift = PM_BFEXT(PBBSEL, cksel) + 1;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700474
475 return bus_clk_get_rate(clk, shift);
476}
477
478static struct clk cpu_clk = {
479 .name = "cpu",
480 .get_rate = cpu_clk_get_rate,
Hans-Christian Egtvedt9e58e182007-06-04 16:10:57 +0200481 .set_rate = cpu_clk_set_rate,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700482 .users = 1,
483};
484static struct clk hsb_clk = {
485 .name = "hsb",
486 .parent = &cpu_clk,
487 .get_rate = hsb_clk_get_rate,
488};
489static struct clk pba_clk = {
490 .name = "pba",
491 .parent = &hsb_clk,
492 .mode = hsb_clk_mode,
493 .get_rate = pba_clk_get_rate,
494 .index = 1,
495};
496static struct clk pbb_clk = {
497 .name = "pbb",
498 .parent = &hsb_clk,
499 .mode = hsb_clk_mode,
500 .get_rate = pbb_clk_get_rate,
501 .users = 1,
502 .index = 2,
503};
504
505/* --------------------------------------------------------------------
506 * Generic Clock operations
507 * -------------------------------------------------------------------- */
508
509static void genclk_mode(struct clk *clk, int enabled)
510{
511 u32 control;
512
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200513 control = pm_readl(GCCTRL(clk->index));
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700514 if (enabled)
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200515 control |= PM_BIT(CEN);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700516 else
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200517 control &= ~PM_BIT(CEN);
518 pm_writel(GCCTRL(clk->index), control);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700519}
520
521static unsigned long genclk_get_rate(struct clk *clk)
522{
523 u32 control;
524 unsigned long div = 1;
525
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200526 control = pm_readl(GCCTRL(clk->index));
527 if (control & PM_BIT(DIVEN))
528 div = 2 * (PM_BFEXT(DIV, control) + 1);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700529
530 return clk->parent->get_rate(clk->parent) / div;
531}
532
533static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
534{
535 u32 control;
536 unsigned long parent_rate, actual_rate, div;
537
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700538 parent_rate = clk->parent->get_rate(clk->parent);
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200539 control = pm_readl(GCCTRL(clk->index));
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700540
541 if (rate > 3 * parent_rate / 4) {
542 actual_rate = parent_rate;
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200543 control &= ~PM_BIT(DIVEN);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700544 } else {
545 div = (parent_rate + rate) / (2 * rate) - 1;
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200546 control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700547 actual_rate = parent_rate / (2 * (div + 1));
548 }
549
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200550 dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n",
551 clk->name, rate, actual_rate);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700552
553 if (apply)
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200554 pm_writel(GCCTRL(clk->index), control);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700555
556 return actual_rate;
557}
558
559int genclk_set_parent(struct clk *clk, struct clk *parent)
560{
561 u32 control;
562
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200563 dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n",
564 clk->name, parent->name, clk->parent->name);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700565
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200566 control = pm_readl(GCCTRL(clk->index));
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700567
568 if (parent == &osc1 || parent == &pll1)
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200569 control |= PM_BIT(OSCSEL);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700570 else if (parent == &osc0 || parent == &pll0)
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200571 control &= ~PM_BIT(OSCSEL);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700572 else
573 return -EINVAL;
574
575 if (parent == &pll0 || parent == &pll1)
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200576 control |= PM_BIT(PLLSEL);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700577 else
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200578 control &= ~PM_BIT(PLLSEL);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700579
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200580 pm_writel(GCCTRL(clk->index), control);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700581 clk->parent = parent;
582
583 return 0;
584}
585
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +0100586static void __init genclk_init_parent(struct clk *clk)
587{
588 u32 control;
589 struct clk *parent;
590
591 BUG_ON(clk->index > 7);
592
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200593 control = pm_readl(GCCTRL(clk->index));
594 if (control & PM_BIT(OSCSEL))
595 parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1;
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +0100596 else
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200597 parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0;
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +0100598
599 clk->parent = parent;
600}
601
Haavard Skinnemoen3bfb1d22008-07-08 11:59:42 -0700602static struct dw_dma_platform_data dw_dmac0_data = {
603 .nr_channels = 3,
604};
605
606static struct resource dw_dmac0_resource[] = {
607 PBMEM(0xff200000),
608 IRQ(2),
609};
610DEFINE_DEV_DATA(dw_dmac, 0);
611DEV_CLK(hclk, dw_dmac0, hsb, 10);
612
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700613/* --------------------------------------------------------------------
614 * System peripherals
615 * -------------------------------------------------------------------- */
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200616static struct resource at32_pm0_resource[] = {
617 {
618 .start = 0xfff00000,
619 .end = 0xfff0007f,
620 .flags = IORESOURCE_MEM,
621 },
622 IRQ(20),
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700623};
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200624
625static struct resource at32ap700x_rtc0_resource[] = {
626 {
627 .start = 0xfff00080,
628 .end = 0xfff000af,
629 .flags = IORESOURCE_MEM,
630 },
631 IRQ(21),
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700632};
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200633
634static struct resource at32_wdt0_resource[] = {
635 {
636 .start = 0xfff000b0,
Hans-Christian Egtvedt9797bed2007-10-30 14:29:50 +0100637 .end = 0xfff000cf,
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200638 .flags = IORESOURCE_MEM,
639 },
640};
641
642static struct resource at32_eic0_resource[] = {
643 {
644 .start = 0xfff00100,
645 .end = 0xfff0013f,
646 .flags = IORESOURCE_MEM,
647 },
648 IRQ(19),
649};
650
651DEFINE_DEV(at32_pm, 0);
652DEFINE_DEV(at32ap700x_rtc, 0);
653DEFINE_DEV(at32_wdt, 0);
654DEFINE_DEV(at32_eic, 0);
655
656/*
657 * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this
658 * is always running.
659 */
660static struct clk at32_pm_pclk = {
Haavard Skinnemoen188ff652007-03-14 13:23:44 +0100661 .name = "pclk",
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200662 .dev = &at32_pm0_device.dev,
Haavard Skinnemoen188ff652007-03-14 13:23:44 +0100663 .parent = &pbb_clk,
664 .mode = pbb_clk_mode,
665 .get_rate = pbb_clk_get_rate,
666 .users = 1,
667 .index = 0,
668};
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700669
670static struct resource intc0_resource[] = {
671 PBMEM(0xfff00400),
672};
673struct platform_device at32_intc0_device = {
674 .name = "intc",
675 .id = 0,
676 .resource = intc0_resource,
677 .num_resources = ARRAY_SIZE(intc0_resource),
678};
679DEV_CLK(pclk, at32_intc0, pbb, 1);
680
681static struct clk ebi_clk = {
682 .name = "ebi",
683 .parent = &hsb_clk,
684 .mode = hsb_clk_mode,
685 .get_rate = hsb_clk_get_rate,
686 .users = 1,
687};
688static struct clk hramc_clk = {
689 .name = "hramc",
690 .parent = &hsb_clk,
691 .mode = hsb_clk_mode,
692 .get_rate = hsb_clk_get_rate,
693 .users = 1,
Haavard Skinnemoen188ff652007-03-14 13:23:44 +0100694 .index = 3,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700695};
Haavard Skinnemoen7951f182008-03-05 15:08:27 +0100696static struct clk sdramc_clk = {
697 .name = "sdramc_clk",
698 .parent = &pbb_clk,
699 .mode = pbb_clk_mode,
700 .get_rate = pbb_clk_get_rate,
701 .users = 1,
702 .index = 14,
703};
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700704
Haavard Skinnemoenbc157b72006-09-25 23:32:16 -0700705static struct resource smc0_resource[] = {
706 PBMEM(0xfff03400),
707};
708DEFINE_DEV(smc, 0);
709DEV_CLK(pclk, smc0, pbb, 13);
710DEV_CLK(mck, smc0, hsb, 0);
711
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700712static struct platform_device pdc_device = {
713 .name = "pdc",
714 .id = 0,
715};
716DEV_CLK(hclk, pdc, hsb, 4);
717DEV_CLK(pclk, pdc, pba, 16);
718
719static struct clk pico_clk = {
720 .name = "pico",
721 .parent = &cpu_clk,
722 .mode = cpu_clk_mode,
723 .get_rate = cpu_clk_get_rate,
724 .users = 1,
725};
726
727/* --------------------------------------------------------------------
Haavard Skinnemoen9c8f8e72007-02-01 16:34:10 +0100728 * HMATRIX
729 * -------------------------------------------------------------------- */
730
Haavard Skinnemoenb47eb402008-07-31 15:56:36 +0200731struct clk at32_hmatrix_clk = {
Haavard Skinnemoen9c8f8e72007-02-01 16:34:10 +0100732 .name = "hmatrix_clk",
733 .parent = &pbb_clk,
734 .mode = pbb_clk_mode,
735 .get_rate = pbb_clk_get_rate,
736 .index = 2,
737 .users = 1,
738};
Haavard Skinnemoen9c8f8e72007-02-01 16:34:10 +0100739
740/*
741 * Set bits in the HMATRIX Special Function Register (SFR) used by the
742 * External Bus Interface (EBI). This can be used to enable special
743 * features like CompactFlash support, NAND Flash support, etc. on
744 * certain chipselects.
745 */
746static inline void set_ebi_sfr_bits(u32 mask)
747{
Haavard Skinnemoenb47eb402008-07-31 15:56:36 +0200748 hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, mask);
Haavard Skinnemoen9c8f8e72007-02-01 16:34:10 +0100749}
750
751/* --------------------------------------------------------------------
David Brownelle723ff62008-02-14 11:24:02 -0800752 * Timer/Counter (TC)
Hans-Christian Egtvedt77609892007-03-12 18:15:16 +0100753 * -------------------------------------------------------------------- */
David Brownelle723ff62008-02-14 11:24:02 -0800754
755static struct resource at32_tcb0_resource[] = {
Hans-Christian Egtvedt77609892007-03-12 18:15:16 +0100756 PBMEM(0xfff00c00),
757 IRQ(22),
758};
David Brownelle723ff62008-02-14 11:24:02 -0800759static struct platform_device at32_tcb0_device = {
760 .name = "atmel_tcb",
Hans-Christian Egtvedt77609892007-03-12 18:15:16 +0100761 .id = 0,
David Brownelle723ff62008-02-14 11:24:02 -0800762 .resource = at32_tcb0_resource,
763 .num_resources = ARRAY_SIZE(at32_tcb0_resource),
Hans-Christian Egtvedt77609892007-03-12 18:15:16 +0100764};
David Brownelle723ff62008-02-14 11:24:02 -0800765DEV_CLK(t0_clk, at32_tcb0, pbb, 3);
766
767static struct resource at32_tcb1_resource[] = {
768 PBMEM(0xfff01000),
769 IRQ(23),
770};
771static struct platform_device at32_tcb1_device = {
772 .name = "atmel_tcb",
773 .id = 1,
774 .resource = at32_tcb1_resource,
775 .num_resources = ARRAY_SIZE(at32_tcb1_resource),
776};
777DEV_CLK(t0_clk, at32_tcb1, pbb, 4);
Hans-Christian Egtvedt77609892007-03-12 18:15:16 +0100778
779/* --------------------------------------------------------------------
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700780 * PIO
781 * -------------------------------------------------------------------- */
782
783static struct resource pio0_resource[] = {
784 PBMEM(0xffe02800),
785 IRQ(13),
786};
787DEFINE_DEV(pio, 0);
788DEV_CLK(mck, pio0, pba, 10);
789
790static struct resource pio1_resource[] = {
791 PBMEM(0xffe02c00),
792 IRQ(14),
793};
794DEFINE_DEV(pio, 1);
795DEV_CLK(mck, pio1, pba, 11);
796
797static struct resource pio2_resource[] = {
798 PBMEM(0xffe03000),
799 IRQ(15),
800};
801DEFINE_DEV(pio, 2);
802DEV_CLK(mck, pio2, pba, 12);
803
804static struct resource pio3_resource[] = {
805 PBMEM(0xffe03400),
806 IRQ(16),
807};
808DEFINE_DEV(pio, 3);
809DEV_CLK(mck, pio3, pba, 13);
810
Haavard Skinnemoen7f9f4672007-01-30 11:16:16 +0100811static struct resource pio4_resource[] = {
812 PBMEM(0xffe03800),
813 IRQ(17),
814};
815DEFINE_DEV(pio, 4);
816DEV_CLK(mck, pio4, pba, 14);
817
Haavard Skinnemoene82c6102008-10-23 14:42:19 +0200818static int __init system_device_init(void)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700819{
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200820 platform_device_register(&at32_pm0_device);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700821 platform_device_register(&at32_intc0_device);
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +0200822 platform_device_register(&at32ap700x_rtc0_device);
823 platform_device_register(&at32_wdt0_device);
824 platform_device_register(&at32_eic0_device);
Haavard Skinnemoenbc157b72006-09-25 23:32:16 -0700825 platform_device_register(&smc0_device);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700826 platform_device_register(&pdc_device);
Haavard Skinnemoen3bfb1d22008-07-08 11:59:42 -0700827 platform_device_register(&dw_dmac0_device);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700828
David Brownelle723ff62008-02-14 11:24:02 -0800829 platform_device_register(&at32_tcb0_device);
830 platform_device_register(&at32_tcb1_device);
Hans-Christian Egtvedt77609892007-03-12 18:15:16 +0100831
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700832 platform_device_register(&pio0_device);
833 platform_device_register(&pio1_device);
834 platform_device_register(&pio2_device);
835 platform_device_register(&pio3_device);
Haavard Skinnemoen7f9f4672007-01-30 11:16:16 +0100836 platform_device_register(&pio4_device);
Haavard Skinnemoene82c6102008-10-23 14:42:19 +0200837
838 return 0;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700839}
Haavard Skinnemoene82c6102008-10-23 14:42:19 +0200840core_initcall(system_device_init);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700841
842/* --------------------------------------------------------------------
Hans-Christian Egtvedtd86d3142008-02-25 11:24:30 +0100843 * PSIF
844 * -------------------------------------------------------------------- */
845static struct resource atmel_psif0_resource[] __initdata = {
846 {
847 .start = 0xffe03c00,
848 .end = 0xffe03cff,
849 .flags = IORESOURCE_MEM,
850 },
851 IRQ(18),
852};
853static struct clk atmel_psif0_pclk = {
854 .name = "pclk",
855 .parent = &pba_clk,
856 .mode = pba_clk_mode,
857 .get_rate = pba_clk_get_rate,
858 .index = 15,
859};
860
861static struct resource atmel_psif1_resource[] __initdata = {
862 {
863 .start = 0xffe03d00,
864 .end = 0xffe03dff,
865 .flags = IORESOURCE_MEM,
866 },
867 IRQ(18),
868};
869static struct clk atmel_psif1_pclk = {
870 .name = "pclk",
871 .parent = &pba_clk,
872 .mode = pba_clk_mode,
873 .get_rate = pba_clk_get_rate,
874 .index = 15,
875};
876
877struct platform_device *__init at32_add_device_psif(unsigned int id)
878{
879 struct platform_device *pdev;
Julien Maycaf18f12008-09-24 10:30:47 +0200880 u32 pin_mask;
Hans-Christian Egtvedtd86d3142008-02-25 11:24:30 +0100881
882 if (!(id == 0 || id == 1))
883 return NULL;
884
885 pdev = platform_device_alloc("atmel_psif", id);
886 if (!pdev)
887 return NULL;
888
889 switch (id) {
890 case 0:
Julien Maycaf18f12008-09-24 10:30:47 +0200891 pin_mask = (1 << 8) | (1 << 9); /* CLOCK & DATA */
892
Hans-Christian Egtvedtd86d3142008-02-25 11:24:30 +0100893 if (platform_device_add_resources(pdev, atmel_psif0_resource,
894 ARRAY_SIZE(atmel_psif0_resource)))
895 goto err_add_resources;
896 atmel_psif0_pclk.dev = &pdev->dev;
Julien Maycaf18f12008-09-24 10:30:47 +0200897 select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
Hans-Christian Egtvedtd86d3142008-02-25 11:24:30 +0100898 break;
899 case 1:
Julien Maycaf18f12008-09-24 10:30:47 +0200900 pin_mask = (1 << 11) | (1 << 12); /* CLOCK & DATA */
901
Hans-Christian Egtvedtd86d3142008-02-25 11:24:30 +0100902 if (platform_device_add_resources(pdev, atmel_psif1_resource,
903 ARRAY_SIZE(atmel_psif1_resource)))
904 goto err_add_resources;
905 atmel_psif1_pclk.dev = &pdev->dev;
Julien Maycaf18f12008-09-24 10:30:47 +0200906 select_peripheral(PIOB, pin_mask, PERIPH_A, 0);
Hans-Christian Egtvedtd86d3142008-02-25 11:24:30 +0100907 break;
908 default:
909 return NULL;
910 }
911
912 platform_device_add(pdev);
913 return pdev;
914
915err_add_resources:
916 platform_device_put(pdev);
917 return NULL;
918}
919
920/* --------------------------------------------------------------------
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700921 * USART
922 * -------------------------------------------------------------------- */
923
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200924static struct atmel_uart_data atmel_usart0_data = {
925 .use_dma_tx = 1,
926 .use_dma_rx = 1,
927};
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +0200928static struct resource atmel_usart0_resource[] = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700929 PBMEM(0xffe00c00),
David Brownella3d912c2007-01-23 20:14:02 -0800930 IRQ(6),
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700931};
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200932DEFINE_DEV_DATA(atmel_usart, 0);
ben.nizette@iinet.net.au80f76c52007-11-07 16:16:22 +0900933DEV_CLK(usart, atmel_usart0, pba, 3);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700934
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200935static struct atmel_uart_data atmel_usart1_data = {
936 .use_dma_tx = 1,
937 .use_dma_rx = 1,
938};
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +0200939static struct resource atmel_usart1_resource[] = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700940 PBMEM(0xffe01000),
941 IRQ(7),
942};
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200943DEFINE_DEV_DATA(atmel_usart, 1);
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +0200944DEV_CLK(usart, atmel_usart1, pba, 4);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700945
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200946static struct atmel_uart_data atmel_usart2_data = {
947 .use_dma_tx = 1,
948 .use_dma_rx = 1,
949};
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +0200950static struct resource atmel_usart2_resource[] = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700951 PBMEM(0xffe01400),
952 IRQ(8),
953};
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200954DEFINE_DEV_DATA(atmel_usart, 2);
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +0200955DEV_CLK(usart, atmel_usart2, pba, 5);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700956
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200957static struct atmel_uart_data atmel_usart3_data = {
958 .use_dma_tx = 1,
959 .use_dma_rx = 1,
960};
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +0200961static struct resource atmel_usart3_resource[] = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700962 PBMEM(0xffe01800),
963 IRQ(9),
964};
Haavard Skinnemoen75d35212006-10-04 16:02:08 +0200965DEFINE_DEV_DATA(atmel_usart, 3);
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +0200966DEV_CLK(usart, atmel_usart3, pba, 6);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700967
968static inline void configure_usart0_pins(void)
969{
Julien Maycaf18f12008-09-24 10:30:47 +0200970 u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */
971
Anders Blomdell10546262008-10-24 14:54:08 +0200972 select_peripheral(PIOA, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700973}
974
975static inline void configure_usart1_pins(void)
976{
Julien Maycaf18f12008-09-24 10:30:47 +0200977 u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */
978
Anders Blomdell10546262008-10-24 14:54:08 +0200979 select_peripheral(PIOA, pin_mask, PERIPH_A, AT32_GPIOF_PULLUP);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700980}
981
982static inline void configure_usart2_pins(void)
983{
Julien Maycaf18f12008-09-24 10:30:47 +0200984 u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */
985
Anders Blomdell10546262008-10-24 14:54:08 +0200986 select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700987}
988
989static inline void configure_usart3_pins(void)
990{
Julien Maycaf18f12008-09-24 10:30:47 +0200991 u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */
992
Anders Blomdell10546262008-10-24 14:54:08 +0200993 select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700994}
995
David Brownella3d912c2007-01-23 20:14:02 -0800996static struct platform_device *__initdata at32_usarts[4];
Haavard Skinnemoenc1945882006-10-04 16:02:10 +0200997
998void __init at32_map_usart(unsigned int hw_id, unsigned int line)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700999{
1000 struct platform_device *pdev;
1001
Haavard Skinnemoenc1945882006-10-04 16:02:10 +02001002 switch (hw_id) {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001003 case 0:
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +02001004 pdev = &atmel_usart0_device;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001005 configure_usart0_pins();
1006 break;
1007 case 1:
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +02001008 pdev = &atmel_usart1_device;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001009 configure_usart1_pins();
1010 break;
1011 case 2:
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +02001012 pdev = &atmel_usart2_device;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001013 configure_usart2_pins();
1014 break;
1015 case 3:
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +02001016 pdev = &atmel_usart3_device;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001017 configure_usart3_pins();
1018 break;
1019 default:
Haavard Skinnemoenc1945882006-10-04 16:02:10 +02001020 return;
Haavard Skinnemoen75d35212006-10-04 16:02:08 +02001021 }
1022
1023 if (PXSEG(pdev->resource[0].start) == P4SEG) {
1024 /* Addresses in the P4 segment are permanently mapped 1:1 */
1025 struct atmel_uart_data *data = pdev->dev.platform_data;
1026 data->regs = (void __iomem *)pdev->resource[0].start;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001027 }
1028
Haavard Skinnemoenc1945882006-10-04 16:02:10 +02001029 pdev->id = line;
1030 at32_usarts[line] = pdev;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001031}
1032
1033struct platform_device *__init at32_add_device_usart(unsigned int id)
1034{
Haavard Skinnemoenc1945882006-10-04 16:02:10 +02001035 platform_device_register(at32_usarts[id]);
1036 return at32_usarts[id];
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001037}
1038
Haavard Skinnemoen73e27982006-10-04 16:02:04 +02001039struct platform_device *atmel_default_console_device;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001040
1041void __init at32_setup_serial_console(unsigned int usart_id)
1042{
Haavard Skinnemoenc1945882006-10-04 16:02:10 +02001043 atmel_default_console_device = at32_usarts[usart_id];
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001044}
1045
1046/* --------------------------------------------------------------------
1047 * Ethernet
1048 * -------------------------------------------------------------------- */
1049
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01001050#ifdef CONFIG_CPU_AT32AP7000
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001051static struct eth_platform_data macb0_data;
1052static struct resource macb0_resource[] = {
1053 PBMEM(0xfff01800),
1054 IRQ(25),
1055};
1056DEFINE_DEV_DATA(macb, 0);
1057DEV_CLK(hclk, macb0, hsb, 8);
1058DEV_CLK(pclk, macb0, pbb, 6);
1059
Haavard Skinnemoencfcb3a82006-10-30 09:23:12 +01001060static struct eth_platform_data macb1_data;
1061static struct resource macb1_resource[] = {
1062 PBMEM(0xfff01c00),
1063 IRQ(26),
1064};
1065DEFINE_DEV_DATA(macb, 1);
1066DEV_CLK(hclk, macb1, hsb, 9);
1067DEV_CLK(pclk, macb1, pbb, 7);
1068
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001069struct platform_device *__init
1070at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
1071{
1072 struct platform_device *pdev;
Julien Maycaf18f12008-09-24 10:30:47 +02001073 u32 pin_mask;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001074
1075 switch (id) {
1076 case 0:
1077 pdev = &macb0_device;
1078
Julien Maycaf18f12008-09-24 10:30:47 +02001079 pin_mask = (1 << 3); /* TXD0 */
1080 pin_mask |= (1 << 4); /* TXD1 */
1081 pin_mask |= (1 << 7); /* TXEN */
1082 pin_mask |= (1 << 8); /* TXCK */
1083 pin_mask |= (1 << 9); /* RXD0 */
1084 pin_mask |= (1 << 10); /* RXD1 */
1085 pin_mask |= (1 << 13); /* RXER */
1086 pin_mask |= (1 << 15); /* RXDV */
1087 pin_mask |= (1 << 16); /* MDC */
1088 pin_mask |= (1 << 17); /* MDIO */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001089
1090 if (!data->is_rmii) {
Julien Maycaf18f12008-09-24 10:30:47 +02001091 pin_mask |= (1 << 0); /* COL */
1092 pin_mask |= (1 << 1); /* CRS */
1093 pin_mask |= (1 << 2); /* TXER */
1094 pin_mask |= (1 << 5); /* TXD2 */
1095 pin_mask |= (1 << 6); /* TXD3 */
1096 pin_mask |= (1 << 11); /* RXD2 */
1097 pin_mask |= (1 << 12); /* RXD3 */
1098 pin_mask |= (1 << 14); /* RXCK */
Mark Jackson198f2932008-10-13 10:46:27 +00001099#ifndef CONFIG_BOARD_MIMC200
Julien Maycaf18f12008-09-24 10:30:47 +02001100 pin_mask |= (1 << 18); /* SPD */
Mark Jackson198f2932008-10-13 10:46:27 +00001101#endif
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001102 }
Julien Maycaf18f12008-09-24 10:30:47 +02001103
1104 select_peripheral(PIOC, pin_mask, PERIPH_A, 0);
1105
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001106 break;
1107
Haavard Skinnemoencfcb3a82006-10-30 09:23:12 +01001108 case 1:
1109 pdev = &macb1_device;
1110
Julien Maycaf18f12008-09-24 10:30:47 +02001111 pin_mask = (1 << 13); /* TXD0 */
1112 pin_mask |= (1 << 14); /* TXD1 */
1113 pin_mask |= (1 << 11); /* TXEN */
1114 pin_mask |= (1 << 12); /* TXCK */
1115 pin_mask |= (1 << 10); /* RXD0 */
1116 pin_mask |= (1 << 6); /* RXD1 */
1117 pin_mask |= (1 << 5); /* RXER */
1118 pin_mask |= (1 << 4); /* RXDV */
1119 pin_mask |= (1 << 3); /* MDC */
1120 pin_mask |= (1 << 2); /* MDIO */
1121
Mark Jackson198f2932008-10-13 10:46:27 +00001122#ifndef CONFIG_BOARD_MIMC200
Julien Maycaf18f12008-09-24 10:30:47 +02001123 if (!data->is_rmii)
1124 pin_mask |= (1 << 15); /* SPD */
Mark Jackson198f2932008-10-13 10:46:27 +00001125#endif
Julien Maycaf18f12008-09-24 10:30:47 +02001126
1127 select_peripheral(PIOD, pin_mask, PERIPH_B, 0);
Haavard Skinnemoencfcb3a82006-10-30 09:23:12 +01001128
1129 if (!data->is_rmii) {
Julien Maycaf18f12008-09-24 10:30:47 +02001130 pin_mask = (1 << 19); /* COL */
1131 pin_mask |= (1 << 23); /* CRS */
1132 pin_mask |= (1 << 26); /* TXER */
1133 pin_mask |= (1 << 27); /* TXD2 */
1134 pin_mask |= (1 << 28); /* TXD3 */
1135 pin_mask |= (1 << 29); /* RXD2 */
1136 pin_mask |= (1 << 30); /* RXD3 */
1137 pin_mask |= (1 << 24); /* RXCK */
1138
1139 select_peripheral(PIOC, pin_mask, PERIPH_B, 0);
Haavard Skinnemoencfcb3a82006-10-30 09:23:12 +01001140 }
1141 break;
1142
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001143 default:
1144 return NULL;
1145 }
1146
1147 memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data));
1148 platform_device_register(pdev);
1149
1150 return pdev;
1151}
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01001152#endif
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001153
1154/* --------------------------------------------------------------------
1155 * SPI
1156 * -------------------------------------------------------------------- */
Haavard Skinnemoen3d60ee12007-01-10 20:20:02 +01001157static struct resource atmel_spi0_resource[] = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001158 PBMEM(0xffe00000),
1159 IRQ(3),
1160};
Haavard Skinnemoen3d60ee12007-01-10 20:20:02 +01001161DEFINE_DEV(atmel_spi, 0);
1162DEV_CLK(spi_clk, atmel_spi0, pba, 0);
1163
1164static struct resource atmel_spi1_resource[] = {
1165 PBMEM(0xffe00400),
1166 IRQ(4),
1167};
1168DEFINE_DEV(atmel_spi, 1);
1169DEV_CLK(spi_clk, atmel_spi1, pba, 1);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001170
Haavard Skinnemoen9a596a62007-02-19 10:38:04 +01001171static void __init
Haavard Skinnemoen41d8ca42007-02-16 13:56:11 +01001172at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b,
1173 unsigned int n, const u8 *pins)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001174{
Haavard Skinnemoen41d8ca42007-02-16 13:56:11 +01001175 unsigned int pin, mode;
1176
1177 for (; n; n--, b++) {
1178 b->bus_num = bus_num;
1179 if (b->chip_select >= 4)
1180 continue;
1181 pin = (unsigned)b->controller_data;
1182 if (!pin) {
1183 pin = pins[b->chip_select];
1184 b->controller_data = (void *)pin;
1185 }
1186 mode = AT32_GPIOF_OUTPUT;
1187 if (!(b->mode & SPI_CS_HIGH))
1188 mode |= AT32_GPIOF_HIGH;
1189 at32_select_gpio(pin, mode);
1190 }
1191}
1192
1193struct platform_device *__init
1194at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
1195{
1196 /*
1197 * Manage the chipselects as GPIOs, normally using the same pins
1198 * the SPI controller expects; but boards can use other pins.
1199 */
1200 static u8 __initdata spi0_pins[] =
1201 { GPIO_PIN_PA(3), GPIO_PIN_PA(4),
1202 GPIO_PIN_PA(5), GPIO_PIN_PA(20), };
1203 static u8 __initdata spi1_pins[] =
1204 { GPIO_PIN_PB(2), GPIO_PIN_PB(3),
1205 GPIO_PIN_PB(4), GPIO_PIN_PA(27), };
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001206 struct platform_device *pdev;
Julien Maycaf18f12008-09-24 10:30:47 +02001207 u32 pin_mask;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001208
1209 switch (id) {
1210 case 0:
Haavard Skinnemoen3d60ee12007-01-10 20:20:02 +01001211 pdev = &atmel_spi0_device;
Julien Maycaf18f12008-09-24 10:30:47 +02001212 pin_mask = (1 << 1) | (1 << 2); /* MOSI & SCK */
1213
David Brownell9c2baf72008-06-18 02:31:43 -07001214 /* pullup MISO so a level is always defined */
Julien Maycaf18f12008-09-24 10:30:47 +02001215 select_peripheral(PIOA, (1 << 0), PERIPH_A, AT32_GPIOF_PULLUP);
1216 select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
1217
Haavard Skinnemoen41d8ca42007-02-16 13:56:11 +01001218 at32_spi_setup_slaves(0, b, n, spi0_pins);
Haavard Skinnemoen3d60ee12007-01-10 20:20:02 +01001219 break;
1220
1221 case 1:
1222 pdev = &atmel_spi1_device;
Julien Maycaf18f12008-09-24 10:30:47 +02001223 pin_mask = (1 << 1) | (1 << 5); /* MOSI */
1224
David Brownell9c2baf72008-06-18 02:31:43 -07001225 /* pullup MISO so a level is always defined */
Julien Maycaf18f12008-09-24 10:30:47 +02001226 select_peripheral(PIOB, (1 << 0), PERIPH_B, AT32_GPIOF_PULLUP);
1227 select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
1228
Haavard Skinnemoen41d8ca42007-02-16 13:56:11 +01001229 at32_spi_setup_slaves(1, b, n, spi1_pins);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001230 break;
1231
1232 default:
1233 return NULL;
1234 }
1235
Haavard Skinnemoen41d8ca42007-02-16 13:56:11 +01001236 spi_register_board_info(b, n);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001237 platform_device_register(pdev);
1238 return pdev;
1239}
1240
1241/* --------------------------------------------------------------------
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001242 * TWI
1243 * -------------------------------------------------------------------- */
1244static struct resource atmel_twi0_resource[] __initdata = {
1245 PBMEM(0xffe00800),
1246 IRQ(5),
1247};
1248static struct clk atmel_twi0_pclk = {
1249 .name = "twi_pclk",
1250 .parent = &pba_clk,
1251 .mode = pba_clk_mode,
1252 .get_rate = pba_clk_get_rate,
1253 .index = 2,
1254};
1255
Ben Nizette040b28f2008-02-07 15:28:57 +11001256struct platform_device *__init at32_add_device_twi(unsigned int id,
1257 struct i2c_board_info *b,
1258 unsigned int n)
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001259{
1260 struct platform_device *pdev;
Julien Maycaf18f12008-09-24 10:30:47 +02001261 u32 pin_mask;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001262
1263 if (id != 0)
1264 return NULL;
1265
1266 pdev = platform_device_alloc("atmel_twi", id);
1267 if (!pdev)
1268 return NULL;
1269
1270 if (platform_device_add_resources(pdev, atmel_twi0_resource,
1271 ARRAY_SIZE(atmel_twi0_resource)))
1272 goto err_add_resources;
1273
Julien Maycaf18f12008-09-24 10:30:47 +02001274 pin_mask = (1 << 6) | (1 << 7); /* SDA & SDL */
1275
1276 select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001277
1278 atmel_twi0_pclk.dev = &pdev->dev;
1279
Ben Nizette040b28f2008-02-07 15:28:57 +11001280 if (b)
1281 i2c_register_board_info(id, b, n);
1282
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001283 platform_device_add(pdev);
1284 return pdev;
1285
1286err_add_resources:
1287 platform_device_put(pdev);
1288 return NULL;
1289}
1290
1291/* --------------------------------------------------------------------
1292 * MMC
1293 * -------------------------------------------------------------------- */
1294static struct resource atmel_mci0_resource[] __initdata = {
1295 PBMEM(0xfff02400),
1296 IRQ(28),
1297};
1298static struct clk atmel_mci0_pclk = {
1299 .name = "mci_clk",
1300 .parent = &pbb_clk,
1301 .mode = pbb_clk_mode,
1302 .get_rate = pbb_clk_get_rate,
1303 .index = 9,
1304};
1305
Haavard Skinnemoen7d2be072008-06-30 18:35:03 +02001306struct platform_device *__init
1307at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001308{
Haavard Skinnemoen7d2be072008-06-30 18:35:03 +02001309 struct platform_device *pdev;
Dan Williams74465b42009-01-06 11:38:16 -07001310 struct dw_dma_slave *dws = &data->dma_slave;
Julien Maycaf18f12008-09-24 10:30:47 +02001311 u32 pioa_mask;
1312 u32 piob_mask;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001313
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001314 if (id != 0 || !data)
1315 return NULL;
1316
1317 /* Must have at least one usable slot */
1318 if (!data->slot[0].bus_width && !data->slot[1].bus_width)
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001319 return NULL;
1320
1321 pdev = platform_device_alloc("atmel_mci", id);
1322 if (!pdev)
Haavard Skinnemoen7d2be072008-06-30 18:35:03 +02001323 goto fail;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001324
1325 if (platform_device_add_resources(pdev, atmel_mci0_resource,
1326 ARRAY_SIZE(atmel_mci0_resource)))
Haavard Skinnemoen7d2be072008-06-30 18:35:03 +02001327 goto fail;
1328
Dan Williams74465b42009-01-06 11:38:16 -07001329 dws->dma_dev = &dw_dmac0_device.dev;
1330 dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
Haavard Skinnemoen65e8b082008-07-30 20:29:03 +02001331 dws->cfg_hi = (DWC_CFGH_SRC_PER(0)
1332 | DWC_CFGH_DST_PER(1));
1333 dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL
1334 | DWC_CFGL_HS_SRC_POL);
1335
Haavard Skinnemoen7d2be072008-06-30 18:35:03 +02001336 if (platform_device_add_data(pdev, data,
1337 sizeof(struct mci_platform_data)))
1338 goto fail;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001339
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001340 /* CLK line is common to both slots */
Julien Maycaf18f12008-09-24 10:30:47 +02001341 pioa_mask = 1 << 10;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001342
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001343 switch (data->slot[0].bus_width) {
1344 case 4:
Julien Maycaf18f12008-09-24 10:30:47 +02001345 pioa_mask |= 1 << 13; /* DATA1 */
1346 pioa_mask |= 1 << 14; /* DATA2 */
1347 pioa_mask |= 1 << 15; /* DATA3 */
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001348 /* fall through */
1349 case 1:
Julien Maycaf18f12008-09-24 10:30:47 +02001350 pioa_mask |= 1 << 11; /* CMD */
1351 pioa_mask |= 1 << 12; /* DATA0 */
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001352
1353 if (gpio_is_valid(data->slot[0].detect_pin))
1354 at32_select_gpio(data->slot[0].detect_pin, 0);
1355 if (gpio_is_valid(data->slot[0].wp_pin))
1356 at32_select_gpio(data->slot[0].wp_pin, 0);
1357 break;
1358 case 0:
1359 /* Slot is unused */
1360 break;
1361 default:
1362 goto fail;
1363 }
1364
Julien Maycaf18f12008-09-24 10:30:47 +02001365 select_peripheral(PIOA, pioa_mask, PERIPH_A, 0);
1366 piob_mask = 0;
1367
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001368 switch (data->slot[1].bus_width) {
1369 case 4:
Julien Maycaf18f12008-09-24 10:30:47 +02001370 piob_mask |= 1 << 8; /* DATA1 */
1371 piob_mask |= 1 << 9; /* DATA2 */
1372 piob_mask |= 1 << 10; /* DATA3 */
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001373 /* fall through */
1374 case 1:
Julien Maycaf18f12008-09-24 10:30:47 +02001375 piob_mask |= 1 << 6; /* CMD */
1376 piob_mask |= 1 << 7; /* DATA0 */
1377 select_peripheral(PIOB, piob_mask, PERIPH_B, 0);
Haavard Skinnemoen6b918652008-08-07 14:08:49 +02001378
1379 if (gpio_is_valid(data->slot[1].detect_pin))
1380 at32_select_gpio(data->slot[1].detect_pin, 0);
1381 if (gpio_is_valid(data->slot[1].wp_pin))
1382 at32_select_gpio(data->slot[1].wp_pin, 0);
1383 break;
1384 case 0:
1385 /* Slot is unused */
1386 break;
1387 default:
1388 if (!data->slot[0].bus_width)
1389 goto fail;
1390
1391 data->slot[1].bus_width = 0;
1392 break;
1393 }
Haavard Skinnemoen7d2be072008-06-30 18:35:03 +02001394
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001395 atmel_mci0_pclk.dev = &pdev->dev;
1396
1397 platform_device_add(pdev);
1398 return pdev;
1399
Haavard Skinnemoen7d2be072008-06-30 18:35:03 +02001400fail:
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001401 platform_device_put(pdev);
1402 return NULL;
1403}
1404
1405/* --------------------------------------------------------------------
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001406 * LCDC
1407 * -------------------------------------------------------------------- */
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01001408#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002)
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001409static struct atmel_lcdfb_info atmel_lcdfb0_data;
1410static struct resource atmel_lcdfb0_resource[] = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001411 {
1412 .start = 0xff000000,
1413 .end = 0xff000fff,
1414 .flags = IORESOURCE_MEM,
1415 },
1416 IRQ(1),
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001417 {
1418 /* Placeholder for pre-allocated fb memory */
1419 .start = 0x00000000,
1420 .end = 0x00000000,
1421 .flags = 0,
1422 },
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001423};
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001424DEFINE_DEV_DATA(atmel_lcdfb, 0);
1425DEV_CLK(hck1, atmel_lcdfb0, hsb, 7);
1426static struct clk atmel_lcdfb0_pixclk = {
1427 .name = "lcdc_clk",
1428 .dev = &atmel_lcdfb0_device.dev,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001429 .mode = genclk_mode,
1430 .get_rate = genclk_get_rate,
1431 .set_rate = genclk_set_rate,
1432 .set_parent = genclk_set_parent,
1433 .index = 7,
1434};
1435
1436struct platform_device *__init
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001437at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
Hans-Christian Egtvedt47882cf2008-02-05 15:27:16 +01001438 unsigned long fbmem_start, unsigned long fbmem_len,
Julien May70664122008-08-04 14:27:38 +02001439 u64 pin_mask)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001440{
1441 struct platform_device *pdev;
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001442 struct atmel_lcdfb_info *info;
1443 struct fb_monspecs *monspecs;
1444 struct fb_videomode *modedb;
1445 unsigned int modedb_size;
Julien Maycaf18f12008-09-24 10:30:47 +02001446 u32 portc_mask, portd_mask, porte_mask;
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001447
1448 /*
1449 * Do a deep copy of the fb data, monspecs and modedb. Make
1450 * sure all allocations are done before setting up the
1451 * portmux.
1452 */
1453 monspecs = kmemdup(data->default_monspecs,
1454 sizeof(struct fb_monspecs), GFP_KERNEL);
1455 if (!monspecs)
1456 return NULL;
1457
1458 modedb_size = sizeof(struct fb_videomode) * monspecs->modedb_len;
1459 modedb = kmemdup(monspecs->modedb, modedb_size, GFP_KERNEL);
1460 if (!modedb)
1461 goto err_dup_modedb;
1462 monspecs->modedb = modedb;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001463
1464 switch (id) {
1465 case 0:
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001466 pdev = &atmel_lcdfb0_device;
Hans-Christian Egtvedt47882cf2008-02-05 15:27:16 +01001467
Julien May70664122008-08-04 14:27:38 +02001468 if (pin_mask == 0ULL)
1469 /* Default to "full" lcdc control signals and 24bit */
1470 pin_mask = ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL;
1471
1472 /* LCDC on port C */
Alex Raimondi60900652008-10-13 16:03:45 +02001473 portc_mask = pin_mask & 0xfff80000;
Julien Maycaf18f12008-09-24 10:30:47 +02001474 select_peripheral(PIOC, portc_mask, PERIPH_A, 0);
Julien May70664122008-08-04 14:27:38 +02001475
1476 /* LCDC on port D */
Julien Maycaf18f12008-09-24 10:30:47 +02001477 portd_mask = pin_mask & 0x0003ffff;
1478 select_peripheral(PIOD, portd_mask, PERIPH_A, 0);
Julien May70664122008-08-04 14:27:38 +02001479
1480 /* LCDC on port E */
Julien Maycaf18f12008-09-24 10:30:47 +02001481 porte_mask = (pin_mask >> 32) & 0x0007ffff;
1482 select_peripheral(PIOE, porte_mask, PERIPH_B, 0);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001483
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001484 clk_set_parent(&atmel_lcdfb0_pixclk, &pll0);
1485 clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0));
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001486 break;
1487
1488 default:
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001489 goto err_invalid_id;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001490 }
1491
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001492 if (fbmem_len) {
1493 pdev->resource[2].start = fbmem_start;
1494 pdev->resource[2].end = fbmem_start + fbmem_len - 1;
1495 pdev->resource[2].flags = IORESOURCE_MEM;
1496 }
1497
1498 info = pdev->dev.platform_data;
1499 memcpy(info, data, sizeof(struct atmel_lcdfb_info));
1500 info->default_monspecs = monspecs;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001501
1502 platform_device_register(pdev);
1503 return pdev;
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01001504
1505err_invalid_id:
1506 kfree(modedb);
1507err_dup_modedb:
1508 kfree(monspecs);
1509 return NULL;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001510}
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01001511#endif
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001512
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +01001513/* --------------------------------------------------------------------
David Brownell9a1e8eb2008-02-08 04:21:21 -08001514 * PWM
1515 * -------------------------------------------------------------------- */
1516static struct resource atmel_pwm0_resource[] __initdata = {
1517 PBMEM(0xfff01400),
1518 IRQ(24),
1519};
1520static struct clk atmel_pwm0_mck = {
Sedji Gaouaou84059962008-06-25 10:32:50 +02001521 .name = "pwm_clk",
David Brownell9a1e8eb2008-02-08 04:21:21 -08001522 .parent = &pbb_clk,
1523 .mode = pbb_clk_mode,
1524 .get_rate = pbb_clk_get_rate,
1525 .index = 5,
1526};
1527
1528struct platform_device *__init at32_add_device_pwm(u32 mask)
1529{
1530 struct platform_device *pdev;
Julien Maycaf18f12008-09-24 10:30:47 +02001531 u32 pin_mask;
David Brownell9a1e8eb2008-02-08 04:21:21 -08001532
1533 if (!mask)
1534 return NULL;
1535
1536 pdev = platform_device_alloc("atmel_pwm", 0);
1537 if (!pdev)
1538 return NULL;
1539
1540 if (platform_device_add_resources(pdev, atmel_pwm0_resource,
1541 ARRAY_SIZE(atmel_pwm0_resource)))
1542 goto out_free_pdev;
1543
1544 if (platform_device_add_data(pdev, &mask, sizeof(mask)))
1545 goto out_free_pdev;
1546
Julien Maycaf18f12008-09-24 10:30:47 +02001547 pin_mask = 0;
David Brownell9a1e8eb2008-02-08 04:21:21 -08001548 if (mask & (1 << 0))
Julien Maycaf18f12008-09-24 10:30:47 +02001549 pin_mask |= (1 << 28);
David Brownell9a1e8eb2008-02-08 04:21:21 -08001550 if (mask & (1 << 1))
Julien Maycaf18f12008-09-24 10:30:47 +02001551 pin_mask |= (1 << 29);
1552 if (pin_mask > 0)
1553 select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
1554
1555 pin_mask = 0;
David Brownell9a1e8eb2008-02-08 04:21:21 -08001556 if (mask & (1 << 2))
Julien Maycaf18f12008-09-24 10:30:47 +02001557 pin_mask |= (1 << 21);
David Brownell9a1e8eb2008-02-08 04:21:21 -08001558 if (mask & (1 << 3))
Julien Maycaf18f12008-09-24 10:30:47 +02001559 pin_mask |= (1 << 22);
1560 if (pin_mask > 0)
1561 select_peripheral(PIOA, pin_mask, PERIPH_B, 0);
David Brownell9a1e8eb2008-02-08 04:21:21 -08001562
1563 atmel_pwm0_mck.dev = &pdev->dev;
1564
1565 platform_device_add(pdev);
1566
1567 return pdev;
1568
1569out_free_pdev:
1570 platform_device_put(pdev);
1571 return NULL;
1572}
1573
1574/* --------------------------------------------------------------------
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001575 * SSC
1576 * -------------------------------------------------------------------- */
1577static struct resource ssc0_resource[] = {
1578 PBMEM(0xffe01c00),
1579 IRQ(10),
1580};
1581DEFINE_DEV(ssc, 0);
1582DEV_CLK(pclk, ssc0, pba, 7);
1583
1584static struct resource ssc1_resource[] = {
1585 PBMEM(0xffe02000),
1586 IRQ(11),
1587};
1588DEFINE_DEV(ssc, 1);
1589DEV_CLK(pclk, ssc1, pba, 8);
1590
1591static struct resource ssc2_resource[] = {
1592 PBMEM(0xffe02400),
1593 IRQ(12),
1594};
1595DEFINE_DEV(ssc, 2);
1596DEV_CLK(pclk, ssc2, pba, 9);
1597
1598struct platform_device *__init
1599at32_add_device_ssc(unsigned int id, unsigned int flags)
1600{
1601 struct platform_device *pdev;
Julien Maycaf18f12008-09-24 10:30:47 +02001602 u32 pin_mask = 0;
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001603
1604 switch (id) {
1605 case 0:
1606 pdev = &ssc0_device;
1607 if (flags & ATMEL_SSC_RF)
Julien Maycaf18f12008-09-24 10:30:47 +02001608 pin_mask |= (1 << 21); /* RF */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001609 if (flags & ATMEL_SSC_RK)
Julien Maycaf18f12008-09-24 10:30:47 +02001610 pin_mask |= (1 << 22); /* RK */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001611 if (flags & ATMEL_SSC_TK)
Julien Maycaf18f12008-09-24 10:30:47 +02001612 pin_mask |= (1 << 23); /* TK */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001613 if (flags & ATMEL_SSC_TF)
Julien Maycaf18f12008-09-24 10:30:47 +02001614 pin_mask |= (1 << 24); /* TF */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001615 if (flags & ATMEL_SSC_TD)
Julien Maycaf18f12008-09-24 10:30:47 +02001616 pin_mask |= (1 << 25); /* TD */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001617 if (flags & ATMEL_SSC_RD)
Julien Maycaf18f12008-09-24 10:30:47 +02001618 pin_mask |= (1 << 26); /* RD */
1619
1620 if (pin_mask > 0)
1621 select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
1622
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001623 break;
1624 case 1:
1625 pdev = &ssc1_device;
1626 if (flags & ATMEL_SSC_RF)
Julien Maycaf18f12008-09-24 10:30:47 +02001627 pin_mask |= (1 << 0); /* RF */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001628 if (flags & ATMEL_SSC_RK)
Julien Maycaf18f12008-09-24 10:30:47 +02001629 pin_mask |= (1 << 1); /* RK */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001630 if (flags & ATMEL_SSC_TK)
Julien Maycaf18f12008-09-24 10:30:47 +02001631 pin_mask |= (1 << 2); /* TK */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001632 if (flags & ATMEL_SSC_TF)
Julien Maycaf18f12008-09-24 10:30:47 +02001633 pin_mask |= (1 << 3); /* TF */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001634 if (flags & ATMEL_SSC_TD)
Julien Maycaf18f12008-09-24 10:30:47 +02001635 pin_mask |= (1 << 4); /* TD */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001636 if (flags & ATMEL_SSC_RD)
Julien Maycaf18f12008-09-24 10:30:47 +02001637 pin_mask |= (1 << 5); /* RD */
1638
1639 if (pin_mask > 0)
1640 select_peripheral(PIOA, pin_mask, PERIPH_B, 0);
1641
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001642 break;
1643 case 2:
1644 pdev = &ssc2_device;
1645 if (flags & ATMEL_SSC_TD)
Julien Maycaf18f12008-09-24 10:30:47 +02001646 pin_mask |= (1 << 13); /* TD */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001647 if (flags & ATMEL_SSC_RD)
Julien Maycaf18f12008-09-24 10:30:47 +02001648 pin_mask |= (1 << 14); /* RD */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001649 if (flags & ATMEL_SSC_TK)
Julien Maycaf18f12008-09-24 10:30:47 +02001650 pin_mask |= (1 << 15); /* TK */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001651 if (flags & ATMEL_SSC_TF)
Julien Maycaf18f12008-09-24 10:30:47 +02001652 pin_mask |= (1 << 16); /* TF */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001653 if (flags & ATMEL_SSC_RF)
Julien Maycaf18f12008-09-24 10:30:47 +02001654 pin_mask |= (1 << 17); /* RF */
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001655 if (flags & ATMEL_SSC_RK)
Julien Maycaf18f12008-09-24 10:30:47 +02001656 pin_mask |= (1 << 18); /* RK */
1657
1658 if (pin_mask > 0)
1659 select_peripheral(PIOB, pin_mask, PERIPH_A, 0);
1660
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02001661 break;
1662 default:
1663 return NULL;
1664 }
1665
1666 platform_device_register(pdev);
1667 return pdev;
1668}
1669
1670/* --------------------------------------------------------------------
Haavard Skinnemoen6fcf0612007-06-14 17:37:31 +02001671 * USB Device Controller
1672 * -------------------------------------------------------------------- */
1673static struct resource usba0_resource[] __initdata = {
1674 {
1675 .start = 0xff300000,
1676 .end = 0xff3fffff,
1677 .flags = IORESOURCE_MEM,
1678 }, {
1679 .start = 0xfff03000,
1680 .end = 0xfff033ff,
1681 .flags = IORESOURCE_MEM,
1682 },
1683 IRQ(31),
1684};
1685static struct clk usba0_pclk = {
1686 .name = "pclk",
1687 .parent = &pbb_clk,
1688 .mode = pbb_clk_mode,
1689 .get_rate = pbb_clk_get_rate,
1690 .index = 12,
1691};
1692static struct clk usba0_hclk = {
1693 .name = "hclk",
1694 .parent = &hsb_clk,
1695 .mode = hsb_clk_mode,
1696 .get_rate = hsb_clk_get_rate,
1697 .index = 6,
1698};
1699
Stelian Pop8d855312008-03-05 00:00:00 +01001700#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
1701 [idx] = { \
1702 .name = nam, \
1703 .index = idx, \
1704 .fifo_size = maxpkt, \
1705 .nr_banks = maxbk, \
1706 .can_dma = dma, \
1707 .can_isoc = isoc, \
1708 }
1709
1710static struct usba_ep_data at32_usba_ep[] __initdata = {
1711 EP("ep0", 0, 64, 1, 0, 0),
1712 EP("ep1", 1, 512, 2, 1, 1),
1713 EP("ep2", 2, 512, 2, 1, 1),
1714 EP("ep3-int", 3, 64, 3, 1, 0),
1715 EP("ep4-int", 4, 64, 3, 1, 0),
1716 EP("ep5", 5, 1024, 3, 1, 1),
1717 EP("ep6", 6, 1024, 3, 1, 1),
1718};
1719
1720#undef EP
1721
Haavard Skinnemoen6fcf0612007-06-14 17:37:31 +02001722struct platform_device *__init
1723at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
1724{
Stelian Pop8d855312008-03-05 00:00:00 +01001725 /*
1726 * pdata doesn't have room for any endpoints, so we need to
1727 * append room for the ones we need right after it.
1728 */
1729 struct {
1730 struct usba_platform_data pdata;
1731 struct usba_ep_data ep[7];
1732 } usba_data;
Haavard Skinnemoen6fcf0612007-06-14 17:37:31 +02001733 struct platform_device *pdev;
1734
1735 if (id != 0)
1736 return NULL;
1737
1738 pdev = platform_device_alloc("atmel_usba_udc", 0);
1739 if (!pdev)
1740 return NULL;
1741
1742 if (platform_device_add_resources(pdev, usba0_resource,
1743 ARRAY_SIZE(usba0_resource)))
1744 goto out_free_pdev;
1745
Stelian Pop8d855312008-03-05 00:00:00 +01001746 if (data)
1747 usba_data.pdata.vbus_pin = data->vbus_pin;
1748 else
1749 usba_data.pdata.vbus_pin = -EINVAL;
Haavard Skinnemoen6fcf0612007-06-14 17:37:31 +02001750
Stelian Pop8d855312008-03-05 00:00:00 +01001751 data = &usba_data.pdata;
1752 data->num_ep = ARRAY_SIZE(at32_usba_ep);
1753 memcpy(data->ep, at32_usba_ep, sizeof(at32_usba_ep));
1754
1755 if (platform_device_add_data(pdev, data, sizeof(usba_data)))
1756 goto out_free_pdev;
1757
Hans-Christian Egtvedt9477ab22009-03-24 15:45:21 +01001758 if (gpio_is_valid(data->vbus_pin))
Stelian Pop8d855312008-03-05 00:00:00 +01001759 at32_select_gpio(data->vbus_pin, 0);
Haavard Skinnemoen6fcf0612007-06-14 17:37:31 +02001760
1761 usba0_pclk.dev = &pdev->dev;
1762 usba0_hclk.dev = &pdev->dev;
1763
1764 platform_device_add(pdev);
1765
1766 return pdev;
1767
1768out_free_pdev:
1769 platform_device_put(pdev);
1770 return NULL;
1771}
1772
1773/* --------------------------------------------------------------------
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001774 * IDE / CompactFlash
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001775 * -------------------------------------------------------------------- */
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01001776#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7001)
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001777static struct resource at32_smc_cs4_resource[] __initdata = {
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001778 {
1779 .start = 0x04000000,
1780 .end = 0x07ffffff,
1781 .flags = IORESOURCE_MEM,
1782 },
1783 IRQ(~0UL), /* Magic IRQ will be overridden */
1784};
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001785static struct resource at32_smc_cs5_resource[] __initdata = {
1786 {
1787 .start = 0x20000000,
1788 .end = 0x23ffffff,
1789 .flags = IORESOURCE_MEM,
1790 },
1791 IRQ(~0UL), /* Magic IRQ will be overridden */
1792};
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001793
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001794static int __init at32_init_ide_or_cf(struct platform_device *pdev,
1795 unsigned int cs, unsigned int extint)
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001796{
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001797 static unsigned int extint_pin_map[4] __initdata = {
Julien Maycaf18f12008-09-24 10:30:47 +02001798 (1 << 25),
1799 (1 << 26),
1800 (1 << 27),
1801 (1 << 28),
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001802 };
1803 static bool common_pins_initialized __initdata = false;
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001804 unsigned int extint_pin;
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001805 int ret;
Julien Maycaf18f12008-09-24 10:30:47 +02001806 u32 pin_mask;
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001807
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001808 if (extint >= ARRAY_SIZE(extint_pin_map))
1809 return -EINVAL;
1810 extint_pin = extint_pin_map[extint];
1811
1812 switch (cs) {
1813 case 4:
1814 ret = platform_device_add_resources(pdev,
1815 at32_smc_cs4_resource,
1816 ARRAY_SIZE(at32_smc_cs4_resource));
1817 if (ret)
1818 return ret;
1819
Julien Maycaf18f12008-09-24 10:30:47 +02001820 /* NCS4 -> OE_N */
1821 select_peripheral(PIOE, (1 << 21), PERIPH_A, 0);
Haavard Skinnemoenb47eb402008-07-31 15:56:36 +02001822 hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF0_ENABLE);
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001823 break;
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001824 case 5:
1825 ret = platform_device_add_resources(pdev,
1826 at32_smc_cs5_resource,
1827 ARRAY_SIZE(at32_smc_cs5_resource));
1828 if (ret)
1829 return ret;
1830
Julien Maycaf18f12008-09-24 10:30:47 +02001831 /* NCS5 -> OE_N */
1832 select_peripheral(PIOE, (1 << 22), PERIPH_A, 0);
Haavard Skinnemoenb47eb402008-07-31 15:56:36 +02001833 hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF1_ENABLE);
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001834 break;
1835 default:
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001836 return -EINVAL;
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001837 }
1838
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001839 if (!common_pins_initialized) {
Julien Maycaf18f12008-09-24 10:30:47 +02001840 pin_mask = (1 << 19); /* CFCE1 -> CS0_N */
1841 pin_mask |= (1 << 20); /* CFCE2 -> CS1_N */
1842 pin_mask |= (1 << 23); /* CFRNW -> DIR */
1843 pin_mask |= (1 << 24); /* NWAIT <- IORDY */
1844
1845 select_peripheral(PIOE, pin_mask, PERIPH_A, 0);
1846
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001847 common_pins_initialized = true;
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001848 }
1849
Julien Maycaf18f12008-09-24 10:30:47 +02001850 select_peripheral(PIOB, extint_pin, PERIPH_A, AT32_GPIOF_DEGLITCH);
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001851
1852 pdev->resource[1].start = EIM_IRQ_BASE + extint;
1853 pdev->resource[1].end = pdev->resource[1].start;
1854
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001855 return 0;
1856}
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001857
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001858struct platform_device *__init
1859at32_add_device_ide(unsigned int id, unsigned int extint,
1860 struct ide_platform_data *data)
1861{
1862 struct platform_device *pdev;
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001863
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001864 pdev = platform_device_alloc("at32_ide", id);
1865 if (!pdev)
1866 goto fail;
1867
1868 if (platform_device_add_data(pdev, data,
1869 sizeof(struct ide_platform_data)))
1870 goto fail;
1871
1872 if (at32_init_ide_or_cf(pdev, data->cs, extint))
1873 goto fail;
1874
1875 platform_device_add(pdev);
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001876 return pdev;
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001877
1878fail:
1879 platform_device_put(pdev);
1880 return NULL;
1881}
1882
1883struct platform_device *__init
1884at32_add_device_cf(unsigned int id, unsigned int extint,
1885 struct cf_platform_data *data)
1886{
1887 struct platform_device *pdev;
1888
1889 pdev = platform_device_alloc("at32_cf", id);
1890 if (!pdev)
1891 goto fail;
1892
1893 if (platform_device_add_data(pdev, data,
1894 sizeof(struct cf_platform_data)))
1895 goto fail;
1896
1897 if (at32_init_ide_or_cf(pdev, data->cs, extint))
1898 goto fail;
1899
David Brownell3c26e172008-07-27 02:34:45 -07001900 if (gpio_is_valid(data->detect_pin))
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001901 at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
David Brownell3c26e172008-07-27 02:34:45 -07001902 if (gpio_is_valid(data->reset_pin))
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001903 at32_select_gpio(data->reset_pin, 0);
David Brownell3c26e172008-07-27 02:34:45 -07001904 if (gpio_is_valid(data->vcc_pin))
Haavard Skinnemoeneaf5f922007-10-22 18:32:14 +02001905 at32_select_gpio(data->vcc_pin, 0);
1906 /* READY is used as extint, so we can't select it as gpio */
1907
1908 platform_device_add(pdev);
1909 return pdev;
1910
1911fail:
1912 platform_device_put(pdev);
1913 return NULL;
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001914}
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01001915#endif
Kristoffer Nyborg Gregertsen48021bd2007-08-16 13:45:00 +02001916
1917/* --------------------------------------------------------------------
HÃ¥vard Skinnemoen62090a02008-06-06 18:04:56 +02001918 * NAND Flash / SmartMedia
1919 * -------------------------------------------------------------------- */
1920static struct resource smc_cs3_resource[] __initdata = {
1921 {
1922 .start = 0x0c000000,
1923 .end = 0x0fffffff,
1924 .flags = IORESOURCE_MEM,
1925 }, {
1926 .start = 0xfff03c00,
1927 .end = 0xfff03fff,
1928 .flags = IORESOURCE_MEM,
1929 },
1930};
1931
1932struct platform_device *__init
1933at32_add_device_nand(unsigned int id, struct atmel_nand_data *data)
1934{
1935 struct platform_device *pdev;
1936
1937 if (id != 0 || !data)
1938 return NULL;
1939
1940 pdev = platform_device_alloc("atmel_nand", id);
1941 if (!pdev)
1942 goto fail;
1943
1944 if (platform_device_add_resources(pdev, smc_cs3_resource,
1945 ARRAY_SIZE(smc_cs3_resource)))
1946 goto fail;
1947
1948 if (platform_device_add_data(pdev, data,
1949 sizeof(struct atmel_nand_data)))
1950 goto fail;
1951
Haavard Skinnemoenb47eb402008-07-31 15:56:36 +02001952 hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_NAND_ENABLE);
HÃ¥vard Skinnemoen62090a02008-06-06 18:04:56 +02001953 if (data->enable_pin)
1954 at32_select_gpio(data->enable_pin,
1955 AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
1956 if (data->rdy_pin)
1957 at32_select_gpio(data->rdy_pin, 0);
1958 if (data->det_pin)
1959 at32_select_gpio(data->det_pin, 0);
1960
1961 platform_device_add(pdev);
1962 return pdev;
1963
1964fail:
1965 platform_device_put(pdev);
1966 return NULL;
1967}
1968
1969/* --------------------------------------------------------------------
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001970 * AC97C
1971 * -------------------------------------------------------------------- */
1972static struct resource atmel_ac97c0_resource[] __initdata = {
1973 PBMEM(0xfff02800),
1974 IRQ(29),
1975};
1976static struct clk atmel_ac97c0_pclk = {
1977 .name = "pclk",
1978 .parent = &pbb_clk,
1979 .mode = pbb_clk_mode,
1980 .get_rate = pbb_clk_get_rate,
1981 .index = 10,
1982};
1983
Hans-Christian Egtvedt218df4a2008-07-01 14:26:45 +02001984struct platform_device *__init
1985at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data)
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001986{
1987 struct platform_device *pdev;
Hans-Christian Egtvedt218df4a2008-07-01 14:26:45 +02001988 struct ac97c_platform_data _data;
Julien Maycaf18f12008-09-24 10:30:47 +02001989 u32 pin_mask;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02001990
1991 if (id != 0)
1992 return NULL;
1993
1994 pdev = platform_device_alloc("atmel_ac97c", id);
1995 if (!pdev)
1996 return NULL;
1997
1998 if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
1999 ARRAY_SIZE(atmel_ac97c0_resource)))
Hans-Christian Egtvedt218df4a2008-07-01 14:26:45 +02002000 goto fail;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002001
Hans-Christian Egtvedt218df4a2008-07-01 14:26:45 +02002002 if (!data) {
2003 data = &_data;
2004 memset(data, 0, sizeof(struct ac97c_platform_data));
2005 data->reset_pin = GPIO_PIN_NONE;
2006 }
2007
2008 data->dma_rx_periph_id = 3;
2009 data->dma_tx_periph_id = 4;
2010 data->dma_controller_id = 0;
2011
2012 if (platform_device_add_data(pdev, data,
2013 sizeof(struct ac97c_platform_data)))
2014 goto fail;
2015
Julien Maycaf18f12008-09-24 10:30:47 +02002016 pin_mask = (1 << 20) | (1 << 21); /* SDO & SYNC */
2017 pin_mask |= (1 << 22) | (1 << 23); /* SCLK & SDI */
2018
2019 select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
Hans-Christian Egtvedt218df4a2008-07-01 14:26:45 +02002020
2021 /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */
2022 if (data->reset_pin != GPIO_PIN_NONE)
2023 at32_select_gpio(data->reset_pin, 0);
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002024
2025 atmel_ac97c0_pclk.dev = &pdev->dev;
2026
2027 platform_device_add(pdev);
2028 return pdev;
2029
Hans-Christian Egtvedt218df4a2008-07-01 14:26:45 +02002030fail:
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002031 platform_device_put(pdev);
2032 return NULL;
2033}
2034
2035/* --------------------------------------------------------------------
2036 * ABDAC
2037 * -------------------------------------------------------------------- */
2038static struct resource abdac0_resource[] __initdata = {
2039 PBMEM(0xfff02000),
2040 IRQ(27),
2041};
2042static struct clk abdac0_pclk = {
2043 .name = "pclk",
2044 .parent = &pbb_clk,
2045 .mode = pbb_clk_mode,
2046 .get_rate = pbb_clk_get_rate,
2047 .index = 8,
2048};
2049static struct clk abdac0_sample_clk = {
2050 .name = "sample_clk",
2051 .mode = genclk_mode,
2052 .get_rate = genclk_get_rate,
2053 .set_rate = genclk_set_rate,
2054 .set_parent = genclk_set_parent,
2055 .index = 6,
2056};
2057
Hans-Christian Egtvedt6b0c9352009-03-24 13:59:22 +01002058struct platform_device *__init
2059at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data)
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002060{
Hans-Christian Egtvedt6b0c9352009-03-24 13:59:22 +01002061 struct platform_device *pdev;
2062 struct dw_dma_slave *dws;
2063 u32 pin_mask;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002064
Hans-Christian Egtvedt6b0c9352009-03-24 13:59:22 +01002065 if (id != 0 || !data)
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002066 return NULL;
2067
Hans-Christian Egtvedt6b0c9352009-03-24 13:59:22 +01002068 pdev = platform_device_alloc("atmel_abdac", id);
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002069 if (!pdev)
2070 return NULL;
2071
2072 if (platform_device_add_resources(pdev, abdac0_resource,
2073 ARRAY_SIZE(abdac0_resource)))
Hans-Christian Egtvedt6b0c9352009-03-24 13:59:22 +01002074 goto out_free_resources;
2075
2076 dws = &data->dws;
2077
2078 dws->dma_dev = &dw_dmac0_device.dev;
2079 dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
2080 dws->cfg_hi = DWC_CFGH_DST_PER(2);
2081 dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
2082
2083 if (platform_device_add_data(pdev, data,
2084 sizeof(struct atmel_abdac_pdata)))
2085 goto out_free_resources;
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002086
Julien Maycaf18f12008-09-24 10:30:47 +02002087 pin_mask = (1 << 20) | (1 << 22); /* DATA1 & DATAN1 */
2088 pin_mask |= (1 << 21) | (1 << 23); /* DATA0 & DATAN0 */
2089
2090 select_peripheral(PIOB, pin_mask, PERIPH_A, 0);
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002091
2092 abdac0_pclk.dev = &pdev->dev;
2093 abdac0_sample_clk.dev = &pdev->dev;
2094
2095 platform_device_add(pdev);
2096 return pdev;
2097
Hans-Christian Egtvedt6b0c9352009-03-24 13:59:22 +01002098out_free_resources:
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002099 platform_device_put(pdev);
2100 return NULL;
2101}
2102
2103/* --------------------------------------------------------------------
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +01002104 * GCLK
2105 * -------------------------------------------------------------------- */
2106static struct clk gclk0 = {
2107 .name = "gclk0",
2108 .mode = genclk_mode,
2109 .get_rate = genclk_get_rate,
2110 .set_rate = genclk_set_rate,
2111 .set_parent = genclk_set_parent,
2112 .index = 0,
2113};
2114static struct clk gclk1 = {
2115 .name = "gclk1",
2116 .mode = genclk_mode,
2117 .get_rate = genclk_get_rate,
2118 .set_rate = genclk_set_rate,
2119 .set_parent = genclk_set_parent,
2120 .index = 1,
2121};
2122static struct clk gclk2 = {
2123 .name = "gclk2",
2124 .mode = genclk_mode,
2125 .get_rate = genclk_get_rate,
2126 .set_rate = genclk_set_rate,
2127 .set_parent = genclk_set_parent,
2128 .index = 2,
2129};
2130static struct clk gclk3 = {
2131 .name = "gclk3",
2132 .mode = genclk_mode,
2133 .get_rate = genclk_get_rate,
2134 .set_rate = genclk_set_rate,
2135 .set_parent = genclk_set_parent,
2136 .index = 3,
2137};
2138static struct clk gclk4 = {
2139 .name = "gclk4",
2140 .mode = genclk_mode,
2141 .get_rate = genclk_get_rate,
2142 .set_rate = genclk_set_rate,
2143 .set_parent = genclk_set_parent,
2144 .index = 4,
2145};
2146
Alex Raimondi300bb762008-09-22 21:40:55 +02002147static __initdata struct clk *init_clocks[] = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002148 &osc32k,
2149 &osc0,
2150 &osc1,
2151 &pll0,
2152 &pll1,
2153 &cpu_clk,
2154 &hsb_clk,
2155 &pba_clk,
2156 &pbb_clk,
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +02002157 &at32_pm_pclk,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002158 &at32_intc0_pclk,
Haavard Skinnemoenb47eb402008-07-31 15:56:36 +02002159 &at32_hmatrix_clk,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002160 &ebi_clk,
2161 &hramc_clk,
Haavard Skinnemoen7951f182008-03-05 15:08:27 +01002162 &sdramc_clk,
Haavard Skinnemoenbc157b72006-09-25 23:32:16 -07002163 &smc0_pclk,
2164 &smc0_mck,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002165 &pdc_hclk,
2166 &pdc_pclk,
Haavard Skinnemoen3bfb1d22008-07-08 11:59:42 -07002167 &dw_dmac0_hclk,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002168 &pico_clk,
2169 &pio0_mck,
2170 &pio1_mck,
2171 &pio2_mck,
2172 &pio3_mck,
Haavard Skinnemoen7f9f4672007-01-30 11:16:16 +01002173 &pio4_mck,
David Brownelle723ff62008-02-14 11:24:02 -08002174 &at32_tcb0_t0_clk,
2175 &at32_tcb1_t0_clk,
Hans-Christian Egtvedtd86d3142008-02-25 11:24:30 +01002176 &atmel_psif0_pclk,
2177 &atmel_psif1_pclk,
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +02002178 &atmel_usart0_usart,
2179 &atmel_usart1_usart,
2180 &atmel_usart2_usart,
2181 &atmel_usart3_usart,
David Brownell9a1e8eb2008-02-08 04:21:21 -08002182 &atmel_pwm0_mck,
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01002183#if defined(CONFIG_CPU_AT32AP7000)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002184 &macb0_hclk,
2185 &macb0_pclk,
Haavard Skinnemoencfcb3a82006-10-30 09:23:12 +01002186 &macb1_hclk,
2187 &macb1_pclk,
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01002188#endif
Haavard Skinnemoen3d60ee12007-01-10 20:20:02 +01002189 &atmel_spi0_spi_clk,
2190 &atmel_spi1_spi_clk,
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002191 &atmel_twi0_pclk,
2192 &atmel_mci0_pclk,
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01002193#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002)
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01002194 &atmel_lcdfb0_hck1,
2195 &atmel_lcdfb0_pixclk,
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01002196#endif
Hans-Christian Egtvedt9cf6cf52007-07-06 14:31:55 +02002197 &ssc0_pclk,
2198 &ssc1_pclk,
2199 &ssc2_pclk,
Haavard Skinnemoen6fcf0612007-06-14 17:37:31 +02002200 &usba0_hclk,
2201 &usba0_pclk,
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002202 &atmel_ac97c0_pclk,
2203 &abdac0_pclk,
2204 &abdac0_sample_clk,
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +01002205 &gclk0,
2206 &gclk1,
2207 &gclk2,
2208 &gclk3,
2209 &gclk4,
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002210};
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002211
Haavard Skinnemoen65033ed2008-03-04 15:15:00 +01002212void __init setup_platform(void)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002213{
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002214 u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
2215 int i;
2216
Hans-Christian Egtvedt9e58e182007-06-04 16:10:57 +02002217 if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002218 main_clock = &pll0;
Hans-Christian Egtvedt9e58e182007-06-04 16:10:57 +02002219 cpu_clk.parent = &pll0;
2220 } else {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002221 main_clock = &osc0;
Hans-Christian Egtvedt9e58e182007-06-04 16:10:57 +02002222 cpu_clk.parent = &osc0;
2223 }
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002224
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +02002225 if (pm_readl(PLL0) & PM_BIT(PLLOSC))
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002226 pll0.parent = &osc1;
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +02002227 if (pm_readl(PLL1) & PM_BIT(PLLOSC))
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002228 pll1.parent = &osc1;
2229
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +01002230 genclk_init_parent(&gclk0);
2231 genclk_init_parent(&gclk1);
2232 genclk_init_parent(&gclk2);
2233 genclk_init_parent(&gclk3);
2234 genclk_init_parent(&gclk4);
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01002235#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002)
Haavard Skinnemoend0a2b7a2007-03-21 18:08:49 +01002236 genclk_init_parent(&atmel_lcdfb0_pixclk);
Haavard Skinnemoen438ff3f2007-10-29 15:28:07 +01002237#endif
Haavard Skinnemoen2042c1c2007-10-22 17:42:35 +02002238 genclk_init_parent(&abdac0_sample_clk);
Haavard Skinnemoen7a5fe232007-02-16 13:14:33 +01002239
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002240 /*
Alex Raimondi300bb762008-09-22 21:40:55 +02002241 * Build initial dynamic clock list by registering all clocks
2242 * from the array.
2243 * At the same time, turn on all clocks that have at least one
2244 * user already, and turn off everything else. We only do this
2245 * for module clocks, and even though it isn't particularly
2246 * pretty to check the address of the mode function, it should
2247 * do the trick...
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002248 */
Alex Raimondi300bb762008-09-22 21:40:55 +02002249 for (i = 0; i < ARRAY_SIZE(init_clocks); i++) {
2250 struct clk *clk = init_clocks[i];
2251
2252 /* first, register clock */
2253 at32_clk_register(clk);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002254
Haavard Skinnemoen188ff652007-03-14 13:23:44 +01002255 if (clk->users == 0)
2256 continue;
2257
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002258 if (clk->mode == &cpu_clk_mode)
2259 cpu_mask |= 1 << clk->index;
2260 else if (clk->mode == &hsb_clk_mode)
2261 hsb_mask |= 1 << clk->index;
2262 else if (clk->mode == &pba_clk_mode)
2263 pba_mask |= 1 << clk->index;
2264 else if (clk->mode == &pbb_clk_mode)
2265 pbb_mask |= 1 << clk->index;
2266 }
2267
Haavard Skinnemoen7a5b8052007-06-04 12:58:30 +02002268 pm_writel(CPU_MASK, cpu_mask);
2269 pm_writel(HSB_MASK, hsb_mask);
2270 pm_writel(PBA_MASK, pba_mask);
2271 pm_writel(PBB_MASK, pbb_mask);
Haavard Skinnemoen65033ed2008-03-04 15:15:00 +01002272
2273 /* Initialize the port muxes */
2274 at32_init_pio(&pio0_device);
2275 at32_init_pio(&pio1_device);
2276 at32_init_pio(&pio2_device);
2277 at32_init_pio(&pio3_device);
2278 at32_init_pio(&pio4_device);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07002279}
Haavard Skinnemoenb83d6ee2008-03-05 10:00:28 +01002280
2281struct gen_pool *sram_pool;
2282
2283static int __init sram_init(void)
2284{
2285 struct gen_pool *pool;
2286
2287 /* 1KiB granularity */
2288 pool = gen_pool_create(10, -1);
2289 if (!pool)
2290 goto fail;
2291
2292 if (gen_pool_add(pool, 0x24000000, 0x8000, -1))
2293 goto err_pool_add;
2294
2295 sram_pool = pool;
2296 return 0;
2297
2298err_pool_add:
2299 gen_pool_destroy(pool);
2300fail:
2301 pr_err("Failed to create SRAM pool\n");
2302 return -ENOMEM;
2303}
2304core_initcall(sram_init);