1/*
2 * arch/arm/mach-at91/at91sam9260.c
3 *
4 *  Copyright (C) 2006 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/cpu.h>
18#include <asm/arch/at91sam9260.h>
19#include <asm/arch/at91_pmc.h>
20#include <asm/arch/at91_rstc.h>
21
22#include "generic.h"
23#include "clock.h"
24
25static struct map_desc at91sam9260_io_desc[] __initdata = {
26	{
27		.virtual	= AT91_VA_BASE_SYS,
28		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
29		.length		= SZ_16K,
30		.type		= MT_DEVICE,
31	}
32};
33
34static struct map_desc at91sam9260_sram_desc[] __initdata = {
35	{
36		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
37		.pfn		= __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
38		.length		= AT91SAM9260_SRAM0_SIZE,
39		.type		= MT_DEVICE,
40	}, {
41		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE,
42		.pfn		= __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
43		.length		= AT91SAM9260_SRAM1_SIZE,
44		.type		= MT_DEVICE,
45	}
46};
47
48static struct map_desc at91sam9xe_sram_desc[] __initdata = {
49	{
50		.pfn		= __phys_to_pfn(AT91SAM9XE_SRAM_BASE),
51		.type		= MT_DEVICE,
52	}
53};
54
55/* --------------------------------------------------------------------
56 *  Clocks
57 * -------------------------------------------------------------------- */
58
59/*
60 * The peripheral clocks.
61 */
62static struct clk pioA_clk = {
63	.name		= "pioA_clk",
64	.pmc_mask	= 1 << AT91SAM9260_ID_PIOA,
65	.type		= CLK_TYPE_PERIPHERAL,
66};
67static struct clk pioB_clk = {
68	.name		= "pioB_clk",
69	.pmc_mask	= 1 << AT91SAM9260_ID_PIOB,
70	.type		= CLK_TYPE_PERIPHERAL,
71};
72static struct clk pioC_clk = {
73	.name		= "pioC_clk",
74	.pmc_mask	= 1 << AT91SAM9260_ID_PIOC,
75	.type		= CLK_TYPE_PERIPHERAL,
76};
77static struct clk adc_clk = {
78	.name		= "adc_clk",
79	.pmc_mask	= 1 << AT91SAM9260_ID_ADC,
80	.type		= CLK_TYPE_PERIPHERAL,
81};
82static struct clk usart0_clk = {
83	.name		= "usart0_clk",
84	.pmc_mask	= 1 << AT91SAM9260_ID_US0,
85	.type		= CLK_TYPE_PERIPHERAL,
86};
87static struct clk usart1_clk = {
88	.name		= "usart1_clk",
89	.pmc_mask	= 1 << AT91SAM9260_ID_US1,
90	.type		= CLK_TYPE_PERIPHERAL,
91};
92static struct clk usart2_clk = {
93	.name		= "usart2_clk",
94	.pmc_mask	= 1 << AT91SAM9260_ID_US2,
95	.type		= CLK_TYPE_PERIPHERAL,
96};
97static struct clk mmc_clk = {
98	.name		= "mci_clk",
99	.pmc_mask	= 1 << AT91SAM9260_ID_MCI,
100	.type		= CLK_TYPE_PERIPHERAL,
101};
102static struct clk udc_clk = {
103	.name		= "udc_clk",
104	.pmc_mask	= 1 << AT91SAM9260_ID_UDP,
105	.type		= CLK_TYPE_PERIPHERAL,
106};
107static struct clk twi_clk = {
108	.name		= "twi_clk",
109	.pmc_mask	= 1 << AT91SAM9260_ID_TWI,
110	.type		= CLK_TYPE_PERIPHERAL,
111};
112static struct clk spi0_clk = {
113	.name		= "spi0_clk",
114	.pmc_mask	= 1 << AT91SAM9260_ID_SPI0,
115	.type		= CLK_TYPE_PERIPHERAL,
116};
117static struct clk spi1_clk = {
118	.name		= "spi1_clk",
119	.pmc_mask	= 1 << AT91SAM9260_ID_SPI1,
120	.type		= CLK_TYPE_PERIPHERAL,
121};
122static struct clk ssc_clk = {
123	.name		= "ssc_clk",
124	.pmc_mask	= 1 << AT91SAM9260_ID_SSC,
125	.type		= CLK_TYPE_PERIPHERAL,
126};
127static struct clk tc0_clk = {
128	.name		= "tc0_clk",
129	.pmc_mask	= 1 << AT91SAM9260_ID_TC0,
130	.type		= CLK_TYPE_PERIPHERAL,
131};
132static struct clk tc1_clk = {
133	.name		= "tc1_clk",
134	.pmc_mask	= 1 << AT91SAM9260_ID_TC1,
135	.type		= CLK_TYPE_PERIPHERAL,
136};
137static struct clk tc2_clk = {
138	.name		= "tc2_clk",
139	.pmc_mask	= 1 << AT91SAM9260_ID_TC2,
140	.type		= CLK_TYPE_PERIPHERAL,
141};
142static struct clk ohci_clk = {
143	.name		= "ohci_clk",
144	.pmc_mask	= 1 << AT91SAM9260_ID_UHP,
145	.type		= CLK_TYPE_PERIPHERAL,
146};
147static struct clk macb_clk = {
148	.name		= "macb_clk",
149	.pmc_mask	= 1 << AT91SAM9260_ID_EMAC,
150	.type		= CLK_TYPE_PERIPHERAL,
151};
152static struct clk isi_clk = {
153	.name		= "isi_clk",
154	.pmc_mask	= 1 << AT91SAM9260_ID_ISI,
155	.type		= CLK_TYPE_PERIPHERAL,
156};
157static struct clk usart3_clk = {
158	.name		= "usart3_clk",
159	.pmc_mask	= 1 << AT91SAM9260_ID_US3,
160	.type		= CLK_TYPE_PERIPHERAL,
161};
162static struct clk usart4_clk = {
163	.name		= "usart4_clk",
164	.pmc_mask	= 1 << AT91SAM9260_ID_US4,
165	.type		= CLK_TYPE_PERIPHERAL,
166};
167static struct clk usart5_clk = {
168	.name		= "usart5_clk",
169	.pmc_mask	= 1 << AT91SAM9260_ID_US5,
170	.type		= CLK_TYPE_PERIPHERAL,
171};
172static struct clk tc3_clk = {
173	.name		= "tc3_clk",
174	.pmc_mask	= 1 << AT91SAM9260_ID_TC3,
175	.type		= CLK_TYPE_PERIPHERAL,
176};
177static struct clk tc4_clk = {
178	.name		= "tc4_clk",
179	.pmc_mask	= 1 << AT91SAM9260_ID_TC4,
180	.type		= CLK_TYPE_PERIPHERAL,
181};
182static struct clk tc5_clk = {
183	.name		= "tc5_clk",
184	.pmc_mask	= 1 << AT91SAM9260_ID_TC5,
185	.type		= CLK_TYPE_PERIPHERAL,
186};
187
188static struct clk *periph_clocks[] __initdata = {
189	&pioA_clk,
190	&pioB_clk,
191	&pioC_clk,
192	&adc_clk,
193	&usart0_clk,
194	&usart1_clk,
195	&usart2_clk,
196	&mmc_clk,
197	&udc_clk,
198	&twi_clk,
199	&spi0_clk,
200	&spi1_clk,
201	&ssc_clk,
202	&tc0_clk,
203	&tc1_clk,
204	&tc2_clk,
205	&ohci_clk,
206	&macb_clk,
207	&isi_clk,
208	&usart3_clk,
209	&usart4_clk,
210	&usart5_clk,
211	&tc3_clk,
212	&tc4_clk,
213	&tc5_clk,
214	// irq0 .. irq2
215};
216
217/*
218 * The two programmable clocks.
219 * You must configure pin multiplexing to bring these signals out.
220 */
221static struct clk pck0 = {
222	.name		= "pck0",
223	.pmc_mask	= AT91_PMC_PCK0,
224	.type		= CLK_TYPE_PROGRAMMABLE,
225	.id		= 0,
226};
227static struct clk pck1 = {
228	.name		= "pck1",
229	.pmc_mask	= AT91_PMC_PCK1,
230	.type		= CLK_TYPE_PROGRAMMABLE,
231	.id		= 1,
232};
233
234static void __init at91sam9260_register_clocks(void)
235{
236	int i;
237
238	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
239		clk_register(periph_clocks[i]);
240
241	clk_register(&pck0);
242	clk_register(&pck1);
243}
244
245/* --------------------------------------------------------------------
246 *  GPIO
247 * -------------------------------------------------------------------- */
248
249static struct at91_gpio_bank at91sam9260_gpio[] = {
250	{
251		.id		= AT91SAM9260_ID_PIOA,
252		.offset		= AT91_PIOA,
253		.clock		= &pioA_clk,
254	}, {
255		.id		= AT91SAM9260_ID_PIOB,
256		.offset		= AT91_PIOB,
257		.clock		= &pioB_clk,
258	}, {
259		.id		= AT91SAM9260_ID_PIOC,
260		.offset		= AT91_PIOC,
261		.clock		= &pioC_clk,
262	}
263};
264
265static void at91sam9260_reset(void)
266{
267	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
268}
269
270
271/* --------------------------------------------------------------------
272 *  AT91SAM9260 processor initialization
273 * -------------------------------------------------------------------- */
274
275static void __init at91sam9xe_initialize(void)
276{
277	unsigned long cidr, sram_size;
278
279	cidr = at91_sys_read(AT91_DBGU_CIDR);
280
281	switch (cidr & AT91_CIDR_SRAMSIZ) {
282		case AT91_CIDR_SRAMSIZ_32K:
283			sram_size = 2 * SZ_16K;
284			break;
285		case AT91_CIDR_SRAMSIZ_16K:
286		default:
287			sram_size = SZ_16K;
288	}
289
290	at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
291	at91sam9xe_sram_desc->length = sram_size;
292
293	iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
294}
295
296void __init at91sam9260_initialize(unsigned long main_clock)
297{
298	/* Map peripherals */
299	iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
300
301	if (cpu_is_at91sam9xe())
302		at91sam9xe_initialize();
303	else
304		iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
305
306	at91_arch_reset = at91sam9260_reset;
307	at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
308			| (1 << AT91SAM9260_ID_IRQ2);
309
310	/* Init clock subsystem */
311	at91_clock_init(main_clock);
312
313	/* Register the processor-specific clocks */
314	at91sam9260_register_clocks();
315
316	/* Register GPIO subsystem */
317	at91_gpio_init(at91sam9260_gpio, 3);
318}
319
320/* --------------------------------------------------------------------
321 *  Interrupt initialization
322 * -------------------------------------------------------------------- */
323
324/*
325 * The default interrupt priority levels (0 = lowest, 7 = highest).
326 */
327static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
328	7,	/* Advanced Interrupt Controller */
329	7,	/* System Peripherals */
330	0,	/* Parallel IO Controller A */
331	0,	/* Parallel IO Controller B */
332	0,	/* Parallel IO Controller C */
333	0,	/* Analog-to-Digital Converter */
334	6,	/* USART 0 */
335	6,	/* USART 1 */
336	6,	/* USART 2 */
337	0,	/* Multimedia Card Interface */
338	4,	/* USB Device Port */
339	0,	/* Two-Wire Interface */
340	6,	/* Serial Peripheral Interface 0 */
341	6,	/* Serial Peripheral Interface 1 */
342	5,	/* Serial Synchronous Controller */
343	0,
344	0,
345	0,	/* Timer Counter 0 */
346	0,	/* Timer Counter 1 */
347	0,	/* Timer Counter 2 */
348	3,	/* USB Host port */
349	3,	/* Ethernet */
350	0,	/* Image Sensor Interface */
351	6,	/* USART 3 */
352	6,	/* USART 4 */
353	6,	/* USART 5 */
354	0,	/* Timer Counter 3 */
355	0,	/* Timer Counter 4 */
356	0,	/* Timer Counter 5 */
357	0,	/* Advanced Interrupt Controller */
358	0,	/* Advanced Interrupt Controller */
359	0,	/* Advanced Interrupt Controller */
360};
361
362void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS])
363{
364	if (!priority)
365		priority = at91sam9260_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}
373