diff options
Diffstat (limited to 'arch/arm/mach-omap2/devices.c')
-rw-r--r-- | arch/arm/mach-omap2/devices.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 90af2ac469aa..9d7216ff6c9f 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -14,16 +14,19 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/clk.h> | ||
17 | 18 | ||
18 | #include <mach/hardware.h> | 19 | #include <mach/hardware.h> |
19 | #include <asm/mach-types.h> | 20 | #include <asm/mach-types.h> |
20 | #include <asm/mach/map.h> | 21 | #include <asm/mach/map.h> |
21 | 22 | ||
23 | #include <mach/control.h> | ||
22 | #include <mach/tc.h> | 24 | #include <mach/tc.h> |
23 | #include <mach/board.h> | 25 | #include <mach/board.h> |
24 | #include <mach/mux.h> | 26 | #include <mach/mux.h> |
25 | #include <mach/gpio.h> | 27 | #include <mach/gpio.h> |
26 | #include <mach/eac.h> | 28 | #include <mach/eac.h> |
29 | #include <mach/mmc.h> | ||
27 | 30 | ||
28 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) | 31 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) |
29 | #define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) | 32 | #define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) |
@@ -295,6 +298,171 @@ static void omap_init_sha1_md5(void) | |||
295 | static inline void omap_init_sha1_md5(void) { } | 298 | static inline void omap_init_sha1_md5(void) { } |
296 | #endif | 299 | #endif |
297 | 300 | ||
301 | /*-------------------------------------------------------------------------*/ | ||
302 | |||
303 | #ifdef CONFIG_ARCH_OMAP3 | ||
304 | |||
305 | #define MMCHS_SYSCONFIG 0x0010 | ||
306 | #define MMCHS_SYSCONFIG_SWRESET (1 << 1) | ||
307 | #define MMCHS_SYSSTATUS 0x0014 | ||
308 | #define MMCHS_SYSSTATUS_RESETDONE (1 << 0) | ||
309 | |||
310 | static struct platform_device dummy_pdev = { | ||
311 | .dev = { | ||
312 | .bus = &platform_bus_type, | ||
313 | }, | ||
314 | }; | ||
315 | |||
316 | /** | ||
317 | * omap_hsmmc_reset() - Full reset of each HS-MMC controller | ||
318 | * | ||
319 | * Ensure that each MMC controller is fully reset. Controllers | ||
320 | * left in an unknown state (by bootloader) may prevent retention | ||
321 | * or OFF-mode. This is especially important in cases where the | ||
322 | * MMC driver is not enabled, _or_ built as a module. | ||
323 | * | ||
324 | * In order for reset to work, interface, functional and debounce | ||
325 | * clocks must be enabled. The debounce clock comes from func_32k_clk | ||
326 | * and is not under SW control, so we only enable i- and f-clocks. | ||
327 | **/ | ||
328 | static void __init omap_hsmmc_reset(void) | ||
329 | { | ||
330 | u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC : | ||
331 | OMAP24XX_NR_MMC; | ||
332 | |||
333 | for (i = 0; i < nr_controllers; i++) { | ||
334 | u32 v, base = 0; | ||
335 | struct clk *iclk, *fclk; | ||
336 | struct device *dev = &dummy_pdev.dev; | ||
337 | |||
338 | switch (i) { | ||
339 | case 0: | ||
340 | base = OMAP2_MMC1_BASE; | ||
341 | break; | ||
342 | case 1: | ||
343 | base = OMAP2_MMC2_BASE; | ||
344 | break; | ||
345 | case 2: | ||
346 | base = OMAP3_MMC3_BASE; | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | dummy_pdev.id = i; | ||
351 | iclk = clk_get(dev, "mmchs_ick"); | ||
352 | if (iclk && clk_enable(iclk)) | ||
353 | iclk = NULL; | ||
354 | |||
355 | fclk = clk_get(dev, "mmchs_fck"); | ||
356 | if (fclk && clk_enable(fclk)) | ||
357 | fclk = NULL; | ||
358 | |||
359 | if (!iclk || !fclk) { | ||
360 | printk(KERN_WARNING | ||
361 | "%s: Unable to enable clocks for MMC%d, " | ||
362 | "cannot reset.\n", __func__, i); | ||
363 | break; | ||
364 | } | ||
365 | |||
366 | omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG); | ||
367 | v = omap_readl(base + MMCHS_SYSSTATUS); | ||
368 | while (!(omap_readl(base + MMCHS_SYSSTATUS) & | ||
369 | MMCHS_SYSSTATUS_RESETDONE)) | ||
370 | cpu_relax(); | ||
371 | |||
372 | if (fclk) { | ||
373 | clk_disable(fclk); | ||
374 | clk_put(fclk); | ||
375 | } | ||
376 | if (iclk) { | ||
377 | clk_disable(iclk); | ||
378 | clk_put(iclk); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | #else | ||
383 | static inline void omap_hsmmc_reset(void) {} | ||
384 | #endif | ||
385 | |||
386 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ | ||
387 | defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) | ||
388 | |||
389 | static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller, | ||
390 | int controller_nr) | ||
391 | { | ||
392 | if (cpu_is_omap2420() && controller_nr == 0) { | ||
393 | omap_cfg_reg(H18_24XX_MMC_CMD); | ||
394 | omap_cfg_reg(H15_24XX_MMC_CLKI); | ||
395 | omap_cfg_reg(G19_24XX_MMC_CLKO); | ||
396 | omap_cfg_reg(F20_24XX_MMC_DAT0); | ||
397 | omap_cfg_reg(F19_24XX_MMC_DAT_DIR0); | ||
398 | omap_cfg_reg(G18_24XX_MMC_CMD_DIR); | ||
399 | if (mmc_controller->slots[0].wires == 4) { | ||
400 | omap_cfg_reg(H14_24XX_MMC_DAT1); | ||
401 | omap_cfg_reg(E19_24XX_MMC_DAT2); | ||
402 | omap_cfg_reg(D19_24XX_MMC_DAT3); | ||
403 | omap_cfg_reg(E20_24XX_MMC_DAT_DIR1); | ||
404 | omap_cfg_reg(F18_24XX_MMC_DAT_DIR2); | ||
405 | omap_cfg_reg(E18_24XX_MMC_DAT_DIR3); | ||
406 | } | ||
407 | |||
408 | /* | ||
409 | * Use internal loop-back in MMC/SDIO Module Input Clock | ||
410 | * selection | ||
411 | */ | ||
412 | if (mmc_controller->slots[0].internal_clock) { | ||
413 | u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); | ||
414 | v |= (1 << 24); | ||
415 | omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | |||
420 | void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, | ||
421 | int nr_controllers) | ||
422 | { | ||
423 | int i; | ||
424 | |||
425 | for (i = 0; i < nr_controllers; i++) { | ||
426 | unsigned long base, size; | ||
427 | unsigned int irq = 0; | ||
428 | |||
429 | if (!mmc_data[i]) | ||
430 | continue; | ||
431 | |||
432 | omap2_mmc_mux(mmc_data[i], i); | ||
433 | |||
434 | switch (i) { | ||
435 | case 0: | ||
436 | base = OMAP2_MMC1_BASE; | ||
437 | irq = INT_24XX_MMC_IRQ; | ||
438 | break; | ||
439 | case 1: | ||
440 | base = OMAP2_MMC2_BASE; | ||
441 | irq = INT_24XX_MMC2_IRQ; | ||
442 | break; | ||
443 | case 2: | ||
444 | if (!cpu_is_omap34xx()) | ||
445 | return; | ||
446 | base = OMAP3_MMC3_BASE; | ||
447 | irq = INT_34XX_MMC3_IRQ; | ||
448 | break; | ||
449 | default: | ||
450 | continue; | ||
451 | } | ||
452 | |||
453 | if (cpu_is_omap2420()) | ||
454 | size = OMAP2420_MMC_SIZE; | ||
455 | else | ||
456 | size = HSMMC_SIZE; | ||
457 | |||
458 | omap_mmc_add(i, base, size, irq, mmc_data[i]); | ||
459 | }; | ||
460 | } | ||
461 | |||
462 | #endif | ||
463 | |||
464 | /*-------------------------------------------------------------------------*/ | ||
465 | |||
298 | #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) | 466 | #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) |
299 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) | 467 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) |
300 | #define OMAP_HDQ_BASE 0x480B2000 | 468 | #define OMAP_HDQ_BASE 0x480B2000 |
@@ -334,6 +502,7 @@ static int __init omap2_init_devices(void) | |||
334 | /* please keep these calls, and their implementations above, | 502 | /* please keep these calls, and their implementations above, |
335 | * in alphabetical order so they're easier to sort through. | 503 | * in alphabetical order so they're easier to sort through. |
336 | */ | 504 | */ |
505 | omap_hsmmc_reset(); | ||
337 | omap_init_mbox(); | 506 | omap_init_mbox(); |
338 | omap_init_mcspi(); | 507 | omap_init_mcspi(); |
339 | omap_hdq_init(); | 508 | omap_hdq_init(); |