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