2 * arch/arm/mach-orion5x/common.c
4 * Core functions for Marvell Orion 5x SoCs
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
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.
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>
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/hardware.h>
29 #include <mach/orion5x.h>
30 #include <plat/ehci-orion.h>
31 #include <plat/mv_xor.h>
32 #include <plat/orion_nand.h>
33 #include <plat/time.h>
36 /*****************************************************************************
38 ****************************************************************************/
39 static struct map_desc orion5x_io_desc
[] __initdata
= {
41 .virtual = ORION5X_REGS_VIRT_BASE
,
42 .pfn
= __phys_to_pfn(ORION5X_REGS_PHYS_BASE
),
43 .length
= ORION5X_REGS_SIZE
,
46 .virtual = ORION5X_PCIE_IO_VIRT_BASE
,
47 .pfn
= __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE
),
48 .length
= ORION5X_PCIE_IO_SIZE
,
51 .virtual = ORION5X_PCI_IO_VIRT_BASE
,
52 .pfn
= __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE
),
53 .length
= ORION5X_PCI_IO_SIZE
,
56 .virtual = ORION5X_PCIE_WA_VIRT_BASE
,
57 .pfn
= __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE
),
58 .length
= ORION5X_PCIE_WA_SIZE
,
63 void __init
orion5x_map_io(void)
65 iotable_init(orion5x_io_desc
, ARRAY_SIZE(orion5x_io_desc
));
69 /*****************************************************************************
71 ****************************************************************************/
72 static struct orion_ehci_data orion5x_ehci_data
= {
73 .dram
= &orion5x_mbus_dram_info
,
76 static u64 ehci_dmamask
= 0xffffffffUL
;
79 /*****************************************************************************
81 ****************************************************************************/
82 static struct resource orion5x_ehci0_resources
[] = {
84 .start
= ORION5X_USB0_PHYS_BASE
,
85 .end
= ORION5X_USB0_PHYS_BASE
+ SZ_4K
- 1,
86 .flags
= IORESOURCE_MEM
,
88 .start
= IRQ_ORION5X_USB0_CTRL
,
89 .end
= IRQ_ORION5X_USB0_CTRL
,
90 .flags
= IORESOURCE_IRQ
,
94 static struct platform_device orion5x_ehci0
= {
98 .dma_mask
= &ehci_dmamask
,
99 .coherent_dma_mask
= 0xffffffff,
100 .platform_data
= &orion5x_ehci_data
,
102 .resource
= orion5x_ehci0_resources
,
103 .num_resources
= ARRAY_SIZE(orion5x_ehci0_resources
),
106 void __init
orion5x_ehci0_init(void)
108 platform_device_register(&orion5x_ehci0
);
112 /*****************************************************************************
114 ****************************************************************************/
115 static struct resource orion5x_ehci1_resources
[] = {
117 .start
= ORION5X_USB1_PHYS_BASE
,
118 .end
= ORION5X_USB1_PHYS_BASE
+ SZ_4K
- 1,
119 .flags
= IORESOURCE_MEM
,
121 .start
= IRQ_ORION5X_USB1_CTRL
,
122 .end
= IRQ_ORION5X_USB1_CTRL
,
123 .flags
= IORESOURCE_IRQ
,
127 static struct platform_device orion5x_ehci1
= {
128 .name
= "orion-ehci",
131 .dma_mask
= &ehci_dmamask
,
132 .coherent_dma_mask
= 0xffffffff,
133 .platform_data
= &orion5x_ehci_data
,
135 .resource
= orion5x_ehci1_resources
,
136 .num_resources
= ARRAY_SIZE(orion5x_ehci1_resources
),
139 void __init
orion5x_ehci1_init(void)
141 platform_device_register(&orion5x_ehci1
);
145 /*****************************************************************************
147 ****************************************************************************/
148 struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data
= {
149 .dram
= &orion5x_mbus_dram_info
,
152 static struct resource orion5x_eth_shared_resources
[] = {
154 .start
= ORION5X_ETH_PHYS_BASE
+ 0x2000,
155 .end
= ORION5X_ETH_PHYS_BASE
+ 0x3fff,
156 .flags
= IORESOURCE_MEM
,
158 .start
= IRQ_ORION5X_ETH_ERR
,
159 .end
= IRQ_ORION5X_ETH_ERR
,
160 .flags
= IORESOURCE_IRQ
,
164 static struct platform_device orion5x_eth_shared
= {
165 .name
= MV643XX_ETH_SHARED_NAME
,
168 .platform_data
= &orion5x_eth_shared_data
,
170 .num_resources
= ARRAY_SIZE(orion5x_eth_shared_resources
),
171 .resource
= orion5x_eth_shared_resources
,
174 static struct resource orion5x_eth_resources
[] = {
177 .start
= IRQ_ORION5X_ETH_SUM
,
178 .end
= IRQ_ORION5X_ETH_SUM
,
179 .flags
= IORESOURCE_IRQ
,
183 static struct platform_device orion5x_eth
= {
184 .name
= MV643XX_ETH_NAME
,
187 .resource
= orion5x_eth_resources
,
190 void __init
orion5x_eth_init(struct mv643xx_eth_platform_data
*eth_data
)
192 eth_data
->shared
= &orion5x_eth_shared
;
193 orion5x_eth
.dev
.platform_data
= eth_data
;
195 platform_device_register(&orion5x_eth_shared
);
196 platform_device_register(&orion5x_eth
);
200 /*****************************************************************************
202 ****************************************************************************/
203 static struct mv64xxx_i2c_pdata orion5x_i2c_pdata
= {
204 .freq_m
= 8, /* assumes 166 MHz TCLK */
206 .timeout
= 1000, /* Default timeout of 1 second */
209 static struct resource orion5x_i2c_resources
[] = {
212 .start
= I2C_PHYS_BASE
,
213 .end
= I2C_PHYS_BASE
+ 0x1f,
214 .flags
= IORESOURCE_MEM
,
217 .start
= IRQ_ORION5X_I2C
,
218 .end
= IRQ_ORION5X_I2C
,
219 .flags
= IORESOURCE_IRQ
,
223 static struct platform_device orion5x_i2c
= {
224 .name
= MV64XXX_I2C_CTLR_NAME
,
226 .num_resources
= ARRAY_SIZE(orion5x_i2c_resources
),
227 .resource
= orion5x_i2c_resources
,
229 .platform_data
= &orion5x_i2c_pdata
,
233 void __init
orion5x_i2c_init(void)
235 platform_device_register(&orion5x_i2c
);
239 /*****************************************************************************
241 ****************************************************************************/
242 static struct resource orion5x_sata_resources
[] = {
245 .start
= ORION5X_SATA_PHYS_BASE
,
246 .end
= ORION5X_SATA_PHYS_BASE
+ 0x5000 - 1,
247 .flags
= IORESOURCE_MEM
,
250 .start
= IRQ_ORION5X_SATA
,
251 .end
= IRQ_ORION5X_SATA
,
252 .flags
= IORESOURCE_IRQ
,
256 static struct platform_device orion5x_sata
= {
260 .coherent_dma_mask
= 0xffffffff,
262 .num_resources
= ARRAY_SIZE(orion5x_sata_resources
),
263 .resource
= orion5x_sata_resources
,
266 void __init
orion5x_sata_init(struct mv_sata_platform_data
*sata_data
)
268 sata_data
->dram
= &orion5x_mbus_dram_info
;
269 orion5x_sata
.dev
.platform_data
= sata_data
;
270 platform_device_register(&orion5x_sata
);
274 /*****************************************************************************
276 ****************************************************************************/
277 static struct orion_spi_info orion5x_spi_plat_data
= {
281 static struct resource orion5x_spi_resources
[] = {
284 .start
= SPI_PHYS_BASE
,
285 .end
= SPI_PHYS_BASE
+ 0x1f,
286 .flags
= IORESOURCE_MEM
,
290 static struct platform_device orion5x_spi
= {
294 .platform_data
= &orion5x_spi_plat_data
,
296 .num_resources
= ARRAY_SIZE(orion5x_spi_resources
),
297 .resource
= orion5x_spi_resources
,
300 void __init
orion5x_spi_init()
302 platform_device_register(&orion5x_spi
);
306 /*****************************************************************************
308 ****************************************************************************/
309 static struct plat_serial8250_port orion5x_uart0_data
[] = {
311 .mapbase
= UART0_PHYS_BASE
,
312 .membase
= (char *)UART0_VIRT_BASE
,
313 .irq
= IRQ_ORION5X_UART0
,
314 .flags
= UPF_SKIP_TEST
| UPF_BOOT_AUTOCONF
,
322 static struct resource orion5x_uart0_resources
[] = {
324 .start
= UART0_PHYS_BASE
,
325 .end
= UART0_PHYS_BASE
+ 0xff,
326 .flags
= IORESOURCE_MEM
,
328 .start
= IRQ_ORION5X_UART0
,
329 .end
= IRQ_ORION5X_UART0
,
330 .flags
= IORESOURCE_IRQ
,
334 static struct platform_device orion5x_uart0
= {
335 .name
= "serial8250",
336 .id
= PLAT8250_DEV_PLATFORM
,
338 .platform_data
= orion5x_uart0_data
,
340 .resource
= orion5x_uart0_resources
,
341 .num_resources
= ARRAY_SIZE(orion5x_uart0_resources
),
344 void __init
orion5x_uart0_init(void)
346 platform_device_register(&orion5x_uart0
);
350 /*****************************************************************************
352 ****************************************************************************/
353 static struct plat_serial8250_port orion5x_uart1_data
[] = {
355 .mapbase
= UART1_PHYS_BASE
,
356 .membase
= (char *)UART1_VIRT_BASE
,
357 .irq
= IRQ_ORION5X_UART1
,
358 .flags
= UPF_SKIP_TEST
| UPF_BOOT_AUTOCONF
,
366 static struct resource orion5x_uart1_resources
[] = {
368 .start
= UART1_PHYS_BASE
,
369 .end
= UART1_PHYS_BASE
+ 0xff,
370 .flags
= IORESOURCE_MEM
,
372 .start
= IRQ_ORION5X_UART1
,
373 .end
= IRQ_ORION5X_UART1
,
374 .flags
= IORESOURCE_IRQ
,
378 static struct platform_device orion5x_uart1
= {
379 .name
= "serial8250",
380 .id
= PLAT8250_DEV_PLATFORM1
,
382 .platform_data
= orion5x_uart1_data
,
384 .resource
= orion5x_uart1_resources
,
385 .num_resources
= ARRAY_SIZE(orion5x_uart1_resources
),
388 void __init
orion5x_uart1_init(void)
390 platform_device_register(&orion5x_uart1
);
394 /*****************************************************************************
396 ****************************************************************************/
397 static struct resource orion5x_xor_shared_resources
[] = {
400 .start
= ORION5X_XOR_PHYS_BASE
,
401 .end
= ORION5X_XOR_PHYS_BASE
+ 0xff,
402 .flags
= IORESOURCE_MEM
,
405 .start
= ORION5X_XOR_PHYS_BASE
+ 0x200,
406 .end
= ORION5X_XOR_PHYS_BASE
+ 0x2ff,
407 .flags
= IORESOURCE_MEM
,
411 static struct platform_device orion5x_xor_shared
= {
412 .name
= MV_XOR_SHARED_NAME
,
414 .num_resources
= ARRAY_SIZE(orion5x_xor_shared_resources
),
415 .resource
= orion5x_xor_shared_resources
,
418 static u64 orion5x_xor_dmamask
= DMA_32BIT_MASK
;
420 static struct resource orion5x_xor0_resources
[] = {
422 .start
= IRQ_ORION5X_XOR0
,
423 .end
= IRQ_ORION5X_XOR0
,
424 .flags
= IORESOURCE_IRQ
,
428 static struct mv_xor_platform_data orion5x_xor0_data
= {
429 .shared
= &orion5x_xor_shared
,
431 .pool_size
= PAGE_SIZE
,
434 static struct platform_device orion5x_xor0_channel
= {
437 .num_resources
= ARRAY_SIZE(orion5x_xor0_resources
),
438 .resource
= orion5x_xor0_resources
,
440 .dma_mask
= &orion5x_xor_dmamask
,
441 .coherent_dma_mask
= DMA_64BIT_MASK
,
442 .platform_data
= (void *)&orion5x_xor0_data
,
446 static struct resource orion5x_xor1_resources
[] = {
448 .start
= IRQ_ORION5X_XOR1
,
449 .end
= IRQ_ORION5X_XOR1
,
450 .flags
= IORESOURCE_IRQ
,
454 static struct mv_xor_platform_data orion5x_xor1_data
= {
455 .shared
= &orion5x_xor_shared
,
457 .pool_size
= PAGE_SIZE
,
460 static struct platform_device orion5x_xor1_channel
= {
463 .num_resources
= ARRAY_SIZE(orion5x_xor1_resources
),
464 .resource
= orion5x_xor1_resources
,
466 .dma_mask
= &orion5x_xor_dmamask
,
467 .coherent_dma_mask
= DMA_64BIT_MASK
,
468 .platform_data
= (void *)&orion5x_xor1_data
,
472 void __init
orion5x_xor_init(void)
474 platform_device_register(&orion5x_xor_shared
);
477 * two engines can't do memset simultaneously, this limitation
478 * satisfied by removing memset support from one of the engines.
480 dma_cap_set(DMA_MEMCPY
, orion5x_xor0_data
.cap_mask
);
481 dma_cap_set(DMA_XOR
, orion5x_xor0_data
.cap_mask
);
482 platform_device_register(&orion5x_xor0_channel
);
484 dma_cap_set(DMA_MEMCPY
, orion5x_xor1_data
.cap_mask
);
485 dma_cap_set(DMA_MEMSET
, orion5x_xor1_data
.cap_mask
);
486 dma_cap_set(DMA_XOR
, orion5x_xor1_data
.cap_mask
);
487 platform_device_register(&orion5x_xor1_channel
);
491 /*****************************************************************************
493 ****************************************************************************/
496 int __init
orion5x_find_tclk(void)
500 orion5x_pcie_id(&dev
, &rev
);
501 if (dev
== MV88F6183_DEV_ID
&&
502 (readl(MPP_RESET_SAMPLE
) & 0x00000200) == 0)
508 static void orion5x_timer_init(void)
510 orion5x_tclk
= orion5x_find_tclk();
511 orion_time_init(IRQ_ORION5X_BRIDGE
, orion5x_tclk
);
514 struct sys_timer orion5x_timer
= {
515 .init
= orion5x_timer_init
,
519 /*****************************************************************************
521 ****************************************************************************/
523 * Identify device ID and rev from PCIe configuration header space '0'.
525 static void __init
orion5x_id(u32
*dev
, u32
*rev
, char **dev_name
)
527 orion5x_pcie_id(dev
, rev
);
529 if (*dev
== MV88F5281_DEV_ID
) {
530 if (*rev
== MV88F5281_REV_D2
) {
531 *dev_name
= "MV88F5281-D2";
532 } else if (*rev
== MV88F5281_REV_D1
) {
533 *dev_name
= "MV88F5281-D1";
534 } else if (*rev
== MV88F5281_REV_D0
) {
535 *dev_name
= "MV88F5281-D0";
537 *dev_name
= "MV88F5281-Rev-Unsupported";
539 } else if (*dev
== MV88F5182_DEV_ID
) {
540 if (*rev
== MV88F5182_REV_A2
) {
541 *dev_name
= "MV88F5182-A2";
543 *dev_name
= "MV88F5182-Rev-Unsupported";
545 } else if (*dev
== MV88F5181_DEV_ID
) {
546 if (*rev
== MV88F5181_REV_B1
) {
547 *dev_name
= "MV88F5181-Rev-B1";
548 } else if (*rev
== MV88F5181L_REV_A1
) {
549 *dev_name
= "MV88F5181L-Rev-A1";
551 *dev_name
= "MV88F5181(L)-Rev-Unsupported";
553 } else if (*dev
== MV88F6183_DEV_ID
) {
554 if (*rev
== MV88F6183_REV_B0
) {
555 *dev_name
= "MV88F6183-Rev-B0";
557 *dev_name
= "MV88F6183-Rev-Unsupported";
560 *dev_name
= "Device-Unknown";
564 void __init
orion5x_init(void)
569 orion5x_id(&dev
, &rev
, &dev_name
);
570 printk(KERN_INFO
"Orion ID: %s. TCLK=%d.\n", dev_name
, orion5x_tclk
);
572 orion5x_eth_shared_data
.t_clk
= orion5x_tclk
;
573 orion5x_spi_plat_data
.tclk
= orion5x_tclk
;
574 orion5x_uart0_data
[0].uartclk
= orion5x_tclk
;
575 orion5x_uart1_data
[0].uartclk
= orion5x_tclk
;
578 * Setup Orion address map
580 orion5x_setup_cpu_mbus_bridge();
583 * Don't issue "Wait for Interrupt" instruction if we are
584 * running on D0 5281 silicon.
586 if (dev
== MV88F5281_DEV_ID
&& rev
== MV88F5281_REV_D0
) {
587 printk(KERN_INFO
"Orion: Applying 5281 D0 WFI workaround.\n");
593 * Many orion-based systems have buggy bootloader implementations.
594 * This is a common fixup for bogus memory tags.
596 void __init
tag_fixup_mem32(struct machine_desc
*mdesc
, struct tag
*t
,
597 char **from
, struct meminfo
*meminfo
)
599 for (; t
->hdr
.size
; t
= tag_next(t
))
600 if (t
->hdr
.tag
== ATAG_MEM
&&
601 (!t
->u
.mem
.size
|| t
->u
.mem
.size
& ~PAGE_MASK
||
602 t
->u
.mem
.start
& ~PAGE_MASK
)) {
604 "Clearing invalid memory bank %dKB@0x%08x\n",
605 t
->u
.mem
.size
/ 1024, t
->u
.mem
.start
);