ARM: orion: Consolidate ethernet platform data
[pandora-kernel.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_i2c.h>
19 #include <linux/ata_platform.h>
20 #include <linux/spi/orion_spi.h>
21 #include <net/dsa.h>
22 #include <asm/page.h>
23 #include <asm/setup.h>
24 #include <asm/timex.h>
25 #include <asm/mach/arch.h>
26 #include <asm/mach/map.h>
27 #include <asm/mach/time.h>
28 #include <mach/bridge-regs.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/orion_wdt.h>
35 #include <plat/time.h>
36 #include <plat/common.h>
37 #include "common.h"
38
39 /*****************************************************************************
40  * I/O Address Mapping
41  ****************************************************************************/
42 static struct map_desc orion5x_io_desc[] __initdata = {
43         {
44                 .virtual        = ORION5X_REGS_VIRT_BASE,
45                 .pfn            = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
46                 .length         = ORION5X_REGS_SIZE,
47                 .type           = MT_DEVICE,
48         }, {
49                 .virtual        = ORION5X_PCIE_IO_VIRT_BASE,
50                 .pfn            = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
51                 .length         = ORION5X_PCIE_IO_SIZE,
52                 .type           = MT_DEVICE,
53         }, {
54                 .virtual        = ORION5X_PCI_IO_VIRT_BASE,
55                 .pfn            = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
56                 .length         = ORION5X_PCI_IO_SIZE,
57                 .type           = MT_DEVICE,
58         }, {
59                 .virtual        = ORION5X_PCIE_WA_VIRT_BASE,
60                 .pfn            = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
61                 .length         = ORION5X_PCIE_WA_SIZE,
62                 .type           = MT_DEVICE,
63         },
64 };
65
66 void __init orion5x_map_io(void)
67 {
68         iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
69 }
70
71
72 /*****************************************************************************
73  * EHCI
74  ****************************************************************************/
75 static struct orion_ehci_data orion5x_ehci_data = {
76         .dram           = &orion5x_mbus_dram_info,
77         .phy_version    = EHCI_PHY_ORION,
78 };
79
80 static u64 ehci_dmamask = DMA_BIT_MASK(32);
81
82
83 /*****************************************************************************
84  * EHCI0
85  ****************************************************************************/
86 static struct resource orion5x_ehci0_resources[] = {
87         {
88                 .start  = ORION5X_USB0_PHYS_BASE,
89                 .end    = ORION5X_USB0_PHYS_BASE + SZ_4K - 1,
90                 .flags  = IORESOURCE_MEM,
91         }, {
92                 .start  = IRQ_ORION5X_USB0_CTRL,
93                 .end    = IRQ_ORION5X_USB0_CTRL,
94                 .flags  = IORESOURCE_IRQ,
95         },
96 };
97
98 static struct platform_device orion5x_ehci0 = {
99         .name           = "orion-ehci",
100         .id             = 0,
101         .dev            = {
102                 .dma_mask               = &ehci_dmamask,
103                 .coherent_dma_mask      = DMA_BIT_MASK(32),
104                 .platform_data          = &orion5x_ehci_data,
105         },
106         .resource       = orion5x_ehci0_resources,
107         .num_resources  = ARRAY_SIZE(orion5x_ehci0_resources),
108 };
109
110 void __init orion5x_ehci0_init(void)
111 {
112         platform_device_register(&orion5x_ehci0);
113 }
114
115
116 /*****************************************************************************
117  * EHCI1
118  ****************************************************************************/
119 static struct resource orion5x_ehci1_resources[] = {
120         {
121                 .start  = ORION5X_USB1_PHYS_BASE,
122                 .end    = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
123                 .flags  = IORESOURCE_MEM,
124         }, {
125                 .start  = IRQ_ORION5X_USB1_CTRL,
126                 .end    = IRQ_ORION5X_USB1_CTRL,
127                 .flags  = IORESOURCE_IRQ,
128         },
129 };
130
131 static struct platform_device orion5x_ehci1 = {
132         .name           = "orion-ehci",
133         .id             = 1,
134         .dev            = {
135                 .dma_mask               = &ehci_dmamask,
136                 .coherent_dma_mask      = DMA_BIT_MASK(32),
137                 .platform_data          = &orion5x_ehci_data,
138         },
139         .resource       = orion5x_ehci1_resources,
140         .num_resources  = ARRAY_SIZE(orion5x_ehci1_resources),
141 };
142
143 void __init orion5x_ehci1_init(void)
144 {
145         platform_device_register(&orion5x_ehci1);
146 }
147
148
149 /*****************************************************************************
150  * GE00
151  ****************************************************************************/
152 void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
153 {
154         orion_ge00_init(eth_data, &orion5x_mbus_dram_info,
155                         ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
156                         IRQ_ORION5X_ETH_ERR, orion5x_tclk);
157 }
158
159
160 /*****************************************************************************
161  * Ethernet switch
162  ****************************************************************************/
163 void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
164 {
165         orion_ge00_switch_init(d, irq);
166 }
167
168
169 /*****************************************************************************
170  * I2C
171  ****************************************************************************/
172 static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
173         .freq_m         = 8, /* assumes 166 MHz TCLK */
174         .freq_n         = 3,
175         .timeout        = 1000, /* Default timeout of 1 second */
176 };
177
178 static struct resource orion5x_i2c_resources[] = {
179         {
180                 .start  = I2C_PHYS_BASE,
181                 .end    = I2C_PHYS_BASE + 0x1f,
182                 .flags  = IORESOURCE_MEM,
183         }, {
184                 .start  = IRQ_ORION5X_I2C,
185                 .end    = IRQ_ORION5X_I2C,
186                 .flags  = IORESOURCE_IRQ,
187         },
188 };
189
190 static struct platform_device orion5x_i2c = {
191         .name           = MV64XXX_I2C_CTLR_NAME,
192         .id             = 0,
193         .num_resources  = ARRAY_SIZE(orion5x_i2c_resources),
194         .resource       = orion5x_i2c_resources,
195         .dev            = {
196                 .platform_data  = &orion5x_i2c_pdata,
197         },
198 };
199
200 void __init orion5x_i2c_init(void)
201 {
202         platform_device_register(&orion5x_i2c);
203 }
204
205
206 /*****************************************************************************
207  * SATA
208  ****************************************************************************/
209 static struct resource orion5x_sata_resources[] = {
210         {
211                 .name   = "sata base",
212                 .start  = ORION5X_SATA_PHYS_BASE,
213                 .end    = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
214                 .flags  = IORESOURCE_MEM,
215         }, {
216                 .name   = "sata irq",
217                 .start  = IRQ_ORION5X_SATA,
218                 .end    = IRQ_ORION5X_SATA,
219                 .flags  = IORESOURCE_IRQ,
220         },
221 };
222
223 static struct platform_device orion5x_sata = {
224         .name           = "sata_mv",
225         .id             = 0,
226         .dev            = {
227                 .coherent_dma_mask      = DMA_BIT_MASK(32),
228         },
229         .num_resources  = ARRAY_SIZE(orion5x_sata_resources),
230         .resource       = orion5x_sata_resources,
231 };
232
233 void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
234 {
235         sata_data->dram = &orion5x_mbus_dram_info;
236         orion5x_sata.dev.platform_data = sata_data;
237         platform_device_register(&orion5x_sata);
238 }
239
240
241 /*****************************************************************************
242  * SPI
243  ****************************************************************************/
244 static struct orion_spi_info orion5x_spi_plat_data = {
245         .tclk                   = 0,
246         .enable_clock_fix       = 1,
247 };
248
249 static struct resource orion5x_spi_resources[] = {
250         {
251                 .name   = "spi base",
252                 .start  = SPI_PHYS_BASE,
253                 .end    = SPI_PHYS_BASE + 0x1f,
254                 .flags  = IORESOURCE_MEM,
255         },
256 };
257
258 static struct platform_device orion5x_spi = {
259         .name           = "orion_spi",
260         .id             = 0,
261         .dev            = {
262                 .platform_data  = &orion5x_spi_plat_data,
263         },
264         .num_resources  = ARRAY_SIZE(orion5x_spi_resources),
265         .resource       = orion5x_spi_resources,
266 };
267
268 void __init orion5x_spi_init()
269 {
270         platform_device_register(&orion5x_spi);
271 }
272
273
274 /*****************************************************************************
275  * UART0
276  ****************************************************************************/
277 void __init orion5x_uart0_init(void)
278 {
279         orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
280                          IRQ_ORION5X_UART0, orion5x_tclk);
281 }
282
283 /*****************************************************************************
284  * UART1
285  ****************************************************************************/
286 void __init orion5x_uart1_init(void)
287 {
288         orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
289                          IRQ_ORION5X_UART1, orion5x_tclk);
290 }
291
292 /*****************************************************************************
293  * XOR engine
294  ****************************************************************************/
295 struct mv_xor_platform_shared_data orion5x_xor_shared_data = {
296         .dram           = &orion5x_mbus_dram_info,
297 };
298
299 static struct resource orion5x_xor_shared_resources[] = {
300         {
301                 .name   = "xor low",
302                 .start  = ORION5X_XOR_PHYS_BASE,
303                 .end    = ORION5X_XOR_PHYS_BASE + 0xff,
304                 .flags  = IORESOURCE_MEM,
305         }, {
306                 .name   = "xor high",
307                 .start  = ORION5X_XOR_PHYS_BASE + 0x200,
308                 .end    = ORION5X_XOR_PHYS_BASE + 0x2ff,
309                 .flags  = IORESOURCE_MEM,
310         },
311 };
312
313 static struct platform_device orion5x_xor_shared = {
314         .name           = MV_XOR_SHARED_NAME,
315         .id             = 0,
316         .dev            = {
317                 .platform_data  = &orion5x_xor_shared_data,
318         },
319         .num_resources  = ARRAY_SIZE(orion5x_xor_shared_resources),
320         .resource       = orion5x_xor_shared_resources,
321 };
322
323 static u64 orion5x_xor_dmamask = DMA_BIT_MASK(32);
324
325 static struct resource orion5x_xor0_resources[] = {
326         [0] = {
327                 .start  = IRQ_ORION5X_XOR0,
328                 .end    = IRQ_ORION5X_XOR0,
329                 .flags  = IORESOURCE_IRQ,
330         },
331 };
332
333 static struct mv_xor_platform_data orion5x_xor0_data = {
334         .shared         = &orion5x_xor_shared,
335         .hw_id          = 0,
336         .pool_size      = PAGE_SIZE,
337 };
338
339 static struct platform_device orion5x_xor0_channel = {
340         .name           = MV_XOR_NAME,
341         .id             = 0,
342         .num_resources  = ARRAY_SIZE(orion5x_xor0_resources),
343         .resource       = orion5x_xor0_resources,
344         .dev            = {
345                 .dma_mask               = &orion5x_xor_dmamask,
346                 .coherent_dma_mask      = DMA_BIT_MASK(64),
347                 .platform_data          = &orion5x_xor0_data,
348         },
349 };
350
351 static struct resource orion5x_xor1_resources[] = {
352         [0] = {
353                 .start  = IRQ_ORION5X_XOR1,
354                 .end    = IRQ_ORION5X_XOR1,
355                 .flags  = IORESOURCE_IRQ,
356         },
357 };
358
359 static struct mv_xor_platform_data orion5x_xor1_data = {
360         .shared         = &orion5x_xor_shared,
361         .hw_id          = 1,
362         .pool_size      = PAGE_SIZE,
363 };
364
365 static struct platform_device orion5x_xor1_channel = {
366         .name           = MV_XOR_NAME,
367         .id             = 1,
368         .num_resources  = ARRAY_SIZE(orion5x_xor1_resources),
369         .resource       = orion5x_xor1_resources,
370         .dev            = {
371                 .dma_mask               = &orion5x_xor_dmamask,
372                 .coherent_dma_mask      = DMA_BIT_MASK(64),
373                 .platform_data          = &orion5x_xor1_data,
374         },
375 };
376
377 void __init orion5x_xor_init(void)
378 {
379         platform_device_register(&orion5x_xor_shared);
380
381         /*
382          * two engines can't do memset simultaneously, this limitation
383          * satisfied by removing memset support from one of the engines.
384          */
385         dma_cap_set(DMA_MEMCPY, orion5x_xor0_data.cap_mask);
386         dma_cap_set(DMA_XOR, orion5x_xor0_data.cap_mask);
387         platform_device_register(&orion5x_xor0_channel);
388
389         dma_cap_set(DMA_MEMCPY, orion5x_xor1_data.cap_mask);
390         dma_cap_set(DMA_MEMSET, orion5x_xor1_data.cap_mask);
391         dma_cap_set(DMA_XOR, orion5x_xor1_data.cap_mask);
392         platform_device_register(&orion5x_xor1_channel);
393 }
394
395 static struct resource orion5x_crypto_res[] = {
396         {
397                 .name   = "regs",
398                 .start  = ORION5X_CRYPTO_PHYS_BASE,
399                 .end    = ORION5X_CRYPTO_PHYS_BASE + 0xffff,
400                 .flags  = IORESOURCE_MEM,
401         }, {
402                 .name   = "sram",
403                 .start  = ORION5X_SRAM_PHYS_BASE,
404                 .end    = ORION5X_SRAM_PHYS_BASE + SZ_8K - 1,
405                 .flags  = IORESOURCE_MEM,
406         }, {
407                 .name   = "crypto interrupt",
408                 .start  = IRQ_ORION5X_CESA,
409                 .end    = IRQ_ORION5X_CESA,
410                 .flags  = IORESOURCE_IRQ,
411         },
412 };
413
414 static struct platform_device orion5x_crypto_device = {
415         .name           = "mv_crypto",
416         .id             = -1,
417         .num_resources  = ARRAY_SIZE(orion5x_crypto_res),
418         .resource       = orion5x_crypto_res,
419 };
420
421 static int __init orion5x_crypto_init(void)
422 {
423         int ret;
424
425         ret = orion5x_setup_sram_win();
426         if (ret)
427                 return ret;
428
429         return platform_device_register(&orion5x_crypto_device);
430 }
431
432 /*****************************************************************************
433  * Watchdog
434  ****************************************************************************/
435 static struct orion_wdt_platform_data orion5x_wdt_data = {
436         .tclk                   = 0,
437 };
438
439 static struct platform_device orion5x_wdt_device = {
440         .name           = "orion_wdt",
441         .id             = -1,
442         .dev            = {
443                 .platform_data  = &orion5x_wdt_data,
444         },
445         .num_resources  = 0,
446 };
447
448 void __init orion5x_wdt_init(void)
449 {
450         orion5x_wdt_data.tclk = orion5x_tclk;
451         platform_device_register(&orion5x_wdt_device);
452 }
453
454
455 /*****************************************************************************
456  * Time handling
457  ****************************************************************************/
458 void __init orion5x_init_early(void)
459 {
460         orion_time_set_base(TIMER_VIRT_BASE);
461 }
462
463 int orion5x_tclk;
464
465 int __init orion5x_find_tclk(void)
466 {
467         u32 dev, rev;
468
469         orion5x_pcie_id(&dev, &rev);
470         if (dev == MV88F6183_DEV_ID &&
471             (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0)
472                 return 133333333;
473
474         return 166666667;
475 }
476
477 static void orion5x_timer_init(void)
478 {
479         orion5x_tclk = orion5x_find_tclk();
480
481         orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
482                         IRQ_ORION5X_BRIDGE, orion5x_tclk);
483 }
484
485 struct sys_timer orion5x_timer = {
486         .init = orion5x_timer_init,
487 };
488
489
490 /*****************************************************************************
491  * General
492  ****************************************************************************/
493 /*
494  * Identify device ID and rev from PCIe configuration header space '0'.
495  */
496 static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
497 {
498         orion5x_pcie_id(dev, rev);
499
500         if (*dev == MV88F5281_DEV_ID) {
501                 if (*rev == MV88F5281_REV_D2) {
502                         *dev_name = "MV88F5281-D2";
503                 } else if (*rev == MV88F5281_REV_D1) {
504                         *dev_name = "MV88F5281-D1";
505                 } else if (*rev == MV88F5281_REV_D0) {
506                         *dev_name = "MV88F5281-D0";
507                 } else {
508                         *dev_name = "MV88F5281-Rev-Unsupported";
509                 }
510         } else if (*dev == MV88F5182_DEV_ID) {
511                 if (*rev == MV88F5182_REV_A2) {
512                         *dev_name = "MV88F5182-A2";
513                 } else {
514                         *dev_name = "MV88F5182-Rev-Unsupported";
515                 }
516         } else if (*dev == MV88F5181_DEV_ID) {
517                 if (*rev == MV88F5181_REV_B1) {
518                         *dev_name = "MV88F5181-Rev-B1";
519                 } else if (*rev == MV88F5181L_REV_A1) {
520                         *dev_name = "MV88F5181L-Rev-A1";
521                 } else {
522                         *dev_name = "MV88F5181(L)-Rev-Unsupported";
523                 }
524         } else if (*dev == MV88F6183_DEV_ID) {
525                 if (*rev == MV88F6183_REV_B0) {
526                         *dev_name = "MV88F6183-Rev-B0";
527                 } else {
528                         *dev_name = "MV88F6183-Rev-Unsupported";
529                 }
530         } else {
531                 *dev_name = "Device-Unknown";
532         }
533 }
534
535 void __init orion5x_init(void)
536 {
537         char *dev_name;
538         u32 dev, rev;
539
540         orion5x_id(&dev, &rev, &dev_name);
541         printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
542
543         orion5x_spi_plat_data.tclk = orion5x_tclk;
544
545         /*
546          * Setup Orion address map
547          */
548         orion5x_setup_cpu_mbus_bridge();
549
550         /*
551          * Don't issue "Wait for Interrupt" instruction if we are
552          * running on D0 5281 silicon.
553          */
554         if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
555                 printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
556                 disable_hlt();
557         }
558
559         /*
560          * The 5082/5181l/5182/6082/6082l/6183 have crypto
561          * while 5180n/5181/5281 don't have crypto.
562          */
563         if ((dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0) ||
564             dev == MV88F5182_DEV_ID || dev == MV88F6183_DEV_ID)
565                 orion5x_crypto_init();
566
567         /*
568          * Register watchdog driver
569          */
570         orion5x_wdt_init();
571 }
572
573 /*
574  * Many orion-based systems have buggy bootloader implementations.
575  * This is a common fixup for bogus memory tags.
576  */
577 void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
578                             char **from, struct meminfo *meminfo)
579 {
580         for (; t->hdr.size; t = tag_next(t))
581                 if (t->hdr.tag == ATAG_MEM &&
582                     (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
583                      t->u.mem.start & ~PAGE_MASK)) {
584                         printk(KERN_WARNING
585                                "Clearing invalid memory bank %dKB@0x%08x\n",
586                                t->u.mem.size / 1024, t->u.mem.start);
587                         t->hdr.tag = 0;
588                 }
589 }