aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorKevin Hilman <khilman@deeprootsystems.com>2008-12-10 20:37:17 -0500
committerTony Lindgren <tony@atomide.com>2008-12-10 20:37:17 -0500
commit917fa280e5e99edcae44a34feab295a59922d16c (patch)
treebcd3aff12a5a40b1be58eced9bdb2f7a43922f2f /arch/arm/mach-omap2
parent90c62bf08f5823faa097271f3346a9142769b9ac (diff)
omap mmc: force MMC module reset on boot
The bootloader may leave the MMC in a state which prevents hitting retention. Even when MMC is not compiled in, each MMC module needs to be forced into reset. Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/devices.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 6e03272b0521..9d7216ff6c9f 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -14,6 +14,7 @@
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>
@@ -299,6 +300,89 @@ static inline void omap_init_sha1_md5(void) { }
299 300
300/*-------------------------------------------------------------------------*/ 301/*-------------------------------------------------------------------------*/
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
310static 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 **/
328static 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
383static inline void omap_hsmmc_reset(void) {}
384#endif
385
302#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ 386#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
303 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) 387 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
304 388
@@ -418,6 +502,7 @@ static int __init omap2_init_devices(void)
418 /* please keep these calls, and their implementations above, 502 /* please keep these calls, and their implementations above,
419 * in alphabetical order so they're easier to sort through. 503 * in alphabetical order so they're easier to sort through.
420 */ 504 */
505 omap_hsmmc_reset();
421 omap_init_mbox(); 506 omap_init_mbox();
422 omap_init_mcspi(); 507 omap_init_mcspi();
423 omap_hdq_init(); 508 omap_hdq_init();