Branch data Line data Source code
1 : : /*
2 : : * Versatile Express V2M Motherboard Support
3 : : */
4 : : #include <linux/device.h>
5 : : #include <linux/amba/bus.h>
6 : : #include <linux/amba/mmci.h>
7 : : #include <linux/io.h>
8 : : #include <linux/smp.h>
9 : : #include <linux/init.h>
10 : : #include <linux/memblock.h>
11 : : #include <linux/of_address.h>
12 : : #include <linux/of_fdt.h>
13 : : #include <linux/of_irq.h>
14 : : #include <linux/of_platform.h>
15 : : #include <linux/platform_device.h>
16 : : #include <linux/ata_platform.h>
17 : : #include <linux/smsc911x.h>
18 : : #include <linux/spinlock.h>
19 : : #include <linux/usb/isp1760.h>
20 : : #include <linux/mtd/physmap.h>
21 : : #include <linux/regulator/fixed.h>
22 : : #include <linux/regulator/machine.h>
23 : : #include <linux/vexpress.h>
24 : : #include <linux/clkdev.h>
25 : :
26 : : #include <asm/mach-types.h>
27 : : #include <asm/sizes.h>
28 : : #include <asm/mach/arch.h>
29 : : #include <asm/mach/map.h>
30 : : #include <asm/mach/time.h>
31 : : #include <asm/hardware/arm_timer.h>
32 : : #include <asm/hardware/cache-l2x0.h>
33 : : #include <asm/hardware/timer-sp.h>
34 : :
35 : : #include <mach/ct-ca9x4.h>
36 : : #include <mach/motherboard.h>
37 : :
38 : : #include <plat/sched_clock.h>
39 : : #include <plat/platsmp.h>
40 : :
41 : : #include "core.h"
42 : :
43 : : #define V2M_PA_CS0 0x40000000
44 : : #define V2M_PA_CS1 0x44000000
45 : : #define V2M_PA_CS2 0x48000000
46 : : #define V2M_PA_CS3 0x4c000000
47 : : #define V2M_PA_CS7 0x10000000
48 : :
49 : : static struct map_desc v2m_io_desc[] __initdata = {
50 : : {
51 : : .virtual = V2M_PERIPH,
52 : : .pfn = __phys_to_pfn(V2M_PA_CS7),
53 : : .length = SZ_128K,
54 : : .type = MT_DEVICE,
55 : : },
56 : : };
57 : :
58 : 0 : static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
59 : : {
60 [ # # ][ # # ]: 0 : if (WARN_ON(!base || irq == NO_IRQ))
61 : 0 : return;
62 : :
63 : 0 : sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1");
64 : : sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
65 : : }
66 : :
67 : :
68 : : static struct resource v2m_pcie_i2c_resource = {
69 : : .start = V2M_SERIAL_BUS_PCI,
70 : : .end = V2M_SERIAL_BUS_PCI + SZ_4K - 1,
71 : : .flags = IORESOURCE_MEM,
72 : : };
73 : :
74 : : static struct platform_device v2m_pcie_i2c_device = {
75 : : .name = "versatile-i2c",
76 : : .id = 0,
77 : : .num_resources = 1,
78 : : .resource = &v2m_pcie_i2c_resource,
79 : : };
80 : :
81 : : static struct resource v2m_ddc_i2c_resource = {
82 : : .start = V2M_SERIAL_BUS_DVI,
83 : : .end = V2M_SERIAL_BUS_DVI + SZ_4K - 1,
84 : : .flags = IORESOURCE_MEM,
85 : : };
86 : :
87 : : static struct platform_device v2m_ddc_i2c_device = {
88 : : .name = "versatile-i2c",
89 : : .id = 1,
90 : : .num_resources = 1,
91 : : .resource = &v2m_ddc_i2c_resource,
92 : : };
93 : :
94 : : static struct resource v2m_eth_resources[] = {
95 : : {
96 : : .start = V2M_LAN9118,
97 : : .end = V2M_LAN9118 + SZ_64K - 1,
98 : : .flags = IORESOURCE_MEM,
99 : : }, {
100 : : .start = IRQ_V2M_LAN9118,
101 : : .end = IRQ_V2M_LAN9118,
102 : : .flags = IORESOURCE_IRQ,
103 : : },
104 : : };
105 : :
106 : : static struct smsc911x_platform_config v2m_eth_config = {
107 : : .flags = SMSC911X_USE_32BIT,
108 : : .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
109 : : .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
110 : : .phy_interface = PHY_INTERFACE_MODE_MII,
111 : : };
112 : :
113 : : static struct platform_device v2m_eth_device = {
114 : : .name = "smsc911x",
115 : : .id = -1,
116 : : .resource = v2m_eth_resources,
117 : : .num_resources = ARRAY_SIZE(v2m_eth_resources),
118 : : .dev.platform_data = &v2m_eth_config,
119 : : };
120 : :
121 : : static struct regulator_consumer_supply v2m_eth_supplies[] = {
122 : : REGULATOR_SUPPLY("vddvario", "smsc911x"),
123 : : REGULATOR_SUPPLY("vdd33a", "smsc911x"),
124 : : };
125 : :
126 : : static struct resource v2m_usb_resources[] = {
127 : : {
128 : : .start = V2M_ISP1761,
129 : : .end = V2M_ISP1761 + SZ_128K - 1,
130 : : .flags = IORESOURCE_MEM,
131 : : }, {
132 : : .start = IRQ_V2M_ISP1761,
133 : : .end = IRQ_V2M_ISP1761,
134 : : .flags = IORESOURCE_IRQ,
135 : : },
136 : : };
137 : :
138 : : static struct isp1760_platform_data v2m_usb_config = {
139 : : .is_isp1761 = true,
140 : : .bus_width_16 = false,
141 : : .port1_otg = true,
142 : : .analog_oc = false,
143 : : .dack_polarity_high = false,
144 : : .dreq_polarity_high = false,
145 : : };
146 : :
147 : : static struct platform_device v2m_usb_device = {
148 : : .name = "isp1760",
149 : : .id = -1,
150 : : .resource = v2m_usb_resources,
151 : : .num_resources = ARRAY_SIZE(v2m_usb_resources),
152 : : .dev.platform_data = &v2m_usb_config,
153 : : };
154 : :
155 : : static struct physmap_flash_data v2m_flash_data = {
156 : : .width = 4,
157 : : };
158 : :
159 : : static struct resource v2m_flash_resources[] = {
160 : : {
161 : : .start = V2M_NOR0,
162 : : .end = V2M_NOR0 + SZ_64M - 1,
163 : : .flags = IORESOURCE_MEM,
164 : : }, {
165 : : .start = V2M_NOR1,
166 : : .end = V2M_NOR1 + SZ_64M - 1,
167 : : .flags = IORESOURCE_MEM,
168 : : },
169 : : };
170 : :
171 : : static struct platform_device v2m_flash_device = {
172 : : .name = "physmap-flash",
173 : : .id = -1,
174 : : .resource = v2m_flash_resources,
175 : : .num_resources = ARRAY_SIZE(v2m_flash_resources),
176 : : .dev.platform_data = &v2m_flash_data,
177 : : };
178 : :
179 : : static struct pata_platform_info v2m_pata_data = {
180 : : .ioport_shift = 2,
181 : : };
182 : :
183 : : static struct resource v2m_pata_resources[] = {
184 : : {
185 : : .start = V2M_CF,
186 : : .end = V2M_CF + 0xff,
187 : : .flags = IORESOURCE_MEM,
188 : : }, {
189 : : .start = V2M_CF + 0x100,
190 : : .end = V2M_CF + SZ_4K - 1,
191 : : .flags = IORESOURCE_MEM,
192 : : },
193 : : };
194 : :
195 : : static struct platform_device v2m_cf_device = {
196 : : .name = "pata_platform",
197 : : .id = -1,
198 : : .resource = v2m_pata_resources,
199 : : .num_resources = ARRAY_SIZE(v2m_pata_resources),
200 : : .dev.platform_data = &v2m_pata_data,
201 : : };
202 : :
203 : : static struct mmci_platform_data v2m_mmci_data = {
204 : : .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
205 : : .gpio_wp = VEXPRESS_GPIO_MMC_WPROT,
206 : : .gpio_cd = VEXPRESS_GPIO_MMC_CARDIN,
207 : : };
208 : :
209 : : static struct resource v2m_sysreg_resources[] = {
210 : : {
211 : : .start = V2M_SYSREGS,
212 : : .end = V2M_SYSREGS + 0xfff,
213 : : .flags = IORESOURCE_MEM,
214 : : },
215 : : };
216 : :
217 : : static struct platform_device v2m_sysreg_device = {
218 : : .name = "vexpress-sysreg",
219 : : .id = -1,
220 : : .resource = v2m_sysreg_resources,
221 : : .num_resources = ARRAY_SIZE(v2m_sysreg_resources),
222 : : };
223 : :
224 : : static struct platform_device v2m_muxfpga_device = {
225 : : .name = "vexpress-muxfpga",
226 : : .id = 0,
227 : : .num_resources = 1,
228 : : .resource = (struct resource []) {
229 : : VEXPRESS_RES_FUNC(0, 7),
230 : : }
231 : : };
232 : :
233 : : static struct platform_device v2m_shutdown_device = {
234 : : .name = "vexpress-shutdown",
235 : : .id = 0,
236 : : .num_resources = 1,
237 : : .resource = (struct resource []) {
238 : : VEXPRESS_RES_FUNC(0, 8),
239 : : }
240 : : };
241 : :
242 : : static struct platform_device v2m_reboot_device = {
243 : : .name = "vexpress-reboot",
244 : : .id = 0,
245 : : .num_resources = 1,
246 : : .resource = (struct resource []) {
247 : : VEXPRESS_RES_FUNC(0, 9),
248 : : }
249 : : };
250 : :
251 : : static struct platform_device v2m_dvimode_device = {
252 : : .name = "vexpress-dvimode",
253 : : .id = 0,
254 : : .num_resources = 1,
255 : : .resource = (struct resource []) {
256 : : VEXPRESS_RES_FUNC(0, 11),
257 : : }
258 : : };
259 : :
260 : : static AMBA_APB_DEVICE(aaci, "mb:aaci", 0, V2M_AACI, IRQ_V2M_AACI, NULL);
261 : : static AMBA_APB_DEVICE(mmci, "mb:mmci", 0, V2M_MMCI, IRQ_V2M_MMCI, &v2m_mmci_data);
262 : : static AMBA_APB_DEVICE(kmi0, "mb:kmi0", 0, V2M_KMI0, IRQ_V2M_KMI0, NULL);
263 : : static AMBA_APB_DEVICE(kmi1, "mb:kmi1", 0, V2M_KMI1, IRQ_V2M_KMI1, NULL);
264 : : static AMBA_APB_DEVICE(uart0, "mb:uart0", 0, V2M_UART0, IRQ_V2M_UART0, NULL);
265 : : static AMBA_APB_DEVICE(uart1, "mb:uart1", 0, V2M_UART1, IRQ_V2M_UART1, NULL);
266 : : static AMBA_APB_DEVICE(uart2, "mb:uart2", 0, V2M_UART2, IRQ_V2M_UART2, NULL);
267 : : static AMBA_APB_DEVICE(uart3, "mb:uart3", 0, V2M_UART3, IRQ_V2M_UART3, NULL);
268 : : static AMBA_APB_DEVICE(wdt, "mb:wdt", 0, V2M_WDT, IRQ_V2M_WDT, NULL);
269 : : static AMBA_APB_DEVICE(rtc, "mb:rtc", 0, V2M_RTC, IRQ_V2M_RTC, NULL);
270 : :
271 : : static struct amba_device *v2m_amba_devs[] __initdata = {
272 : : &aaci_device,
273 : : &mmci_device,
274 : : &kmi0_device,
275 : : &kmi1_device,
276 : : &uart0_device,
277 : : &uart1_device,
278 : : &uart2_device,
279 : : &uart3_device,
280 : : &wdt_device,
281 : : &rtc_device,
282 : : };
283 : :
284 : 0 : static void __init v2m_timer_init(void)
285 : : {
286 : 0 : vexpress_clk_init(ioremap(V2M_SYSCTL, SZ_4K));
287 : 0 : v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
288 : 0 : }
289 : :
290 : 0 : static void __init v2m_init_early(void)
291 : : {
292 [ # # ]: 0 : if (ct_desc->init_early)
293 : 0 : ct_desc->init_early();
294 : 0 : versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
295 : 0 : }
296 : :
297 : : struct ct_desc *ct_desc;
298 : :
299 : : static struct ct_desc *ct_descs[] __initdata = {
300 : : #ifdef CONFIG_ARCH_VEXPRESS_CA9X4
301 : : &ct_ca9x4_desc,
302 : : #endif
303 : : };
304 : :
305 : 0 : static void __init v2m_populate_ct_desc(void)
306 : : {
307 : : int i;
308 : : u32 current_tile_id;
309 : :
310 : 0 : ct_desc = NULL;
311 : 0 : current_tile_id = vexpress_get_procid(VEXPRESS_SITE_MASTER)
312 : : & V2M_CT_ID_MASK;
313 : :
314 [ # # ][ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
315 [ # # ]: 0 : if (ct_descs[i]->id == current_tile_id)
316 : 0 : ct_desc = ct_descs[i];
317 : :
318 [ # # ]: 0 : if (!ct_desc)
319 : 0 : panic("vexpress: this kernel does not support core tile ID 0x%08x when booting via ATAGs.\n"
320 : : "You may need a device tree blob or a different kernel to boot on this board.\n",
321 : : current_tile_id);
322 : 0 : }
323 : :
324 : 0 : static void __init v2m_map_io(void)
325 : : {
326 : 0 : iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
327 : 0 : vexpress_sysreg_early_init(ioremap(V2M_SYSREGS, SZ_4K));
328 : 0 : v2m_populate_ct_desc();
329 : 0 : ct_desc->map_io();
330 : 0 : }
331 : :
332 : 0 : static void __init v2m_init_irq(void)
333 : : {
334 : 0 : ct_desc->init_irq();
335 : 0 : }
336 : :
337 : 0 : static void __init v2m_init(void)
338 : : {
339 : : int i;
340 : :
341 : 0 : regulator_register_fixed(0, v2m_eth_supplies,
342 : : ARRAY_SIZE(v2m_eth_supplies));
343 : :
344 : 0 : platform_device_register(&v2m_muxfpga_device);
345 : 0 : platform_device_register(&v2m_shutdown_device);
346 : 0 : platform_device_register(&v2m_reboot_device);
347 : 0 : platform_device_register(&v2m_dvimode_device);
348 : :
349 : 0 : platform_device_register(&v2m_sysreg_device);
350 : 0 : platform_device_register(&v2m_pcie_i2c_device);
351 : 0 : platform_device_register(&v2m_ddc_i2c_device);
352 : 0 : platform_device_register(&v2m_flash_device);
353 : 0 : platform_device_register(&v2m_cf_device);
354 : 0 : platform_device_register(&v2m_eth_device);
355 : 0 : platform_device_register(&v2m_usb_device);
356 : :
357 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
358 : 0 : amba_device_register(v2m_amba_devs[i], &iomem_resource);
359 : :
360 : 0 : ct_desc->init_tile();
361 : 0 : }
362 : :
363 : : MACHINE_START(VEXPRESS, "ARM-Versatile Express")
364 : : .atag_offset = 0x100,
365 : : .smp = smp_ops(vexpress_smp_ops),
366 : : .map_io = v2m_map_io,
367 : : .init_early = v2m_init_early,
368 : : .init_irq = v2m_init_irq,
369 : : .init_time = v2m_timer_init,
370 : : .init_machine = v2m_init,
371 : : MACHINE_END
372 : :
373 : 0 : static void __init v2m_dt_hdlcd_init(void)
374 : : {
375 : : struct device_node *node;
376 : : int len, na, ns;
377 : : const __be32 *prop;
378 : : phys_addr_t fb_base, fb_size;
379 : :
380 : 0 : node = of_find_compatible_node(NULL, NULL, "arm,hdlcd");
381 [ # # ]: 0 : if (!node)
382 : 0 : return;
383 : :
384 : 0 : na = of_n_addr_cells(node);
385 : 0 : ns = of_n_size_cells(node);
386 : :
387 : 0 : prop = of_get_property(node, "framebuffer", &len);
388 [ # # ][ # # ]: 0 : if (WARN_ON(!prop || len < (na + ns) * sizeof(*prop)))
[ # # ][ # # ]
389 : : return;
390 : :
391 : 0 : fb_base = of_read_number(prop, na);
392 : 0 : fb_size = of_read_number(prop + na, ns);
393 : :
394 [ # # ][ # # ]: 0 : if (WARN_ON(memblock_remove(fb_base, fb_size)))
395 : : return;
396 : : };
397 : :
398 : : static struct map_desc v2m_rs1_io_desc __initdata = {
399 : : .virtual = V2M_PERIPH,
400 : : .pfn = __phys_to_pfn(0x1c000000),
401 : : .length = SZ_2M,
402 : : .type = MT_DEVICE,
403 : : };
404 : :
405 : 0 : static int __init v2m_dt_scan_memory_map(unsigned long node, const char *uname,
406 : : int depth, void *data)
407 : : {
408 : : const char **map = data;
409 : :
410 [ # # ]: 0 : if (strcmp(uname, "motherboard") != 0)
411 : : return 0;
412 : :
413 : 0 : *map = of_get_flat_dt_prop(node, "arm,v2m-memory-map", NULL);
414 : :
415 : 0 : return 1;
416 : : }
417 : :
418 : 0 : void __init v2m_dt_map_io(void)
419 : : {
420 : 0 : const char *map = NULL;
421 : :
422 : 0 : of_scan_flat_dt(v2m_dt_scan_memory_map, &map);
423 : :
424 [ # # ][ # # ]: 0 : if (map && strcmp(map, "rs1") == 0)
425 : 0 : iotable_init(&v2m_rs1_io_desc, 1);
426 : : else
427 : 0 : iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
428 : :
429 : : #if defined(CONFIG_SMP)
430 : 0 : vexpress_dt_smp_map_io();
431 : : #endif
432 : 0 : }
433 : :
434 : 0 : void __init v2m_dt_init_early(void)
435 : : {
436 : : u32 dt_hbi;
437 : :
438 : 0 : vexpress_sysreg_of_early_init();
439 : :
440 : : /* Confirm board type against DT property, if available */
441 [ # # ]: 0 : if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) {
442 : 0 : u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER);
443 : :
444 [ # # ][ # # ]: 0 : if (WARN_ON(dt_hbi != hbi))
445 : 0 : pr_warning("vexpress: DT HBI (%x) is not matching "
446 : : "hardware (%x)!\n", dt_hbi, hbi);
447 : : }
448 : :
449 : 0 : versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
450 : :
451 : 0 : v2m_dt_hdlcd_init();
452 : 0 : }
453 : :
454 : : static const struct of_device_id v2m_dt_bus_match[] __initconst = {
455 : : { .compatible = "simple-bus", },
456 : : { .compatible = "arm,amba-bus", },
457 : : { .compatible = "arm,vexpress,config-bus", },
458 : : {}
459 : : };
460 : :
461 : 0 : static void __init v2m_dt_init(void)
462 : : {
463 : 0 : l2x0_of_init(0x00400000, 0xfe0fffff);
464 : 0 : of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL);
465 : 0 : }
466 : :
467 : : static const char * const v2m_dt_match[] __initconst = {
468 : : "arm,vexpress",
469 : : NULL,
470 : : };
471 : :
472 : : DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
473 : : .dt_compat = v2m_dt_match,
474 : : .smp = smp_ops(vexpress_smp_ops),
475 : : .smp_init = smp_init_ops(vexpress_smp_init_ops),
476 : : .map_io = v2m_dt_map_io,
477 : : .init_early = v2m_dt_init_early,
478 : : .init_machine = v2m_dt_init,
479 : : MACHINE_END
|