blob: 3e48b59dfa745169050131ff1553a89cee0ab73b [file] [log] [blame]
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +08001/*
2 * Copyright (C) 2007 Atmel Corporation.
3 * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
4 *
5 * Under GPLv2
6 */
7
8#include <linux/module.h>
9#include <linux/io.h>
Jean-Christophe PLAGNIOL-VILLARDfb149f92011-05-07 11:16:00 +080010#include <linux/mm.h>
Jean-Christophe PLAGNIOL-VILLARDf22deee2011-11-01 01:23:20 +080011#include <linux/pm.h>
Jean-Christophe PLAGNIOL-VILLARD2b11ea52012-02-28 13:57:51 +080012#include <linux/of_address.h>
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +080013
14#include <asm/mach/map.h>
15
16#include <mach/hardware.h>
17#include <mach/cpu.h>
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +080018#include <mach/at91_dbgu.h>
19#include <mach/at91_pmc.h>
Jean-Christophe PLAGNIOL-VILLARDf22deee2011-11-01 01:23:20 +080020#include <mach/at91_shdwc.h>
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +080021
22#include "soc.h"
23#include "generic.h"
24
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +080025struct at91_init_soc __initdata at91_boot_soc;
26
27struct at91_socinfo at91_soc_initdata;
28EXPORT_SYMBOL(at91_soc_initdata);
29
30void __init at91rm9200_set_type(int type)
31{
32 if (type == ARCH_REVISON_9200_PQFP)
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +080033 at91_soc_initdata.subtype = AT91_SOC_RM9200_PQFP;
Nicolas Ferre3e907722011-12-28 13:10:04 +020034 else
35 at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
36
37 pr_info("AT91: filled in soc subtype: %s\n",
38 at91_get_soc_subtype(&at91_soc_initdata));
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +080039}
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +080040
Jean-Christophe PLAGNIOL-VILLARD92100c12011-04-23 15:28:34 +080041void __init at91_init_irq_default(void)
42{
43 at91_init_interrupts(at91_boot_soc.default_irq_priority);
44}
45
46void __init at91_init_interrupts(unsigned int *priority)
47{
48 /* Initialize the AIC interrupt controller */
49 at91_aic_init(priority);
50
51 /* Enable GPIO interrupts */
52 at91_gpio_irq_setup();
53}
54
Jean-Christophe PLAGNIOL-VILLARDf0051d82011-05-10 03:20:09 +080055static struct map_desc sram_desc[2] __initdata;
56
57void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
58{
59 struct map_desc *desc = &sram_desc[bank];
60
61 desc->virtual = AT91_IO_VIRT_BASE - length;
62 if (bank > 0)
63 desc->virtual -= sram_desc[bank - 1].length;
64
65 desc->pfn = __phys_to_pfn(base);
66 desc->length = length;
67 desc->type = MT_DEVICE;
68
69 pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n",
70 base, length, desc->virtual);
71
72 iotable_init(desc, 1);
73}
74
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +080075static struct map_desc at91_io_desc __initdata = {
76 .virtual = AT91_VA_BASE_SYS,
77 .pfn = __phys_to_pfn(AT91_BASE_SYS),
78 .length = SZ_16K,
79 .type = MT_DEVICE,
80};
81
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +080082static void __init soc_detect(u32 dbgu_base)
83{
84 u32 cidr, socid;
85
86 cidr = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_CIDR);
87 socid = cidr & ~AT91_CIDR_VERSION;
88
89 switch (socid) {
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +080090 case ARCH_ID_AT91RM9200:
91 at91_soc_initdata.type = AT91_SOC_RM9200;
92 at91_boot_soc = at91rm9200_soc;
93 break;
94
95 case ARCH_ID_AT91SAM9260:
96 at91_soc_initdata.type = AT91_SOC_SAM9260;
97 at91_boot_soc = at91sam9260_soc;
98 break;
99
100 case ARCH_ID_AT91SAM9261:
101 at91_soc_initdata.type = AT91_SOC_SAM9261;
102 at91_boot_soc = at91sam9261_soc;
103 break;
104
105 case ARCH_ID_AT91SAM9263:
106 at91_soc_initdata.type = AT91_SOC_SAM9263;
107 at91_boot_soc = at91sam9263_soc;
108 break;
109
110 case ARCH_ID_AT91SAM9G20:
111 at91_soc_initdata.type = AT91_SOC_SAM9G20;
112 at91_boot_soc = at91sam9260_soc;
113 break;
114
115 case ARCH_ID_AT91SAM9G45:
116 at91_soc_initdata.type = AT91_SOC_SAM9G45;
117 if (cidr == ARCH_ID_AT91SAM9G45ES)
118 at91_soc_initdata.subtype = AT91_SOC_SAM9G45ES;
119 at91_boot_soc = at91sam9g45_soc;
120 break;
121
122 case ARCH_ID_AT91SAM9RL64:
123 at91_soc_initdata.type = AT91_SOC_SAM9RL;
124 at91_boot_soc = at91sam9rl_soc;
125 break;
126
127 case ARCH_ID_AT91SAM9X5:
128 at91_soc_initdata.type = AT91_SOC_SAM9X5;
129 at91_boot_soc = at91sam9x5_soc;
130 break;
131 }
132
133 /* at91sam9g10 */
134 if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
135 at91_soc_initdata.type = AT91_SOC_SAM9G10;
136 at91_boot_soc = at91sam9261_soc;
137 }
138 /* at91sam9xe */
139 else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
140 at91_soc_initdata.type = AT91_SOC_SAM9260;
141 at91_soc_initdata.subtype = AT91_SOC_SAM9XE;
142 at91_boot_soc = at91sam9260_soc;
143 }
144
145 if (!at91_soc_is_detected())
146 return;
147
148 at91_soc_initdata.cidr = cidr;
149
150 /* sub version of soc */
151 at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
152
153 if (at91_soc_initdata.type == AT91_SOC_SAM9G45) {
154 switch (at91_soc_initdata.exid) {
155 case ARCH_EXID_AT91SAM9M10:
156 at91_soc_initdata.subtype = AT91_SOC_SAM9M10;
157 break;
158 case ARCH_EXID_AT91SAM9G46:
159 at91_soc_initdata.subtype = AT91_SOC_SAM9G46;
160 break;
161 case ARCH_EXID_AT91SAM9M11:
162 at91_soc_initdata.subtype = AT91_SOC_SAM9M11;
163 break;
164 }
165 }
166
167 if (at91_soc_initdata.type == AT91_SOC_SAM9X5) {
168 switch (at91_soc_initdata.exid) {
169 case ARCH_EXID_AT91SAM9G15:
170 at91_soc_initdata.subtype = AT91_SOC_SAM9G15;
171 break;
172 case ARCH_EXID_AT91SAM9G35:
173 at91_soc_initdata.subtype = AT91_SOC_SAM9G35;
174 break;
175 case ARCH_EXID_AT91SAM9X35:
176 at91_soc_initdata.subtype = AT91_SOC_SAM9X35;
177 break;
178 case ARCH_EXID_AT91SAM9G25:
179 at91_soc_initdata.subtype = AT91_SOC_SAM9G25;
180 break;
181 case ARCH_EXID_AT91SAM9X25:
182 at91_soc_initdata.subtype = AT91_SOC_SAM9X25;
183 break;
184 }
185 }
186}
187
188static const char *soc_name[] = {
189 [AT91_SOC_RM9200] = "at91rm9200",
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +0800190 [AT91_SOC_SAM9260] = "at91sam9260",
191 [AT91_SOC_SAM9261] = "at91sam9261",
192 [AT91_SOC_SAM9263] = "at91sam9263",
193 [AT91_SOC_SAM9G10] = "at91sam9g10",
194 [AT91_SOC_SAM9G20] = "at91sam9g20",
195 [AT91_SOC_SAM9G45] = "at91sam9g45",
196 [AT91_SOC_SAM9RL] = "at91sam9rl",
197 [AT91_SOC_SAM9X5] = "at91sam9x5",
198 [AT91_SOC_NONE] = "Unknown"
199};
200
201const char *at91_get_soc_type(struct at91_socinfo *c)
202{
203 return soc_name[c->type];
204}
205EXPORT_SYMBOL(at91_get_soc_type);
206
207static const char *soc_subtype_name[] = {
208 [AT91_SOC_RM9200_BGA] = "at91rm9200 BGA",
209 [AT91_SOC_RM9200_PQFP] = "at91rm9200 PQFP",
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +0800210 [AT91_SOC_SAM9XE] = "at91sam9xe",
211 [AT91_SOC_SAM9G45ES] = "at91sam9g45es",
212 [AT91_SOC_SAM9M10] = "at91sam9m10",
213 [AT91_SOC_SAM9G46] = "at91sam9g46",
214 [AT91_SOC_SAM9M11] = "at91sam9m11",
215 [AT91_SOC_SAM9G15] = "at91sam9g15",
216 [AT91_SOC_SAM9G35] = "at91sam9g35",
217 [AT91_SOC_SAM9X35] = "at91sam9x35",
218 [AT91_SOC_SAM9G25] = "at91sam9g25",
219 [AT91_SOC_SAM9X25] = "at91sam9x25",
220 [AT91_SOC_SUBTYPE_NONE] = "Unknown"
221};
222
223const char *at91_get_soc_subtype(struct at91_socinfo *c)
224{
225 return soc_subtype_name[c->subtype];
226}
227EXPORT_SYMBOL(at91_get_soc_subtype);
228
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +0800229void __init at91_map_io(void)
230{
231 /* Map peripherals */
232 iotable_init(&at91_io_desc, 1);
233
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +0800234 at91_soc_initdata.type = AT91_SOC_NONE;
235 at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
236
Jean-Christophe PLAGNIOL-VILLARD13079a72011-11-02 01:43:31 +0800237 soc_detect(AT91_BASE_DBGU0);
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +0800238 if (!at91_soc_is_detected())
Jean-Christophe PLAGNIOL-VILLARD13079a72011-11-02 01:43:31 +0800239 soc_detect(AT91_BASE_DBGU1);
Jean-Christophe PLAGNIOL-VILLARD8c3583b2011-04-23 22:12:57 +0800240
241 if (!at91_soc_is_detected())
242 panic("AT91: Impossible to detect the SOC type");
243
244 pr_info("AT91: Detected soc type: %s\n",
245 at91_get_soc_type(&at91_soc_initdata));
246 pr_info("AT91: Detected soc subtype: %s\n",
247 at91_get_soc_subtype(&at91_soc_initdata));
248
249 if (!at91_soc_is_enabled())
250 panic("AT91: Soc not enabled");
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +0800251
252 if (at91_boot_soc.map_io)
253 at91_boot_soc.map_io();
254}
255
Jean-Christophe PLAGNIOL-VILLARDf22deee2011-11-01 01:23:20 +0800256void __iomem *at91_shdwc_base = NULL;
257
258static void at91sam9_poweroff(void)
259{
260 at91_shdwc_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
261}
262
263void __init at91_ioremap_shdwc(u32 base_addr)
264{
265 at91_shdwc_base = ioremap(base_addr, 16);
266 if (!at91_shdwc_base)
267 panic("Impossible to ioremap at91_shdwc_base\n");
268 pm_power_off = at91sam9_poweroff;
269}
270
Jean-Christophe PLAGNIOL-VILLARDe9f68b52011-11-18 01:25:52 +0800271void __iomem *at91_rstc_base;
272
273void __init at91_ioremap_rstc(u32 base_addr)
274{
275 at91_rstc_base = ioremap(base_addr, 16);
276 if (!at91_rstc_base)
277 panic("Impossible to ioremap at91_rstc_base\n");
278}
279
Jean-Christophe PLAGNIOL-VILLARD4342d642011-11-27 23:15:50 +0800280void __iomem *at91_matrix_base;
281
282void __init at91_ioremap_matrix(u32 base_addr)
283{
284 at91_matrix_base = ioremap(base_addr, 512);
285 if (!at91_matrix_base)
286 panic("Impossible to ioremap at91_matrix_base\n");
287}
288
Jean-Christophe PLAGNIOL-VILLARD2b11ea52012-02-28 13:57:51 +0800289#if defined(CONFIG_OF)
Jean-Christophe PLAGNIOL-VILLARDc8082d32012-03-03 03:16:27 +0800290static struct of_device_id rstc_ids[] = {
291 { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_alt_restart },
292 { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
293 { /*sentinel*/ }
294};
295
296static void at91_dt_rstc(void)
297{
298 struct device_node *np;
299 const struct of_device_id *of_id;
300
301 np = of_find_matching_node(NULL, rstc_ids);
302 if (!np)
303 panic("unable to find compatible rstc node in dtb\n");
304
305 at91_rstc_base = of_iomap(np, 0);
306 if (!at91_rstc_base)
307 panic("unable to map rstc cpu registers\n");
308
309 of_id = of_match_node(rstc_ids, np);
310 if (!of_id)
311 panic("AT91: rtsc no restart function availlable\n");
312
313 arm_pm_restart = of_id->data;
314
315 of_node_put(np);
316}
317
Jean-Christophe PLAGNIOL-VILLARD2b11ea52012-02-28 13:57:51 +0800318void __init at91_dt_initialize(void)
319{
Jean-Christophe PLAGNIOL-VILLARDc8082d32012-03-03 03:16:27 +0800320 at91_dt_rstc();
321
Jean-Christophe PLAGNIOL-VILLARD2b11ea52012-02-28 13:57:51 +0800322 /* temporary until have the ramc binding*/
323 at91_boot_soc.ioremap_registers();
324
Jean-Christophe PLAGNIOL-VILLARD2b11ea52012-02-28 13:57:51 +0800325 /* Init clock subsystem */
Jean-Christophe PLAGNIOL-VILLARDeb5e76f2012-03-02 20:44:23 +0800326 at91_dt_clock_init();
Jean-Christophe PLAGNIOL-VILLARD2b11ea52012-02-28 13:57:51 +0800327
328 /* Register the processor-specific clocks */
329 at91_boot_soc.register_clocks();
330
331 at91_boot_soc.init();
332}
333#endif
334
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +0800335void __init at91_initialize(unsigned long main_clock)
336{
Jean-Christophe PLAGNIOL-VILLARDcfa5a1f2011-10-14 01:17:18 +0800337 at91_boot_soc.ioremap_registers();
338
Jean-Christophe PLAGNIOL-VILLARD46539372011-04-24 18:20:28 +0800339 /* Init clock subsystem */
340 at91_clock_init(main_clock);
341
Jean-Christophe PLAGNIOL-VILLARD51ddec72011-04-24 18:15:34 +0800342 /* Register the processor-specific clocks */
343 at91_boot_soc.register_clocks();
344
Jean-Christophe PLAGNIOL-VILLARD46539372011-04-24 18:20:28 +0800345 at91_boot_soc.init();
Jean-Christophe PLAGNIOL-VILLARD21d08b92011-04-23 15:28:34 +0800346}