After a runtime or system-wide suspend the clock frequency can change,
therefore it must be re-read.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxx>
---
v2: move updating the clock frequency from .runtime_resume() to .start(),
since the former is not called, when power domains are used and when the
domain is not powered off and on - thanks to Magnus for pointing out. This
version requires my patch from several minutes ago "PM: provide a dummy
dev_gpd_data() when generic domains are not used."
http://article.gmane.org/gmane.linux.ports.sh.devel/13487
drivers/mmc/host/sh_mobile_sdhi.c | 20 ++++++++++++++++++++
drivers/mmc/host/tmio_mmc.h | 1 +
drivers/mmc/host/tmio_mmc_pio.c | 26 +++++++++++++++++++++-----
include/linux/mfd/tmio.h | 1 +
4 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 2c3a9d3..2842ab9 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h>
@@ -47,6 +48,15 @@ static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
p->set_pwr(pdev, state);
}
+static unsigned int sh_mobile_sdhi_get_clk_rate(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+ struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
+
+ return clk_get_rate(priv->clk);
+}
+
static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
{
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
@@ -95,6 +105,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
struct sh_mobile_sdhi *priv;
struct tmio_mmc_data *mmc_data;
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+ struct generic_pm_domain_data *gpdd;
struct tmio_mmc_host *host;
char clk_name[8];
int irq, ret, i = 0;
@@ -120,6 +131,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
mmc_data->hclk = clk_get_rate(priv->clk);
mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+ mmc_data->get_clk_rate = sh_mobile_sdhi_get_clk_rate;
mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
if (p) {
mmc_data->flags = p->tmio_flags;
@@ -208,6 +220,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
goto eirq_multiplexed;
}
+ gpdd = dev_gpd_data(&pdev->dev);
+ if (gpdd)
+ gpdd->ops.start = tmio_mmc_host_start;
+
dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
mmc_hostname(host->mmc), (unsigned long)
(platform_get_resource(pdev, IORESOURCE_MEM, 0)->start),
@@ -243,8 +259,12 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
struct tmio_mmc_host *host = mmc_priv(mmc);
struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+ struct generic_pm_domain_data *gpdd = dev_gpd_data(&pdev->dev);
int i = 0, irq;
+ if (gpdd)
+ gpdd->ops.start = NULL;
+
p->pdata = NULL;
tmio_mmc_host_remove(host);
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index d857f5c..3943647 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -156,6 +156,7 @@ int tmio_mmc_host_resume(struct device *dev);
int tmio_mmc_host_runtime_suspend(struct device *dev);
int tmio_mmc_host_runtime_resume(struct device *dev);
+int tmio_mmc_host_start(struct device *dev);
static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
{
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 08f3e67..69b826a 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -900,7 +900,10 @@ 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;
+ if (pdata->get_clk_rate)
+ mmc->f_max = pdata->get_clk_rate(pdev);
+ else
+ mmc->f_max = pdata->hclk;
mmc->f_min = mmc->f_max / 512;
mmc->max_segs = 32;
mmc->max_blk_size = 512;
@@ -1034,16 +1037,14 @@ EXPORT_SYMBOL(tmio_mmc_host_suspend);
int tmio_mmc_host_resume(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
- struct tmio_mmc_host *host = mmc_priv(mmc);
- tmio_mmc_reset(host);
- tmio_mmc_enable_dma(host, true);
+ tmio_mmc_host_start(dev);
+ tmio_mmc_host_runtime_resume(dev);
/* The MMC core will perform the complete set up */
return mmc_resume_host(mmc);
}
EXPORT_SYMBOL(tmio_mmc_host_resume);
-
#endif /* CONFIG_PM */
int tmio_mmc_host_runtime_suspend(struct device *dev)
@@ -1064,4 +1065,19 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
}
EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
+int tmio_mmc_host_start(struct device *dev)
+{
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+ struct tmio_mmc_data *pdata = host->pdata;
+
+ if (pdata->get_clk_rate) {
+ mmc->f_max = pdata->get_clk_rate(host->pdev);
+ mmc->f_min = mmc->f_max / 512;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(tmio_mmc_host_start);
+
MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index f5171db..020a737 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -108,6 +108,7 @@ struct tmio_mmc_data {
unsigned int cd_gpio;
void (*set_pwr)(struct platform_device *host, int state);
void (*set_clk_div)(struct platform_device *host, int state);
+ unsigned int (*get_clk_rate)(struct platform_device *host);
int (*get_cd)(struct platform_device *host);
int (*write16_hook)(struct tmio_mmc_host *host, int addr);
};
--
1.7.2.5
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[Linux OMAP]
[Linux USB Devel]
[Video for Linux]
[Linux Audio Users]
[Photo]
[Yosemite News]
[Yosemite Photos]
[Free Online Dating]
[Linux Kernel]
[Linux SCSI]
[XFree86]