aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorAndy Shevchenko <ext-andriy.shevchenko@nokia.com>2011-05-06 05:14:06 -0400
committerChris Ball <cjb@laptop.org>2011-07-21 10:35:03 -0400
commit5934df2f10a48d048fafe0d3c8b242a7c9106e69 (patch)
tree0a7321ab6a3a55187284cb7d72fcc1342acebb96 /drivers/mmc
parente0c7f99b863b485ad0cde371ea1f62ec8ff70c5d (diff)
mmc: omap_hsmmc: fix a few bugs when setting the clock divisor
There are two pieces of code which are similar, but not the same. Each of them contains a bug. The SYSCTL register should be read before writing to it in omap_hsmmc_context_restore() to retain the state of the reserved bits. Before setting the clock divisor and DTO bits the value from the SYSCTL register should be masked properly. We were lucky to have no problems with DTO bits. So, make sure we have clear DTO bits properly in omap_hsmmc_set_ios(). Additionally get rid of msleep(1). The actual time is rarely higher than 30us on OMAP 3630. The resulting pieces of code are refactored into the omap_hsmmc_set_clock() function. Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/omap_hsmmc.c59
1 files changed, 28 insertions, 31 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 2645bdc94dae..bda284ba1303 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -612,6 +612,32 @@ static u16 calc_divisor(struct mmc_ios *ios)
612 return dsor; 612 return dsor;
613} 613}
614 614
615static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
616{
617 struct mmc_ios *ios = &host->mmc->ios;
618 unsigned long regval;
619 unsigned long timeout;
620
621 dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
622
623 omap_hsmmc_stop_clock(host);
624
625 regval = OMAP_HSMMC_READ(host->base, SYSCTL);
626 regval = regval & ~(CLKD_MASK | DTO_MASK);
627 regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
628 OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
629 OMAP_HSMMC_WRITE(host->base, SYSCTL,
630 OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
631
632 /* Wait till the ICS bit is set */
633 timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
634 while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
635 && time_before(jiffies, timeout))
636 cpu_relax();
637
638 omap_hsmmc_start_clock(host);
639}
640
615#ifdef CONFIG_PM 641#ifdef CONFIG_PM
616 642
617/* 643/*
@@ -702,19 +728,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
702 break; 728 break;
703 } 729 }
704 730
705 omap_hsmmc_stop_clock(host); 731 omap_hsmmc_set_clock(host);
706
707 OMAP_HSMMC_WRITE(host->base, SYSCTL,
708 (calc_divisor(ios) << 6) | (DTO << 16));
709 OMAP_HSMMC_WRITE(host->base, SYSCTL,
710 OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
711
712 timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
713 while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
714 && time_before(jiffies, timeout))
715 ;
716
717 omap_hsmmc_start_clock(host);
718 732
719 con = OMAP_HSMMC_READ(host->base, CON); 733 con = OMAP_HSMMC_READ(host->base, CON);
720 if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) 734 if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
@@ -1614,8 +1628,6 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
1614static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 1628static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1615{ 1629{
1616 struct omap_hsmmc_host *host = mmc_priv(mmc); 1630 struct omap_hsmmc_host *host = mmc_priv(mmc);
1617 unsigned long regval;
1618 unsigned long timeout;
1619 u32 con; 1631 u32 con;
1620 int do_send_init_stream = 0; 1632 int do_send_init_stream = 0;
1621 1633
@@ -1677,22 +1689,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1677 } 1689 }
1678 } 1690 }
1679 1691
1680 omap_hsmmc_stop_clock(host); 1692 omap_hsmmc_set_clock(host);
1681
1682 regval = OMAP_HSMMC_READ(host->base, SYSCTL);
1683 regval = regval & ~(CLKD_MASK);
1684 regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
1685 OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
1686 OMAP_HSMMC_WRITE(host->base, SYSCTL,
1687 OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
1688
1689 /* Wait till the ICS bit is set */
1690 timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
1691 while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
1692 && time_before(jiffies, timeout))
1693 msleep(1);
1694
1695 omap_hsmmc_start_clock(host);
1696 1693
1697 if (do_send_init_stream) 1694 if (do_send_init_stream)
1698 send_init_stream(host); 1695 send_init_stream(host);