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