blob: 8ff7720b3e4a4b80ca627d005a2b5ae0591258d0 [file] [log] [blame]
Andrew Victor877d7722007-05-11 20:49:56 +01001/*
2 * arch/arm/mach-at91/at91sam9rl.c
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2007 Atmel Corporation
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
9 * more details.
10 */
11
12#include <linux/module.h>
Andrew Victor3ef2fb42008-04-02 21:36:06 +010013#include <linux/pm.h>
Andrew Victor877d7722007-05-11 20:49:56 +010014
Russell King80b02c12009-01-08 10:01:47 +000015#include <asm/irq.h>
Andrew Victor877d7722007-05-11 20:49:56 +010016#include <asm/mach/arch.h>
17#include <asm/mach/map.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010018#include <mach/cpu.h>
19#include <mach/at91sam9rl.h>
20#include <mach/at91_pmc.h>
21#include <mach/at91_rstc.h>
22#include <mach/at91_shdwc.h>
Andrew Victor877d7722007-05-11 20:49:56 +010023
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +080024#include "soc.h"
Andrew Victor877d7722007-05-11 20:49:56 +010025#include "generic.h"
26#include "clock.h"
27
Andrew Victor877d7722007-05-11 20:49:56 +010028static struct map_desc at91sam9rl_sram_desc[] __initdata = {
29 {
30 .pfn = __phys_to_pfn(AT91SAM9RL_SRAM_BASE),
31 .type = MT_DEVICE,
32 }
33};
34
35/* --------------------------------------------------------------------
36 * Clocks
37 * -------------------------------------------------------------------- */
38
39/*
40 * The peripheral clocks.
41 */
42static struct clk pioA_clk = {
43 .name = "pioA_clk",
44 .pmc_mask = 1 << AT91SAM9RL_ID_PIOA,
45 .type = CLK_TYPE_PERIPHERAL,
46};
47static struct clk pioB_clk = {
48 .name = "pioB_clk",
49 .pmc_mask = 1 << AT91SAM9RL_ID_PIOB,
50 .type = CLK_TYPE_PERIPHERAL,
51};
52static struct clk pioC_clk = {
53 .name = "pioC_clk",
54 .pmc_mask = 1 << AT91SAM9RL_ID_PIOC,
55 .type = CLK_TYPE_PERIPHERAL,
56};
57static struct clk pioD_clk = {
58 .name = "pioD_clk",
59 .pmc_mask = 1 << AT91SAM9RL_ID_PIOD,
60 .type = CLK_TYPE_PERIPHERAL,
61};
62static struct clk usart0_clk = {
63 .name = "usart0_clk",
64 .pmc_mask = 1 << AT91SAM9RL_ID_US0,
65 .type = CLK_TYPE_PERIPHERAL,
66};
67static struct clk usart1_clk = {
68 .name = "usart1_clk",
69 .pmc_mask = 1 << AT91SAM9RL_ID_US1,
70 .type = CLK_TYPE_PERIPHERAL,
71};
72static struct clk usart2_clk = {
73 .name = "usart2_clk",
74 .pmc_mask = 1 << AT91SAM9RL_ID_US2,
75 .type = CLK_TYPE_PERIPHERAL,
76};
77static struct clk usart3_clk = {
78 .name = "usart3_clk",
79 .pmc_mask = 1 << AT91SAM9RL_ID_US3,
80 .type = CLK_TYPE_PERIPHERAL,
81};
82static struct clk mmc_clk = {
83 .name = "mci_clk",
84 .pmc_mask = 1 << AT91SAM9RL_ID_MCI,
85 .type = CLK_TYPE_PERIPHERAL,
86};
87static struct clk twi0_clk = {
88 .name = "twi0_clk",
89 .pmc_mask = 1 << AT91SAM9RL_ID_TWI0,
90 .type = CLK_TYPE_PERIPHERAL,
91};
92static struct clk twi1_clk = {
93 .name = "twi1_clk",
94 .pmc_mask = 1 << AT91SAM9RL_ID_TWI1,
95 .type = CLK_TYPE_PERIPHERAL,
96};
97static struct clk spi_clk = {
98 .name = "spi_clk",
99 .pmc_mask = 1 << AT91SAM9RL_ID_SPI,
100 .type = CLK_TYPE_PERIPHERAL,
101};
102static struct clk ssc0_clk = {
103 .name = "ssc0_clk",
104 .pmc_mask = 1 << AT91SAM9RL_ID_SSC0,
105 .type = CLK_TYPE_PERIPHERAL,
106};
107static struct clk ssc1_clk = {
108 .name = "ssc1_clk",
109 .pmc_mask = 1 << AT91SAM9RL_ID_SSC1,
110 .type = CLK_TYPE_PERIPHERAL,
111};
112static struct clk tc0_clk = {
113 .name = "tc0_clk",
114 .pmc_mask = 1 << AT91SAM9RL_ID_TC0,
115 .type = CLK_TYPE_PERIPHERAL,
116};
117static struct clk tc1_clk = {
118 .name = "tc1_clk",
119 .pmc_mask = 1 << AT91SAM9RL_ID_TC1,
120 .type = CLK_TYPE_PERIPHERAL,
121};
122static struct clk tc2_clk = {
123 .name = "tc2_clk",
124 .pmc_mask = 1 << AT91SAM9RL_ID_TC2,
125 .type = CLK_TYPE_PERIPHERAL,
126};
Andrew Victorbb1ad682008-09-18 19:42:37 +0100127static struct clk pwm_clk = {
128 .name = "pwm_clk",
Andrew Victor877d7722007-05-11 20:49:56 +0100129 .pmc_mask = 1 << AT91SAM9RL_ID_PWMC,
130 .type = CLK_TYPE_PERIPHERAL,
131};
132static struct clk tsc_clk = {
133 .name = "tsc_clk",
134 .pmc_mask = 1 << AT91SAM9RL_ID_TSC,
135 .type = CLK_TYPE_PERIPHERAL,
136};
137static struct clk dma_clk = {
138 .name = "dma_clk",
139 .pmc_mask = 1 << AT91SAM9RL_ID_DMA,
140 .type = CLK_TYPE_PERIPHERAL,
141};
142static struct clk udphs_clk = {
143 .name = "udphs_clk",
144 .pmc_mask = 1 << AT91SAM9RL_ID_UDPHS,
145 .type = CLK_TYPE_PERIPHERAL,
146};
147static struct clk lcdc_clk = {
148 .name = "lcdc_clk",
149 .pmc_mask = 1 << AT91SAM9RL_ID_LCDC,
150 .type = CLK_TYPE_PERIPHERAL,
151};
152static struct clk ac97_clk = {
153 .name = "ac97_clk",
154 .pmc_mask = 1 << AT91SAM9RL_ID_AC97C,
155 .type = CLK_TYPE_PERIPHERAL,
156};
157
158static struct clk *periph_clocks[] __initdata = {
159 &pioA_clk,
160 &pioB_clk,
161 &pioC_clk,
162 &pioD_clk,
163 &usart0_clk,
164 &usart1_clk,
165 &usart2_clk,
166 &usart3_clk,
167 &mmc_clk,
168 &twi0_clk,
169 &twi1_clk,
170 &spi_clk,
171 &ssc0_clk,
172 &ssc1_clk,
173 &tc0_clk,
174 &tc1_clk,
175 &tc2_clk,
Andrew Victorbb1ad682008-09-18 19:42:37 +0100176 &pwm_clk,
Andrew Victor877d7722007-05-11 20:49:56 +0100177 &tsc_clk,
178 &dma_clk,
179 &udphs_clk,
180 &lcdc_clk,
181 &ac97_clk,
182 // irq0
183};
184
Jean-Christophe PLAGNIOL-VILLARDbd602992011-02-02 07:27:07 +0100185static struct clk_lookup periph_clocks_lookups[] = {
Jean-Christophe PLAGNIOL-VILLARD9d871592011-06-21 14:24:33 +0800186 CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
187 CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
Jean-Christophe PLAGNIOL-VILLARDbd602992011-02-02 07:27:07 +0100188 CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
189 CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
190 CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
191 CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
192 CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
193};
194
195static struct clk_lookup usart_clocks_lookups[] = {
196 CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),
197 CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),
198 CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),
199 CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),
200 CLKDEV_CON_DEV_ID("usart", "atmel_usart.4", &usart3_clk),
201};
202
Andrew Victor877d7722007-05-11 20:49:56 +0100203/*
204 * The two programmable clocks.
205 * You must configure pin multiplexing to bring these signals out.
206 */
207static struct clk pck0 = {
208 .name = "pck0",
209 .pmc_mask = AT91_PMC_PCK0,
210 .type = CLK_TYPE_PROGRAMMABLE,
211 .id = 0,
212};
213static struct clk pck1 = {
214 .name = "pck1",
215 .pmc_mask = AT91_PMC_PCK1,
216 .type = CLK_TYPE_PROGRAMMABLE,
217 .id = 1,
218};
219
220static void __init at91sam9rl_register_clocks(void)
221{
222 int i;
223
224 for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
225 clk_register(periph_clocks[i]);
226
Jean-Christophe PLAGNIOL-VILLARDbd602992011-02-02 07:27:07 +0100227 clkdev_add_table(periph_clocks_lookups,
228 ARRAY_SIZE(periph_clocks_lookups));
229 clkdev_add_table(usart_clocks_lookups,
230 ARRAY_SIZE(usart_clocks_lookups));
231
Andrew Victor877d7722007-05-11 20:49:56 +0100232 clk_register(&pck0);
233 clk_register(&pck1);
234}
235
Jean-Christophe PLAGNIOL-VILLARDbd602992011-02-02 07:27:07 +0100236static struct clk_lookup console_clock_lookup;
237
238void __init at91sam9rl_set_console_clock(int id)
239{
240 if (id >= ARRAY_SIZE(usart_clocks_lookups))
241 return;
242
243 console_clock_lookup.con_id = "usart";
244 console_clock_lookup.clk = usart_clocks_lookups[id].clk;
245 clkdev_add(&console_clock_lookup);
246}
247
Andrew Victor877d7722007-05-11 20:49:56 +0100248/* --------------------------------------------------------------------
249 * GPIO
250 * -------------------------------------------------------------------- */
251
252static struct at91_gpio_bank at91sam9rl_gpio[] = {
253 {
254 .id = AT91SAM9RL_ID_PIOA,
255 .offset = AT91_PIOA,
256 .clock = &pioA_clk,
257 }, {
258 .id = AT91SAM9RL_ID_PIOB,
259 .offset = AT91_PIOB,
260 .clock = &pioB_clk,
261 }, {
262 .id = AT91SAM9RL_ID_PIOC,
263 .offset = AT91_PIOC,
264 .clock = &pioC_clk,
265 }, {
266 .id = AT91SAM9RL_ID_PIOD,
267 .offset = AT91_PIOD,
268 .clock = &pioD_clk,
269 }
270};
271
Andrew Victor3ef2fb42008-04-02 21:36:06 +0100272static void at91sam9rl_poweroff(void)
273{
274 at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
275}
276
Andrew Victor877d7722007-05-11 20:49:56 +0100277
278/* --------------------------------------------------------------------
279 * AT91SAM9RL processor initialization
280 * -------------------------------------------------------------------- */
281
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +0800282static void __init at91sam9rl_map_io(void)
Andrew Victor877d7722007-05-11 20:49:56 +0100283{
284 unsigned long cidr, sram_size;
285
Andrew Victor877d7722007-05-11 20:49:56 +0100286 cidr = at91_sys_read(AT91_DBGU_CIDR);
287
288 switch (cidr & AT91_CIDR_SRAMSIZ) {
289 case AT91_CIDR_SRAMSIZ_32K:
290 sram_size = 2 * SZ_16K;
291 break;
292 case AT91_CIDR_SRAMSIZ_16K:
293 default:
294 sram_size = SZ_16K;
295 }
296
297 at91sam9rl_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
298 at91sam9rl_sram_desc->length = sram_size;
299
300 /* Map SRAM */
301 iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc));
Jean-Christophe PLAGNIOL-VILLARD1b021a32011-04-28 20:19:32 +0800302}
Andrew Victor877d7722007-05-11 20:49:56 +0100303
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +0800304static void __init at91sam9rl_initialize(unsigned long main_clock)
Jean-Christophe PLAGNIOL-VILLARD1b021a32011-04-28 20:19:32 +0800305{
Nicolas Ferrebb413db2010-10-14 19:14:00 +0200306 at91_arch_reset = at91sam9_alt_reset;
Andrew Victor3ef2fb42008-04-02 21:36:06 +0100307 pm_power_off = at91sam9rl_poweroff;
Andrew Victor877d7722007-05-11 20:49:56 +0100308 at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0);
309
310 /* Init clock subsystem */
311 at91_clock_init(main_clock);
312
313 /* Register the processor-specific clocks */
314 at91sam9rl_register_clocks();
315
316 /* Register GPIO subsystem */
317 at91_gpio_init(at91sam9rl_gpio, 4);
318}
319
320/* --------------------------------------------------------------------
321 * Interrupt initialization
322 * -------------------------------------------------------------------- */
323
324/*
325 * The default interrupt priority levels (0 = lowest, 7 = highest).
326 */
327static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
328 7, /* Advanced Interrupt Controller */
329 7, /* System Peripherals */
330 1, /* Parallel IO Controller A */
331 1, /* Parallel IO Controller B */
332 1, /* Parallel IO Controller C */
333 1, /* Parallel IO Controller D */
334 5, /* USART 0 */
335 5, /* USART 1 */
336 5, /* USART 2 */
337 5, /* USART 3 */
338 0, /* Multimedia Card Interface */
339 6, /* Two-Wire Interface 0 */
340 6, /* Two-Wire Interface 1 */
341 5, /* Serial Peripheral Interface */
342 4, /* Serial Synchronous Controller 0 */
343 4, /* Serial Synchronous Controller 1 */
344 0, /* Timer Counter 0 */
345 0, /* Timer Counter 1 */
346 0, /* Timer Counter 2 */
347 0,
348 0, /* Touch Screen Controller */
349 0, /* DMA Controller */
350 2, /* USB Device High speed port */
351 2, /* LCD Controller */
352 6, /* AC97 Controller */
353 0,
354 0,
355 0,
356 0,
357 0,
358 0,
359 0, /* Advanced Interrupt Controller */
360};
361
362void __init at91sam9rl_init_interrupts(unsigned int priority[NR_AIC_IRQS])
363{
364 if (!priority)
365 priority = at91sam9rl_default_irq_priority;
366
367 /* Initialize the AIC interrupt controller */
368 at91_aic_init(priority);
369
370 /* Enable GPIO interrupts */
371 at91_gpio_irq_setup();
372}
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +0800373
374struct at91_soc __initdata at91sam9rl_soc = {
375 .map_io = at91sam9rl_map_io,
376 .init = at91sam9rl_initialize,
377};