Commit | Line | Data |
---|---|---|
794d15b2 SS |
1 | /* |
2 | * arch/arm/mach-mv78xx0/common.c | |
3 | * | |
4 | * Core functions for Marvell MV78xx0 SoCs | |
5 | * | |
6 | * This file is licensed under the terms of the GNU General Public | |
7 | * License version 2. This program is licensed "as is" without any | |
8 | * warranty of any kind, whether express or implied. | |
9 | */ | |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/platform_device.h> | |
14 | #include <linux/serial_8250.h> | |
15 | #include <linux/mbus.h> | |
16 | #include <linux/mv643xx_eth.h> | |
69359943 | 17 | #include <linux/mv643xx_i2c.h> |
794d15b2 | 18 | #include <linux/ata_platform.h> |
712424fd | 19 | #include <linux/ethtool.h> |
794d15b2 SS |
20 | #include <asm/mach/map.h> |
21 | #include <asm/mach/time.h> | |
a09e64fb | 22 | #include <mach/mv78xx0.h> |
fdd8b079 | 23 | #include <mach/bridge-regs.h> |
6f088f1d LB |
24 | #include <plat/cache-feroceon-l2.h> |
25 | #include <plat/ehci-orion.h> | |
26 | #include <plat/orion_nand.h> | |
27 | #include <plat/time.h> | |
794d15b2 SS |
28 | #include "common.h" |
29 | ||
30 | ||
31 | /***************************************************************************** | |
32 | * Common bits | |
33 | ****************************************************************************/ | |
34 | int mv78xx0_core_index(void) | |
35 | { | |
36 | u32 extra; | |
37 | ||
38 | /* | |
39 | * Read Extra Features register. | |
40 | */ | |
41 | __asm__("mrc p15, 1, %0, c15, c1, 0" : "=r" (extra)); | |
42 | ||
43 | return !!(extra & 0x00004000); | |
44 | } | |
45 | ||
46 | static int get_hclk(void) | |
47 | { | |
48 | int hclk; | |
49 | ||
50 | /* | |
51 | * HCLK tick rate is configured by DEV_D[7:5] pins. | |
52 | */ | |
53 | switch ((readl(SAMPLE_AT_RESET_LOW) >> 5) & 7) { | |
54 | case 0: | |
55 | hclk = 166666667; | |
56 | break; | |
57 | case 1: | |
58 | hclk = 200000000; | |
59 | break; | |
60 | case 2: | |
61 | hclk = 266666667; | |
62 | break; | |
63 | case 3: | |
64 | hclk = 333333333; | |
65 | break; | |
66 | case 4: | |
67 | hclk = 400000000; | |
68 | break; | |
69 | default: | |
70 | panic("unknown HCLK PLL setting: %.8x\n", | |
71 | readl(SAMPLE_AT_RESET_LOW)); | |
72 | } | |
73 | ||
74 | return hclk; | |
75 | } | |
76 | ||
77 | static void get_pclk_l2clk(int hclk, int core_index, int *pclk, int *l2clk) | |
78 | { | |
79 | u32 cfg; | |
80 | ||
81 | /* | |
82 | * Core #0 PCLK/L2CLK is configured by bits [13:8], core #1 | |
83 | * PCLK/L2CLK by bits [19:14]. | |
84 | */ | |
85 | if (core_index == 0) { | |
86 | cfg = (readl(SAMPLE_AT_RESET_LOW) >> 8) & 0x3f; | |
87 | } else { | |
88 | cfg = (readl(SAMPLE_AT_RESET_LOW) >> 14) & 0x3f; | |
89 | } | |
90 | ||
91 | /* | |
92 | * Bits [11:8] ([17:14] for core #1) configure the PCLK:HCLK | |
93 | * ratio (1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6). | |
94 | */ | |
95 | *pclk = ((u64)hclk * (2 + (cfg & 0xf))) >> 1; | |
96 | ||
97 | /* | |
98 | * Bits [13:12] ([19:18] for core #1) configure the PCLK:L2CLK | |
99 | * ratio (1, 2, 3). | |
100 | */ | |
101 | *l2clk = *pclk / (((cfg >> 4) & 3) + 1); | |
102 | } | |
103 | ||
104 | static int get_tclk(void) | |
105 | { | |
106 | int tclk; | |
107 | ||
108 | /* | |
109 | * TCLK tick rate is configured by DEV_A[2:0] strap pins. | |
110 | */ | |
111 | switch ((readl(SAMPLE_AT_RESET_HIGH) >> 6) & 7) { | |
112 | case 1: | |
113 | tclk = 166666667; | |
114 | break; | |
115 | case 3: | |
116 | tclk = 200000000; | |
117 | break; | |
118 | default: | |
119 | panic("unknown TCLK PLL setting: %.8x\n", | |
120 | readl(SAMPLE_AT_RESET_HIGH)); | |
121 | } | |
122 | ||
123 | return tclk; | |
124 | } | |
125 | ||
126 | ||
127 | /***************************************************************************** | |
128 | * I/O Address Mapping | |
129 | ****************************************************************************/ | |
130 | static struct map_desc mv78xx0_io_desc[] __initdata = { | |
131 | { | |
132 | .virtual = MV78XX0_CORE_REGS_VIRT_BASE, | |
133 | .pfn = 0, | |
134 | .length = MV78XX0_CORE_REGS_SIZE, | |
135 | .type = MT_DEVICE, | |
136 | }, { | |
137 | .virtual = MV78XX0_PCIE_IO_VIRT_BASE(0), | |
138 | .pfn = __phys_to_pfn(MV78XX0_PCIE_IO_PHYS_BASE(0)), | |
139 | .length = MV78XX0_PCIE_IO_SIZE * 8, | |
140 | .type = MT_DEVICE, | |
141 | }, { | |
142 | .virtual = MV78XX0_REGS_VIRT_BASE, | |
143 | .pfn = __phys_to_pfn(MV78XX0_REGS_PHYS_BASE), | |
144 | .length = MV78XX0_REGS_SIZE, | |
145 | .type = MT_DEVICE, | |
146 | }, | |
147 | }; | |
148 | ||
149 | void __init mv78xx0_map_io(void) | |
150 | { | |
151 | unsigned long phys; | |
152 | ||
153 | /* | |
154 | * Map the right set of per-core registers depending on | |
155 | * which core we are running on. | |
156 | */ | |
157 | if (mv78xx0_core_index() == 0) { | |
158 | phys = MV78XX0_CORE0_REGS_PHYS_BASE; | |
159 | } else { | |
160 | phys = MV78XX0_CORE1_REGS_PHYS_BASE; | |
161 | } | |
162 | mv78xx0_io_desc[0].pfn = __phys_to_pfn(phys); | |
163 | ||
164 | iotable_init(mv78xx0_io_desc, ARRAY_SIZE(mv78xx0_io_desc)); | |
165 | } | |
166 | ||
167 | ||
168 | /***************************************************************************** | |
169 | * EHCI | |
170 | ****************************************************************************/ | |
171 | static struct orion_ehci_data mv78xx0_ehci_data = { | |
172 | .dram = &mv78xx0_mbus_dram_info, | |
fb6f5529 | 173 | .phy_version = EHCI_PHY_NA, |
794d15b2 SS |
174 | }; |
175 | ||
176 | static u64 ehci_dmamask = 0xffffffffUL; | |
177 | ||
178 | ||
179 | /***************************************************************************** | |
180 | * EHCI0 | |
181 | ****************************************************************************/ | |
182 | static struct resource mv78xx0_ehci0_resources[] = { | |
183 | { | |
184 | .start = USB0_PHYS_BASE, | |
185 | .end = USB0_PHYS_BASE + 0x0fff, | |
186 | .flags = IORESOURCE_MEM, | |
187 | }, { | |
188 | .start = IRQ_MV78XX0_USB_0, | |
189 | .end = IRQ_MV78XX0_USB_0, | |
190 | .flags = IORESOURCE_IRQ, | |
191 | }, | |
192 | }; | |
193 | ||
194 | static struct platform_device mv78xx0_ehci0 = { | |
195 | .name = "orion-ehci", | |
196 | .id = 0, | |
197 | .dev = { | |
198 | .dma_mask = &ehci_dmamask, | |
199 | .coherent_dma_mask = 0xffffffff, | |
200 | .platform_data = &mv78xx0_ehci_data, | |
201 | }, | |
202 | .resource = mv78xx0_ehci0_resources, | |
203 | .num_resources = ARRAY_SIZE(mv78xx0_ehci0_resources), | |
204 | }; | |
205 | ||
206 | void __init mv78xx0_ehci0_init(void) | |
207 | { | |
208 | platform_device_register(&mv78xx0_ehci0); | |
209 | } | |
210 | ||
211 | ||
212 | /***************************************************************************** | |
213 | * EHCI1 | |
214 | ****************************************************************************/ | |
215 | static struct resource mv78xx0_ehci1_resources[] = { | |
216 | { | |
217 | .start = USB1_PHYS_BASE, | |
218 | .end = USB1_PHYS_BASE + 0x0fff, | |
219 | .flags = IORESOURCE_MEM, | |
220 | }, { | |
221 | .start = IRQ_MV78XX0_USB_1, | |
222 | .end = IRQ_MV78XX0_USB_1, | |
223 | .flags = IORESOURCE_IRQ, | |
224 | }, | |
225 | }; | |
226 | ||
227 | static struct platform_device mv78xx0_ehci1 = { | |
228 | .name = "orion-ehci", | |
229 | .id = 1, | |
230 | .dev = { | |
231 | .dma_mask = &ehci_dmamask, | |
232 | .coherent_dma_mask = 0xffffffff, | |
233 | .platform_data = &mv78xx0_ehci_data, | |
234 | }, | |
235 | .resource = mv78xx0_ehci1_resources, | |
236 | .num_resources = ARRAY_SIZE(mv78xx0_ehci1_resources), | |
237 | }; | |
238 | ||
239 | void __init mv78xx0_ehci1_init(void) | |
240 | { | |
241 | platform_device_register(&mv78xx0_ehci1); | |
242 | } | |
243 | ||
244 | ||
245 | /***************************************************************************** | |
246 | * EHCI2 | |
247 | ****************************************************************************/ | |
248 | static struct resource mv78xx0_ehci2_resources[] = { | |
249 | { | |
250 | .start = USB2_PHYS_BASE, | |
251 | .end = USB2_PHYS_BASE + 0x0fff, | |
252 | .flags = IORESOURCE_MEM, | |
253 | }, { | |
254 | .start = IRQ_MV78XX0_USB_2, | |
255 | .end = IRQ_MV78XX0_USB_2, | |
256 | .flags = IORESOURCE_IRQ, | |
257 | }, | |
258 | }; | |
259 | ||
260 | static struct platform_device mv78xx0_ehci2 = { | |
261 | .name = "orion-ehci", | |
262 | .id = 2, | |
263 | .dev = { | |
264 | .dma_mask = &ehci_dmamask, | |
265 | .coherent_dma_mask = 0xffffffff, | |
266 | .platform_data = &mv78xx0_ehci_data, | |
267 | }, | |
268 | .resource = mv78xx0_ehci2_resources, | |
269 | .num_resources = ARRAY_SIZE(mv78xx0_ehci2_resources), | |
270 | }; | |
271 | ||
272 | void __init mv78xx0_ehci2_init(void) | |
273 | { | |
274 | platform_device_register(&mv78xx0_ehci2); | |
275 | } | |
276 | ||
277 | ||
278 | /***************************************************************************** | |
279 | * GE00 | |
280 | ****************************************************************************/ | |
281 | struct mv643xx_eth_shared_platform_data mv78xx0_ge00_shared_data = { | |
282 | .t_clk = 0, | |
283 | .dram = &mv78xx0_mbus_dram_info, | |
284 | }; | |
285 | ||
286 | static struct resource mv78xx0_ge00_shared_resources[] = { | |
287 | { | |
288 | .name = "ge00 base", | |
289 | .start = GE00_PHYS_BASE + 0x2000, | |
290 | .end = GE00_PHYS_BASE + 0x3fff, | |
291 | .flags = IORESOURCE_MEM, | |
1f8081f5 LB |
292 | }, { |
293 | .name = "ge err irq", | |
294 | .start = IRQ_MV78XX0_GE_ERR, | |
295 | .end = IRQ_MV78XX0_GE_ERR, | |
296 | .flags = IORESOURCE_IRQ, | |
794d15b2 SS |
297 | }, |
298 | }; | |
299 | ||
300 | static struct platform_device mv78xx0_ge00_shared = { | |
301 | .name = MV643XX_ETH_SHARED_NAME, | |
302 | .id = 0, | |
303 | .dev = { | |
304 | .platform_data = &mv78xx0_ge00_shared_data, | |
305 | }, | |
1f8081f5 | 306 | .num_resources = ARRAY_SIZE(mv78xx0_ge00_shared_resources), |
794d15b2 SS |
307 | .resource = mv78xx0_ge00_shared_resources, |
308 | }; | |
309 | ||
310 | static struct resource mv78xx0_ge00_resources[] = { | |
311 | { | |
312 | .name = "ge00 irq", | |
313 | .start = IRQ_MV78XX0_GE00_SUM, | |
314 | .end = IRQ_MV78XX0_GE00_SUM, | |
315 | .flags = IORESOURCE_IRQ, | |
316 | }, | |
317 | }; | |
318 | ||
319 | static struct platform_device mv78xx0_ge00 = { | |
320 | .name = MV643XX_ETH_NAME, | |
321 | .id = 0, | |
322 | .num_resources = 1, | |
323 | .resource = mv78xx0_ge00_resources, | |
a49a018a NP |
324 | .dev = { |
325 | .coherent_dma_mask = 0xffffffff, | |
326 | }, | |
794d15b2 SS |
327 | }; |
328 | ||
329 | void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data) | |
330 | { | |
331 | eth_data->shared = &mv78xx0_ge00_shared; | |
332 | mv78xx0_ge00.dev.platform_data = eth_data; | |
333 | ||
334 | platform_device_register(&mv78xx0_ge00_shared); | |
335 | platform_device_register(&mv78xx0_ge00); | |
336 | } | |
337 | ||
338 | ||
339 | /***************************************************************************** | |
340 | * GE01 | |
341 | ****************************************************************************/ | |
342 | struct mv643xx_eth_shared_platform_data mv78xx0_ge01_shared_data = { | |
343 | .t_clk = 0, | |
344 | .dram = &mv78xx0_mbus_dram_info, | |
fc0eb9f2 | 345 | .shared_smi = &mv78xx0_ge00_shared, |
794d15b2 SS |
346 | }; |
347 | ||
348 | static struct resource mv78xx0_ge01_shared_resources[] = { | |
349 | { | |
350 | .name = "ge01 base", | |
351 | .start = GE01_PHYS_BASE + 0x2000, | |
352 | .end = GE01_PHYS_BASE + 0x3fff, | |
353 | .flags = IORESOURCE_MEM, | |
354 | }, | |
355 | }; | |
356 | ||
357 | static struct platform_device mv78xx0_ge01_shared = { | |
358 | .name = MV643XX_ETH_SHARED_NAME, | |
359 | .id = 1, | |
360 | .dev = { | |
361 | .platform_data = &mv78xx0_ge01_shared_data, | |
362 | }, | |
363 | .num_resources = 1, | |
364 | .resource = mv78xx0_ge01_shared_resources, | |
365 | }; | |
366 | ||
367 | static struct resource mv78xx0_ge01_resources[] = { | |
368 | { | |
369 | .name = "ge01 irq", | |
370 | .start = IRQ_MV78XX0_GE01_SUM, | |
371 | .end = IRQ_MV78XX0_GE01_SUM, | |
372 | .flags = IORESOURCE_IRQ, | |
373 | }, | |
374 | }; | |
375 | ||
376 | static struct platform_device mv78xx0_ge01 = { | |
377 | .name = MV643XX_ETH_NAME, | |
378 | .id = 1, | |
379 | .num_resources = 1, | |
380 | .resource = mv78xx0_ge01_resources, | |
a49a018a NP |
381 | .dev = { |
382 | .coherent_dma_mask = 0xffffffff, | |
383 | }, | |
794d15b2 SS |
384 | }; |
385 | ||
386 | void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data) | |
387 | { | |
388 | eth_data->shared = &mv78xx0_ge01_shared; | |
794d15b2 SS |
389 | mv78xx0_ge01.dev.platform_data = eth_data; |
390 | ||
391 | platform_device_register(&mv78xx0_ge01_shared); | |
392 | platform_device_register(&mv78xx0_ge01); | |
393 | } | |
394 | ||
395 | ||
396 | /***************************************************************************** | |
397 | * GE10 | |
398 | ****************************************************************************/ | |
399 | struct mv643xx_eth_shared_platform_data mv78xx0_ge10_shared_data = { | |
400 | .t_clk = 0, | |
401 | .dram = &mv78xx0_mbus_dram_info, | |
fc0eb9f2 | 402 | .shared_smi = &mv78xx0_ge00_shared, |
794d15b2 SS |
403 | }; |
404 | ||
405 | static struct resource mv78xx0_ge10_shared_resources[] = { | |
406 | { | |
407 | .name = "ge10 base", | |
408 | .start = GE10_PHYS_BASE + 0x2000, | |
409 | .end = GE10_PHYS_BASE + 0x3fff, | |
410 | .flags = IORESOURCE_MEM, | |
411 | }, | |
412 | }; | |
413 | ||
414 | static struct platform_device mv78xx0_ge10_shared = { | |
415 | .name = MV643XX_ETH_SHARED_NAME, | |
416 | .id = 2, | |
417 | .dev = { | |
418 | .platform_data = &mv78xx0_ge10_shared_data, | |
419 | }, | |
420 | .num_resources = 1, | |
421 | .resource = mv78xx0_ge10_shared_resources, | |
422 | }; | |
423 | ||
424 | static struct resource mv78xx0_ge10_resources[] = { | |
425 | { | |
426 | .name = "ge10 irq", | |
427 | .start = IRQ_MV78XX0_GE10_SUM, | |
428 | .end = IRQ_MV78XX0_GE10_SUM, | |
429 | .flags = IORESOURCE_IRQ, | |
430 | }, | |
431 | }; | |
432 | ||
433 | static struct platform_device mv78xx0_ge10 = { | |
434 | .name = MV643XX_ETH_NAME, | |
435 | .id = 2, | |
436 | .num_resources = 1, | |
437 | .resource = mv78xx0_ge10_resources, | |
a49a018a NP |
438 | .dev = { |
439 | .coherent_dma_mask = 0xffffffff, | |
440 | }, | |
794d15b2 SS |
441 | }; |
442 | ||
443 | void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data) | |
444 | { | |
712424fd LB |
445 | u32 dev, rev; |
446 | ||
794d15b2 | 447 | eth_data->shared = &mv78xx0_ge10_shared; |
794d15b2 SS |
448 | mv78xx0_ge10.dev.platform_data = eth_data; |
449 | ||
712424fd LB |
450 | /* |
451 | * On the Z0, ge10 and ge11 are internally connected back | |
452 | * to back, and not brought out. | |
453 | */ | |
454 | mv78xx0_pcie_id(&dev, &rev); | |
455 | if (dev == MV78X00_Z0_DEV_ID) { | |
456 | eth_data->phy_addr = MV643XX_ETH_PHY_NONE; | |
457 | eth_data->speed = SPEED_1000; | |
458 | eth_data->duplex = DUPLEX_FULL; | |
459 | } | |
460 | ||
794d15b2 SS |
461 | platform_device_register(&mv78xx0_ge10_shared); |
462 | platform_device_register(&mv78xx0_ge10); | |
463 | } | |
464 | ||
465 | ||
466 | /***************************************************************************** | |
467 | * GE11 | |
468 | ****************************************************************************/ | |
469 | struct mv643xx_eth_shared_platform_data mv78xx0_ge11_shared_data = { | |
470 | .t_clk = 0, | |
471 | .dram = &mv78xx0_mbus_dram_info, | |
fc0eb9f2 | 472 | .shared_smi = &mv78xx0_ge00_shared, |
794d15b2 SS |
473 | }; |
474 | ||
475 | static struct resource mv78xx0_ge11_shared_resources[] = { | |
476 | { | |
477 | .name = "ge11 base", | |
478 | .start = GE11_PHYS_BASE + 0x2000, | |
479 | .end = GE11_PHYS_BASE + 0x3fff, | |
480 | .flags = IORESOURCE_MEM, | |
481 | }, | |
482 | }; | |
483 | ||
484 | static struct platform_device mv78xx0_ge11_shared = { | |
485 | .name = MV643XX_ETH_SHARED_NAME, | |
486 | .id = 3, | |
487 | .dev = { | |
488 | .platform_data = &mv78xx0_ge11_shared_data, | |
489 | }, | |
490 | .num_resources = 1, | |
491 | .resource = mv78xx0_ge11_shared_resources, | |
492 | }; | |
493 | ||
494 | static struct resource mv78xx0_ge11_resources[] = { | |
495 | { | |
496 | .name = "ge11 irq", | |
497 | .start = IRQ_MV78XX0_GE11_SUM, | |
498 | .end = IRQ_MV78XX0_GE11_SUM, | |
499 | .flags = IORESOURCE_IRQ, | |
500 | }, | |
501 | }; | |
502 | ||
503 | static struct platform_device mv78xx0_ge11 = { | |
504 | .name = MV643XX_ETH_NAME, | |
505 | .id = 3, | |
506 | .num_resources = 1, | |
507 | .resource = mv78xx0_ge11_resources, | |
a49a018a NP |
508 | .dev = { |
509 | .coherent_dma_mask = 0xffffffff, | |
510 | }, | |
794d15b2 SS |
511 | }; |
512 | ||
513 | void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data) | |
514 | { | |
712424fd LB |
515 | u32 dev, rev; |
516 | ||
794d15b2 | 517 | eth_data->shared = &mv78xx0_ge11_shared; |
794d15b2 SS |
518 | mv78xx0_ge11.dev.platform_data = eth_data; |
519 | ||
712424fd LB |
520 | /* |
521 | * On the Z0, ge10 and ge11 are internally connected back | |
522 | * to back, and not brought out. | |
523 | */ | |
524 | mv78xx0_pcie_id(&dev, &rev); | |
525 | if (dev == MV78X00_Z0_DEV_ID) { | |
526 | eth_data->phy_addr = MV643XX_ETH_PHY_NONE; | |
527 | eth_data->speed = SPEED_1000; | |
528 | eth_data->duplex = DUPLEX_FULL; | |
529 | } | |
530 | ||
794d15b2 SS |
531 | platform_device_register(&mv78xx0_ge11_shared); |
532 | platform_device_register(&mv78xx0_ge11); | |
533 | } | |
534 | ||
69359943 RV |
535 | /***************************************************************************** |
536 | * I2C bus 0 | |
537 | ****************************************************************************/ | |
538 | ||
539 | static struct mv64xxx_i2c_pdata mv78xx0_i2c_0_pdata = { | |
540 | .freq_m = 8, /* assumes 166 MHz TCLK */ | |
541 | .freq_n = 3, | |
542 | .timeout = 1000, /* Default timeout of 1 second */ | |
543 | }; | |
544 | ||
545 | static struct resource mv78xx0_i2c_0_resources[] = { | |
546 | { | |
69359943 RV |
547 | .start = I2C_0_PHYS_BASE, |
548 | .end = I2C_0_PHYS_BASE + 0x1f, | |
549 | .flags = IORESOURCE_MEM, | |
550 | }, { | |
69359943 RV |
551 | .start = IRQ_MV78XX0_I2C_0, |
552 | .end = IRQ_MV78XX0_I2C_0, | |
553 | .flags = IORESOURCE_IRQ, | |
554 | }, | |
555 | }; | |
556 | ||
557 | ||
558 | static struct platform_device mv78xx0_i2c_0 = { | |
559 | .name = MV64XXX_I2C_CTLR_NAME, | |
560 | .id = 0, | |
561 | .num_resources = ARRAY_SIZE(mv78xx0_i2c_0_resources), | |
562 | .resource = mv78xx0_i2c_0_resources, | |
563 | .dev = { | |
564 | .platform_data = &mv78xx0_i2c_0_pdata, | |
565 | }, | |
566 | }; | |
567 | ||
568 | /***************************************************************************** | |
569 | * I2C bus 1 | |
570 | ****************************************************************************/ | |
571 | ||
572 | static struct mv64xxx_i2c_pdata mv78xx0_i2c_1_pdata = { | |
573 | .freq_m = 8, /* assumes 166 MHz TCLK */ | |
574 | .freq_n = 3, | |
575 | .timeout = 1000, /* Default timeout of 1 second */ | |
576 | }; | |
577 | ||
578 | static struct resource mv78xx0_i2c_1_resources[] = { | |
579 | { | |
69359943 RV |
580 | .start = I2C_1_PHYS_BASE, |
581 | .end = I2C_1_PHYS_BASE + 0x1f, | |
582 | .flags = IORESOURCE_MEM, | |
583 | }, { | |
69359943 RV |
584 | .start = IRQ_MV78XX0_I2C_1, |
585 | .end = IRQ_MV78XX0_I2C_1, | |
586 | .flags = IORESOURCE_IRQ, | |
587 | }, | |
588 | }; | |
589 | ||
590 | ||
591 | static struct platform_device mv78xx0_i2c_1 = { | |
592 | .name = MV64XXX_I2C_CTLR_NAME, | |
593 | .id = 1, | |
594 | .num_resources = ARRAY_SIZE(mv78xx0_i2c_1_resources), | |
595 | .resource = mv78xx0_i2c_1_resources, | |
596 | .dev = { | |
597 | .platform_data = &mv78xx0_i2c_1_pdata, | |
598 | }, | |
599 | }; | |
600 | ||
601 | void __init mv78xx0_i2c_init(void) | |
602 | { | |
603 | platform_device_register(&mv78xx0_i2c_0); | |
604 | platform_device_register(&mv78xx0_i2c_1); | |
605 | } | |
794d15b2 SS |
606 | |
607 | /***************************************************************************** | |
608 | * SATA | |
609 | ****************************************************************************/ | |
610 | static struct resource mv78xx0_sata_resources[] = { | |
611 | { | |
612 | .name = "sata base", | |
613 | .start = SATA_PHYS_BASE, | |
614 | .end = SATA_PHYS_BASE + 0x5000 - 1, | |
615 | .flags = IORESOURCE_MEM, | |
616 | }, { | |
617 | .name = "sata irq", | |
618 | .start = IRQ_MV78XX0_SATA, | |
619 | .end = IRQ_MV78XX0_SATA, | |
620 | .flags = IORESOURCE_IRQ, | |
621 | }, | |
622 | }; | |
623 | ||
624 | static struct platform_device mv78xx0_sata = { | |
625 | .name = "sata_mv", | |
626 | .id = 0, | |
627 | .dev = { | |
628 | .coherent_dma_mask = 0xffffffff, | |
629 | }, | |
630 | .num_resources = ARRAY_SIZE(mv78xx0_sata_resources), | |
631 | .resource = mv78xx0_sata_resources, | |
632 | }; | |
633 | ||
634 | void __init mv78xx0_sata_init(struct mv_sata_platform_data *sata_data) | |
635 | { | |
636 | sata_data->dram = &mv78xx0_mbus_dram_info; | |
637 | mv78xx0_sata.dev.platform_data = sata_data; | |
638 | platform_device_register(&mv78xx0_sata); | |
639 | } | |
640 | ||
641 | ||
642 | /***************************************************************************** | |
643 | * UART0 | |
644 | ****************************************************************************/ | |
645 | static struct plat_serial8250_port mv78xx0_uart0_data[] = { | |
646 | { | |
647 | .mapbase = UART0_PHYS_BASE, | |
648 | .membase = (char *)UART0_VIRT_BASE, | |
649 | .irq = IRQ_MV78XX0_UART_0, | |
650 | .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, | |
651 | .iotype = UPIO_MEM, | |
652 | .regshift = 2, | |
653 | .uartclk = 0, | |
654 | }, { | |
655 | }, | |
656 | }; | |
657 | ||
658 | static struct resource mv78xx0_uart0_resources[] = { | |
659 | { | |
660 | .start = UART0_PHYS_BASE, | |
661 | .end = UART0_PHYS_BASE + 0xff, | |
662 | .flags = IORESOURCE_MEM, | |
663 | }, { | |
664 | .start = IRQ_MV78XX0_UART_0, | |
665 | .end = IRQ_MV78XX0_UART_0, | |
666 | .flags = IORESOURCE_IRQ, | |
667 | }, | |
668 | }; | |
669 | ||
670 | static struct platform_device mv78xx0_uart0 = { | |
671 | .name = "serial8250", | |
672 | .id = 0, | |
673 | .dev = { | |
674 | .platform_data = mv78xx0_uart0_data, | |
675 | }, | |
676 | .resource = mv78xx0_uart0_resources, | |
677 | .num_resources = ARRAY_SIZE(mv78xx0_uart0_resources), | |
678 | }; | |
679 | ||
680 | void __init mv78xx0_uart0_init(void) | |
681 | { | |
682 | platform_device_register(&mv78xx0_uart0); | |
683 | } | |
684 | ||
685 | ||
686 | /***************************************************************************** | |
687 | * UART1 | |
688 | ****************************************************************************/ | |
689 | static struct plat_serial8250_port mv78xx0_uart1_data[] = { | |
690 | { | |
691 | .mapbase = UART1_PHYS_BASE, | |
692 | .membase = (char *)UART1_VIRT_BASE, | |
693 | .irq = IRQ_MV78XX0_UART_1, | |
694 | .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, | |
695 | .iotype = UPIO_MEM, | |
696 | .regshift = 2, | |
697 | .uartclk = 0, | |
698 | }, { | |
699 | }, | |
700 | }; | |
701 | ||
702 | static struct resource mv78xx0_uart1_resources[] = { | |
703 | { | |
704 | .start = UART1_PHYS_BASE, | |
705 | .end = UART1_PHYS_BASE + 0xff, | |
706 | .flags = IORESOURCE_MEM, | |
707 | }, { | |
708 | .start = IRQ_MV78XX0_UART_1, | |
709 | .end = IRQ_MV78XX0_UART_1, | |
710 | .flags = IORESOURCE_IRQ, | |
711 | }, | |
712 | }; | |
713 | ||
714 | static struct platform_device mv78xx0_uart1 = { | |
715 | .name = "serial8250", | |
716 | .id = 1, | |
717 | .dev = { | |
718 | .platform_data = mv78xx0_uart1_data, | |
719 | }, | |
720 | .resource = mv78xx0_uart1_resources, | |
721 | .num_resources = ARRAY_SIZE(mv78xx0_uart1_resources), | |
722 | }; | |
723 | ||
724 | void __init mv78xx0_uart1_init(void) | |
725 | { | |
726 | platform_device_register(&mv78xx0_uart1); | |
727 | } | |
728 | ||
729 | ||
730 | /***************************************************************************** | |
731 | * UART2 | |
732 | ****************************************************************************/ | |
733 | static struct plat_serial8250_port mv78xx0_uart2_data[] = { | |
734 | { | |
735 | .mapbase = UART2_PHYS_BASE, | |
736 | .membase = (char *)UART2_VIRT_BASE, | |
737 | .irq = IRQ_MV78XX0_UART_2, | |
738 | .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, | |
739 | .iotype = UPIO_MEM, | |
740 | .regshift = 2, | |
741 | .uartclk = 0, | |
742 | }, { | |
743 | }, | |
744 | }; | |
745 | ||
746 | static struct resource mv78xx0_uart2_resources[] = { | |
747 | { | |
748 | .start = UART2_PHYS_BASE, | |
749 | .end = UART2_PHYS_BASE + 0xff, | |
750 | .flags = IORESOURCE_MEM, | |
751 | }, { | |
752 | .start = IRQ_MV78XX0_UART_2, | |
753 | .end = IRQ_MV78XX0_UART_2, | |
754 | .flags = IORESOURCE_IRQ, | |
755 | }, | |
756 | }; | |
757 | ||
758 | static struct platform_device mv78xx0_uart2 = { | |
759 | .name = "serial8250", | |
760 | .id = 2, | |
761 | .dev = { | |
762 | .platform_data = mv78xx0_uart2_data, | |
763 | }, | |
764 | .resource = mv78xx0_uart2_resources, | |
765 | .num_resources = ARRAY_SIZE(mv78xx0_uart2_resources), | |
766 | }; | |
767 | ||
768 | void __init mv78xx0_uart2_init(void) | |
769 | { | |
770 | platform_device_register(&mv78xx0_uart2); | |
771 | } | |
772 | ||
773 | ||
774 | /***************************************************************************** | |
775 | * UART3 | |
776 | ****************************************************************************/ | |
777 | static struct plat_serial8250_port mv78xx0_uart3_data[] = { | |
778 | { | |
779 | .mapbase = UART3_PHYS_BASE, | |
780 | .membase = (char *)UART3_VIRT_BASE, | |
781 | .irq = IRQ_MV78XX0_UART_3, | |
782 | .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, | |
783 | .iotype = UPIO_MEM, | |
784 | .regshift = 2, | |
785 | .uartclk = 0, | |
786 | }, { | |
787 | }, | |
788 | }; | |
789 | ||
790 | static struct resource mv78xx0_uart3_resources[] = { | |
791 | { | |
792 | .start = UART3_PHYS_BASE, | |
793 | .end = UART3_PHYS_BASE + 0xff, | |
794 | .flags = IORESOURCE_MEM, | |
795 | }, { | |
796 | .start = IRQ_MV78XX0_UART_3, | |
797 | .end = IRQ_MV78XX0_UART_3, | |
798 | .flags = IORESOURCE_IRQ, | |
799 | }, | |
800 | }; | |
801 | ||
802 | static struct platform_device mv78xx0_uart3 = { | |
803 | .name = "serial8250", | |
804 | .id = 3, | |
805 | .dev = { | |
806 | .platform_data = mv78xx0_uart3_data, | |
807 | }, | |
808 | .resource = mv78xx0_uart3_resources, | |
809 | .num_resources = ARRAY_SIZE(mv78xx0_uart3_resources), | |
810 | }; | |
811 | ||
812 | void __init mv78xx0_uart3_init(void) | |
813 | { | |
814 | platform_device_register(&mv78xx0_uart3); | |
815 | } | |
816 | ||
817 | ||
818 | /***************************************************************************** | |
819 | * Time handling | |
820 | ****************************************************************************/ | |
821 | static void mv78xx0_timer_init(void) | |
822 | { | |
823 | orion_time_init(IRQ_MV78XX0_TIMER_1, get_tclk()); | |
824 | } | |
825 | ||
826 | struct sys_timer mv78xx0_timer = { | |
827 | .init = mv78xx0_timer_init, | |
828 | }; | |
829 | ||
830 | ||
831 | /***************************************************************************** | |
832 | * General | |
833 | ****************************************************************************/ | |
cfdeb637 LB |
834 | static char * __init mv78xx0_id(void) |
835 | { | |
836 | u32 dev, rev; | |
837 | ||
838 | mv78xx0_pcie_id(&dev, &rev); | |
839 | ||
840 | if (dev == MV78X00_Z0_DEV_ID) { | |
841 | if (rev == MV78X00_REV_Z0) | |
842 | return "MV78X00-Z0"; | |
843 | else | |
844 | return "MV78X00-Rev-Unsupported"; | |
845 | } else if (dev == MV78100_DEV_ID) { | |
846 | if (rev == MV78100_REV_A0) | |
847 | return "MV78100-A0"; | |
662aeced LB |
848 | else if (rev == MV78100_REV_A1) |
849 | return "MV78100-A1"; | |
cfdeb637 LB |
850 | else |
851 | return "MV78100-Rev-Unsupported"; | |
852 | } else if (dev == MV78200_DEV_ID) { | |
853 | if (rev == MV78100_REV_A0) | |
854 | return "MV78200-A0"; | |
855 | else | |
856 | return "MV78200-Rev-Unsupported"; | |
857 | } else { | |
858 | return "Device-Unknown"; | |
859 | } | |
860 | } | |
861 | ||
794d15b2 SS |
862 | static int __init is_l2_writethrough(void) |
863 | { | |
864 | return !!(readl(CPU_CONTROL) & L2_WRITETHROUGH); | |
865 | } | |
866 | ||
867 | void __init mv78xx0_init(void) | |
868 | { | |
869 | int core_index; | |
870 | int hclk; | |
871 | int pclk; | |
872 | int l2clk; | |
873 | int tclk; | |
874 | ||
875 | core_index = mv78xx0_core_index(); | |
876 | hclk = get_hclk(); | |
877 | get_pclk_l2clk(hclk, core_index, &pclk, &l2clk); | |
878 | tclk = get_tclk(); | |
879 | ||
cfdeb637 LB |
880 | printk(KERN_INFO "%s ", mv78xx0_id()); |
881 | printk("core #%d, ", core_index); | |
794d15b2 SS |
882 | printk("PCLK = %dMHz, ", (pclk + 499999) / 1000000); |
883 | printk("L2 = %dMHz, ", (l2clk + 499999) / 1000000); | |
884 | printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000); | |
885 | printk("TCLK = %dMHz\n", (tclk + 499999) / 1000000); | |
886 | ||
887 | mv78xx0_setup_cpu_mbus(); | |
888 | ||
889 | #ifdef CONFIG_CACHE_FEROCEON_L2 | |
890 | feroceon_l2_init(is_l2_writethrough()); | |
891 | #endif | |
892 | ||
893 | mv78xx0_ge00_shared_data.t_clk = tclk; | |
894 | mv78xx0_ge01_shared_data.t_clk = tclk; | |
895 | mv78xx0_ge10_shared_data.t_clk = tclk; | |
896 | mv78xx0_ge11_shared_data.t_clk = tclk; | |
897 | mv78xx0_uart0_data[0].uartclk = tclk; | |
898 | mv78xx0_uart1_data[0].uartclk = tclk; | |
899 | mv78xx0_uart2_data[0].uartclk = tclk; | |
900 | mv78xx0_uart3_data[0].uartclk = tclk; | |
901 | } |