blob: 5c7e39164c5e549624cf941083eb42b5f011fccd [file] [log] [blame]
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -04001/*
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>
Andrew Lunnee962722011-05-15 13:32:48 +020016#include <linux/dma-mapping.h>
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040017#include <linux/serial_8250.h>
18#include <linux/mbus.h>
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040019#include <linux/mv643xx_i2c.h>
20#include <linux/ata_platform.h>
Lennert Buytenhekdcf1cec2008-09-25 16:23:48 +020021#include <net/dsa.h>
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040022#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>
Lennert Buytenhek4ee1f6b2010-10-15 16:50:26 +020028#include <mach/bridge-regs.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010029#include <mach/hardware.h>
30#include <mach/orion5x.h>
Lennert Buytenhek6f088f12008-08-09 13:44:58 +020031#include <plat/ehci-orion.h>
32#include <plat/orion_nand.h>
33#include <plat/time.h>
Andrew Lunn28a2b452011-05-15 13:32:41 +020034#include <plat/common.h>
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040035#include "common.h"
36
37/*****************************************************************************
38 * I/O Address Mapping
39 ****************************************************************************/
40static 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,
Lennert Buytenheke7068ad2008-05-10 16:30:01 +020045 .type = MT_DEVICE,
46 }, {
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040047 .virtual = ORION5X_PCIE_IO_VIRT_BASE,
48 .pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
49 .length = ORION5X_PCIE_IO_SIZE,
Lennert Buytenheke7068ad2008-05-10 16:30:01 +020050 .type = MT_DEVICE,
51 }, {
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040052 .virtual = ORION5X_PCI_IO_VIRT_BASE,
53 .pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
54 .length = ORION5X_PCI_IO_SIZE,
Lennert Buytenheke7068ad2008-05-10 16:30:01 +020055 .type = MT_DEVICE,
56 }, {
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040057 .virtual = ORION5X_PCIE_WA_VIRT_BASE,
58 .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
59 .length = ORION5X_PCIE_WA_SIZE,
Lennert Buytenheke7068ad2008-05-10 16:30:01 +020060 .type = MT_DEVICE,
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040061 },
62};
63
64void __init orion5x_map_io(void)
65{
66 iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
67}
68
Lennert Buytenhek044f6c72008-04-22 05:37:12 +020069
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040070/*****************************************************************************
Lennert Buytenhek044f6c72008-04-22 05:37:12 +020071 * EHCI
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040072 ****************************************************************************/
Lennert Buytenhek044f6c72008-04-22 05:37:12 +020073static struct orion_ehci_data orion5x_ehci_data = {
74 .dram = &orion5x_mbus_dram_info,
Ronen Shitritfb6f5522008-09-17 10:08:05 +030075 .phy_version = EHCI_PHY_ORION,
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040076};
77
Andrew Lunn5c602552011-05-15 13:32:40 +020078static u64 ehci_dmamask = DMA_BIT_MASK(32);
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040079
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040080
Lennert Buytenhek044f6c72008-04-22 05:37:12 +020081/*****************************************************************************
82 * EHCI0
83 ****************************************************************************/
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040084static struct resource orion5x_ehci0_resources[] = {
85 {
86 .start = ORION5X_USB0_PHYS_BASE,
Lennert Buytenhek994cab82008-04-25 16:30:21 -040087 .end = ORION5X_USB0_PHYS_BASE + SZ_4K - 1,
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040088 .flags = IORESOURCE_MEM,
Lennert Buytenheke7068ad2008-05-10 16:30:01 +020089 }, {
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040090 .start = IRQ_ORION5X_USB0_CTRL,
91 .end = IRQ_ORION5X_USB0_CTRL,
92 .flags = IORESOURCE_IRQ,
93 },
94};
95
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -040096static struct platform_device orion5x_ehci0 = {
97 .name = "orion-ehci",
98 .id = 0,
99 .dev = {
100 .dma_mask = &ehci_dmamask,
Andrew Lunn5c602552011-05-15 13:32:40 +0200101 .coherent_dma_mask = DMA_BIT_MASK(32),
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400102 .platform_data = &orion5x_ehci_data,
103 },
104 .resource = orion5x_ehci0_resources,
105 .num_resources = ARRAY_SIZE(orion5x_ehci0_resources),
106};
107
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200108void __init orion5x_ehci0_init(void)
109{
110 platform_device_register(&orion5x_ehci0);
111}
112
113
114/*****************************************************************************
115 * EHCI1
116 ****************************************************************************/
117static struct resource orion5x_ehci1_resources[] = {
118 {
119 .start = ORION5X_USB1_PHYS_BASE,
120 .end = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
121 .flags = IORESOURCE_MEM,
122 }, {
123 .start = IRQ_ORION5X_USB1_CTRL,
124 .end = IRQ_ORION5X_USB1_CTRL,
125 .flags = IORESOURCE_IRQ,
126 },
127};
128
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400129static struct platform_device orion5x_ehci1 = {
130 .name = "orion-ehci",
131 .id = 1,
132 .dev = {
133 .dma_mask = &ehci_dmamask,
Andrew Lunn5c602552011-05-15 13:32:40 +0200134 .coherent_dma_mask = DMA_BIT_MASK(32),
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400135 .platform_data = &orion5x_ehci_data,
136 },
137 .resource = orion5x_ehci1_resources,
138 .num_resources = ARRAY_SIZE(orion5x_ehci1_resources),
139};
140
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200141void __init orion5x_ehci1_init(void)
142{
143 platform_device_register(&orion5x_ehci1);
144}
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400145
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200146
147/*****************************************************************************
Andrew Lunn5c602552011-05-15 13:32:40 +0200148 * GE00
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200149 ****************************************************************************/
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400150void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
151{
Andrew Lunn7e3819d2011-05-15 13:32:44 +0200152 orion_ge00_init(eth_data, &orion5x_mbus_dram_info,
153 ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
154 IRQ_ORION5X_ETH_ERR, orion5x_tclk);
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400155}
156
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400157
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200158/*****************************************************************************
Lennert Buytenhekdcf1cec2008-09-25 16:23:48 +0200159 * Ethernet switch
160 ****************************************************************************/
Lennert Buytenhekdcf1cec2008-09-25 16:23:48 +0200161void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
162{
Andrew Lunn7e3819d2011-05-15 13:32:44 +0200163 orion_ge00_switch_init(d, irq);
Lennert Buytenhekdcf1cec2008-09-25 16:23:48 +0200164}
165
166
167/*****************************************************************************
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200168 * I2C
169 ****************************************************************************/
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200170void __init orion5x_i2c_init(void)
171{
Andrew Lunnaac7ffa2011-05-15 13:32:45 +0200172 orion_i2c_init(I2C_PHYS_BASE, IRQ_ORION5X_I2C, 8);
173
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200174}
175
176
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400177/*****************************************************************************
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200178 * SATA
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400179 ****************************************************************************/
180static struct resource orion5x_sata_resources[] = {
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400181 {
Lennert Buytenheke7068ad2008-05-10 16:30:01 +0200182 .name = "sata base",
183 .start = ORION5X_SATA_PHYS_BASE,
184 .end = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
185 .flags = IORESOURCE_MEM,
186 }, {
187 .name = "sata irq",
188 .start = IRQ_ORION5X_SATA,
189 .end = IRQ_ORION5X_SATA,
190 .flags = IORESOURCE_IRQ,
191 },
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400192};
193
194static struct platform_device orion5x_sata = {
Lennert Buytenheke7068ad2008-05-10 16:30:01 +0200195 .name = "sata_mv",
196 .id = 0,
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400197 .dev = {
Andrew Lunn5c602552011-05-15 13:32:40 +0200198 .coherent_dma_mask = DMA_BIT_MASK(32),
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400199 },
Lennert Buytenheke7068ad2008-05-10 16:30:01 +0200200 .num_resources = ARRAY_SIZE(orion5x_sata_resources),
201 .resource = orion5x_sata_resources,
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400202};
203
204void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
205{
206 sata_data->dram = &orion5x_mbus_dram_info;
207 orion5x_sata.dev.platform_data = sata_data;
208 platform_device_register(&orion5x_sata);
209}
210
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200211
212/*****************************************************************************
Lennert Buytenhekd323ade2008-08-29 06:55:06 +0200213 * SPI
214 ****************************************************************************/
Lennert Buytenhekd323ade2008-08-29 06:55:06 +0200215void __init orion5x_spi_init()
216{
Andrew Lunn980f9f62011-05-15 13:32:46 +0200217 orion_spi_init(SPI_PHYS_BASE, orion5x_tclk);
Lennert Buytenhekd323ade2008-08-29 06:55:06 +0200218}
219
220
221/*****************************************************************************
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200222 * UART0
223 ****************************************************************************/
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200224void __init orion5x_uart0_init(void)
225{
Andrew Lunn28a2b452011-05-15 13:32:41 +0200226 orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
227 IRQ_ORION5X_UART0, orion5x_tclk);
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200228}
229
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200230/*****************************************************************************
231 * UART1
232 ****************************************************************************/
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200233void __init orion5x_uart1_init(void)
234{
Andrew Lunn28a2b452011-05-15 13:32:41 +0200235 orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
236 IRQ_ORION5X_UART1, orion5x_tclk);
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200237}
238
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400239/*****************************************************************************
Saeed Bishara1d5a1a62008-06-16 23:25:12 -1100240 * XOR engine
241 ****************************************************************************/
Saeed Bishara1d5a1a62008-06-16 23:25:12 -1100242void __init orion5x_xor_init(void)
243{
Andrew Lunnee962722011-05-15 13:32:48 +0200244 orion_xor0_init(&orion5x_mbus_dram_info,
245 ORION5X_XOR_PHYS_BASE,
246 ORION5X_XOR_PHYS_BASE + 0x200,
247 IRQ_ORION5X_XOR0, IRQ_ORION5X_XOR1);
Saeed Bishara1d5a1a62008-06-16 23:25:12 -1100248}
249
Sebastian Andrzej Siewior3a8f7442009-05-07 22:59:24 +0200250static struct resource orion5x_crypto_res[] = {
251 {
252 .name = "regs",
253 .start = ORION5X_CRYPTO_PHYS_BASE,
254 .end = ORION5X_CRYPTO_PHYS_BASE + 0xffff,
255 .flags = IORESOURCE_MEM,
256 }, {
257 .name = "sram",
258 .start = ORION5X_SRAM_PHYS_BASE,
259 .end = ORION5X_SRAM_PHYS_BASE + SZ_8K - 1,
260 .flags = IORESOURCE_MEM,
261 }, {
262 .name = "crypto interrupt",
263 .start = IRQ_ORION5X_CESA,
264 .end = IRQ_ORION5X_CESA,
265 .flags = IORESOURCE_IRQ,
266 },
267};
268
269static struct platform_device orion5x_crypto_device = {
270 .name = "mv_crypto",
271 .id = -1,
272 .num_resources = ARRAY_SIZE(orion5x_crypto_res),
273 .resource = orion5x_crypto_res,
274};
275
Nicolas Pitre3fade492009-06-11 22:27:20 +0200276static int __init orion5x_crypto_init(void)
Sebastian Andrzej Siewior3a8f7442009-05-07 22:59:24 +0200277{
278 int ret;
279
280 ret = orion5x_setup_sram_win();
281 if (ret)
282 return ret;
283
284 return platform_device_register(&orion5x_crypto_device);
285}
Saeed Bishara1d5a1a62008-06-16 23:25:12 -1100286
287/*****************************************************************************
Thomas Reitmayr9e058d42009-02-24 14:59:22 -0800288 * Watchdog
289 ****************************************************************************/
Thomas Reitmayr9e058d42009-02-24 14:59:22 -0800290void __init orion5x_wdt_init(void)
291{
Andrew Lunn5e00d372011-05-15 13:32:47 +0200292 orion_wdt_init(orion5x_tclk);
Thomas Reitmayr9e058d42009-02-24 14:59:22 -0800293}
294
295
296/*****************************************************************************
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400297 * Time handling
298 ****************************************************************************/
Lennert Buytenhek4ee1f6b2010-10-15 16:50:26 +0200299void __init orion5x_init_early(void)
300{
301 orion_time_set_base(TIMER_VIRT_BASE);
302}
303
Lennert Buytenhekebe35af2008-08-29 05:55:51 +0200304int orion5x_tclk;
305
306int __init orion5x_find_tclk(void)
307{
Lennert Buytenhekd323ade2008-08-29 06:55:06 +0200308 u32 dev, rev;
309
310 orion5x_pcie_id(&dev, &rev);
311 if (dev == MV88F6183_DEV_ID &&
312 (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0)
313 return 133333333;
314
Lennert Buytenhekebe35af2008-08-29 05:55:51 +0200315 return 166666667;
316}
317
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400318static void orion5x_timer_init(void)
319{
Lennert Buytenhekebe35af2008-08-29 05:55:51 +0200320 orion5x_tclk = orion5x_find_tclk();
Lennert Buytenhek4ee1f6b2010-10-15 16:50:26 +0200321
322 orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
323 IRQ_ORION5X_BRIDGE, orion5x_tclk);
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400324}
325
326struct sys_timer orion5x_timer = {
Lennert Buytenheke7068ad2008-05-10 16:30:01 +0200327 .init = orion5x_timer_init,
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400328};
329
Lennert Buytenhek044f6c72008-04-22 05:37:12 +0200330
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400331/*****************************************************************************
332 * General
333 ****************************************************************************/
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400334/*
Lennert Buytenhekb46926b2008-04-25 16:31:32 -0400335 * Identify device ID and rev from PCIe configuration header space '0'.
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400336 */
337static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
338{
339 orion5x_pcie_id(dev, rev);
340
341 if (*dev == MV88F5281_DEV_ID) {
342 if (*rev == MV88F5281_REV_D2) {
343 *dev_name = "MV88F5281-D2";
344 } else if (*rev == MV88F5281_REV_D1) {
345 *dev_name = "MV88F5281-D1";
Lennert Buytenhekce72e36e2008-08-09 15:17:27 +0200346 } else if (*rev == MV88F5281_REV_D0) {
347 *dev_name = "MV88F5281-D0";
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400348 } else {
349 *dev_name = "MV88F5281-Rev-Unsupported";
350 }
351 } else if (*dev == MV88F5182_DEV_ID) {
352 if (*rev == MV88F5182_REV_A2) {
353 *dev_name = "MV88F5182-A2";
354 } else {
355 *dev_name = "MV88F5182-Rev-Unsupported";
356 }
357 } else if (*dev == MV88F5181_DEV_ID) {
358 if (*rev == MV88F5181_REV_B1) {
359 *dev_name = "MV88F5181-Rev-B1";
Lennert Buytenhekd2b2a6b2008-05-31 08:30:40 +0200360 } else if (*rev == MV88F5181L_REV_A1) {
361 *dev_name = "MV88F5181L-Rev-A1";
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400362 } else {
Lennert Buytenhekd2b2a6b2008-05-31 08:30:40 +0200363 *dev_name = "MV88F5181(L)-Rev-Unsupported";
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400364 }
Lennert Buytenhekd323ade2008-08-29 06:55:06 +0200365 } else if (*dev == MV88F6183_DEV_ID) {
366 if (*rev == MV88F6183_REV_B0) {
367 *dev_name = "MV88F6183-Rev-B0";
368 } else {
369 *dev_name = "MV88F6183-Rev-Unsupported";
370 }
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400371 } else {
372 *dev_name = "Device-Unknown";
373 }
374}
375
376void __init orion5x_init(void)
377{
378 char *dev_name;
379 u32 dev, rev;
380
381 orion5x_id(&dev, &rev, &dev_name);
Lennert Buytenhekebe35af2008-08-29 05:55:51 +0200382 printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
383
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400384 /*
385 * Setup Orion address map
386 */
387 orion5x_setup_cpu_mbus_bridge();
Lennert Buytenhekce72e36e2008-08-09 15:17:27 +0200388
389 /*
390 * Don't issue "Wait for Interrupt" instruction if we are
391 * running on D0 5281 silicon.
392 */
393 if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
394 printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
395 disable_hlt();
396 }
Thomas Reitmayr9e058d42009-02-24 14:59:22 -0800397
398 /*
Nicolas Pitre3fade492009-06-11 22:27:20 +0200399 * The 5082/5181l/5182/6082/6082l/6183 have crypto
400 * while 5180n/5181/5281 don't have crypto.
401 */
402 if ((dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0) ||
403 dev == MV88F5182_DEV_ID || dev == MV88F6183_DEV_ID)
404 orion5x_crypto_init();
405
406 /*
Thomas Reitmayr9e058d42009-02-24 14:59:22 -0800407 * Register watchdog driver
408 */
409 orion5x_wdt_init();
Lennert Buytenhek9dd0b192008-03-27 14:51:41 -0400410}
411
412/*
413 * Many orion-based systems have buggy bootloader implementations.
414 * This is a common fixup for bogus memory tags.
415 */
416void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
417 char **from, struct meminfo *meminfo)
418{
419 for (; t->hdr.size; t = tag_next(t))
420 if (t->hdr.tag == ATAG_MEM &&
421 (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
422 t->u.mem.start & ~PAGE_MASK)) {
423 printk(KERN_WARNING
424 "Clearing invalid memory bank %dKB@0x%08x\n",
425 t->u.mem.size / 1024, t->u.mem.start);
426 t->hdr.tag = 0;
427 }
428}