aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2014-06-02 05:09:55 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2014-07-09 05:25:57 -0400
commit3f4e6f7b9175e2914b82134c4a6a02825f4766db (patch)
treee80ffec0c4e86a829b6b9d37bae2f4452cb58942
parentdc6500bfe889321f7f4fd01e96062a80643d81c1 (diff)
mmc: mmci: add explicit clk control
On Controllers like Qcom SD card controller where cclk is mclk and mclk should be directly controlled by the driver. This patch adds support to control mclk directly in the driver, and also adds explicit_mclk_control flag in variant structure giving more flexibility to the driver. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> [Ulf Hansson] Fixed checkpatch warning Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/mmci.c29
-rw-r--r--drivers/mmc/host/mmci.h2
2 files changed, 28 insertions, 3 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b588810fd1a4..2e6075fdce46 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -72,6 +72,7 @@ static unsigned int fmax = 515633;
72 * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock 72 * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
73 * @busy_detect: true if busy detection on dat0 is supported 73 * @busy_detect: true if busy detection on dat0 is supported
74 * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply 74 * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
75 * @explicit_mclk_control: enable explicit mclk control in driver.
75 */ 76 */
76struct variant_data { 77struct variant_data {
77 unsigned int clkreg; 78 unsigned int clkreg;
@@ -93,6 +94,7 @@ struct variant_data {
93 bool pwrreg_clkgate; 94 bool pwrreg_clkgate;
94 bool busy_detect; 95 bool busy_detect;
95 bool pwrreg_nopower; 96 bool pwrreg_nopower;
97 bool explicit_mclk_control;
96}; 98};
97 99
98static struct variant_data variant_arm = { 100static struct variant_data variant_arm = {
@@ -286,7 +288,9 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
286 host->cclk = 0; 288 host->cclk = 0;
287 289
288 if (desired) { 290 if (desired) {
289 if (desired >= host->mclk) { 291 if (variant->explicit_mclk_control) {
292 host->cclk = host->mclk;
293 } else if (desired >= host->mclk) {
290 clk = MCI_CLK_BYPASS; 294 clk = MCI_CLK_BYPASS;
291 if (variant->st_clkdiv) 295 if (variant->st_clkdiv)
292 clk |= MCI_ST_UX500_NEG_EDGE; 296 clk |= MCI_ST_UX500_NEG_EDGE;
@@ -1327,6 +1331,17 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1327 if (!ios->clock && variant->pwrreg_clkgate) 1331 if (!ios->clock && variant->pwrreg_clkgate)
1328 pwr &= ~MCI_PWR_ON; 1332 pwr &= ~MCI_PWR_ON;
1329 1333
1334 if (host->variant->explicit_mclk_control &&
1335 ios->clock != host->clock_cache) {
1336 ret = clk_set_rate(host->clk, ios->clock);
1337 if (ret < 0)
1338 dev_err(mmc_dev(host->mmc),
1339 "Error setting clock rate (%d)\n", ret);
1340 else
1341 host->mclk = clk_get_rate(host->clk);
1342 }
1343 host->clock_cache = ios->clock;
1344
1330 spin_lock_irqsave(&host->lock, flags); 1345 spin_lock_irqsave(&host->lock, flags);
1331 1346
1332 mmci_set_clkreg(host, ios->clock); 1347 mmci_set_clkreg(host, ios->clock);
@@ -1502,9 +1517,12 @@ static int mmci_probe(struct amba_device *dev,
1502 * The ARM and ST versions of the block have slightly different 1517 * The ARM and ST versions of the block have slightly different
1503 * clock divider equations which means that the minimum divider 1518 * clock divider equations which means that the minimum divider
1504 * differs too. 1519 * differs too.
1520 * on Qualcomm like controllers get the nearest minimum clock to 100Khz
1505 */ 1521 */
1506 if (variant->st_clkdiv) 1522 if (variant->st_clkdiv)
1507 mmc->f_min = DIV_ROUND_UP(host->mclk, 257); 1523 mmc->f_min = DIV_ROUND_UP(host->mclk, 257);
1524 else if (variant->explicit_mclk_control)
1525 mmc->f_min = clk_round_rate(host->clk, 100000);
1508 else 1526 else
1509 mmc->f_min = DIV_ROUND_UP(host->mclk, 512); 1527 mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
1510 /* 1528 /*
@@ -1514,9 +1532,14 @@ static int mmci_probe(struct amba_device *dev,
1514 * the block, of course. 1532 * the block, of course.
1515 */ 1533 */
1516 if (mmc->f_max) 1534 if (mmc->f_max)
1517 mmc->f_max = min(host->mclk, mmc->f_max); 1535 mmc->f_max = variant->explicit_mclk_control ?
1536 min(variant->f_max, mmc->f_max) :
1537 min(host->mclk, mmc->f_max);
1518 else 1538 else
1519 mmc->f_max = min(host->mclk, fmax); 1539 mmc->f_max = variant->explicit_mclk_control ?
1540 fmax : min(host->mclk, fmax);
1541
1542
1520 dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); 1543 dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
1521 1544
1522 /* Get regulators and the supported OCR mask */ 1545 /* Get regulators and the supported OCR mask */
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index d38a99df1820..ef346170b241 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -208,6 +208,8 @@ struct mmci_host {
208 spinlock_t lock; 208 spinlock_t lock;
209 209
210 unsigned int mclk; 210 unsigned int mclk;
211 /* cached value of requested clk in set_ios */
212 unsigned int clock_cache;
211 unsigned int cclk; 213 unsigned int cclk;
212 u32 pwr_reg; 214 u32 pwr_reg;
213 u32 pwr_reg_add; 215 u32 pwr_reg_add;