ARM: orion: Consolidate ethernet platform data
[deliverable/linux.git] / arch / arm / mach-orion5x / common.c
CommitLineData
585cf175 1/*
9dd0b194 2 * arch/arm/mach-orion5x/common.c
585cf175 3 *
9dd0b194 4 * Core functions for Marvell Orion 5x SoCs
585cf175
TP
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
159ffb3a
LB
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
585cf175
TP
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
ca26f7d3
TP
15#include <linux/platform_device.h>
16#include <linux/serial_8250.h>
83b6d822 17#include <linux/mbus.h>
144aa3db 18#include <linux/mv643xx_i2c.h>
15a32632 19#include <linux/ata_platform.h>
d323ade1 20#include <linux/spi/orion_spi.h>
dcf1cece 21#include <net/dsa.h>
585cf175 22#include <asm/page.h>
be73a347 23#include <asm/setup.h>
c67de5b3 24#include <asm/timex.h>
be73a347 25#include <asm/mach/arch.h>
585cf175 26#include <asm/mach/map.h>
2bac1de2 27#include <asm/mach/time.h>
4ee1f6b5 28#include <mach/bridge-regs.h>
a09e64fb
RK
29#include <mach/hardware.h>
30#include <mach/orion5x.h>
6f088f1d 31#include <plat/ehci-orion.h>
1d5a1a6e 32#include <plat/mv_xor.h>
6f088f1d 33#include <plat/orion_nand.h>
3b937a7d 34#include <plat/orion_wdt.h>
6f088f1d 35#include <plat/time.h>
28a2b450 36#include <plat/common.h>
585cf175
TP
37#include "common.h"
38
39/*****************************************************************************
40 * I/O Address Mapping
41 ****************************************************************************/
9dd0b194 42static struct map_desc orion5x_io_desc[] __initdata = {
585cf175 43 {
9dd0b194
LB
44 .virtual = ORION5X_REGS_VIRT_BASE,
45 .pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
46 .length = ORION5X_REGS_SIZE,
e7068ad3
LB
47 .type = MT_DEVICE,
48 }, {
9dd0b194
LB
49 .virtual = ORION5X_PCIE_IO_VIRT_BASE,
50 .pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
51 .length = ORION5X_PCIE_IO_SIZE,
e7068ad3
LB
52 .type = MT_DEVICE,
53 }, {
9dd0b194
LB
54 .virtual = ORION5X_PCI_IO_VIRT_BASE,
55 .pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
56 .length = ORION5X_PCI_IO_SIZE,
e7068ad3
LB
57 .type = MT_DEVICE,
58 }, {
9dd0b194
LB
59 .virtual = ORION5X_PCIE_WA_VIRT_BASE,
60 .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
61 .length = ORION5X_PCIE_WA_SIZE,
e7068ad3 62 .type = MT_DEVICE,
585cf175
TP
63 },
64};
65
9dd0b194 66void __init orion5x_map_io(void)
585cf175 67{
9dd0b194 68 iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
585cf175 69}
c67de5b3 70
044f6c7c 71
ca26f7d3 72/*****************************************************************************
044f6c7c 73 * EHCI
ca26f7d3 74 ****************************************************************************/
044f6c7c
LB
75static struct orion_ehci_data orion5x_ehci_data = {
76 .dram = &orion5x_mbus_dram_info,
fb6f5529 77 .phy_version = EHCI_PHY_ORION,
ca26f7d3
TP
78};
79
5c602551 80static u64 ehci_dmamask = DMA_BIT_MASK(32);
ca26f7d3 81
ca26f7d3 82
044f6c7c
LB
83/*****************************************************************************
84 * EHCI0
85 ****************************************************************************/
9dd0b194 86static struct resource orion5x_ehci0_resources[] = {
ca26f7d3 87 {
9dd0b194 88 .start = ORION5X_USB0_PHYS_BASE,
994cab84 89 .end = ORION5X_USB0_PHYS_BASE + SZ_4K - 1,
ca26f7d3 90 .flags = IORESOURCE_MEM,
e7068ad3 91 }, {
9dd0b194
LB
92 .start = IRQ_ORION5X_USB0_CTRL,
93 .end = IRQ_ORION5X_USB0_CTRL,
ca26f7d3
TP
94 .flags = IORESOURCE_IRQ,
95 },
96};
97
9dd0b194 98static struct platform_device orion5x_ehci0 = {
ca26f7d3
TP
99 .name = "orion-ehci",
100 .id = 0,
101 .dev = {
102 .dma_mask = &ehci_dmamask,
5c602551 103 .coherent_dma_mask = DMA_BIT_MASK(32),
9dd0b194 104 .platform_data = &orion5x_ehci_data,
ca26f7d3 105 },
9dd0b194
LB
106 .resource = orion5x_ehci0_resources,
107 .num_resources = ARRAY_SIZE(orion5x_ehci0_resources),
ca26f7d3
TP
108};
109
044f6c7c
LB
110void __init orion5x_ehci0_init(void)
111{
112 platform_device_register(&orion5x_ehci0);
113}
114
115
116/*****************************************************************************
117 * EHCI1
118 ****************************************************************************/
119static 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
9dd0b194 131static struct platform_device orion5x_ehci1 = {
ca26f7d3
TP
132 .name = "orion-ehci",
133 .id = 1,
134 .dev = {
135 .dma_mask = &ehci_dmamask,
5c602551 136 .coherent_dma_mask = DMA_BIT_MASK(32),
9dd0b194 137 .platform_data = &orion5x_ehci_data,
ca26f7d3 138 },
9dd0b194
LB
139 .resource = orion5x_ehci1_resources,
140 .num_resources = ARRAY_SIZE(orion5x_ehci1_resources),
ca26f7d3
TP
141};
142
044f6c7c
LB
143void __init orion5x_ehci1_init(void)
144{
145 platform_device_register(&orion5x_ehci1);
146}
147
148
e07c9d85 149/*****************************************************************************
5c602551 150 * GE00
e07c9d85 151 ****************************************************************************/
9dd0b194 152void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
e07c9d85 153{
7e3819d8
AL
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);
e07c9d85
TP
157}
158
044f6c7c 159
dcf1cece
LB
160/*****************************************************************************
161 * Ethernet switch
162 ****************************************************************************/
dcf1cece
LB
163void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
164{
7e3819d8 165 orion_ge00_switch_init(d, irq);
dcf1cece
LB
166}
167
168
144aa3db 169/*****************************************************************************
044f6c7c 170 * I2C
144aa3db 171 ****************************************************************************/
9dd0b194 172static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
144aa3db
HVR
173 .freq_m = 8, /* assumes 166 MHz TCLK */
174 .freq_n = 3,
175 .timeout = 1000, /* Default timeout of 1 second */
176};
177
9dd0b194 178static struct resource orion5x_i2c_resources[] = {
144aa3db 179 {
e7068ad3 180 .start = I2C_PHYS_BASE,
044f6c7c 181 .end = I2C_PHYS_BASE + 0x1f,
e7068ad3
LB
182 .flags = IORESOURCE_MEM,
183 }, {
e7068ad3
LB
184 .start = IRQ_ORION5X_I2C,
185 .end = IRQ_ORION5X_I2C,
186 .flags = IORESOURCE_IRQ,
144aa3db
HVR
187 },
188};
189
9dd0b194 190static struct platform_device orion5x_i2c = {
144aa3db
HVR
191 .name = MV64XXX_I2C_CTLR_NAME,
192 .id = 0,
9dd0b194
LB
193 .num_resources = ARRAY_SIZE(orion5x_i2c_resources),
194 .resource = orion5x_i2c_resources,
144aa3db 195 .dev = {
e7068ad3 196 .platform_data = &orion5x_i2c_pdata,
144aa3db
HVR
197 },
198};
199
044f6c7c
LB
200void __init orion5x_i2c_init(void)
201{
202 platform_device_register(&orion5x_i2c);
203}
204
205
f244baa3 206/*****************************************************************************
044f6c7c 207 * SATA
f244baa3 208 ****************************************************************************/
9dd0b194 209static struct resource orion5x_sata_resources[] = {
f244baa3 210 {
e7068ad3
LB
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 },
f244baa3
SB
221};
222
9dd0b194 223static struct platform_device orion5x_sata = {
e7068ad3
LB
224 .name = "sata_mv",
225 .id = 0,
f244baa3 226 .dev = {
5c602551 227 .coherent_dma_mask = DMA_BIT_MASK(32),
f244baa3 228 },
e7068ad3
LB
229 .num_resources = ARRAY_SIZE(orion5x_sata_resources),
230 .resource = orion5x_sata_resources,
f244baa3
SB
231};
232
9dd0b194 233void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
f244baa3 234{
9dd0b194
LB
235 sata_data->dram = &orion5x_mbus_dram_info;
236 orion5x_sata.dev.platform_data = sata_data;
237 platform_device_register(&orion5x_sata);
f244baa3
SB
238}
239
044f6c7c 240
d323ade1
LB
241/*****************************************************************************
242 * SPI
243 ****************************************************************************/
244static struct orion_spi_info orion5x_spi_plat_data = {
c0e19363
NP
245 .tclk = 0,
246 .enable_clock_fix = 1,
d323ade1
LB
247};
248
249static 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
258static 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
268void __init orion5x_spi_init()
269{
270 platform_device_register(&orion5x_spi);
271}
272
273
2bac1de2 274/*****************************************************************************
044f6c7c
LB
275 * UART0
276 ****************************************************************************/
044f6c7c
LB
277void __init orion5x_uart0_init(void)
278{
28a2b450
AL
279 orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
280 IRQ_ORION5X_UART0, orion5x_tclk);
044f6c7c
LB
281}
282
044f6c7c
LB
283/*****************************************************************************
284 * UART1
2bac1de2 285 ****************************************************************************/
044f6c7c
LB
286void __init orion5x_uart1_init(void)
287{
28a2b450
AL
288 orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
289 IRQ_ORION5X_UART1, orion5x_tclk);
044f6c7c 290}
2bac1de2 291
1d5a1a6e
SB
292/*****************************************************************************
293 * XOR engine
294 ****************************************************************************/
f45964ed
SB
295struct mv_xor_platform_shared_data orion5x_xor_shared_data = {
296 .dram = &orion5x_mbus_dram_info,
297};
298
1d5a1a6e
SB
299static 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
313static struct platform_device orion5x_xor_shared = {
314 .name = MV_XOR_SHARED_NAME,
315 .id = 0,
f45964ed
SB
316 .dev = {
317 .platform_data = &orion5x_xor_shared_data,
318 },
1d5a1a6e
SB
319 .num_resources = ARRAY_SIZE(orion5x_xor_shared_resources),
320 .resource = orion5x_xor_shared_resources,
321};
322
284901a9 323static u64 orion5x_xor_dmamask = DMA_BIT_MASK(32);
1d5a1a6e
SB
324
325static struct resource orion5x_xor0_resources[] = {
326 [0] = {
327 .start = IRQ_ORION5X_XOR0,
328 .end = IRQ_ORION5X_XOR0,
329 .flags = IORESOURCE_IRQ,
330 },
331};
332
333static struct mv_xor_platform_data orion5x_xor0_data = {
334 .shared = &orion5x_xor_shared,
335 .hw_id = 0,
336 .pool_size = PAGE_SIZE,
337};
338
339static 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,
6a35528a 346 .coherent_dma_mask = DMA_BIT_MASK(64),
ef4a6777 347 .platform_data = &orion5x_xor0_data,
1d5a1a6e
SB
348 },
349};
350
351static struct resource orion5x_xor1_resources[] = {
352 [0] = {
353 .start = IRQ_ORION5X_XOR1,
354 .end = IRQ_ORION5X_XOR1,
355 .flags = IORESOURCE_IRQ,
356 },
357};
358
359static struct mv_xor_platform_data orion5x_xor1_data = {
360 .shared = &orion5x_xor_shared,
361 .hw_id = 1,
362 .pool_size = PAGE_SIZE,
363};
364
365static 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,
6a35528a 372 .coherent_dma_mask = DMA_BIT_MASK(64),
ef4a6777 373 .platform_data = &orion5x_xor1_data,
1d5a1a6e
SB
374 },
375};
376
377void __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
3a8f7441
SAS
395static 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
414static 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
3fade49b 421static int __init orion5x_crypto_init(void)
3a8f7441
SAS
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}
1d5a1a6e 431
9e058d4f
TR
432/*****************************************************************************
433 * Watchdog
434 ****************************************************************************/
3b937a7d 435static struct orion_wdt_platform_data orion5x_wdt_data = {
9e058d4f
TR
436 .tclk = 0,
437};
438
439static struct platform_device orion5x_wdt_device = {
3b937a7d 440 .name = "orion_wdt",
9e058d4f
TR
441 .id = -1,
442 .dev = {
443 .platform_data = &orion5x_wdt_data,
444 },
445 .num_resources = 0,
446};
447
448void __init orion5x_wdt_init(void)
449{
450 orion5x_wdt_data.tclk = orion5x_tclk;
451 platform_device_register(&orion5x_wdt_device);
452}
453
454
044f6c7c
LB
455/*****************************************************************************
456 * Time handling
457 ****************************************************************************/
4ee1f6b5
LB
458void __init orion5x_init_early(void)
459{
460 orion_time_set_base(TIMER_VIRT_BASE);
461}
462
ebe35aff
LB
463int orion5x_tclk;
464
465int __init orion5x_find_tclk(void)
466{
d323ade1
LB
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
ebe35aff
LB
474 return 166666667;
475}
476
9dd0b194 477static void orion5x_timer_init(void)
2bac1de2 478{
ebe35aff 479 orion5x_tclk = orion5x_find_tclk();
4ee1f6b5
LB
480
481 orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
482 IRQ_ORION5X_BRIDGE, orion5x_tclk);
2bac1de2
LB
483}
484
9dd0b194 485struct sys_timer orion5x_timer = {
e7068ad3 486 .init = orion5x_timer_init,
2bac1de2
LB
487};
488
044f6c7c 489
c67de5b3
TP
490/*****************************************************************************
491 * General
492 ****************************************************************************/
c67de5b3 493/*
b46926bb 494 * Identify device ID and rev from PCIe configuration header space '0'.
c67de5b3 495 */
9dd0b194 496static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
c67de5b3 497{
9dd0b194 498 orion5x_pcie_id(dev, rev);
c67de5b3
TP
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";
ce72e36e
LB
505 } else if (*rev == MV88F5281_REV_D0) {
506 *dev_name = "MV88F5281-D0";
c67de5b3
TP
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 }
c9e3de94
HVR
516 } else if (*dev == MV88F5181_DEV_ID) {
517 if (*rev == MV88F5181_REV_B1) {
518 *dev_name = "MV88F5181-Rev-B1";
d2b2a6bb
LB
519 } else if (*rev == MV88F5181L_REV_A1) {
520 *dev_name = "MV88F5181L-Rev-A1";
c9e3de94 521 } else {
d2b2a6bb 522 *dev_name = "MV88F5181(L)-Rev-Unsupported";
c9e3de94 523 }
d323ade1
LB
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 }
c67de5b3
TP
530 } else {
531 *dev_name = "Device-Unknown";
532 }
533}
534
9dd0b194 535void __init orion5x_init(void)
c67de5b3
TP
536{
537 char *dev_name;
538 u32 dev, rev;
539
9dd0b194 540 orion5x_id(&dev, &rev, &dev_name);
ebe35aff
LB
541 printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
542
d323ade1 543 orion5x_spi_plat_data.tclk = orion5x_tclk;
c67de5b3
TP
544
545 /*
546 * Setup Orion address map
547 */
9dd0b194 548 orion5x_setup_cpu_mbus_bridge();
ce72e36e
LB
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 }
9e058d4f 558
3fade49b
NP
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
9e058d4f
TR
567 /*
568 * Register watchdog driver
569 */
570 orion5x_wdt_init();
c67de5b3 571}
be73a347
GL
572
573/*
574 * Many orion-based systems have buggy bootloader implementations.
575 * This is a common fixup for bogus memory tags.
576 */
577void __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}
This page took 0.237832 seconds and 5 git commands to generate.