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