Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-orion5x/common.c
10817 views
1
/*
2
* arch/arm/mach-orion5x/common.c
3
*
4
* Core functions for Marvell Orion 5x SoCs
5
*
6
* Maintainer: Tzachi Perelstein <[email protected]>
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/dma-mapping.h>
17
#include <linux/serial_8250.h>
18
#include <linux/mbus.h>
19
#include <linux/mv643xx_i2c.h>
20
#include <linux/ata_platform.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/orion_nand.h>
32
#include <plat/time.h>
33
#include <plat/common.h>
34
#include "common.h"
35
36
/*****************************************************************************
37
* I/O Address Mapping
38
****************************************************************************/
39
static struct map_desc orion5x_io_desc[] __initdata = {
40
{
41
.virtual = ORION5X_REGS_VIRT_BASE,
42
.pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
43
.length = ORION5X_REGS_SIZE,
44
.type = MT_DEVICE,
45
}, {
46
.virtual = ORION5X_PCIE_IO_VIRT_BASE,
47
.pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
48
.length = ORION5X_PCIE_IO_SIZE,
49
.type = MT_DEVICE,
50
}, {
51
.virtual = ORION5X_PCI_IO_VIRT_BASE,
52
.pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
53
.length = ORION5X_PCI_IO_SIZE,
54
.type = MT_DEVICE,
55
}, {
56
.virtual = ORION5X_PCIE_WA_VIRT_BASE,
57
.pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
58
.length = ORION5X_PCIE_WA_SIZE,
59
.type = MT_DEVICE,
60
},
61
};
62
63
void __init orion5x_map_io(void)
64
{
65
iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
66
}
67
68
69
/*****************************************************************************
70
* EHCI0
71
****************************************************************************/
72
void __init orion5x_ehci0_init(void)
73
{
74
orion_ehci_init(&orion5x_mbus_dram_info,
75
ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL);
76
}
77
78
79
/*****************************************************************************
80
* EHCI1
81
****************************************************************************/
82
void __init orion5x_ehci1_init(void)
83
{
84
orion_ehci_1_init(&orion5x_mbus_dram_info,
85
ORION5X_USB1_PHYS_BASE, IRQ_ORION5X_USB1_CTRL);
86
}
87
88
89
/*****************************************************************************
90
* GE00
91
****************************************************************************/
92
void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
93
{
94
orion_ge00_init(eth_data, &orion5x_mbus_dram_info,
95
ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
96
IRQ_ORION5X_ETH_ERR, orion5x_tclk);
97
}
98
99
100
/*****************************************************************************
101
* Ethernet switch
102
****************************************************************************/
103
void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
104
{
105
orion_ge00_switch_init(d, irq);
106
}
107
108
109
/*****************************************************************************
110
* I2C
111
****************************************************************************/
112
void __init orion5x_i2c_init(void)
113
{
114
orion_i2c_init(I2C_PHYS_BASE, IRQ_ORION5X_I2C, 8);
115
116
}
117
118
119
/*****************************************************************************
120
* SATA
121
****************************************************************************/
122
void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
123
{
124
orion_sata_init(sata_data, &orion5x_mbus_dram_info,
125
ORION5X_SATA_PHYS_BASE, IRQ_ORION5X_SATA);
126
}
127
128
129
/*****************************************************************************
130
* SPI
131
****************************************************************************/
132
void __init orion5x_spi_init()
133
{
134
orion_spi_init(SPI_PHYS_BASE, orion5x_tclk);
135
}
136
137
138
/*****************************************************************************
139
* UART0
140
****************************************************************************/
141
void __init orion5x_uart0_init(void)
142
{
143
orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
144
IRQ_ORION5X_UART0, orion5x_tclk);
145
}
146
147
/*****************************************************************************
148
* UART1
149
****************************************************************************/
150
void __init orion5x_uart1_init(void)
151
{
152
orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
153
IRQ_ORION5X_UART1, orion5x_tclk);
154
}
155
156
/*****************************************************************************
157
* XOR engine
158
****************************************************************************/
159
void __init orion5x_xor_init(void)
160
{
161
orion_xor0_init(&orion5x_mbus_dram_info,
162
ORION5X_XOR_PHYS_BASE,
163
ORION5X_XOR_PHYS_BASE + 0x200,
164
IRQ_ORION5X_XOR0, IRQ_ORION5X_XOR1);
165
}
166
167
/*****************************************************************************
168
* Cryptographic Engines and Security Accelerator (CESA)
169
****************************************************************************/
170
static void __init orion5x_crypto_init(void)
171
{
172
int ret;
173
174
ret = orion5x_setup_sram_win();
175
if (ret)
176
return;
177
178
orion_crypto_init(ORION5X_CRYPTO_PHYS_BASE, ORION5X_SRAM_PHYS_BASE,
179
SZ_8K, IRQ_ORION5X_CESA);
180
}
181
182
/*****************************************************************************
183
* Watchdog
184
****************************************************************************/
185
void __init orion5x_wdt_init(void)
186
{
187
orion_wdt_init(orion5x_tclk);
188
}
189
190
191
/*****************************************************************************
192
* Time handling
193
****************************************************************************/
194
void __init orion5x_init_early(void)
195
{
196
orion_time_set_base(TIMER_VIRT_BASE);
197
}
198
199
int orion5x_tclk;
200
201
int __init orion5x_find_tclk(void)
202
{
203
u32 dev, rev;
204
205
orion5x_pcie_id(&dev, &rev);
206
if (dev == MV88F6183_DEV_ID &&
207
(readl(MPP_RESET_SAMPLE) & 0x00000200) == 0)
208
return 133333333;
209
210
return 166666667;
211
}
212
213
static void orion5x_timer_init(void)
214
{
215
orion5x_tclk = orion5x_find_tclk();
216
217
orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
218
IRQ_ORION5X_BRIDGE, orion5x_tclk);
219
}
220
221
struct sys_timer orion5x_timer = {
222
.init = orion5x_timer_init,
223
};
224
225
226
/*****************************************************************************
227
* General
228
****************************************************************************/
229
/*
230
* Identify device ID and rev from PCIe configuration header space '0'.
231
*/
232
static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
233
{
234
orion5x_pcie_id(dev, rev);
235
236
if (*dev == MV88F5281_DEV_ID) {
237
if (*rev == MV88F5281_REV_D2) {
238
*dev_name = "MV88F5281-D2";
239
} else if (*rev == MV88F5281_REV_D1) {
240
*dev_name = "MV88F5281-D1";
241
} else if (*rev == MV88F5281_REV_D0) {
242
*dev_name = "MV88F5281-D0";
243
} else {
244
*dev_name = "MV88F5281-Rev-Unsupported";
245
}
246
} else if (*dev == MV88F5182_DEV_ID) {
247
if (*rev == MV88F5182_REV_A2) {
248
*dev_name = "MV88F5182-A2";
249
} else {
250
*dev_name = "MV88F5182-Rev-Unsupported";
251
}
252
} else if (*dev == MV88F5181_DEV_ID) {
253
if (*rev == MV88F5181_REV_B1) {
254
*dev_name = "MV88F5181-Rev-B1";
255
} else if (*rev == MV88F5181L_REV_A1) {
256
*dev_name = "MV88F5181L-Rev-A1";
257
} else {
258
*dev_name = "MV88F5181(L)-Rev-Unsupported";
259
}
260
} else if (*dev == MV88F6183_DEV_ID) {
261
if (*rev == MV88F6183_REV_B0) {
262
*dev_name = "MV88F6183-Rev-B0";
263
} else {
264
*dev_name = "MV88F6183-Rev-Unsupported";
265
}
266
} else {
267
*dev_name = "Device-Unknown";
268
}
269
}
270
271
void __init orion5x_init(void)
272
{
273
char *dev_name;
274
u32 dev, rev;
275
276
orion5x_id(&dev, &rev, &dev_name);
277
printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
278
279
/*
280
* Setup Orion address map
281
*/
282
orion5x_setup_cpu_mbus_bridge();
283
284
/*
285
* Don't issue "Wait for Interrupt" instruction if we are
286
* running on D0 5281 silicon.
287
*/
288
if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
289
printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
290
disable_hlt();
291
}
292
293
/*
294
* The 5082/5181l/5182/6082/6082l/6183 have crypto
295
* while 5180n/5181/5281 don't have crypto.
296
*/
297
if ((dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0) ||
298
dev == MV88F5182_DEV_ID || dev == MV88F6183_DEV_ID)
299
orion5x_crypto_init();
300
301
/*
302
* Register watchdog driver
303
*/
304
orion5x_wdt_init();
305
}
306
307
/*
308
* Many orion-based systems have buggy bootloader implementations.
309
* This is a common fixup for bogus memory tags.
310
*/
311
void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
312
char **from, struct meminfo *meminfo)
313
{
314
for (; t->hdr.size; t = tag_next(t))
315
if (t->hdr.tag == ATAG_MEM &&
316
(!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
317
t->u.mem.start & ~PAGE_MASK)) {
318
printk(KERN_WARNING
319
"Clearing invalid memory bank %dKB@0x%08x\n",
320
t->u.mem.size / 1024, t->u.mem.start);
321
t->hdr.tag = 0;
322
}
323
}
324
325