summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/dw_mmc.c52
-rw-r--r--include/linux/mmc/dw_mmc.h4
2 files changed, 53 insertions, 3 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 227c42ef18c..de45ad24bec 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1960,13 +1960,42 @@ int dw_mci_probe(struct dw_mci *host)
return -ENODEV;
}
- if (!host->pdata->bus_hz) {
+ host->biu_clk = clk_get(host->dev, "biu");
+ if (IS_ERR(host->biu_clk)) {
+ dev_dbg(host->dev, "biu clock not available\n");
+ } else {
+ ret = clk_prepare_enable(host->biu_clk);
+ if (ret) {
+ dev_err(host->dev, "failed to enable biu clock\n");
+ clk_put(host->biu_clk);
+ return ret;
+ }
+ }
+
+ host->ciu_clk = clk_get(host->dev, "ciu");
+ if (IS_ERR(host->ciu_clk)) {
+ dev_dbg(host->dev, "ciu clock not available\n");
+ } else {
+ ret = clk_prepare_enable(host->ciu_clk);
+ if (ret) {
+ dev_err(host->dev, "failed to enable ciu clock\n");
+ clk_put(host->ciu_clk);
+ goto err_clk_biu;
+ }
+ }
+
+ if (IS_ERR(host->ciu_clk))
+ host->bus_hz = host->pdata->bus_hz;
+ else
+ host->bus_hz = clk_get_rate(host->ciu_clk);
+
+ if (!host->bus_hz) {
dev_err(host->dev,
"Platform data must supply bus speed\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_clk_ciu;
}
- host->bus_hz = host->pdata->bus_hz;
host->quirks = host->pdata->quirks;
spin_lock_init(&host->lock);
@@ -2116,6 +2145,17 @@ err_dmaunmap:
regulator_disable(host->vmmc);
regulator_put(host->vmmc);
}
+
+err_clk_ciu:
+ if (!IS_ERR(host->ciu_clk)) {
+ clk_disable_unprepare(host->ciu_clk);
+ clk_put(host->ciu_clk);
+ }
+err_clk_biu:
+ if (!IS_ERR(host->biu_clk)) {
+ clk_disable_unprepare(host->biu_clk);
+ clk_put(host->biu_clk);
+ }
return ret;
}
EXPORT_SYMBOL(dw_mci_probe);
@@ -2149,6 +2189,12 @@ void dw_mci_remove(struct dw_mci *host)
regulator_put(host->vmmc);
}
+ if (!IS_ERR(host->ciu_clk))
+ clk_disable_unprepare(host->ciu_clk);
+ if (!IS_ERR(host->biu_clk))
+ clk_disable_unprepare(host->biu_clk);
+ clk_put(host->ciu_clk);
+ clk_put(host->biu_clk);
}
EXPORT_SYMBOL(dw_mci_remove);
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index a37a573fa13..787ad569c99 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -78,6 +78,8 @@ struct mmc_data;
* @data_offset: Set the offset of DATA register according to VERID.
* @dev: Device associated with the MMC controller.
* @pdata: Platform data associated with the MMC controller.
+ * @biu_clk: Pointer to bus interface unit clock instance.
+ * @ciu_clk: Pointer to card interface unit clock instance.
* @slot: Slots sharing this MMC controller.
* @fifo_depth: depth of FIFO.
* @data_shift: log2 of FIFO item size.
@@ -158,6 +160,8 @@ struct dw_mci {
u16 data_offset;
struct device *dev;
struct dw_mci_board *pdata;
+ struct clk *biu_clk;
+ struct clk *ciu_clk;
struct dw_mci_slot *slot[MAX_MCI_SLOTS];
/* FIFO push and pull */