Skip to content

Commit

Permalink
mmc: sdhci-esdhc: move common esdhc_set_clock to platform driver
Browse files Browse the repository at this point in the history
We need a lot of imx6 specific things into common esdhc_set_clock
for support SD3.0 and eMMC DDR mode which is not needed for power pc
platforms, so esdhc_set_clock seems not so common anymore.

Instead of keeping add platform specfics things into this common API,
we choose to move that code into platform driver itself to handle.
This can also exclude the dependency between imx and power pc on this
headfile and is easy for maintain in the future.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
  • Loading branch information
Dong Aisheng authored and Chris Ball committed Sep 26, 2013
1 parent c0e5512 commit d31fc00
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 41 deletions.
35 changes: 33 additions & 2 deletions drivers/mmc/host/sdhci-esdhc-imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,39 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);

esdhc_set_clock(host, clock, clk_get_rate(pltfm_host->clk));
unsigned int host_clock = clk_get_rate(pltfm_host->clk);
int pre_div = 2;
int div = 1;
u32 temp;

if (clock == 0)
goto out;

temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);

while (host_clock / pre_div / 16 > clock && pre_div < 256)
pre_div *= 2;

while (host_clock / pre_div / div > clock && div < 16)
div++;

dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
clock, host_clock / pre_div / div);

pre_div >>= 1;
div--;

temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| (div << ESDHC_DIVIDER_SHIFT)
| (pre_div << ESDHC_PREDIV_SHIFT));
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
mdelay(1);
out:
host->clock = clock;
}

static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
Expand Down
37 changes: 0 additions & 37 deletions drivers/mmc/host/sdhci-esdhc.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,41 +49,4 @@

#define ESDHC_HOST_CONTROL_RES 0x05

static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock,
unsigned int host_clock)
{
int pre_div = 2;
int div = 1;
u32 temp;

if (clock == 0)
goto out;

temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);

while (host_clock / pre_div / 16 > clock && pre_div < 256)
pre_div *= 2;

while (host_clock / pre_div / div > clock && div < 16)
div++;

dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
clock, host_clock / pre_div / div);

pre_div >>= 1;
div--;

temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| (div << ESDHC_DIVIDER_SHIFT)
| (pre_div << ESDHC_PREDIV_SHIFT));
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
mdelay(1);
out:
host->clock = clock;
}

#endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
35 changes: 33 additions & 2 deletions drivers/mmc/host/sdhci-of-esdhc.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,14 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)

static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
{

int pre_div = 2;
int div = 1;
u32 temp;

if (clock == 0)
goto out;

/* Workaround to reduce the clock frequency for p1010 esdhc */
if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
if (clock > 20000000)
Expand All @@ -207,8 +215,31 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
clock -= 5000000;
}

/* Set the clock */
esdhc_set_clock(host, clock, host->max_clk);
temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);

while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
pre_div *= 2;

while (host->max_clk / pre_div / div > clock && div < 16)
div++;

dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
clock, host_clock / pre_div / div);

pre_div >>= 1;
div--;

temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| (div << ESDHC_DIVIDER_SHIFT)
| (pre_div << ESDHC_PREDIV_SHIFT));
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
mdelay(1);
out:
host->clock = clock;
}

#ifdef CONFIG_PM
Expand Down

0 comments on commit d31fc00

Please sign in to comment.