Merge branch 'topic/ctxfi' into for-linus
[sfrench/cifs-2.6.git] / arch / arm / mach-orion5x / common.c
1 /*
2  * arch/arm/mach-orion5x/common.c
3  *
4  * Core functions for Marvell Orion 5x SoCs
5  *
6  * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2.  This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/platform_device.h>
16 #include <linux/serial_8250.h>
17 #include <linux/mbus.h>
18 #include <linux/mv643xx_eth.h>
19 #include <linux/mv643xx_i2c.h>
20 #include <linux/ata_platform.h>
21 #include <linux/spi/orion_spi.h>
22 #include <net/dsa.h>
23 #include <asm/page.h>
24 #include <asm/setup.h>
25 #include <asm/timex.h>
26 #include <asm/mach/arch.h>
27 #include <asm/mach/map.h>
28 #include <asm/mach/time.h>
29 #include <mach/hardware.h>
30 #include <mach/orion5x.h>
31 #include <plat/ehci-orion.h>
32 #include <plat/mv_xor.h>
33 #include <plat/orion_nand.h>
34 #include <plat/orion5x_wdt.h>
35 #include <plat/time.h>
36 #include "common.h"
37
38 /*****************************************************************************
39  * I/O Address Mapping
40  ****************************************************************************/
41 static struct map_desc orion5x_io_desc[] __initdata = {
42         {
43                 .virtual        = ORION5X_REGS_VIRT_BASE,
44                 .pfn            = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
45                 .length         = ORION5X_REGS_SIZE,
46                 .type           = MT_DEVICE,
47         }, {
48                 .virtual        = ORION5X_PCIE_IO_VIRT_BASE,
49                 .pfn            = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
50                 .length         = ORION5X_PCIE_IO_SIZE,
51                 .type           = MT_DEVICE,
52         }, {
53                 .virtual        = ORION5X_PCI_IO_VIRT_BASE,
54                 .pfn            = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
55                 .length         = ORION5X_PCI_IO_SIZE,
56                 .type           = MT_DEVICE,
57         }, {
58                 .virtual        = ORION5X_PCIE_WA_VIRT_BASE,
59                 .pfn            = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
60                 .length         = ORION5X_PCIE_WA_SIZE,
61                 .type           = MT_DEVICE,
62         },
63 };
64
65 void __init orion5x_map_io(void)
66 {
67         iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
68 }
69
70
71 /*****************************************************************************
72  * EHCI
73  ****************************************************************************/
74 static struct orion_ehci_data orion5x_ehci_data = {
75         .dram           = &orion5x_mbus_dram_info,
76         .phy_version    = EHCI_PHY_ORION,
77 };
78
79 static u64 ehci_dmamask = 0xffffffffUL;
80
81
82 /*****************************************************************************
83  * EHCI0
84  ****************************************************************************/
85 static struct resource orion5x_ehci0_resources[] = {
86         {
87                 .start  = ORION5X_USB0_PHYS_BASE,
88                 .end    = ORION5X_USB0_PHYS_BASE + SZ_4K - 1,
89                 .flags  = IORESOURCE_MEM,
90         }, {
91                 .start  = IRQ_ORION5X_USB0_CTRL,
92                 .end    = IRQ_ORION5X_USB0_CTRL,
93                 .flags  = IORESOURCE_IRQ,
94         },
95 };
96
97 static struct platform_device orion5x_ehci0 = {
98         .name           = "orion-ehci",
99         .id             = 0,
100         .dev            = {
101                 .dma_mask               = &ehci_dmamask,
102                 .coherent_dma_mask      = 0xffffffff,
103                 .platform_data          = &orion5x_ehci_data,
104         },
105         .resource       = orion5x_ehci0_resources,
106         .num_resources  = ARRAY_SIZE(orion5x_ehci0_resources),
107 };
108
109 void __init orion5x_ehci0_init(void)
110 {
111         platform_device_register(&orion5x_ehci0);
112 }
113
114
115 /*****************************************************************************
116  * EHCI1
117  ****************************************************************************/
118 static struct resource orion5x_ehci1_resources[] = {
119         {
120                 .start  = ORION5X_USB1_PHYS_BASE,
121                 .end    = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
122                 .flags  = IORESOURCE_MEM,
123         }, {
124                 .start  = IRQ_ORION5X_USB1_CTRL,
125                 .end    = IRQ_ORION5X_USB1_CTRL,
126                 .flags  = IORESOURCE_IRQ,
127         },
128 };
129
130 static struct platform_device orion5x_ehci1 = {
131         .name           = "orion-ehci",
132         .id             = 1,
133         .dev            = {
134                 .dma_mask               = &ehci_dmamask,
135                 .coherent_dma_mask      = 0xffffffff,
136                 .platform_data          = &orion5x_ehci_data,
137         },
138         .resource       = orion5x_ehci1_resources,
139         .num_resources  = ARRAY_SIZE(orion5x_ehci1_resources),
140 };
141
142 void __init orion5x_ehci1_init(void)
143 {
144         platform_device_register(&orion5x_ehci1);
145 }
146
147
148 /*****************************************************************************
149  * GigE
150  ****************************************************************************/
151 struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data = {
152         .dram           = &orion5x_mbus_dram_info,
153 };
154
155 static struct resource orion5x_eth_shared_resources[] = {
156         {
157                 .start  = ORION5X_ETH_PHYS_BASE + 0x2000,
158                 .end    = ORION5X_ETH_PHYS_BASE + 0x3fff,
159                 .flags  = IORESOURCE_MEM,
160         }, {
161                 .start  = IRQ_ORION5X_ETH_ERR,
162                 .end    = IRQ_ORION5X_ETH_ERR,
163                 .flags  = IORESOURCE_IRQ,
164         },
165 };
166
167 static struct platform_device orion5x_eth_shared = {
168         .name           = MV643XX_ETH_SHARED_NAME,
169         .id             = 0,
170         .dev            = {
171                 .platform_data  = &orion5x_eth_shared_data,
172         },
173         .num_resources  = ARRAY_SIZE(orion5x_eth_shared_resources),
174         .resource       = orion5x_eth_shared_resources,
175 };
176
177 static struct resource orion5x_eth_resources[] = {
178         {
179                 .name   = "eth irq",
180                 .start  = IRQ_ORION5X_ETH_SUM,
181                 .end    = IRQ_ORION5X_ETH_SUM,
182                 .flags  = IORESOURCE_IRQ,
183         },
184 };
185
186 static struct platform_device orion5x_eth = {
187         .name           = MV643XX_ETH_NAME,
188         .id             = 0,
189         .num_resources  = 1,
190         .resource       = orion5x_eth_resources,
191         .dev            = {
192                 .coherent_dma_mask      = 0xffffffff,
193         },
194 };
195
196 void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
197 {
198         eth_data->shared = &orion5x_eth_shared;
199         orion5x_eth.dev.platform_data = eth_data;
200
201         platform_device_register(&orion5x_eth_shared);
202         platform_device_register(&orion5x_eth);
203 }
204
205
206 /*****************************************************************************
207  * Ethernet switch
208  ****************************************************************************/
209 static struct resource orion5x_switch_resources[] = {
210         {
211                 .start  = 0,
212                 .end    = 0,
213                 .flags  = IORESOURCE_IRQ,
214         },
215 };
216
217 static struct platform_device orion5x_switch_device = {
218         .name           = "dsa",
219         .id             = 0,
220         .num_resources  = 0,
221         .resource       = orion5x_switch_resources,
222 };
223
224 void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
225 {
226         int i;
227
228         if (irq != NO_IRQ) {
229                 orion5x_switch_resources[0].start = irq;
230                 orion5x_switch_resources[0].end = irq;
231                 orion5x_switch_device.num_resources = 1;
232         }
233
234         d->netdev = &orion5x_eth.dev;
235         for (i = 0; i < d->nr_chips; i++)
236                 d->chip[i].mii_bus = &orion5x_eth_shared.dev;
237         orion5x_switch_device.dev.platform_data = d;
238
239         platform_device_register(&orion5x_switch_device);
240 }
241
242
243 /*****************************************************************************
244  * I2C
245  ****************************************************************************/
246 static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
247         .freq_m         = 8, /* assumes 166 MHz TCLK */
248         .freq_n         = 3,
249         .timeout        = 1000, /* Default timeout of 1 second */
250 };
251
252 static struct resource orion5x_i2c_resources[] = {
253         {
254                 .start  = I2C_PHYS_BASE,
255                 .end    = I2C_PHYS_BASE + 0x1f,
256                 .flags  = IORESOURCE_MEM,
257         }, {
258                 .start  = IRQ_ORION5X_I2C,
259                 .end    = IRQ_ORION5X_I2C,
260                 .flags  = IORESOURCE_IRQ,
261         },
262 };
263
264 static struct platform_device orion5x_i2c = {
265         .name           = MV64XXX_I2C_CTLR_NAME,
266         .id             = 0,
267         .num_resources  = ARRAY_SIZE(orion5x_i2c_resources),
268         .resource       = orion5x_i2c_resources,
269         .dev            = {
270                 .platform_data  = &orion5x_i2c_pdata,
271         },
272 };
273
274 void __init orion5x_i2c_init(void)
275 {
276         platform_device_register(&orion5x_i2c);
277 }
278
279
280 /*****************************************************************************
281  * SATA
282  ****************************************************************************/
283 static struct resource orion5x_sata_resources[] = {
284         {
285                 .name   = "sata base",
286                 .start  = ORION5X_SATA_PHYS_BASE,
287                 .end    = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
288                 .flags  = IORESOURCE_MEM,
289         }, {
290                 .name   = "sata irq",
291                 .start  = IRQ_ORION5X_SATA,
292                 .end    = IRQ_ORION5X_SATA,
293                 .flags  = IORESOURCE_IRQ,
294         },
295 };
296
297 static struct platform_device orion5x_sata = {
298         .name           = "sata_mv",
299         .id             = 0,
300         .dev            = {
301                 .coherent_dma_mask      = 0xffffffff,
302         },
303         .num_resources  = ARRAY_SIZE(orion5x_sata_resources),
304         .resource       = orion5x_sata_resources,
305 };
306
307 void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
308 {
309         sata_data->dram = &orion5x_mbus_dram_info;
310         orion5x_sata.dev.platform_data = sata_data;
311         platform_device_register(&orion5x_sata);
312 }
313
314
315 /*****************************************************************************
316  * SPI
317  ****************************************************************************/
318 static struct orion_spi_info orion5x_spi_plat_data = {
319         .tclk                   = 0,
320         .enable_clock_fix       = 1,
321 };
322
323 static struct resource orion5x_spi_resources[] = {
324         {
325                 .name   = "spi base",
326                 .start  = SPI_PHYS_BASE,
327                 .end    = SPI_PHYS_BASE + 0x1f,
328                 .flags  = IORESOURCE_MEM,
329         },
330 };
331
332 static struct platform_device orion5x_spi = {
333         .name           = "orion_spi",
334         .id             = 0,
335         .dev            = {
336                 .platform_data  = &orion5x_spi_plat_data,
337         },
338         .num_resources  = ARRAY_SIZE(orion5x_spi_resources),
339         .resource       = orion5x_spi_resources,
340 };
341
342 void __init orion5x_spi_init()
343 {
344         platform_device_register(&orion5x_spi);
345 }
346
347
348 /*****************************************************************************
349  * UART0
350  ****************************************************************************/
351 static struct plat_serial8250_port orion5x_uart0_data[] = {
352         {
353                 .mapbase        = UART0_PHYS_BASE,
354                 .membase        = (char *)UART0_VIRT_BASE,
355                 .irq            = IRQ_ORION5X_UART0,
356                 .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
357                 .iotype         = UPIO_MEM,
358                 .regshift       = 2,
359                 .uartclk        = 0,
360         }, {
361         },
362 };
363
364 static struct resource orion5x_uart0_resources[] = {
365         {
366                 .start          = UART0_PHYS_BASE,
367                 .end            = UART0_PHYS_BASE + 0xff,
368                 .flags          = IORESOURCE_MEM,
369         }, {
370                 .start          = IRQ_ORION5X_UART0,
371                 .end            = IRQ_ORION5X_UART0,
372                 .flags          = IORESOURCE_IRQ,
373         },
374 };
375
376 static struct platform_device orion5x_uart0 = {
377         .name                   = "serial8250",
378         .id                     = PLAT8250_DEV_PLATFORM,
379         .dev                    = {
380                 .platform_data  = orion5x_uart0_data,
381         },
382         .resource               = orion5x_uart0_resources,
383         .num_resources          = ARRAY_SIZE(orion5x_uart0_resources),
384 };
385
386 void __init orion5x_uart0_init(void)
387 {
388         platform_device_register(&orion5x_uart0);
389 }
390
391
392 /*****************************************************************************
393  * UART1
394  ****************************************************************************/
395 static struct plat_serial8250_port orion5x_uart1_data[] = {
396         {
397                 .mapbase        = UART1_PHYS_BASE,
398                 .membase        = (char *)UART1_VIRT_BASE,
399                 .irq            = IRQ_ORION5X_UART1,
400                 .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
401                 .iotype         = UPIO_MEM,
402                 .regshift       = 2,
403                 .uartclk        = 0,
404         }, {
405         },
406 };
407
408 static struct resource orion5x_uart1_resources[] = {
409         {
410                 .start          = UART1_PHYS_BASE,
411                 .end            = UART1_PHYS_BASE + 0xff,
412                 .flags          = IORESOURCE_MEM,
413         }, {
414                 .start          = IRQ_ORION5X_UART1,
415                 .end            = IRQ_ORION5X_UART1,
416                 .flags          = IORESOURCE_IRQ,
417         },
418 };
419
420 static struct platform_device orion5x_uart1 = {
421         .name                   = "serial8250",
422         .id                     = PLAT8250_DEV_PLATFORM1,
423         .dev                    = {
424                 .platform_data  = orion5x_uart1_data,
425         },
426         .resource               = orion5x_uart1_resources,
427         .num_resources          = ARRAY_SIZE(orion5x_uart1_resources),
428 };
429
430 void __init orion5x_uart1_init(void)
431 {
432         platform_device_register(&orion5x_uart1);
433 }
434
435
436 /*****************************************************************************
437  * XOR engine
438  ****************************************************************************/
439 struct mv_xor_platform_shared_data orion5x_xor_shared_data = {
440         .dram           = &orion5x_mbus_dram_info,
441 };
442
443 static struct resource orion5x_xor_shared_resources[] = {
444         {
445                 .name   = "xor low",
446                 .start  = ORION5X_XOR_PHYS_BASE,
447                 .end    = ORION5X_XOR_PHYS_BASE + 0xff,
448                 .flags  = IORESOURCE_MEM,
449         }, {
450                 .name   = "xor high",
451                 .start  = ORION5X_XOR_PHYS_BASE + 0x200,
452                 .end    = ORION5X_XOR_PHYS_BASE + 0x2ff,
453                 .flags  = IORESOURCE_MEM,
454         },
455 };
456
457 static struct platform_device orion5x_xor_shared = {
458         .name           = MV_XOR_SHARED_NAME,
459         .id             = 0,
460         .dev            = {
461                 .platform_data  = &orion5x_xor_shared_data,
462         },
463         .num_resources  = ARRAY_SIZE(orion5x_xor_shared_resources),
464         .resource       = orion5x_xor_shared_resources,
465 };
466
467 static u64 orion5x_xor_dmamask = DMA_BIT_MASK(32);
468
469 static struct resource orion5x_xor0_resources[] = {
470         [0] = {
471                 .start  = IRQ_ORION5X_XOR0,
472                 .end    = IRQ_ORION5X_XOR0,
473                 .flags  = IORESOURCE_IRQ,
474         },
475 };
476
477 static struct mv_xor_platform_data orion5x_xor0_data = {
478         .shared         = &orion5x_xor_shared,
479         .hw_id          = 0,
480         .pool_size      = PAGE_SIZE,
481 };
482
483 static struct platform_device orion5x_xor0_channel = {
484         .name           = MV_XOR_NAME,
485         .id             = 0,
486         .num_resources  = ARRAY_SIZE(orion5x_xor0_resources),
487         .resource       = orion5x_xor0_resources,
488         .dev            = {
489                 .dma_mask               = &orion5x_xor_dmamask,
490                 .coherent_dma_mask      = DMA_BIT_MASK(64),
491                 .platform_data          = (void *)&orion5x_xor0_data,
492         },
493 };
494
495 static struct resource orion5x_xor1_resources[] = {
496         [0] = {
497                 .start  = IRQ_ORION5X_XOR1,
498                 .end    = IRQ_ORION5X_XOR1,
499                 .flags  = IORESOURCE_IRQ,
500         },
501 };
502
503 static struct mv_xor_platform_data orion5x_xor1_data = {
504         .shared         = &orion5x_xor_shared,
505         .hw_id          = 1,
506         .pool_size      = PAGE_SIZE,
507 };
508
509 static struct platform_device orion5x_xor1_channel = {
510         .name           = MV_XOR_NAME,
511         .id             = 1,
512         .num_resources  = ARRAY_SIZE(orion5x_xor1_resources),
513         .resource       = orion5x_xor1_resources,
514         .dev            = {
515                 .dma_mask               = &orion5x_xor_dmamask,
516                 .coherent_dma_mask      = DMA_BIT_MASK(64),
517                 .platform_data          = (void *)&orion5x_xor1_data,
518         },
519 };
520
521 void __init orion5x_xor_init(void)
522 {
523         platform_device_register(&orion5x_xor_shared);
524
525         /*
526          * two engines can't do memset simultaneously, this limitation
527          * satisfied by removing memset support from one of the engines.
528          */
529         dma_cap_set(DMA_MEMCPY, orion5x_xor0_data.cap_mask);
530         dma_cap_set(DMA_XOR, orion5x_xor0_data.cap_mask);
531         platform_device_register(&orion5x_xor0_channel);
532
533         dma_cap_set(DMA_MEMCPY, orion5x_xor1_data.cap_mask);
534         dma_cap_set(DMA_MEMSET, orion5x_xor1_data.cap_mask);
535         dma_cap_set(DMA_XOR, orion5x_xor1_data.cap_mask);
536         platform_device_register(&orion5x_xor1_channel);
537 }
538
539
540 /*****************************************************************************
541  * Watchdog
542  ****************************************************************************/
543 static struct orion5x_wdt_platform_data orion5x_wdt_data = {
544         .tclk                   = 0,
545 };
546
547 static struct platform_device orion5x_wdt_device = {
548         .name           = "orion5x_wdt",
549         .id             = -1,
550         .dev            = {
551                 .platform_data  = &orion5x_wdt_data,
552         },
553         .num_resources  = 0,
554 };
555
556 void __init orion5x_wdt_init(void)
557 {
558         orion5x_wdt_data.tclk = orion5x_tclk;
559         platform_device_register(&orion5x_wdt_device);
560 }
561
562
563 /*****************************************************************************
564  * Time handling
565  ****************************************************************************/
566 int orion5x_tclk;
567
568 int __init orion5x_find_tclk(void)
569 {
570         u32 dev, rev;
571
572         orion5x_pcie_id(&dev, &rev);
573         if (dev == MV88F6183_DEV_ID &&
574             (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0)
575                 return 133333333;
576
577         return 166666667;
578 }
579
580 static void orion5x_timer_init(void)
581 {
582         orion5x_tclk = orion5x_find_tclk();
583         orion_time_init(IRQ_ORION5X_BRIDGE, orion5x_tclk);
584 }
585
586 struct sys_timer orion5x_timer = {
587         .init = orion5x_timer_init,
588 };
589
590
591 /*****************************************************************************
592  * General
593  ****************************************************************************/
594 /*
595  * Identify device ID and rev from PCIe configuration header space '0'.
596  */
597 static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
598 {
599         orion5x_pcie_id(dev, rev);
600
601         if (*dev == MV88F5281_DEV_ID) {
602                 if (*rev == MV88F5281_REV_D2) {
603                         *dev_name = "MV88F5281-D2";
604                 } else if (*rev == MV88F5281_REV_D1) {
605                         *dev_name = "MV88F5281-D1";
606                 } else if (*rev == MV88F5281_REV_D0) {
607                         *dev_name = "MV88F5281-D0";
608                 } else {
609                         *dev_name = "MV88F5281-Rev-Unsupported";
610                 }
611         } else if (*dev == MV88F5182_DEV_ID) {
612                 if (*rev == MV88F5182_REV_A2) {
613                         *dev_name = "MV88F5182-A2";
614                 } else {
615                         *dev_name = "MV88F5182-Rev-Unsupported";
616                 }
617         } else if (*dev == MV88F5181_DEV_ID) {
618                 if (*rev == MV88F5181_REV_B1) {
619                         *dev_name = "MV88F5181-Rev-B1";
620                 } else if (*rev == MV88F5181L_REV_A1) {
621                         *dev_name = "MV88F5181L-Rev-A1";
622                 } else {
623                         *dev_name = "MV88F5181(L)-Rev-Unsupported";
624                 }
625         } else if (*dev == MV88F6183_DEV_ID) {
626                 if (*rev == MV88F6183_REV_B0) {
627                         *dev_name = "MV88F6183-Rev-B0";
628                 } else {
629                         *dev_name = "MV88F6183-Rev-Unsupported";
630                 }
631         } else {
632                 *dev_name = "Device-Unknown";
633         }
634 }
635
636 void __init orion5x_init(void)
637 {
638         char *dev_name;
639         u32 dev, rev;
640
641         orion5x_id(&dev, &rev, &dev_name);
642         printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
643
644         orion5x_eth_shared_data.t_clk = orion5x_tclk;
645         orion5x_spi_plat_data.tclk = orion5x_tclk;
646         orion5x_uart0_data[0].uartclk = orion5x_tclk;
647         orion5x_uart1_data[0].uartclk = orion5x_tclk;
648
649         /*
650          * Setup Orion address map
651          */
652         orion5x_setup_cpu_mbus_bridge();
653
654         /*
655          * Don't issue "Wait for Interrupt" instruction if we are
656          * running on D0 5281 silicon.
657          */
658         if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
659                 printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
660                 disable_hlt();
661         }
662
663         /*
664          * Register watchdog driver
665          */
666         orion5x_wdt_init();
667 }
668
669 /*
670  * Many orion-based systems have buggy bootloader implementations.
671  * This is a common fixup for bogus memory tags.
672  */
673 void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
674                             char **from, struct meminfo *meminfo)
675 {
676         for (; t->hdr.size; t = tag_next(t))
677                 if (t->hdr.tag == ATAG_MEM &&
678                     (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
679                      t->u.mem.start & ~PAGE_MASK)) {
680                         printk(KERN_WARNING
681                                "Clearing invalid memory bank %dKB@0x%08x\n",
682                                t->u.mem.size / 1024, t->u.mem.start);
683                         t->hdr.tag = 0;
684                 }
685 }