diff options
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 125 |
1 files changed, 79 insertions, 46 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4526d2791f29..dedf3dab8a3b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -118,7 +118,7 @@ | |||
118 | 118 | ||
119 | #define MMC_TIMEOUT_MS 20 | 119 | #define MMC_TIMEOUT_MS 20 |
120 | #define OMAP_MMC_MASTER_CLOCK 96000000 | 120 | #define OMAP_MMC_MASTER_CLOCK 96000000 |
121 | #define DRIVER_NAME "mmci-omap-hs" | 121 | #define DRIVER_NAME "omap_hsmmc" |
122 | 122 | ||
123 | /* Timeouts for entering power saving states on inactivity, msec */ | 123 | /* Timeouts for entering power saving states on inactivity, msec */ |
124 | #define OMAP_MMC_DISABLED_TIMEOUT 100 | 124 | #define OMAP_MMC_DISABLED_TIMEOUT 100 |
@@ -250,9 +250,9 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, | |||
250 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); | 250 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); |
251 | 251 | ||
252 | if (power_on) | 252 | if (power_on) |
253 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | 253 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); |
254 | else | 254 | else |
255 | ret = mmc_regulator_set_ocr(host->vcc, 0); | 255 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); |
256 | 256 | ||
257 | if (mmc_slot(host).after_set_reg) | 257 | if (mmc_slot(host).after_set_reg) |
258 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); | 258 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); |
@@ -260,7 +260,7 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, | |||
260 | return ret; | 260 | return ret; |
261 | } | 261 | } |
262 | 262 | ||
263 | static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, | 263 | static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on, |
264 | int vdd) | 264 | int vdd) |
265 | { | 265 | { |
266 | struct omap_hsmmc_host *host = | 266 | struct omap_hsmmc_host *host = |
@@ -291,18 +291,23 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, | |||
291 | * chips/cards need an interface voltage rail too. | 291 | * chips/cards need an interface voltage rail too. |
292 | */ | 292 | */ |
293 | if (power_on) { | 293 | if (power_on) { |
294 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | 294 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); |
295 | /* Enable interface voltage rail, if needed */ | 295 | /* Enable interface voltage rail, if needed */ |
296 | if (ret == 0 && host->vcc_aux) { | 296 | if (ret == 0 && host->vcc_aux) { |
297 | ret = regulator_enable(host->vcc_aux); | 297 | ret = regulator_enable(host->vcc_aux); |
298 | if (ret < 0) | 298 | if (ret < 0) |
299 | ret = mmc_regulator_set_ocr(host->vcc, 0); | 299 | ret = mmc_regulator_set_ocr(host->mmc, |
300 | host->vcc, 0); | ||
300 | } | 301 | } |
301 | } else { | 302 | } else { |
303 | /* Shut down the rail */ | ||
302 | if (host->vcc_aux) | 304 | if (host->vcc_aux) |
303 | ret = regulator_disable(host->vcc_aux); | 305 | ret = regulator_disable(host->vcc_aux); |
304 | if (ret == 0) | 306 | if (!ret) { |
305 | ret = mmc_regulator_set_ocr(host->vcc, 0); | 307 | /* Then proceed to shut down the local regulator */ |
308 | ret = mmc_regulator_set_ocr(host->mmc, | ||
309 | host->vcc, 0); | ||
310 | } | ||
306 | } | 311 | } |
307 | 312 | ||
308 | if (mmc_slot(host).after_set_reg) | 313 | if (mmc_slot(host).after_set_reg) |
@@ -311,6 +316,12 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, | |||
311 | return ret; | 316 | return ret; |
312 | } | 317 | } |
313 | 318 | ||
319 | static int omap_hsmmc_4_set_power(struct device *dev, int slot, int power_on, | ||
320 | int vdd) | ||
321 | { | ||
322 | return 0; | ||
323 | } | ||
324 | |||
314 | static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, | 325 | static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, |
315 | int vdd, int cardsleep) | 326 | int vdd, int cardsleep) |
316 | { | 327 | { |
@@ -321,7 +332,7 @@ static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, | |||
321 | return regulator_set_mode(host->vcc, mode); | 332 | return regulator_set_mode(host->vcc, mode); |
322 | } | 333 | } |
323 | 334 | ||
324 | static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, | 335 | static int omap_hsmmc_235_set_sleep(struct device *dev, int slot, int sleep, |
325 | int vdd, int cardsleep) | 336 | int vdd, int cardsleep) |
326 | { | 337 | { |
327 | struct omap_hsmmc_host *host = | 338 | struct omap_hsmmc_host *host = |
@@ -343,9 +354,9 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, | |||
343 | if (cardsleep) { | 354 | if (cardsleep) { |
344 | /* VCC can be turned off if card is asleep */ | 355 | /* VCC can be turned off if card is asleep */ |
345 | if (sleep) | 356 | if (sleep) |
346 | err = mmc_regulator_set_ocr(host->vcc, 0); | 357 | err = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); |
347 | else | 358 | else |
348 | err = mmc_regulator_set_ocr(host->vcc, vdd); | 359 | err = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); |
349 | } else | 360 | } else |
350 | err = regulator_set_mode(host->vcc, mode); | 361 | err = regulator_set_mode(host->vcc, mode); |
351 | if (err) | 362 | if (err) |
@@ -360,10 +371,17 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, | |||
360 | return regulator_enable(host->vcc_aux); | 371 | return regulator_enable(host->vcc_aux); |
361 | } | 372 | } |
362 | 373 | ||
374 | static int omap_hsmmc_4_set_sleep(struct device *dev, int slot, int sleep, | ||
375 | int vdd, int cardsleep) | ||
376 | { | ||
377 | return 0; | ||
378 | } | ||
379 | |||
363 | static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | 380 | static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) |
364 | { | 381 | { |
365 | struct regulator *reg; | 382 | struct regulator *reg; |
366 | int ret = 0; | 383 | int ret = 0; |
384 | int ocr_value = 0; | ||
367 | 385 | ||
368 | switch (host->id) { | 386 | switch (host->id) { |
369 | case OMAP_MMC1_DEVID: | 387 | case OMAP_MMC1_DEVID: |
@@ -373,10 +391,14 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
373 | break; | 391 | break; |
374 | case OMAP_MMC2_DEVID: | 392 | case OMAP_MMC2_DEVID: |
375 | case OMAP_MMC3_DEVID: | 393 | case OMAP_MMC3_DEVID: |
394 | case OMAP_MMC5_DEVID: | ||
376 | /* Off-chip level shifting, or none */ | 395 | /* Off-chip level shifting, or none */ |
377 | mmc_slot(host).set_power = omap_hsmmc_23_set_power; | 396 | mmc_slot(host).set_power = omap_hsmmc_235_set_power; |
378 | mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep; | 397 | mmc_slot(host).set_sleep = omap_hsmmc_235_set_sleep; |
379 | break; | 398 | break; |
399 | case OMAP_MMC4_DEVID: | ||
400 | mmc_slot(host).set_power = omap_hsmmc_4_set_power; | ||
401 | mmc_slot(host).set_sleep = omap_hsmmc_4_set_sleep; | ||
380 | default: | 402 | default: |
381 | pr_err("MMC%d configuration not supported!\n", host->id); | 403 | pr_err("MMC%d configuration not supported!\n", host->id); |
382 | return -EINVAL; | 404 | return -EINVAL; |
@@ -396,12 +418,25 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
396 | } | 418 | } |
397 | } else { | 419 | } else { |
398 | host->vcc = reg; | 420 | host->vcc = reg; |
399 | mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg); | 421 | ocr_value = mmc_regulator_get_ocrmask(reg); |
422 | if (!mmc_slot(host).ocr_mask) { | ||
423 | mmc_slot(host).ocr_mask = ocr_value; | ||
424 | } else { | ||
425 | if (!(mmc_slot(host).ocr_mask & ocr_value)) { | ||
426 | pr_err("MMC%d ocrmask %x is not supported\n", | ||
427 | host->id, mmc_slot(host).ocr_mask); | ||
428 | mmc_slot(host).ocr_mask = 0; | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | } | ||
400 | 432 | ||
401 | /* Allow an aux regulator */ | 433 | /* Allow an aux regulator */ |
402 | reg = regulator_get(host->dev, "vmmc_aux"); | 434 | reg = regulator_get(host->dev, "vmmc_aux"); |
403 | host->vcc_aux = IS_ERR(reg) ? NULL : reg; | 435 | host->vcc_aux = IS_ERR(reg) ? NULL : reg; |
404 | 436 | ||
437 | /* For eMMC do not power off when not in sleep state */ | ||
438 | if (mmc_slot(host).no_regulator_off_init) | ||
439 | return 0; | ||
405 | /* | 440 | /* |
406 | * UGLY HACK: workaround regulator framework bugs. | 441 | * UGLY HACK: workaround regulator framework bugs. |
407 | * When the bootloader leaves a supply active, it's | 442 | * When the bootloader leaves a supply active, it's |
@@ -466,8 +501,6 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) | |||
466 | int ret; | 501 | int ret; |
467 | 502 | ||
468 | if (gpio_is_valid(pdata->slots[0].switch_pin)) { | 503 | if (gpio_is_valid(pdata->slots[0].switch_pin)) { |
469 | pdata->suspend = omap_hsmmc_suspend_cdirq; | ||
470 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
471 | if (pdata->slots[0].cover) | 504 | if (pdata->slots[0].cover) |
472 | pdata->slots[0].get_cover_state = | 505 | pdata->slots[0].get_cover_state = |
473 | omap_hsmmc_get_cover_state; | 506 | omap_hsmmc_get_cover_state; |
@@ -928,7 +961,8 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) | |||
928 | spin_unlock(&host->irq_lock); | 961 | spin_unlock(&host->irq_lock); |
929 | 962 | ||
930 | if (host->use_dma && dma_ch != -1) { | 963 | if (host->use_dma && dma_ch != -1) { |
931 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, | 964 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, |
965 | host->data->sg_len, | ||
932 | omap_hsmmc_get_dma_dir(host, host->data)); | 966 | omap_hsmmc_get_dma_dir(host, host->data)); |
933 | omap_free_dma(dma_ch); | 967 | omap_free_dma(dma_ch); |
934 | } | 968 | } |
@@ -982,6 +1016,17 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | |||
982 | OMAP_HSMMC_WRITE(host->base, SYSCTL, | 1016 | OMAP_HSMMC_WRITE(host->base, SYSCTL, |
983 | OMAP_HSMMC_READ(host->base, SYSCTL) | bit); | 1017 | OMAP_HSMMC_READ(host->base, SYSCTL) | bit); |
984 | 1018 | ||
1019 | /* | ||
1020 | * OMAP4 ES2 and greater has an updated reset logic. | ||
1021 | * Monitor a 0->1 transition first | ||
1022 | */ | ||
1023 | if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { | ||
1024 | while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) | ||
1025 | && (i++ < limit)) | ||
1026 | cpu_relax(); | ||
1027 | } | ||
1028 | i = 0; | ||
1029 | |||
985 | while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) && | 1030 | while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) && |
986 | (i++ < limit)) | 1031 | (i++ < limit)) |
987 | cpu_relax(); | 1032 | cpu_relax(); |
@@ -1301,7 +1346,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) | |||
1301 | return; | 1346 | return; |
1302 | } | 1347 | } |
1303 | 1348 | ||
1304 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, | 1349 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, |
1305 | omap_hsmmc_get_dma_dir(host, data)); | 1350 | omap_hsmmc_get_dma_dir(host, data)); |
1306 | 1351 | ||
1307 | req_in_progress = host->req_in_progress; | 1352 | req_in_progress = host->req_in_progress; |
@@ -1529,7 +1574,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1529 | break; | 1574 | break; |
1530 | } | 1575 | } |
1531 | 1576 | ||
1532 | if (host->id == OMAP_MMC1_DEVID) { | 1577 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
1533 | /* Only MMC1 can interface at 3V without some flavor | 1578 | /* Only MMC1 can interface at 3V without some flavor |
1534 | * of external transceiver; but they all handle 1.8V. | 1579 | * of external transceiver; but they all handle 1.8V. |
1535 | */ | 1580 | */ |
@@ -1621,7 +1666,7 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | |||
1621 | u32 hctl, capa, value; | 1666 | u32 hctl, capa, value; |
1622 | 1667 | ||
1623 | /* Only MMC1 supports 3.0V */ | 1668 | /* Only MMC1 supports 3.0V */ |
1624 | if (host->id == OMAP_MMC1_DEVID) { | 1669 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
1625 | hctl = SDVS30; | 1670 | hctl = SDVS30; |
1626 | capa = VS30 | VS18; | 1671 | capa = VS30 | VS18; |
1627 | } else { | 1672 | } else { |
@@ -2003,8 +2048,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2003 | if (res == NULL || irq < 0) | 2048 | if (res == NULL || irq < 0) |
2004 | return -ENXIO; | 2049 | return -ENXIO; |
2005 | 2050 | ||
2006 | res = request_mem_region(res->start, res->end - res->start + 1, | 2051 | res->start += pdata->reg_offset; |
2007 | pdev->name); | 2052 | res->end += pdata->reg_offset; |
2053 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
2008 | if (res == NULL) | 2054 | if (res == NULL) |
2009 | return -EBUSY; | 2055 | return -EBUSY; |
2010 | 2056 | ||
@@ -2073,14 +2119,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2073 | /* we start off in DISABLED state */ | 2119 | /* we start off in DISABLED state */ |
2074 | host->dpm_state = DISABLED; | 2120 | host->dpm_state = DISABLED; |
2075 | 2121 | ||
2076 | if (mmc_host_enable(host->mmc) != 0) { | 2122 | if (clk_enable(host->iclk) != 0) { |
2077 | clk_put(host->iclk); | 2123 | clk_put(host->iclk); |
2078 | clk_put(host->fclk); | 2124 | clk_put(host->fclk); |
2079 | goto err1; | 2125 | goto err1; |
2080 | } | 2126 | } |
2081 | 2127 | ||
2082 | if (clk_enable(host->iclk) != 0) { | 2128 | if (mmc_host_enable(host->mmc) != 0) { |
2083 | mmc_host_disable(host->mmc); | 2129 | clk_disable(host->iclk); |
2084 | clk_put(host->iclk); | 2130 | clk_put(host->iclk); |
2085 | clk_put(host->fclk); | 2131 | clk_put(host->fclk); |
2086 | goto err1; | 2132 | goto err1; |
@@ -2105,8 +2151,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2105 | 2151 | ||
2106 | /* Since we do only SG emulation, we can have as many segs | 2152 | /* Since we do only SG emulation, we can have as many segs |
2107 | * as we want. */ | 2153 | * as we want. */ |
2108 | mmc->max_phys_segs = 1024; | 2154 | mmc->max_segs = 1024; |
2109 | mmc->max_hw_segs = 1024; | ||
2110 | 2155 | ||
2111 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ | 2156 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ |
2112 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ | 2157 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ |
@@ -2116,23 +2161,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2116 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | | 2161 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | |
2117 | MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; | 2162 | MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; |
2118 | 2163 | ||
2119 | switch (mmc_slot(host).wires) { | 2164 | mmc->caps |= mmc_slot(host).caps; |
2120 | case 8: | 2165 | if (mmc->caps & MMC_CAP_8_BIT_DATA) |
2121 | mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
2122 | /* Fall through */ | ||
2123 | case 4: | ||
2124 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 2166 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
2125 | break; | ||
2126 | case 1: | ||
2127 | /* Nothing to crib here */ | ||
2128 | case 0: | ||
2129 | /* Assuming nothing was given by board, Core use's 1-Bit */ | ||
2130 | break; | ||
2131 | default: | ||
2132 | /* Completely unexpected.. Core goes with 1-Bit Width */ | ||
2133 | dev_crit(mmc_dev(host->mmc), "Invalid width %d\n used!" | ||
2134 | "using 1 instead\n", mmc_slot(host).wires); | ||
2135 | } | ||
2136 | 2167 | ||
2137 | if (mmc_slot(host).nonremovable) | 2168 | if (mmc_slot(host).nonremovable) |
2138 | mmc->caps |= MMC_CAP_NONREMOVABLE; | 2169 | mmc->caps |= MMC_CAP_NONREMOVABLE; |
@@ -2203,6 +2234,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2203 | "Unable to grab MMC CD IRQ\n"); | 2234 | "Unable to grab MMC CD IRQ\n"); |
2204 | goto err_irq_cd; | 2235 | goto err_irq_cd; |
2205 | } | 2236 | } |
2237 | pdata->suspend = omap_hsmmc_suspend_cdirq; | ||
2238 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
2206 | } | 2239 | } |
2207 | 2240 | ||
2208 | omap_hsmmc_disable_irq(host); | 2241 | omap_hsmmc_disable_irq(host); |
@@ -2256,7 +2289,7 @@ err1: | |||
2256 | err_alloc: | 2289 | err_alloc: |
2257 | omap_hsmmc_gpio_free(pdata); | 2290 | omap_hsmmc_gpio_free(pdata); |
2258 | err: | 2291 | err: |
2259 | release_mem_region(res->start, res->end - res->start + 1); | 2292 | release_mem_region(res->start, resource_size(res)); |
2260 | return ret; | 2293 | return ret; |
2261 | } | 2294 | } |
2262 | 2295 | ||
@@ -2275,7 +2308,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2275 | free_irq(host->irq, host); | 2308 | free_irq(host->irq, host); |
2276 | if (mmc_slot(host).card_detect_irq) | 2309 | if (mmc_slot(host).card_detect_irq) |
2277 | free_irq(mmc_slot(host).card_detect_irq, host); | 2310 | free_irq(mmc_slot(host).card_detect_irq, host); |
2278 | flush_scheduled_work(); | 2311 | flush_work_sync(&host->mmc_carddetect_work); |
2279 | 2312 | ||
2280 | mmc_host_disable(host->mmc); | 2313 | mmc_host_disable(host->mmc); |
2281 | clk_disable(host->iclk); | 2314 | clk_disable(host->iclk); |
@@ -2293,7 +2326,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2293 | 2326 | ||
2294 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2327 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2295 | if (res) | 2328 | if (res) |
2296 | release_mem_region(res->start, res->end - res->start + 1); | 2329 | release_mem_region(res->start, resource_size(res)); |
2297 | platform_set_drvdata(pdev, NULL); | 2330 | platform_set_drvdata(pdev, NULL); |
2298 | 2331 | ||
2299 | return 0; | 2332 | return 0; |