diff options
-rw-r--r-- | drivers/mmc/host/mmci.c | 29 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 2 |
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 | */ |
76 | struct variant_data { | 77 | struct 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 | ||
98 | static struct variant_data variant_arm = { | 100 | static 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; |