aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mv78xx0/common.c
diff options
context:
space:
mode:
authorStanislav Samsonov <samsonov@marvell.com>2008-06-22 16:45:10 -0400
committerLennert Buytenhek <buytenh@marvell.com>2008-06-22 16:45:10 -0400
commit794d15b25df5dda10efba600d6dd6cd74a7aa9cb (patch)
tree10797e90295895994ea3f2363e84e555e40abb97 /arch/arm/mach-mv78xx0/common.c
parenta9311cfed241ebcd6b5f9be5c8c6d519bf22f9e7 (diff)
[ARM] add Marvell 78xx0 ARM SoC support
The Marvell Discovery Duo (MV78xx0) is a family of ARM SoCs featuring (depending on the model) one or two Feroceon CPU cores with 512K of L2 cache and VFP coprocessors running at (depending on the model) between 800 MHz and 1.2 GHz, and features a DDR2 controller, two PCIe interfaces that can each run either in x4 or quad x1 mode, three USB 2.0 interfaces, two 3Gb/s SATA II interfaces, a SPI interface, two TWSI interfaces, a crypto accelerator, IDMA/XOR engines, a SPI interface, four UARTs, and depending on the model, two or four gigabit ethernet interfaces. This patch adds basic support for the platform, and allows booting on the MV78x00 development board, with functional UARTs, SATA, PCIe, GigE and USB ports. Signed-off-by: Stanislav Samsonov <samsonov@marvell.com> Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'arch/arm/mach-mv78xx0/common.c')
-rw-r--r--arch/arm/mach-mv78xx0/common.c754
1 files changed, 754 insertions, 0 deletions
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
new file mode 100644
index 000000000000..d27b83b7bf62
--- /dev/null
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -0,0 +1,754 @@
1/*
2 * arch/arm/mach-mv78xx0/common.c
3 *
4 * Core functions for Marvell MV78xx0 SoCs
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/platform_device.h>
14#include <linux/serial_8250.h>
15#include <linux/mbus.h>
16#include <linux/mv643xx_eth.h>
17#include <linux/ata_platform.h>
18#include <asm/mach/map.h>
19#include <asm/mach/time.h>
20#include <asm/arch/mv78xx0.h>
21#include <asm/plat-orion/cache-feroceon-l2.h>
22#include <asm/plat-orion/ehci-orion.h>
23#include <asm/plat-orion/orion_nand.h>
24#include <asm/plat-orion/time.h>
25#include "common.h"
26
27
28/*****************************************************************************
29 * Common bits
30 ****************************************************************************/
31int mv78xx0_core_index(void)
32{
33 u32 extra;
34
35 /*
36 * Read Extra Features register.
37 */
38 __asm__("mrc p15, 1, %0, c15, c1, 0" : "=r" (extra));
39
40 return !!(extra & 0x00004000);
41}
42
43static int get_hclk(void)
44{
45 int hclk;
46
47 /*
48 * HCLK tick rate is configured by DEV_D[7:5] pins.
49 */
50 switch ((readl(SAMPLE_AT_RESET_LOW) >> 5) & 7) {
51 case 0:
52 hclk = 166666667;
53 break;
54 case 1:
55 hclk = 200000000;
56 break;
57 case 2:
58 hclk = 266666667;
59 break;
60 case 3:
61 hclk = 333333333;
62 break;
63 case 4:
64 hclk = 400000000;
65 break;
66 default:
67 panic("unknown HCLK PLL setting: %.8x\n",
68 readl(SAMPLE_AT_RESET_LOW));
69 }
70
71 return hclk;
72}
73
74static void get_pclk_l2clk(int hclk, int core_index, int *pclk, int *l2clk)
75{
76 u32 cfg;
77
78 /*
79 * Core #0 PCLK/L2CLK is configured by bits [13:8], core #1
80 * PCLK/L2CLK by bits [19:14].
81 */
82 if (core_index == 0) {
83 cfg = (readl(SAMPLE_AT_RESET_LOW) >> 8) & 0x3f;
84 } else {
85 cfg = (readl(SAMPLE_AT_RESET_LOW) >> 14) & 0x3f;
86 }
87
88 /*
89 * Bits [11:8] ([17:14] for core #1) configure the PCLK:HCLK
90 * ratio (1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6).
91 */
92 *pclk = ((u64)hclk * (2 + (cfg & 0xf))) >> 1;
93
94 /*
95 * Bits [13:12] ([19:18] for core #1) configure the PCLK:L2CLK
96 * ratio (1, 2, 3).
97 */
98 *l2clk = *pclk / (((cfg >> 4) & 3) + 1);
99}
100
101static int get_tclk(void)
102{
103 int tclk;
104
105 /*
106 * TCLK tick rate is configured by DEV_A[2:0] strap pins.
107 */
108 switch ((readl(SAMPLE_AT_RESET_HIGH) >> 6) & 7) {
109 case 1:
110 tclk = 166666667;
111 break;
112 case 3:
113 tclk = 200000000;
114 break;
115 default:
116 panic("unknown TCLK PLL setting: %.8x\n",
117 readl(SAMPLE_AT_RESET_HIGH));
118 }
119
120 return tclk;
121}
122
123
124/*****************************************************************************
125 * I/O Address Mapping
126 ****************************************************************************/
127static struct map_desc mv78xx0_io_desc[] __initdata = {
128 {
129 .virtual = MV78XX0_CORE_REGS_VIRT_BASE,
130 .pfn = 0,
131 .length = MV78XX0_CORE_REGS_SIZE,
132 .type = MT_DEVICE,
133 }, {
134 .virtual = MV78XX0_PCIE_IO_VIRT_BASE(0),
135 .pfn = __phys_to_pfn(MV78XX0_PCIE_IO_PHYS_BASE(0)),
136 .length = MV78XX0_PCIE_IO_SIZE * 8,
137 .type = MT_DEVICE,
138 }, {
139 .virtual = MV78XX0_REGS_VIRT_BASE,
140 .pfn = __phys_to_pfn(MV78XX0_REGS_PHYS_BASE),
141 .length = MV78XX0_REGS_SIZE,
142 .type = MT_DEVICE,
143 },
144};
145
146void __init mv78xx0_map_io(void)
147{
148 unsigned long phys;
149
150 /*
151 * Map the right set of per-core registers depending on
152 * which core we are running on.
153 */
154 if (mv78xx0_core_index() == 0) {
155 phys = MV78XX0_CORE0_REGS_PHYS_BASE;
156 } else {
157 phys = MV78XX0_CORE1_REGS_PHYS_BASE;
158 }
159 mv78xx0_io_desc[0].pfn = __phys_to_pfn(phys);
160
161 iotable_init(mv78xx0_io_desc, ARRAY_SIZE(mv78xx0_io_desc));
162}
163
164
165/*****************************************************************************
166 * EHCI
167 ****************************************************************************/
168static struct orion_ehci_data mv78xx0_ehci_data = {
169 .dram = &mv78xx0_mbus_dram_info,
170};
171
172static u64 ehci_dmamask = 0xffffffffUL;
173
174
175/*****************************************************************************
176 * EHCI0
177 ****************************************************************************/
178static struct resource mv78xx0_ehci0_resources[] = {
179 {
180 .start = USB0_PHYS_BASE,
181 .end = USB0_PHYS_BASE + 0x0fff,
182 .flags = IORESOURCE_MEM,
183 }, {
184 .start = IRQ_MV78XX0_USB_0,
185 .end = IRQ_MV78XX0_USB_0,
186 .flags = IORESOURCE_IRQ,
187 },
188};
189
190static struct platform_device mv78xx0_ehci0 = {
191 .name = "orion-ehci",
192 .id = 0,
193 .dev = {
194 .dma_mask = &ehci_dmamask,
195 .coherent_dma_mask = 0xffffffff,
196 .platform_data = &mv78xx0_ehci_data,
197 },
198 .resource = mv78xx0_ehci0_resources,
199 .num_resources = ARRAY_SIZE(mv78xx0_ehci0_resources),
200};
201
202void __init mv78xx0_ehci0_init(void)
203{
204 platform_device_register(&mv78xx0_ehci0);
205}
206
207
208/*****************************************************************************
209 * EHCI1
210 ****************************************************************************/
211static struct resource mv78xx0_ehci1_resources[] = {
212 {
213 .start = USB1_PHYS_BASE,
214 .end = USB1_PHYS_BASE + 0x0fff,
215 .flags = IORESOURCE_MEM,
216 }, {
217 .start = IRQ_MV78XX0_USB_1,
218 .end = IRQ_MV78XX0_USB_1,
219 .flags = IORESOURCE_IRQ,
220 },
221};
222
223static struct platform_device mv78xx0_ehci1 = {
224 .name = "orion-ehci",
225 .id = 1,
226 .dev = {
227 .dma_mask = &ehci_dmamask,
228 .coherent_dma_mask = 0xffffffff,
229 .platform_data = &mv78xx0_ehci_data,
230 },
231 .resource = mv78xx0_ehci1_resources,
232 .num_resources = ARRAY_SIZE(mv78xx0_ehci1_resources),
233};
234
235void __init mv78xx0_ehci1_init(void)
236{
237 platform_device_register(&mv78xx0_ehci1);
238}
239
240
241/*****************************************************************************
242 * EHCI2
243 ****************************************************************************/
244static struct resource mv78xx0_ehci2_resources[] = {
245 {
246 .start = USB2_PHYS_BASE,
247 .end = USB2_PHYS_BASE + 0x0fff,
248 .flags = IORESOURCE_MEM,
249 }, {
250 .start = IRQ_MV78XX0_USB_2,
251 .end = IRQ_MV78XX0_USB_2,
252 .flags = IORESOURCE_IRQ,
253 },
254};
255
256static struct platform_device mv78xx0_ehci2 = {
257 .name = "orion-ehci",
258 .id = 2,
259 .dev = {
260 .dma_mask = &ehci_dmamask,
261 .coherent_dma_mask = 0xffffffff,
262 .platform_data = &mv78xx0_ehci_data,
263 },
264 .resource = mv78xx0_ehci2_resources,
265 .num_resources = ARRAY_SIZE(mv78xx0_ehci2_resources),
266};
267
268void __init mv78xx0_ehci2_init(void)
269{
270 platform_device_register(&mv78xx0_ehci2);
271}
272
273
274/*****************************************************************************
275 * GE00
276 ****************************************************************************/
277struct mv643xx_eth_shared_platform_data mv78xx0_ge00_shared_data = {
278 .t_clk = 0,
279 .dram = &mv78xx0_mbus_dram_info,
280};
281
282static struct resource mv78xx0_ge00_shared_resources[] = {
283 {
284 .name = "ge00 base",
285 .start = GE00_PHYS_BASE + 0x2000,
286 .end = GE00_PHYS_BASE + 0x3fff,
287 .flags = IORESOURCE_MEM,
288 },
289};
290
291static struct platform_device mv78xx0_ge00_shared = {
292 .name = MV643XX_ETH_SHARED_NAME,
293 .id = 0,
294 .dev = {
295 .platform_data = &mv78xx0_ge00_shared_data,
296 },
297 .num_resources = 1,
298 .resource = mv78xx0_ge00_shared_resources,
299};
300
301static struct resource mv78xx0_ge00_resources[] = {
302 {
303 .name = "ge00 irq",
304 .start = IRQ_MV78XX0_GE00_SUM,
305 .end = IRQ_MV78XX0_GE00_SUM,
306 .flags = IORESOURCE_IRQ,
307 },
308};
309
310static struct platform_device mv78xx0_ge00 = {
311 .name = MV643XX_ETH_NAME,
312 .id = 0,
313 .num_resources = 1,
314 .resource = mv78xx0_ge00_resources,
315};
316
317void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
318{
319 eth_data->shared = &mv78xx0_ge00_shared;
320 mv78xx0_ge00.dev.platform_data = eth_data;
321
322 platform_device_register(&mv78xx0_ge00_shared);
323 platform_device_register(&mv78xx0_ge00);
324}
325
326
327/*****************************************************************************
328 * GE01
329 ****************************************************************************/
330struct mv643xx_eth_shared_platform_data mv78xx0_ge01_shared_data = {
331 .t_clk = 0,
332 .dram = &mv78xx0_mbus_dram_info,
333};
334
335static struct resource mv78xx0_ge01_shared_resources[] = {
336 {
337 .name = "ge01 base",
338 .start = GE01_PHYS_BASE + 0x2000,
339 .end = GE01_PHYS_BASE + 0x3fff,
340 .flags = IORESOURCE_MEM,
341 },
342};
343
344static struct platform_device mv78xx0_ge01_shared = {
345 .name = MV643XX_ETH_SHARED_NAME,
346 .id = 1,
347 .dev = {
348 .platform_data = &mv78xx0_ge01_shared_data,
349 },
350 .num_resources = 1,
351 .resource = mv78xx0_ge01_shared_resources,
352};
353
354static struct resource mv78xx0_ge01_resources[] = {
355 {
356 .name = "ge01 irq",
357 .start = IRQ_MV78XX0_GE01_SUM,
358 .end = IRQ_MV78XX0_GE01_SUM,
359 .flags = IORESOURCE_IRQ,
360 },
361};
362
363static struct platform_device mv78xx0_ge01 = {
364 .name = MV643XX_ETH_NAME,
365 .id = 1,
366 .num_resources = 1,
367 .resource = mv78xx0_ge01_resources,
368};
369
370void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
371{
372 eth_data->shared = &mv78xx0_ge01_shared;
373 eth_data->shared_smi = &mv78xx0_ge00_shared;
374 mv78xx0_ge01.dev.platform_data = eth_data;
375
376 platform_device_register(&mv78xx0_ge01_shared);
377 platform_device_register(&mv78xx0_ge01);
378}
379
380
381/*****************************************************************************
382 * GE10
383 ****************************************************************************/
384struct mv643xx_eth_shared_platform_data mv78xx0_ge10_shared_data = {
385 .t_clk = 0,
386 .dram = &mv78xx0_mbus_dram_info,
387};
388
389static struct resource mv78xx0_ge10_shared_resources[] = {
390 {
391 .name = "ge10 base",
392 .start = GE10_PHYS_BASE + 0x2000,
393 .end = GE10_PHYS_BASE + 0x3fff,
394 .flags = IORESOURCE_MEM,
395 },
396};
397
398static struct platform_device mv78xx0_ge10_shared = {
399 .name = MV643XX_ETH_SHARED_NAME,
400 .id = 2,
401 .dev = {
402 .platform_data = &mv78xx0_ge10_shared_data,
403 },
404 .num_resources = 1,
405 .resource = mv78xx0_ge10_shared_resources,
406};
407
408static struct resource mv78xx0_ge10_resources[] = {
409 {
410 .name = "ge10 irq",
411 .start = IRQ_MV78XX0_GE10_SUM,
412 .end = IRQ_MV78XX0_GE10_SUM,
413 .flags = IORESOURCE_IRQ,
414 },
415};
416
417static struct platform_device mv78xx0_ge10 = {
418 .name = MV643XX_ETH_NAME,
419 .id = 2,
420 .num_resources = 1,
421 .resource = mv78xx0_ge10_resources,
422};
423
424void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
425{
426 eth_data->shared = &mv78xx0_ge10_shared;
427 eth_data->shared_smi = &mv78xx0_ge00_shared;
428 mv78xx0_ge10.dev.platform_data = eth_data;
429
430 platform_device_register(&mv78xx0_ge10_shared);
431 platform_device_register(&mv78xx0_ge10);
432}
433
434
435/*****************************************************************************
436 * GE11
437 ****************************************************************************/
438struct mv643xx_eth_shared_platform_data mv78xx0_ge11_shared_data = {
439 .t_clk = 0,
440 .dram = &mv78xx0_mbus_dram_info,
441};
442
443static struct resource mv78xx0_ge11_shared_resources[] = {
444 {
445 .name = "ge11 base",
446 .start = GE11_PHYS_BASE + 0x2000,
447 .end = GE11_PHYS_BASE + 0x3fff,
448 .flags = IORESOURCE_MEM,
449 },
450};
451
452static struct platform_device mv78xx0_ge11_shared = {
453 .name = MV643XX_ETH_SHARED_NAME,
454 .id = 3,
455 .dev = {
456 .platform_data = &mv78xx0_ge11_shared_data,
457 },
458 .num_resources = 1,
459 .resource = mv78xx0_ge11_shared_resources,
460};
461
462static struct resource mv78xx0_ge11_resources[] = {
463 {
464 .name = "ge11 irq",
465 .start = IRQ_MV78XX0_GE11_SUM,
466 .end = IRQ_MV78XX0_GE11_SUM,
467 .flags = IORESOURCE_IRQ,
468 },
469};
470
471static struct platform_device mv78xx0_ge11 = {
472 .name = MV643XX_ETH_NAME,
473 .id = 3,
474 .num_resources = 1,
475 .resource = mv78xx0_ge11_resources,
476};
477
478void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
479{
480 eth_data->shared = &mv78xx0_ge11_shared;
481 eth_data->shared_smi = &mv78xx0_ge00_shared;
482 mv78xx0_ge11.dev.platform_data = eth_data;
483
484 platform_device_register(&mv78xx0_ge11_shared);
485 platform_device_register(&mv78xx0_ge11);
486}
487
488
489/*****************************************************************************
490 * SATA
491 ****************************************************************************/
492static struct resource mv78xx0_sata_resources[] = {
493 {
494 .name = "sata base",
495 .start = SATA_PHYS_BASE,
496 .end = SATA_PHYS_BASE + 0x5000 - 1,
497 .flags = IORESOURCE_MEM,
498 }, {
499 .name = "sata irq",
500 .start = IRQ_MV78XX0_SATA,
501 .end = IRQ_MV78XX0_SATA,
502 .flags = IORESOURCE_IRQ,
503 },
504};
505
506static struct platform_device mv78xx0_sata = {
507 .name = "sata_mv",
508 .id = 0,
509 .dev = {
510 .coherent_dma_mask = 0xffffffff,
511 },
512 .num_resources = ARRAY_SIZE(mv78xx0_sata_resources),
513 .resource = mv78xx0_sata_resources,
514};
515
516void __init mv78xx0_sata_init(struct mv_sata_platform_data *sata_data)
517{
518 sata_data->dram = &mv78xx0_mbus_dram_info;
519 mv78xx0_sata.dev.platform_data = sata_data;
520 platform_device_register(&mv78xx0_sata);
521}
522
523
524/*****************************************************************************
525 * UART0
526 ****************************************************************************/
527static struct plat_serial8250_port mv78xx0_uart0_data[] = {
528 {
529 .mapbase = UART0_PHYS_BASE,
530 .membase = (char *)UART0_VIRT_BASE,
531 .irq = IRQ_MV78XX0_UART_0,
532 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
533 .iotype = UPIO_MEM,
534 .regshift = 2,
535 .uartclk = 0,
536 }, {
537 },
538};
539
540static struct resource mv78xx0_uart0_resources[] = {
541 {
542 .start = UART0_PHYS_BASE,
543 .end = UART0_PHYS_BASE + 0xff,
544 .flags = IORESOURCE_MEM,
545 }, {
546 .start = IRQ_MV78XX0_UART_0,
547 .end = IRQ_MV78XX0_UART_0,
548 .flags = IORESOURCE_IRQ,
549 },
550};
551
552static struct platform_device mv78xx0_uart0 = {
553 .name = "serial8250",
554 .id = 0,
555 .dev = {
556 .platform_data = mv78xx0_uart0_data,
557 },
558 .resource = mv78xx0_uart0_resources,
559 .num_resources = ARRAY_SIZE(mv78xx0_uart0_resources),
560};
561
562void __init mv78xx0_uart0_init(void)
563{
564 platform_device_register(&mv78xx0_uart0);
565}
566
567
568/*****************************************************************************
569 * UART1
570 ****************************************************************************/
571static struct plat_serial8250_port mv78xx0_uart1_data[] = {
572 {
573 .mapbase = UART1_PHYS_BASE,
574 .membase = (char *)UART1_VIRT_BASE,
575 .irq = IRQ_MV78XX0_UART_1,
576 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
577 .iotype = UPIO_MEM,
578 .regshift = 2,
579 .uartclk = 0,
580 }, {
581 },
582};
583
584static struct resource mv78xx0_uart1_resources[] = {
585 {
586 .start = UART1_PHYS_BASE,
587 .end = UART1_PHYS_BASE + 0xff,
588 .flags = IORESOURCE_MEM,
589 }, {
590 .start = IRQ_MV78XX0_UART_1,
591 .end = IRQ_MV78XX0_UART_1,
592 .flags = IORESOURCE_IRQ,
593 },
594};
595
596static struct platform_device mv78xx0_uart1 = {
597 .name = "serial8250",
598 .id = 1,
599 .dev = {
600 .platform_data = mv78xx0_uart1_data,
601 },
602 .resource = mv78xx0_uart1_resources,
603 .num_resources = ARRAY_SIZE(mv78xx0_uart1_resources),
604};
605
606void __init mv78xx0_uart1_init(void)
607{
608 platform_device_register(&mv78xx0_uart1);
609}
610
611
612/*****************************************************************************
613 * UART2
614 ****************************************************************************/
615static struct plat_serial8250_port mv78xx0_uart2_data[] = {
616 {
617 .mapbase = UART2_PHYS_BASE,
618 .membase = (char *)UART2_VIRT_BASE,
619 .irq = IRQ_MV78XX0_UART_2,
620 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
621 .iotype = UPIO_MEM,
622 .regshift = 2,
623 .uartclk = 0,
624 }, {
625 },
626};
627
628static struct resource mv78xx0_uart2_resources[] = {
629 {
630 .start = UART2_PHYS_BASE,
631 .end = UART2_PHYS_BASE + 0xff,
632 .flags = IORESOURCE_MEM,
633 }, {
634 .start = IRQ_MV78XX0_UART_2,
635 .end = IRQ_MV78XX0_UART_2,
636 .flags = IORESOURCE_IRQ,
637 },
638};
639
640static struct platform_device mv78xx0_uart2 = {
641 .name = "serial8250",
642 .id = 2,
643 .dev = {
644 .platform_data = mv78xx0_uart2_data,
645 },
646 .resource = mv78xx0_uart2_resources,
647 .num_resources = ARRAY_SIZE(mv78xx0_uart2_resources),
648};
649
650void __init mv78xx0_uart2_init(void)
651{
652 platform_device_register(&mv78xx0_uart2);
653}
654
655
656/*****************************************************************************
657 * UART3
658 ****************************************************************************/
659static struct plat_serial8250_port mv78xx0_uart3_data[] = {
660 {
661 .mapbase = UART3_PHYS_BASE,
662 .membase = (char *)UART3_VIRT_BASE,
663 .irq = IRQ_MV78XX0_UART_3,
664 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
665 .iotype = UPIO_MEM,
666 .regshift = 2,
667 .uartclk = 0,
668 }, {
669 },
670};
671
672static struct resource mv78xx0_uart3_resources[] = {
673 {
674 .start = UART3_PHYS_BASE,
675 .end = UART3_PHYS_BASE + 0xff,
676 .flags = IORESOURCE_MEM,
677 }, {
678 .start = IRQ_MV78XX0_UART_3,
679 .end = IRQ_MV78XX0_UART_3,
680 .flags = IORESOURCE_IRQ,
681 },
682};
683
684static struct platform_device mv78xx0_uart3 = {
685 .name = "serial8250",
686 .id = 3,
687 .dev = {
688 .platform_data = mv78xx0_uart3_data,
689 },
690 .resource = mv78xx0_uart3_resources,
691 .num_resources = ARRAY_SIZE(mv78xx0_uart3_resources),
692};
693
694void __init mv78xx0_uart3_init(void)
695{
696 platform_device_register(&mv78xx0_uart3);
697}
698
699
700/*****************************************************************************
701 * Time handling
702 ****************************************************************************/
703static void mv78xx0_timer_init(void)
704{
705 orion_time_init(IRQ_MV78XX0_TIMER_1, get_tclk());
706}
707
708struct sys_timer mv78xx0_timer = {
709 .init = mv78xx0_timer_init,
710};
711
712
713/*****************************************************************************
714 * General
715 ****************************************************************************/
716static int __init is_l2_writethrough(void)
717{
718 return !!(readl(CPU_CONTROL) & L2_WRITETHROUGH);
719}
720
721void __init mv78xx0_init(void)
722{
723 int core_index;
724 int hclk;
725 int pclk;
726 int l2clk;
727 int tclk;
728
729 core_index = mv78xx0_core_index();
730 hclk = get_hclk();
731 get_pclk_l2clk(hclk, core_index, &pclk, &l2clk);
732 tclk = get_tclk();
733
734 printk(KERN_INFO "MV78xx0 core #%d, ", core_index);
735 printk("PCLK = %dMHz, ", (pclk + 499999) / 1000000);
736 printk("L2 = %dMHz, ", (l2clk + 499999) / 1000000);
737 printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000);
738 printk("TCLK = %dMHz\n", (tclk + 499999) / 1000000);
739
740 mv78xx0_setup_cpu_mbus();
741
742#ifdef CONFIG_CACHE_FEROCEON_L2
743 feroceon_l2_init(is_l2_writethrough());
744#endif
745
746 mv78xx0_ge00_shared_data.t_clk = tclk;
747 mv78xx0_ge01_shared_data.t_clk = tclk;
748 mv78xx0_ge10_shared_data.t_clk = tclk;
749 mv78xx0_ge11_shared_data.t_clk = tclk;
750 mv78xx0_uart0_data[0].uartclk = tclk;
751 mv78xx0_uart1_data[0].uartclk = tclk;
752 mv78xx0_uart2_data[0].uartclk = tclk;
753 mv78xx0_uart3_data[0].uartclk = tclk;
754}