Commit | Line | Data |
---|---|---|
f411fade MD |
1 | /* |
2 | * r8a7779 processor support | |
3 | * | |
dace48d0 | 4 | * Copyright (C) 2011, 2013 Renesas Solutions Corp. |
f411fade | 5 | * Copyright (C) 2011 Magnus Damm |
dace48d0 | 6 | * Copyright (C) 2013 Cogent Embedded, Inc. |
f411fade MD |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; version 2 of the License. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/init.h> | |
23 | #include <linux/interrupt.h> | |
24 | #include <linux/irq.h> | |
10e8d4f6 | 25 | #include <linux/of_platform.h> |
37a72d07 | 26 | #include <linux/platform_data/gpio-rcar.h> |
f411fade MD |
27 | #include <linux/platform_device.h> |
28 | #include <linux/delay.h> | |
29 | #include <linux/input.h> | |
30 | #include <linux/io.h> | |
31 | #include <linux/serial_sci.h> | |
32 | #include <linux/sh_intc.h> | |
33 | #include <linux/sh_timer.h> | |
a7b9837c | 34 | #include <linux/dma-mapping.h> |
f411fade | 35 | #include <mach/hardware.h> |
250a2723 | 36 | #include <mach/irqs.h> |
f411fade | 37 | #include <mach/r8a7779.h> |
a662c082 | 38 | #include <mach/common.h> |
f411fade MD |
39 | #include <asm/mach-types.h> |
40 | #include <asm/mach/arch.h> | |
df27a2d8 | 41 | #include <asm/mach/time.h> |
3e353b87 | 42 | #include <asm/mach/map.h> |
8bac13f5 | 43 | #include <asm/hardware/cache-l2x0.h> |
3e353b87 MD |
44 | |
45 | static struct map_desc r8a7779_io_desc[] __initdata = { | |
46 | /* 2M entity map for 0xf0000000 (MPCORE) */ | |
47 | { | |
48 | .virtual = 0xf0000000, | |
49 | .pfn = __phys_to_pfn(0xf0000000), | |
50 | .length = SZ_2M, | |
51 | .type = MT_DEVICE_NONSHARED | |
52 | }, | |
53 | /* 16M entity map for 0xfexxxxxx (DMAC-S/HPBREG/INTC2/LRAM/DBSC) */ | |
54 | { | |
55 | .virtual = 0xfe000000, | |
56 | .pfn = __phys_to_pfn(0xfe000000), | |
57 | .length = SZ_16M, | |
58 | .type = MT_DEVICE_NONSHARED | |
59 | }, | |
60 | }; | |
61 | ||
62 | void __init r8a7779_map_io(void) | |
63 | { | |
64 | iotable_init(r8a7779_io_desc, ARRAY_SIZE(r8a7779_io_desc)); | |
65 | } | |
f411fade | 66 | |
8b6edf36 LP |
67 | static struct resource r8a7779_pfc_resources[] = { |
68 | [0] = { | |
69 | .start = 0xfffc0000, | |
70 | .end = 0xfffc023b, | |
71 | .flags = IORESOURCE_MEM, | |
72 | }, | |
8b6edf36 LP |
73 | }; |
74 | ||
75 | static struct platform_device r8a7779_pfc_device = { | |
76 | .name = "pfc-r8a7779", | |
77 | .id = -1, | |
78 | .resource = r8a7779_pfc_resources, | |
79 | .num_resources = ARRAY_SIZE(r8a7779_pfc_resources), | |
80 | }; | |
81 | ||
37a72d07 LP |
82 | #define R8A7779_GPIO(idx, npins) \ |
83 | static struct resource r8a7779_gpio##idx##_resources[] = { \ | |
84 | [0] = { \ | |
85 | .start = 0xffc40000 + 0x1000 * (idx), \ | |
86 | .end = 0xffc4002b + 0x1000 * (idx), \ | |
87 | .flags = IORESOURCE_MEM, \ | |
88 | }, \ | |
89 | [1] = { \ | |
90 | .start = gic_iid(0xad + (idx)), \ | |
91 | .flags = IORESOURCE_IRQ, \ | |
92 | } \ | |
93 | }; \ | |
94 | \ | |
95 | static struct gpio_rcar_config r8a7779_gpio##idx##_platform_data = { \ | |
96 | .gpio_base = 32 * (idx), \ | |
97 | .irq_base = 0, \ | |
98 | .number_of_pins = npins, \ | |
99 | .pctl_name = "pfc-r8a7779", \ | |
100 | }; \ | |
101 | \ | |
102 | static struct platform_device r8a7779_gpio##idx##_device = { \ | |
103 | .name = "gpio_rcar", \ | |
104 | .id = idx, \ | |
105 | .resource = r8a7779_gpio##idx##_resources, \ | |
106 | .num_resources = ARRAY_SIZE(r8a7779_gpio##idx##_resources), \ | |
107 | .dev = { \ | |
108 | .platform_data = &r8a7779_gpio##idx##_platform_data, \ | |
109 | }, \ | |
110 | } | |
111 | ||
112 | R8A7779_GPIO(0, 32); | |
113 | R8A7779_GPIO(1, 32); | |
114 | R8A7779_GPIO(2, 32); | |
115 | R8A7779_GPIO(3, 32); | |
116 | R8A7779_GPIO(4, 32); | |
117 | R8A7779_GPIO(5, 32); | |
118 | R8A7779_GPIO(6, 9); | |
119 | ||
120 | static struct platform_device *r8a7779_pinctrl_devices[] __initdata = { | |
121 | &r8a7779_pfc_device, | |
122 | &r8a7779_gpio0_device, | |
123 | &r8a7779_gpio1_device, | |
124 | &r8a7779_gpio2_device, | |
125 | &r8a7779_gpio3_device, | |
126 | &r8a7779_gpio4_device, | |
127 | &r8a7779_gpio5_device, | |
128 | &r8a7779_gpio6_device, | |
129 | }; | |
130 | ||
8b6edf36 LP |
131 | void __init r8a7779_pinmux_init(void) |
132 | { | |
37a72d07 LP |
133 | platform_add_devices(r8a7779_pinctrl_devices, |
134 | ARRAY_SIZE(r8a7779_pinctrl_devices)); | |
8b6edf36 LP |
135 | } |
136 | ||
f411fade MD |
137 | static struct plat_sci_port scif0_platform_data = { |
138 | .mapbase = 0xffe40000, | |
139 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | |
140 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | |
141 | .scbrr_algo_id = SCBRR_ALGO_2, | |
142 | .type = PORT_SCIF, | |
dbe95ad0 | 143 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x78)), |
f411fade MD |
144 | }; |
145 | ||
146 | static struct platform_device scif0_device = { | |
147 | .name = "sh-sci", | |
148 | .id = 0, | |
149 | .dev = { | |
150 | .platform_data = &scif0_platform_data, | |
151 | }, | |
152 | }; | |
153 | ||
154 | static struct plat_sci_port scif1_platform_data = { | |
155 | .mapbase = 0xffe41000, | |
156 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | |
157 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | |
158 | .scbrr_algo_id = SCBRR_ALGO_2, | |
159 | .type = PORT_SCIF, | |
dbe95ad0 | 160 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x79)), |
f411fade MD |
161 | }; |
162 | ||
163 | static struct platform_device scif1_device = { | |
164 | .name = "sh-sci", | |
165 | .id = 1, | |
166 | .dev = { | |
167 | .platform_data = &scif1_platform_data, | |
168 | }, | |
169 | }; | |
170 | ||
171 | static struct plat_sci_port scif2_platform_data = { | |
172 | .mapbase = 0xffe42000, | |
173 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | |
174 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | |
175 | .scbrr_algo_id = SCBRR_ALGO_2, | |
176 | .type = PORT_SCIF, | |
dbe95ad0 | 177 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7a)), |
f411fade MD |
178 | }; |
179 | ||
180 | static struct platform_device scif2_device = { | |
181 | .name = "sh-sci", | |
182 | .id = 2, | |
183 | .dev = { | |
184 | .platform_data = &scif2_platform_data, | |
185 | }, | |
186 | }; | |
187 | ||
188 | static struct plat_sci_port scif3_platform_data = { | |
189 | .mapbase = 0xffe43000, | |
190 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | |
191 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | |
192 | .scbrr_algo_id = SCBRR_ALGO_2, | |
193 | .type = PORT_SCIF, | |
dbe95ad0 | 194 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7b)), |
f411fade MD |
195 | }; |
196 | ||
197 | static struct platform_device scif3_device = { | |
198 | .name = "sh-sci", | |
199 | .id = 3, | |
200 | .dev = { | |
201 | .platform_data = &scif3_platform_data, | |
202 | }, | |
203 | }; | |
204 | ||
205 | static struct plat_sci_port scif4_platform_data = { | |
206 | .mapbase = 0xffe44000, | |
207 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | |
208 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | |
209 | .scbrr_algo_id = SCBRR_ALGO_2, | |
210 | .type = PORT_SCIF, | |
dbe95ad0 | 211 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7c)), |
f411fade MD |
212 | }; |
213 | ||
214 | static struct platform_device scif4_device = { | |
215 | .name = "sh-sci", | |
216 | .id = 4, | |
217 | .dev = { | |
218 | .platform_data = &scif4_platform_data, | |
219 | }, | |
220 | }; | |
221 | ||
222 | static struct plat_sci_port scif5_platform_data = { | |
223 | .mapbase = 0xffe45000, | |
224 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | |
225 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | |
226 | .scbrr_algo_id = SCBRR_ALGO_2, | |
227 | .type = PORT_SCIF, | |
dbe95ad0 | 228 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7d)), |
f411fade MD |
229 | }; |
230 | ||
231 | static struct platform_device scif5_device = { | |
232 | .name = "sh-sci", | |
233 | .id = 5, | |
234 | .dev = { | |
235 | .platform_data = &scif5_platform_data, | |
236 | }, | |
237 | }; | |
238 | ||
239 | /* TMU */ | |
240 | static struct sh_timer_config tmu00_platform_data = { | |
241 | .name = "TMU00", | |
242 | .channel_offset = 0x4, | |
243 | .timer_bit = 0, | |
244 | .clockevent_rating = 200, | |
245 | }; | |
246 | ||
247 | static struct resource tmu00_resources[] = { | |
248 | [0] = { | |
249 | .name = "TMU00", | |
250 | .start = 0xffd80008, | |
251 | .end = 0xffd80013, | |
252 | .flags = IORESOURCE_MEM, | |
253 | }, | |
254 | [1] = { | |
dbe95ad0 | 255 | .start = gic_iid(0x40), |
f411fade MD |
256 | .flags = IORESOURCE_IRQ, |
257 | }, | |
258 | }; | |
259 | ||
260 | static struct platform_device tmu00_device = { | |
261 | .name = "sh_tmu", | |
262 | .id = 0, | |
263 | .dev = { | |
264 | .platform_data = &tmu00_platform_data, | |
265 | }, | |
266 | .resource = tmu00_resources, | |
267 | .num_resources = ARRAY_SIZE(tmu00_resources), | |
268 | }; | |
269 | ||
270 | static struct sh_timer_config tmu01_platform_data = { | |
271 | .name = "TMU01", | |
272 | .channel_offset = 0x10, | |
273 | .timer_bit = 1, | |
274 | .clocksource_rating = 200, | |
275 | }; | |
276 | ||
277 | static struct resource tmu01_resources[] = { | |
278 | [0] = { | |
279 | .name = "TMU01", | |
280 | .start = 0xffd80014, | |
281 | .end = 0xffd8001f, | |
282 | .flags = IORESOURCE_MEM, | |
283 | }, | |
284 | [1] = { | |
dbe95ad0 | 285 | .start = gic_iid(0x41), |
f411fade MD |
286 | .flags = IORESOURCE_IRQ, |
287 | }, | |
288 | }; | |
289 | ||
290 | static struct platform_device tmu01_device = { | |
291 | .name = "sh_tmu", | |
292 | .id = 1, | |
293 | .dev = { | |
294 | .platform_data = &tmu01_platform_data, | |
295 | }, | |
296 | .resource = tmu01_resources, | |
297 | .num_resources = ARRAY_SIZE(tmu01_resources), | |
298 | }; | |
299 | ||
ccc2a27b KM |
300 | /* I2C */ |
301 | static struct resource rcar_i2c0_res[] = { | |
302 | { | |
303 | .start = 0xffc70000, | |
304 | .end = 0xffc70fff, | |
305 | .flags = IORESOURCE_MEM, | |
306 | }, { | |
dbe95ad0 | 307 | .start = gic_iid(0x6f), |
ccc2a27b KM |
308 | .flags = IORESOURCE_IRQ, |
309 | }, | |
310 | }; | |
311 | ||
312 | static struct platform_device i2c0_device = { | |
313 | .name = "i2c-rcar", | |
314 | .id = 0, | |
315 | .resource = rcar_i2c0_res, | |
316 | .num_resources = ARRAY_SIZE(rcar_i2c0_res), | |
317 | }; | |
318 | ||
319 | static struct resource rcar_i2c1_res[] = { | |
320 | { | |
321 | .start = 0xffc71000, | |
322 | .end = 0xffc71fff, | |
323 | .flags = IORESOURCE_MEM, | |
324 | }, { | |
dbe95ad0 | 325 | .start = gic_iid(0x72), |
ccc2a27b KM |
326 | .flags = IORESOURCE_IRQ, |
327 | }, | |
328 | }; | |
329 | ||
330 | static struct platform_device i2c1_device = { | |
331 | .name = "i2c-rcar", | |
332 | .id = 1, | |
333 | .resource = rcar_i2c1_res, | |
334 | .num_resources = ARRAY_SIZE(rcar_i2c1_res), | |
335 | }; | |
336 | ||
337 | static struct resource rcar_i2c2_res[] = { | |
338 | { | |
339 | .start = 0xffc72000, | |
340 | .end = 0xffc72fff, | |
341 | .flags = IORESOURCE_MEM, | |
342 | }, { | |
dbe95ad0 | 343 | .start = gic_iid(0x70), |
ccc2a27b KM |
344 | .flags = IORESOURCE_IRQ, |
345 | }, | |
346 | }; | |
347 | ||
348 | static struct platform_device i2c2_device = { | |
349 | .name = "i2c-rcar", | |
350 | .id = 2, | |
351 | .resource = rcar_i2c2_res, | |
352 | .num_resources = ARRAY_SIZE(rcar_i2c2_res), | |
353 | }; | |
354 | ||
355 | static struct resource rcar_i2c3_res[] = { | |
356 | { | |
357 | .start = 0xffc73000, | |
358 | .end = 0xffc73fff, | |
359 | .flags = IORESOURCE_MEM, | |
360 | }, { | |
dbe95ad0 | 361 | .start = gic_iid(0x71), |
ccc2a27b KM |
362 | .flags = IORESOURCE_IRQ, |
363 | }, | |
364 | }; | |
365 | ||
366 | static struct platform_device i2c3_device = { | |
367 | .name = "i2c-rcar", | |
368 | .id = 3, | |
369 | .resource = rcar_i2c3_res, | |
370 | .num_resources = ARRAY_SIZE(rcar_i2c3_res), | |
371 | }; | |
372 | ||
a7b9837c VB |
373 | static struct resource sata_resources[] = { |
374 | [0] = { | |
375 | .name = "rcar-sata", | |
376 | .start = 0xfc600000, | |
377 | .end = 0xfc601fff, | |
378 | .flags = IORESOURCE_MEM, | |
379 | }, | |
380 | [1] = { | |
d60cd5f1 | 381 | .start = gic_iid(0x84), |
a7b9837c VB |
382 | .flags = IORESOURCE_IRQ, |
383 | }, | |
384 | }; | |
385 | ||
386 | static struct platform_device sata_device = { | |
387 | .name = "sata_rcar", | |
388 | .id = -1, | |
389 | .resource = sata_resources, | |
390 | .num_resources = ARRAY_SIZE(sata_resources), | |
391 | .dev = { | |
392 | .dma_mask = &sata_device.dev.coherent_dma_mask, | |
393 | .coherent_dma_mask = DMA_BIT_MASK(32), | |
394 | }, | |
395 | }; | |
396 | ||
dace48d0 SS |
397 | /* Ether */ |
398 | static struct resource ether_resources[] = { | |
399 | { | |
400 | .start = 0xfde00000, | |
401 | .end = 0xfde003ff, | |
402 | .flags = IORESOURCE_MEM, | |
403 | }, { | |
404 | .start = gic_iid(0xb4), | |
405 | .flags = IORESOURCE_IRQ, | |
406 | }, | |
407 | }; | |
408 | ||
916ddc35 | 409 | static struct platform_device *r8a7779_devices_dt[] __initdata = { |
f411fade MD |
410 | &scif0_device, |
411 | &scif1_device, | |
412 | &scif2_device, | |
413 | &scif3_device, | |
414 | &scif4_device, | |
415 | &scif5_device, | |
416 | &tmu00_device, | |
417 | &tmu01_device, | |
10e8d4f6 SH |
418 | }; |
419 | ||
e7921202 | 420 | static struct platform_device *r8a7779_late_devices[] __initdata = { |
ccc2a27b KM |
421 | &i2c0_device, |
422 | &i2c1_device, | |
423 | &i2c2_device, | |
424 | &i2c3_device, | |
a7b9837c | 425 | &sata_device, |
f411fade MD |
426 | }; |
427 | ||
f411fade MD |
428 | void __init r8a7779_add_standard_devices(void) |
429 | { | |
8bac13f5 MD |
430 | #ifdef CONFIG_CACHE_L2X0 |
431 | /* Early BRESP enable, Shared attribute override enable, 64K*16way */ | |
ed7d132a | 432 | l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff); |
8bac13f5 | 433 | #endif |
a662c082 MD |
434 | r8a7779_pm_init(); |
435 | ||
45e5ca57 | 436 | r8a7779_init_pm_domains(); |
a662c082 | 437 | |
916ddc35 SH |
438 | platform_add_devices(r8a7779_devices_dt, |
439 | ARRAY_SIZE(r8a7779_devices_dt)); | |
e7921202 SH |
440 | platform_add_devices(r8a7779_late_devices, |
441 | ARRAY_SIZE(r8a7779_late_devices)); | |
f411fade MD |
442 | } |
443 | ||
dace48d0 SS |
444 | void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata) |
445 | { | |
446 | platform_device_register_resndata(&platform_bus, "sh_eth", -1, | |
447 | ether_resources, | |
448 | ARRAY_SIZE(ether_resources), | |
449 | pdata, sizeof(*pdata)); | |
450 | } | |
451 | ||
b759bd11 MD |
452 | /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ |
453 | void __init __weak r8a7779_register_twd(void) { } | |
454 | ||
6bb27d73 | 455 | void __init r8a7779_earlytimer_init(void) |
df27a2d8 MD |
456 | { |
457 | r8a7779_clock_init(); | |
458 | shmobile_earlytimer_init(); | |
b759bd11 | 459 | r8a7779_register_twd(); |
df27a2d8 MD |
460 | } |
461 | ||
f411fade MD |
462 | void __init r8a7779_add_early_devices(void) |
463 | { | |
916ddc35 SH |
464 | early_platform_add_devices(r8a7779_devices_dt, |
465 | ARRAY_SIZE(r8a7779_devices_dt)); | |
3e353b87 MD |
466 | |
467 | /* Early serial console setup is not included here due to | |
468 | * memory map collisions. The SCIF serial ports in r8a7779 | |
469 | * are difficult to entity map 1:1 due to collision with the | |
470 | * virtual memory range used by the coherent DMA code on ARM. | |
471 | * | |
472 | * Anyone wanting to debug early can remove UPF_IOREMAP from | |
473 | * the sh-sci serial console platform data, adjust mapbase | |
474 | * to a static M:N virt:phys mapping that needs to be added to | |
475 | * the mappings passed with iotable_init() above. | |
476 | * | |
477 | * Then add a call to shmobile_setup_console() from this function. | |
478 | * | |
479 | * As a final step pass earlyprint=sh-sci.2,115200 on the kernel | |
480 | * command line in case of the marzen board. | |
481 | */ | |
f411fade | 482 | } |
10e8d4f6 SH |
483 | |
484 | #ifdef CONFIG_USE_OF | |
916ddc35 | 485 | void __init r8a7779_init_delay(void) |
10e8d4f6 SH |
486 | { |
487 | shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */ | |
10e8d4f6 SH |
488 | } |
489 | ||
490 | static const struct of_dev_auxdata r8a7779_auxdata_lookup[] __initconst = { | |
491 | {}, | |
492 | }; | |
493 | ||
494 | void __init r8a7779_add_standard_devices_dt(void) | |
495 | { | |
496 | /* clocks are setup late during boot in the case of DT */ | |
497 | r8a7779_clock_init(); | |
498 | ||
916ddc35 SH |
499 | platform_add_devices(r8a7779_devices_dt, |
500 | ARRAY_SIZE(r8a7779_devices_dt)); | |
10e8d4f6 SH |
501 | of_platform_populate(NULL, of_default_bus_match_table, |
502 | r8a7779_auxdata_lookup, NULL); | |
503 | } | |
504 | ||
505 | static const char *r8a7779_compat_dt[] __initdata = { | |
506 | "renesas,r8a7779", | |
507 | NULL, | |
508 | }; | |
509 | ||
abe0e14b | 510 | DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)") |
10e8d4f6 | 511 | .map_io = r8a7779_map_io, |
916ddc35 | 512 | .init_early = r8a7779_init_delay, |
10e8d4f6 SH |
513 | .nr_irqs = NR_IRQS_LEGACY, |
514 | .init_irq = r8a7779_init_irq_dt, | |
515 | .init_machine = r8a7779_add_standard_devices_dt, | |
516 | .init_time = shmobile_timer_init, | |
517 | .dt_compat = r8a7779_compat_dt, | |
518 | MACHINE_END | |
519 | #endif /* CONFIG_USE_OF */ |