Skip to content

Commit

Permalink
mmc: tmio: add callbacks to enable-update and disable the interface c…
Browse files Browse the repository at this point in the history
…lock

Every time the clock is enabled after possibly being disabled, we have
to re-read its frequency and update our configuration.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
  • Loading branch information
Guennadi Liakhovetski authored and Chris Ball committed Jul 21, 2012
1 parent e0337cc commit 8c102a9
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
35 changes: 32 additions & 3 deletions drivers/mmc/host/tmio_mmc_pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,22 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
mmc_request_done(mmc, mrq);
}

static int tmio_mmc_clk_update(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
struct tmio_mmc_data *pdata = host->pdata;
int ret;

if (!pdata->clk_enable)
return -ENOTSUPP;

ret = pdata->clk_enable(host->pdev, &mmc->f_max);
if (!ret)
mmc->f_min = mmc->f_max / 512;

return ret;
}

/* Set MMC clock / power.
* Note: This controller uses a simple divider scheme therefore it cannot
* run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
Expand Down Expand Up @@ -798,6 +814,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
*/
if (ios->power_mode == MMC_POWER_ON && ios->clock) {
if (!host->power) {
tmio_mmc_clk_update(mmc);
pm_runtime_get_sync(dev);
host->power = true;
}
Expand All @@ -811,9 +828,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
host->set_pwr(host->pdev, 0);
if (host->power) {
struct tmio_mmc_data *pdata = host->pdata;
tmio_mmc_clk_stop(host);
host->power = false;
pm_runtime_put(dev);
if (pdata->clk_disable)
pdata->clk_disable(host->pdev);
}
}

Expand Down Expand Up @@ -907,8 +927,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,

mmc->ops = &tmio_mmc_ops;
mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
mmc->f_max = pdata->hclk;
mmc->f_min = mmc->f_max / 512;
mmc->max_segs = 32;
mmc->max_blk_size = 512;
mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
Expand All @@ -930,6 +948,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
if (ret < 0)
goto pm_disable;

if (tmio_mmc_clk_update(mmc) < 0) {
mmc->f_max = pdata->hclk;
mmc->f_min = mmc->f_max / 512;
}

/*
* There are 4 different scenarios for the card detection:
* 1) an external gpio irq handles the cd (best for power savings)
Expand Down Expand Up @@ -975,7 +998,13 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
/* See if we also get DMA */
tmio_mmc_request_dma(_host, pdata);

mmc_add_host(mmc);
ret = mmc_add_host(mmc);
if (pdata->clk_disable)
pdata->clk_disable(pdev);
if (ret < 0) {
tmio_mmc_host_remove(_host);
return ret;
}

dev_pm_qos_expose_latency_limit(&pdev->dev, 100);

Expand Down
3 changes: 3 additions & 0 deletions include/linux/mfd/tmio.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ struct tmio_mmc_data {
void (*set_clk_div)(struct platform_device *host, int state);
int (*get_cd)(struct platform_device *host);
int (*write16_hook)(struct tmio_mmc_host *host, int addr);
/* clock management callbacks */
int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
void (*clk_disable)(struct platform_device *pdev);
};

/*
Expand Down

0 comments on commit 8c102a9

Please sign in to comment.