blob: d5f2a8118df3f7db3d9072b830d32b765e7dd36f [file] [log] [blame]
Tony Lindgren1dbae812005-11-10 14:26:51 +00001/*
2 * linux/arch/arm/mach-omap2/devices.c
3 *
4 * OMAP2 platform device setup/initialization
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
Tony Lindgren1dbae812005-11-10 14:26:51 +000012#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
Russell Kingfced80c2008-09-06 12:10:45 +010016#include <linux/io.h>
Kevin Hilman917fa282008-12-10 17:37:17 -080017#include <linux/clk.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000018
Russell Kinga09e64f2008-08-05 16:14:15 +010019#include <mach/hardware.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000020#include <asm/mach-types.h>
21#include <asm/mach/map.h>
22
Tony Lindgren90c62bf2008-12-10 17:37:17 -080023#include <mach/control.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010024#include <mach/tc.h>
25#include <mach/board.h>
26#include <mach/mux.h>
27#include <mach/gpio.h>
Tony Lindgren646e3ed2008-10-06 15:49:36 +030028#include <mach/eac.h>
Tony Lindgrend8874662008-12-10 17:37:16 -080029#include <mach/mmc.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000030
Hiroshi DOYU6c20a682009-03-23 18:07:23 -070031#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
Tony Lindgrenc40fae952006-12-07 13:58:10 -080032
Hiroshi DOYU6c20a682009-03-23 18:07:23 -070033#define MBOX_REG_SIZE 0x120
34
35static struct resource omap2_mbox_resources[] = {
Tony Lindgrenc40fae952006-12-07 13:58:10 -080036 {
Hiroshi DOYU6c20a682009-03-23 18:07:23 -070037 .start = OMAP24XX_MAILBOX_BASE,
38 .end = OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
Tony Lindgrenc40fae952006-12-07 13:58:10 -080039 .flags = IORESOURCE_MEM,
40 },
41 {
42 .start = INT_24XX_MAIL_U0_MPU,
43 .flags = IORESOURCE_IRQ,
44 },
45 {
46 .start = INT_24XX_MAIL_U3_MPU,
47 .flags = IORESOURCE_IRQ,
48 },
49};
50
Hiroshi DOYU6c20a682009-03-23 18:07:23 -070051static struct resource omap3_mbox_resources[] = {
52 {
53 .start = OMAP34XX_MAILBOX_BASE,
54 .end = OMAP34XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
55 .flags = IORESOURCE_MEM,
56 },
57 {
58 .start = INT_24XX_MAIL_U0_MPU,
59 .flags = IORESOURCE_IRQ,
60 },
61};
62
Tony Lindgrenc40fae952006-12-07 13:58:10 -080063static struct platform_device mbox_device = {
64 .name = "mailbox",
65 .id = -1,
Tony Lindgrenc40fae952006-12-07 13:58:10 -080066};
67
68static inline void omap_init_mbox(void)
69{
Hiroshi DOYU6c20a682009-03-23 18:07:23 -070070 if (cpu_is_omap2420()) {
71 mbox_device.num_resources = ARRAY_SIZE(omap2_mbox_resources);
72 mbox_device.resource = omap2_mbox_resources;
73 } else if (cpu_is_omap3430()) {
74 mbox_device.num_resources = ARRAY_SIZE(omap3_mbox_resources);
75 mbox_device.resource = omap3_mbox_resources;
76 } else {
77 pr_err("%s: platform not supported\n", __func__);
78 return;
79 }
Tony Lindgrenc40fae952006-12-07 13:58:10 -080080 platform_device_register(&mbox_device);
81}
82#else
83static inline void omap_init_mbox(void) { }
Hiroshi DOYU6c20a682009-03-23 18:07:23 -070084#endif /* CONFIG_OMAP_MBOX_FWK */
Tony Lindgrenc40fae952006-12-07 13:58:10 -080085
Tony Lindgren9b6553c2006-04-02 17:46:30 +010086#if defined(CONFIG_OMAP_STI)
87
Tony Lindgren646e3ed2008-10-06 15:49:36 +030088#if defined(CONFIG_ARCH_OMAP2)
89
90#define OMAP2_STI_BASE 0x48068000
Tony Lindgren9b6553c2006-04-02 17:46:30 +010091#define OMAP2_STI_CHANNEL_BASE 0x54000000
92#define OMAP2_STI_IRQ 4
93
94static struct resource sti_resources[] = {
95 {
96 .start = OMAP2_STI_BASE,
97 .end = OMAP2_STI_BASE + 0x7ff,
98 .flags = IORESOURCE_MEM,
99 },
100 {
101 .start = OMAP2_STI_CHANNEL_BASE,
102 .end = OMAP2_STI_CHANNEL_BASE + SZ_64K - 1,
103 .flags = IORESOURCE_MEM,
104 },
105 {
106 .start = OMAP2_STI_IRQ,
107 .flags = IORESOURCE_IRQ,
108 }
109};
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300110#elif defined(CONFIG_ARCH_OMAP3)
111
112#define OMAP3_SDTI_BASE 0x54500000
113#define OMAP3_SDTI_CHANNEL_BASE 0x54600000
114
115static struct resource sti_resources[] = {
116 {
117 .start = OMAP3_SDTI_BASE,
118 .end = OMAP3_SDTI_BASE + 0xFFF,
119 .flags = IORESOURCE_MEM,
120 },
121 {
122 .start = OMAP3_SDTI_CHANNEL_BASE,
123 .end = OMAP3_SDTI_CHANNEL_BASE + SZ_1M - 1,
124 .flags = IORESOURCE_MEM,
125 }
126};
127
128#endif
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100129
130static struct platform_device sti_device = {
131 .name = "sti",
132 .id = -1,
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100133 .num_resources = ARRAY_SIZE(sti_resources),
134 .resource = sti_resources,
135};
136
137static inline void omap_init_sti(void)
138{
139 platform_device_register(&sti_device);
140}
141#else
142static inline void omap_init_sti(void) {}
143#endif
144
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300145#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700146
Russell Kinga09e64f2008-08-05 16:14:15 +0100147#include <mach/mcspi.h>
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700148
149#define OMAP2_MCSPI1_BASE 0x48098000
150#define OMAP2_MCSPI2_BASE 0x4809a000
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300151#define OMAP2_MCSPI3_BASE 0x480b8000
152#define OMAP2_MCSPI4_BASE 0x480ba000
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700153
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700154static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700155 .num_cs = 4,
156};
157
Tony Lindgrenc40fae952006-12-07 13:58:10 -0800158static struct resource omap2_mcspi1_resources[] = {
159 {
160 .start = OMAP2_MCSPI1_BASE,
161 .end = OMAP2_MCSPI1_BASE + 0xff,
162 .flags = IORESOURCE_MEM,
163 },
164};
165
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300166static struct platform_device omap2_mcspi1 = {
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700167 .name = "omap2_mcspi",
168 .id = 1,
Tony Lindgrenc40fae952006-12-07 13:58:10 -0800169 .num_resources = ARRAY_SIZE(omap2_mcspi1_resources),
170 .resource = omap2_mcspi1_resources,
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700171 .dev = {
172 .platform_data = &omap2_mcspi1_config,
173 },
174};
175
176static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700177 .num_cs = 2,
178};
179
Tony Lindgrenc40fae952006-12-07 13:58:10 -0800180static struct resource omap2_mcspi2_resources[] = {
181 {
182 .start = OMAP2_MCSPI2_BASE,
183 .end = OMAP2_MCSPI2_BASE + 0xff,
184 .flags = IORESOURCE_MEM,
185 },
186};
187
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300188static struct platform_device omap2_mcspi2 = {
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700189 .name = "omap2_mcspi",
190 .id = 2,
Tony Lindgrenc40fae952006-12-07 13:58:10 -0800191 .num_resources = ARRAY_SIZE(omap2_mcspi2_resources),
192 .resource = omap2_mcspi2_resources,
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700193 .dev = {
194 .platform_data = &omap2_mcspi2_config,
195 },
196};
197
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300198#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
199static struct omap2_mcspi_platform_config omap2_mcspi3_config = {
200 .num_cs = 2,
201};
202
203static struct resource omap2_mcspi3_resources[] = {
204 {
205 .start = OMAP2_MCSPI3_BASE,
206 .end = OMAP2_MCSPI3_BASE + 0xff,
207 .flags = IORESOURCE_MEM,
208 },
209};
210
211static struct platform_device omap2_mcspi3 = {
212 .name = "omap2_mcspi",
213 .id = 3,
214 .num_resources = ARRAY_SIZE(omap2_mcspi3_resources),
215 .resource = omap2_mcspi3_resources,
216 .dev = {
217 .platform_data = &omap2_mcspi3_config,
218 },
219};
220#endif
221
222#ifdef CONFIG_ARCH_OMAP3
223static struct omap2_mcspi_platform_config omap2_mcspi4_config = {
224 .num_cs = 1,
225};
226
227static struct resource omap2_mcspi4_resources[] = {
228 {
229 .start = OMAP2_MCSPI4_BASE,
230 .end = OMAP2_MCSPI4_BASE + 0xff,
231 .flags = IORESOURCE_MEM,
232 },
233};
234
235static struct platform_device omap2_mcspi4 = {
236 .name = "omap2_mcspi",
237 .id = 4,
238 .num_resources = ARRAY_SIZE(omap2_mcspi4_resources),
239 .resource = omap2_mcspi4_resources,
240 .dev = {
241 .platform_data = &omap2_mcspi4_config,
242 },
243};
244#endif
245
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700246static void omap_init_mcspi(void)
247{
248 platform_device_register(&omap2_mcspi1);
249 platform_device_register(&omap2_mcspi2);
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300250#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
251 platform_device_register(&omap2_mcspi3);
252#endif
253#ifdef CONFIG_ARCH_OMAP3
254 platform_device_register(&omap2_mcspi4);
255#endif
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700256}
257
258#else
259static inline void omap_init_mcspi(void) {}
260#endif
261
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300262#ifdef CONFIG_SND_OMAP24XX_EAC
263
264#define OMAP2_EAC_BASE 0x48090000
265
266static struct resource omap2_eac_resources[] = {
267 {
268 .start = OMAP2_EAC_BASE,
269 .end = OMAP2_EAC_BASE + 0x109,
270 .flags = IORESOURCE_MEM,
271 },
272};
273
274static struct platform_device omap2_eac_device = {
275 .name = "omap24xx-eac",
276 .id = -1,
277 .num_resources = ARRAY_SIZE(omap2_eac_resources),
278 .resource = omap2_eac_resources,
279 .dev = {
280 .platform_data = NULL,
281 },
282};
283
284void omap_init_eac(struct eac_platform_data *pdata)
285{
286 omap2_eac_device.dev.platform_data = pdata;
287 platform_device_register(&omap2_eac_device);
288}
289
290#else
291void omap_init_eac(struct eac_platform_data *pdata) {}
292#endif
293
294#ifdef CONFIG_OMAP_SHA1_MD5
295static struct resource sha1_md5_resources[] = {
296 {
297 .start = OMAP24XX_SEC_SHA1MD5_BASE,
298 .end = OMAP24XX_SEC_SHA1MD5_BASE + 0x64,
299 .flags = IORESOURCE_MEM,
300 },
301 {
302 .start = INT_24XX_SHA1MD5,
303 .flags = IORESOURCE_IRQ,
304 }
305};
306
307static struct platform_device sha1_md5_device = {
308 .name = "OMAP SHA1/MD5",
309 .id = -1,
310 .num_resources = ARRAY_SIZE(sha1_md5_resources),
311 .resource = sha1_md5_resources,
312};
313
314static void omap_init_sha1_md5(void)
315{
316 platform_device_register(&sha1_md5_device);
317}
318#else
319static inline void omap_init_sha1_md5(void) { }
320#endif
321
Tony Lindgrend8874662008-12-10 17:37:16 -0800322/*-------------------------------------------------------------------------*/
323
Kevin Hilman917fa282008-12-10 17:37:17 -0800324#ifdef CONFIG_ARCH_OMAP3
325
326#define MMCHS_SYSCONFIG 0x0010
327#define MMCHS_SYSCONFIG_SWRESET (1 << 1)
328#define MMCHS_SYSSTATUS 0x0014
329#define MMCHS_SYSSTATUS_RESETDONE (1 << 0)
330
331static struct platform_device dummy_pdev = {
332 .dev = {
333 .bus = &platform_bus_type,
334 },
335};
336
337/**
338 * omap_hsmmc_reset() - Full reset of each HS-MMC controller
339 *
340 * Ensure that each MMC controller is fully reset. Controllers
341 * left in an unknown state (by bootloader) may prevent retention
342 * or OFF-mode. This is especially important in cases where the
343 * MMC driver is not enabled, _or_ built as a module.
344 *
345 * In order for reset to work, interface, functional and debounce
346 * clocks must be enabled. The debounce clock comes from func_32k_clk
347 * and is not under SW control, so we only enable i- and f-clocks.
348 **/
349static void __init omap_hsmmc_reset(void)
350{
351 u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC :
352 OMAP24XX_NR_MMC;
353
354 for (i = 0; i < nr_controllers; i++) {
355 u32 v, base = 0;
356 struct clk *iclk, *fclk;
357 struct device *dev = &dummy_pdev.dev;
358
359 switch (i) {
360 case 0:
361 base = OMAP2_MMC1_BASE;
362 break;
363 case 1:
364 base = OMAP2_MMC2_BASE;
365 break;
366 case 2:
367 base = OMAP3_MMC3_BASE;
368 break;
369 }
370
371 dummy_pdev.id = i;
372 iclk = clk_get(dev, "mmchs_ick");
373 if (iclk && clk_enable(iclk))
374 iclk = NULL;
375
376 fclk = clk_get(dev, "mmchs_fck");
377 if (fclk && clk_enable(fclk))
378 fclk = NULL;
379
380 if (!iclk || !fclk) {
381 printk(KERN_WARNING
382 "%s: Unable to enable clocks for MMC%d, "
383 "cannot reset.\n", __func__, i);
384 break;
385 }
386
387 omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
388 v = omap_readl(base + MMCHS_SYSSTATUS);
389 while (!(omap_readl(base + MMCHS_SYSSTATUS) &
390 MMCHS_SYSSTATUS_RESETDONE))
391 cpu_relax();
392
393 if (fclk) {
394 clk_disable(fclk);
395 clk_put(fclk);
396 }
397 if (iclk) {
398 clk_disable(iclk);
399 clk_put(iclk);
400 }
401 }
402}
403#else
404static inline void omap_hsmmc_reset(void) {}
405#endif
406
Tony Lindgrend8874662008-12-10 17:37:16 -0800407#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
408 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
409
410static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
411 int controller_nr)
412{
413 if (cpu_is_omap2420() && controller_nr == 0) {
414 omap_cfg_reg(H18_24XX_MMC_CMD);
415 omap_cfg_reg(H15_24XX_MMC_CLKI);
416 omap_cfg_reg(G19_24XX_MMC_CLKO);
417 omap_cfg_reg(F20_24XX_MMC_DAT0);
418 omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
419 omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
Tony Lindgren90c62bf2008-12-10 17:37:17 -0800420 if (mmc_controller->slots[0].wires == 4) {
Tony Lindgrend8874662008-12-10 17:37:16 -0800421 omap_cfg_reg(H14_24XX_MMC_DAT1);
422 omap_cfg_reg(E19_24XX_MMC_DAT2);
423 omap_cfg_reg(D19_24XX_MMC_DAT3);
424 omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
425 omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
426 omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
427 }
428
429 /*
430 * Use internal loop-back in MMC/SDIO Module Input Clock
431 * selection
432 */
433 if (mmc_controller->slots[0].internal_clock) {
434 u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
435 v |= (1 << 24);
436 omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
437 }
438 }
439}
440
441void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
442 int nr_controllers)
443{
444 int i;
Tony Lindgren0dffb5c2009-01-29 08:57:16 -0800445 char *name;
Tony Lindgrend8874662008-12-10 17:37:16 -0800446
447 for (i = 0; i < nr_controllers; i++) {
448 unsigned long base, size;
449 unsigned int irq = 0;
450
451 if (!mmc_data[i])
452 continue;
453
454 omap2_mmc_mux(mmc_data[i], i);
455
456 switch (i) {
457 case 0:
458 base = OMAP2_MMC1_BASE;
459 irq = INT_24XX_MMC_IRQ;
460 break;
461 case 1:
462 base = OMAP2_MMC2_BASE;
463 irq = INT_24XX_MMC2_IRQ;
464 break;
465 case 2:
466 if (!cpu_is_omap34xx())
467 return;
468 base = OMAP3_MMC3_BASE;
469 irq = INT_34XX_MMC3_IRQ;
470 break;
471 default:
472 continue;
473 }
474
Tony Lindgren0dffb5c2009-01-29 08:57:16 -0800475 if (cpu_is_omap2420()) {
Tony Lindgrend8874662008-12-10 17:37:16 -0800476 size = OMAP2420_MMC_SIZE;
Tony Lindgren0dffb5c2009-01-29 08:57:16 -0800477 name = "mmci-omap";
478 } else {
Tony Lindgrend8874662008-12-10 17:37:16 -0800479 size = HSMMC_SIZE;
Tony Lindgren0dffb5c2009-01-29 08:57:16 -0800480 name = "mmci-omap-hs";
481 }
482 omap_mmc_add(name, i, base, size, irq, mmc_data[i]);
Tony Lindgrend8874662008-12-10 17:37:16 -0800483 };
484}
485
486#endif
487
488/*-------------------------------------------------------------------------*/
489
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300490#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
491#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
492#define OMAP_HDQ_BASE 0x480B2000
493#endif
494static struct resource omap_hdq_resources[] = {
495 {
496 .start = OMAP_HDQ_BASE,
497 .end = OMAP_HDQ_BASE + 0x1C,
498 .flags = IORESOURCE_MEM,
499 },
500 {
501 .start = INT_24XX_HDQ_IRQ,
502 .flags = IORESOURCE_IRQ,
503 },
504};
505static struct platform_device omap_hdq_dev = {
506 .name = "omap_hdq",
507 .id = 0,
508 .dev = {
509 .platform_data = NULL,
510 },
511 .num_resources = ARRAY_SIZE(omap_hdq_resources),
512 .resource = omap_hdq_resources,
513};
514static inline void omap_hdq_init(void)
515{
516 (void) platform_device_register(&omap_hdq_dev);
517}
518#else
519static inline void omap_hdq_init(void) {}
520#endif
521
Tony Lindgren1dbae812005-11-10 14:26:51 +0000522/*-------------------------------------------------------------------------*/
523
524static int __init omap2_init_devices(void)
525{
526 /* please keep these calls, and their implementations above,
527 * in alphabetical order so they're easier to sort through.
528 */
Kevin Hilman917fa282008-12-10 17:37:17 -0800529 omap_hsmmc_reset();
Tony Lindgrenc40fae952006-12-07 13:58:10 -0800530 omap_init_mbox();
Juha Yrjolaed7eb9d2006-06-26 16:16:10 -0700531 omap_init_mcspi();
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300532 omap_hdq_init();
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100533 omap_init_sti();
Tony Lindgren646e3ed2008-10-06 15:49:36 +0300534 omap_init_sha1_md5();
Tony Lindgren1dbae812005-11-10 14:26:51 +0000535
536 return 0;
537}
538arch_initcall(omap2_init_devices);