1/*
2 * arch/arm/mach-at91/at91sam9261.c
3 *
4 *  Copyright (C) 2005 SAN People
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12
13#include <linux/module.h>
14
15#include <asm/mach/arch.h>
16#include <asm/mach/map.h>
17#include <asm/arch/at91sam9261.h>
18#include <asm/arch/at91_pmc.h>
19#include <asm/arch/at91_rstc.h>
20
21#include "generic.h"
22#include "clock.h"
23
24static struct map_desc at91sam9261_io_desc[] __initdata = {
25	{
26		.virtual	= AT91_VA_BASE_SYS,
27		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
28		.length		= SZ_16K,
29		.type		= MT_DEVICE,
30	}, {
31		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE,
32		.pfn		= __phys_to_pfn(AT91SAM9261_SRAM_BASE),
33		.length		= AT91SAM9261_SRAM_SIZE,
34		.type		= MT_DEVICE,
35	},
36};
37
38/* --------------------------------------------------------------------
39 *  Clocks
40 * -------------------------------------------------------------------- */
41
42/*
43 * The peripheral clocks.
44 */
45static struct clk pioA_clk = {
46	.name		= "pioA_clk",
47	.pmc_mask	= 1 << AT91SAM9261_ID_PIOA,
48	.type		= CLK_TYPE_PERIPHERAL,
49};
50static struct clk pioB_clk = {
51	.name		= "pioB_clk",
52	.pmc_mask	= 1 << AT91SAM9261_ID_PIOB,
53	.type		= CLK_TYPE_PERIPHERAL,
54};
55static struct clk pioC_clk = {
56	.name		= "pioC_clk",
57	.pmc_mask	= 1 << AT91SAM9261_ID_PIOC,
58	.type		= CLK_TYPE_PERIPHERAL,
59};
60static struct clk usart0_clk = {
61	.name		= "usart0_clk",
62	.pmc_mask	= 1 << AT91SAM9261_ID_US0,
63	.type		= CLK_TYPE_PERIPHERAL,
64};
65static struct clk usart1_clk = {
66	.name		= "usart1_clk",
67	.pmc_mask	= 1 << AT91SAM9261_ID_US1,
68	.type		= CLK_TYPE_PERIPHERAL,
69};
70static struct clk usart2_clk = {
71	.name		= "usart2_clk",
72	.pmc_mask	= 1 << AT91SAM9261_ID_US2,
73	.type		= CLK_TYPE_PERIPHERAL,
74};
75static struct clk mmc_clk = {
76	.name		= "mci_clk",
77	.pmc_mask	= 1 << AT91SAM9261_ID_MCI,
78	.type		= CLK_TYPE_PERIPHERAL,
79};
80static struct clk udc_clk = {
81	.name		= "udc_clk",
82	.pmc_mask	= 1 << AT91SAM9261_ID_UDP,
83	.type		= CLK_TYPE_PERIPHERAL,
84};
85static struct clk twi_clk = {
86	.name		= "twi_clk",
87	.pmc_mask	= 1 << AT91SAM9261_ID_TWI,
88	.type		= CLK_TYPE_PERIPHERAL,
89};
90static struct clk spi0_clk = {
91	.name		= "spi0_clk",
92	.pmc_mask	= 1 << AT91SAM9261_ID_SPI0,
93	.type		= CLK_TYPE_PERIPHERAL,
94};
95static struct clk spi1_clk = {
96	.name		= "spi1_clk",
97	.pmc_mask	= 1 << AT91SAM9261_ID_SPI1,
98	.type		= CLK_TYPE_PERIPHERAL,
99};
100static struct clk ssc0_clk = {
101	.name		= "ssc0_clk",
102	.pmc_mask	= 1 << AT91SAM9261_ID_SSC0,
103	.type		= CLK_TYPE_PERIPHERAL,
104};
105static struct clk ssc1_clk = {
106	.name		= "ssc1_clk",
107	.pmc_mask	= 1 << AT91SAM9261_ID_SSC1,
108	.type		= CLK_TYPE_PERIPHERAL,
109};
110static struct clk ssc2_clk = {
111	.name		= "ssc2_clk",
112	.pmc_mask	= 1 << AT91SAM9261_ID_SSC2,
113	.type		= CLK_TYPE_PERIPHERAL,
114};
115static struct clk tc0_clk = {
116	.name		= "tc0_clk",
117	.pmc_mask	= 1 << AT91SAM9261_ID_TC0,
118	.type		= CLK_TYPE_PERIPHERAL,
119};
120static struct clk tc1_clk = {
121	.name		= "tc1_clk",
122	.pmc_mask	= 1 << AT91SAM9261_ID_TC1,
123	.type		= CLK_TYPE_PERIPHERAL,
124};
125static struct clk tc2_clk = {
126	.name		= "tc2_clk",
127	.pmc_mask	= 1 << AT91SAM9261_ID_TC2,
128	.type		= CLK_TYPE_PERIPHERAL,
129};
130static struct clk ohci_clk = {
131	.name		= "ohci_clk",
132	.pmc_mask	= 1 << AT91SAM9261_ID_UHP,
133	.type		= CLK_TYPE_PERIPHERAL,
134};
135static struct clk lcdc_clk = {
136	.name		= "lcdc_clk",
137	.pmc_mask	= 1 << AT91SAM9261_ID_LCDC,
138	.type		= CLK_TYPE_PERIPHERAL,
139};
140
141static struct clk *periph_clocks[] __initdata = {
142	&pioA_clk,
143	&pioB_clk,
144	&pioC_clk,
145	&usart0_clk,
146	&usart1_clk,
147	&usart2_clk,
148	&mmc_clk,
149	&udc_clk,
150	&twi_clk,
151	&spi0_clk,
152	&spi1_clk,
153	&ssc0_clk,
154	&ssc1_clk,
155	&ssc2_clk,
156	&tc0_clk,
157	&tc1_clk,
158	&tc2_clk,
159	&ohci_clk,
160	&lcdc_clk,
161	// irq0 .. irq2
162};
163
164/*
165 * The four programmable clocks.
166 * You must configure pin multiplexing to bring these signals out.
167 */
168static struct clk pck0 = {
169	.name		= "pck0",
170	.pmc_mask	= AT91_PMC_PCK0,
171	.type		= CLK_TYPE_PROGRAMMABLE,
172	.id		= 0,
173};
174static struct clk pck1 = {
175	.name		= "pck1",
176	.pmc_mask	= AT91_PMC_PCK1,
177	.type		= CLK_TYPE_PROGRAMMABLE,
178	.id		= 1,
179};
180static struct clk pck2 = {
181	.name		= "pck2",
182	.pmc_mask	= AT91_PMC_PCK2,
183	.type		= CLK_TYPE_PROGRAMMABLE,
184	.id		= 2,
185};
186static struct clk pck3 = {
187	.name		= "pck3",
188	.pmc_mask	= AT91_PMC_PCK3,
189	.type		= CLK_TYPE_PROGRAMMABLE,
190	.id		= 3,
191};
192
193/* HClocks */
194static struct clk hck0 = {
195	.name		= "hck0",
196	.pmc_mask	= AT91_PMC_HCK0,
197	.type		= CLK_TYPE_SYSTEM,
198	.id		= 0,
199};
200static struct clk hck1 = {
201	.name		= "hck1",
202	.pmc_mask	= AT91_PMC_HCK1,
203	.type		= CLK_TYPE_SYSTEM,
204	.id		= 1,
205};
206
207static void __init at91sam9261_register_clocks(void)
208{
209	int i;
210
211	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
212		clk_register(periph_clocks[i]);
213
214	clk_register(&pck0);
215	clk_register(&pck1);
216	clk_register(&pck2);
217	clk_register(&pck3);
218
219	clk_register(&hck0);
220	clk_register(&hck1);
221}
222
223/* --------------------------------------------------------------------
224 *  GPIO
225 * -------------------------------------------------------------------- */
226
227static struct at91_gpio_bank at91sam9261_gpio[] = {
228	{
229		.id		= AT91SAM9261_ID_PIOA,
230		.offset		= AT91_PIOA,
231		.clock		= &pioA_clk,
232	}, {
233		.id		= AT91SAM9261_ID_PIOB,
234		.offset		= AT91_PIOB,
235		.clock		= &pioB_clk,
236	}, {
237		.id		= AT91SAM9261_ID_PIOC,
238		.offset		= AT91_PIOC,
239		.clock		= &pioC_clk,
240	}
241};
242
243static void at91sam9261_reset(void)
244{
245	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
246}
247
248
249/* --------------------------------------------------------------------
250 *  AT91SAM9261 processor initialization
251 * -------------------------------------------------------------------- */
252
253void __init at91sam9261_initialize(unsigned long main_clock)
254{
255	/* Map peripherals */
256	iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
257
258	at91_arch_reset = at91sam9261_reset;
259	at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
260			| (1 << AT91SAM9261_ID_IRQ2);
261
262	/* Init clock subsystem */
263	at91_clock_init(main_clock);
264
265	/* Register the processor-specific clocks */
266	at91sam9261_register_clocks();
267
268	/* Register GPIO subsystem */
269	at91_gpio_init(at91sam9261_gpio, 3);
270}
271
272/* --------------------------------------------------------------------
273 *  Interrupt initialization
274 * -------------------------------------------------------------------- */
275
276/*
277 * The default interrupt priority levels (0 = lowest, 7 = highest).
278 */
279static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
280	7,	/* Advanced Interrupt Controller */
281	7,	/* System Peripherals */
282	0,	/* Parallel IO Controller A */
283	0,	/* Parallel IO Controller B */
284	0,	/* Parallel IO Controller C */
285	0,
286	6,	/* USART 0 */
287	6,	/* USART 1 */
288	6,	/* USART 2 */
289	0,	/* Multimedia Card Interface */
290	4,	/* USB Device Port */
291	0,	/* Two-Wire Interface */
292	6,	/* Serial Peripheral Interface 0 */
293	6,	/* Serial Peripheral Interface 1 */
294	5,	/* Serial Synchronous Controller 0 */
295	5,	/* Serial Synchronous Controller 1 */
296	5,	/* Serial Synchronous Controller 2 */
297	0,	/* Timer Counter 0 */
298	0,	/* Timer Counter 1 */
299	0,	/* Timer Counter 2 */
300	3,	/* USB Host port */
301	3,	/* LCD Controller */
302	0,
303	0,
304	0,
305	0,
306	0,
307	0,
308	0,
309	0,	/* Advanced Interrupt Controller */
310	0,	/* Advanced Interrupt Controller */
311	0,	/* Advanced Interrupt Controller */
312};
313
314void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS])
315{
316	if (!priority)
317		priority = at91sam9261_default_irq_priority;
318
319	/* Initialize the AIC interrupt controller */
320	at91_aic_init(priority);
321
322	/* Enable GPIO interrupts */
323	at91_gpio_irq_setup();
324}
325