diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-20 11:59:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-20 11:59:12 -0400 |
commit | 0ea67fae9e80bfd69713b51ba3fa53879be5383b (patch) | |
tree | cd5a3d50a1005605adc33561ce68b22ac06cb8d3 | |
parent | a28ad14e057b6ec2ad9a8b09a44aa859d79c0ff8 (diff) | |
parent | 82bb095ee9dcd9380b6ab608b5fa9f64e65f3a3b (diff) |
Merge tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC fixes from Ulf Hansson:
"Here are some mmc fixes intended for v4.9 rc2.
This time I have also included a few changes for a memstick driver
which has a corresponding mmc driver. They use the same USB device as
parent, hence both needs to play nice with runtime PM, which they
didn't.
MMC core:
- Update MAINTAINERS as the mmc tree moved to kernel.org
- A few fixes for HS400es mode
- A few other minor fixes
MMC host:
- sdhci: Fix an issue when dealing with stop commands
- sdhci-pci: Fix a bus power failure issue
- sdhci-esdhc-imx: Correct two register accesses
- sdhci-of-arasan: Fix the 1.8V I/O signal switch behaviour
- rtsx_usb_sdmmc: Fix runtime PM issues
Other: (Because of no maintainer)
- memstick: rtsx_usb_ms: Fix runtime PM issues"
* tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
MAINTAINERS: mmc: Move the mmc tree to kernel.org
memstick: rtsx_usb_ms: Manage runtime PM when accessing the device
memstick: rtsx_usb_ms: Runtime resume the device when polling for cards
mmc: rtsx_usb_sdmmc: Handle runtime PM while changing the led
mmc: rtsx_usb_sdmmc: Avoid keeping the device runtime resumed when unused
mmc: sdhci: cast unsigned int to unsigned long long to avoid unexpeted error
mmc: sdhci-esdhc-imx: Correct two register accesses
mmc: sdhci-pci: Fix bus power failing to enable for some Intel controllers
mmc: sdhci-pci: Let devices define their own sdhci_ops
mmc: sdhci: Rename sdhci_set_power() to sdhci_set_power_noreg()
mmc: sdhci: Fix SDHCI_QUIRK2_STOP_WITH_TC
mmc: core: Annotate cmd_hdr as __le32
mmc: sdhci-of-arasan: add sdhci_arasan_voltage_switch for arasan, 5.1
mmc: core: changes frequency to hs_max_dtr when selecting hs400es
mmc: core: switch to 1V8 or 1V2 for hs400es mode
mmc: block: add missing header dependencies
mmc: sdhci-of-arasan: Fix non static symbol warning
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | drivers/memstick/host/rtsx_usb_ms.c | 6 | ||||
-rw-r--r-- | drivers/mmc/card/block.c | 3 | ||||
-rw-r--r-- | drivers/mmc/card/queue.h | 2 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 12 | ||||
-rw-r--r-- | drivers/mmc/host/rtsx_usb_sdmmc.c | 7 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 23 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-of-arasan.c | 26 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 54 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci.h | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pxav3.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 42 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 2 |
13 files changed, 149 insertions, 34 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 1cd38a7e0064..c72fa185c374 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8212,7 +8212,7 @@ F: include/linux/mfd/ | |||
8212 | MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM | 8212 | MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM |
8213 | M: Ulf Hansson <ulf.hansson@linaro.org> | 8213 | M: Ulf Hansson <ulf.hansson@linaro.org> |
8214 | L: linux-mmc@vger.kernel.org | 8214 | L: linux-mmc@vger.kernel.org |
8215 | T: git git://git.linaro.org/people/ulf.hansson/mmc.git | 8215 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git |
8216 | S: Maintained | 8216 | S: Maintained |
8217 | F: Documentation/devicetree/bindings/mmc/ | 8217 | F: Documentation/devicetree/bindings/mmc/ |
8218 | F: drivers/mmc/ | 8218 | F: drivers/mmc/ |
diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c index d34bc3530385..2e3cf012ef48 100644 --- a/drivers/memstick/host/rtsx_usb_ms.c +++ b/drivers/memstick/host/rtsx_usb_ms.c | |||
@@ -524,6 +524,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work) | |||
524 | int rc; | 524 | int rc; |
525 | 525 | ||
526 | if (!host->req) { | 526 | if (!host->req) { |
527 | pm_runtime_get_sync(ms_dev(host)); | ||
527 | do { | 528 | do { |
528 | rc = memstick_next_req(msh, &host->req); | 529 | rc = memstick_next_req(msh, &host->req); |
529 | dev_dbg(ms_dev(host), "next req %d\n", rc); | 530 | dev_dbg(ms_dev(host), "next req %d\n", rc); |
@@ -544,6 +545,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work) | |||
544 | host->req->error); | 545 | host->req->error); |
545 | } | 546 | } |
546 | } while (!rc); | 547 | } while (!rc); |
548 | pm_runtime_put(ms_dev(host)); | ||
547 | } | 549 | } |
548 | 550 | ||
549 | } | 551 | } |
@@ -570,6 +572,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh, | |||
570 | dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", | 572 | dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", |
571 | __func__, param, value); | 573 | __func__, param, value); |
572 | 574 | ||
575 | pm_runtime_get_sync(ms_dev(host)); | ||
573 | mutex_lock(&ucr->dev_mutex); | 576 | mutex_lock(&ucr->dev_mutex); |
574 | 577 | ||
575 | err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD); | 578 | err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD); |
@@ -635,6 +638,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh, | |||
635 | } | 638 | } |
636 | out: | 639 | out: |
637 | mutex_unlock(&ucr->dev_mutex); | 640 | mutex_unlock(&ucr->dev_mutex); |
641 | pm_runtime_put(ms_dev(host)); | ||
638 | 642 | ||
639 | /* power-on delay */ | 643 | /* power-on delay */ |
640 | if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) | 644 | if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) |
@@ -681,6 +685,7 @@ static int rtsx_usb_detect_ms_card(void *__host) | |||
681 | int err; | 685 | int err; |
682 | 686 | ||
683 | for (;;) { | 687 | for (;;) { |
688 | pm_runtime_get_sync(ms_dev(host)); | ||
684 | mutex_lock(&ucr->dev_mutex); | 689 | mutex_lock(&ucr->dev_mutex); |
685 | 690 | ||
686 | /* Check pending MS card changes */ | 691 | /* Check pending MS card changes */ |
@@ -703,6 +708,7 @@ static int rtsx_usb_detect_ms_card(void *__host) | |||
703 | } | 708 | } |
704 | 709 | ||
705 | poll_again: | 710 | poll_again: |
711 | pm_runtime_put(ms_dev(host)); | ||
706 | if (host->eject) | 712 | if (host->eject) |
707 | break; | 713 | break; |
708 | 714 | ||
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c3335112e68c..709a872ed484 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/uaccess.h> | 46 | #include <asm/uaccess.h> |
47 | 47 | ||
48 | #include "queue.h" | 48 | #include "queue.h" |
49 | #include "block.h" | ||
49 | 50 | ||
50 | MODULE_ALIAS("mmc:block"); | 51 | MODULE_ALIAS("mmc:block"); |
51 | #ifdef MODULE_PARAM_PREFIX | 52 | #ifdef MODULE_PARAM_PREFIX |
@@ -1786,7 +1787,7 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, | |||
1786 | struct mmc_blk_data *md = mq->data; | 1787 | struct mmc_blk_data *md = mq->data; |
1787 | struct mmc_packed *packed = mqrq->packed; | 1788 | struct mmc_packed *packed = mqrq->packed; |
1788 | bool do_rel_wr, do_data_tag; | 1789 | bool do_rel_wr, do_data_tag; |
1789 | u32 *packed_cmd_hdr; | 1790 | __le32 *packed_cmd_hdr; |
1790 | u8 hdr_blocks; | 1791 | u8 hdr_blocks; |
1791 | u8 i = 1; | 1792 | u8 i = 1; |
1792 | 1793 | ||
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index 3c15a75bae86..342f1e3f301e 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h | |||
@@ -31,7 +31,7 @@ enum mmc_packed_type { | |||
31 | 31 | ||
32 | struct mmc_packed { | 32 | struct mmc_packed { |
33 | struct list_head list; | 33 | struct list_head list; |
34 | u32 cmd_hdr[1024]; | 34 | __le32 cmd_hdr[1024]; |
35 | unsigned int blocks; | 35 | unsigned int blocks; |
36 | u8 nr_entries; | 36 | u8 nr_entries; |
37 | u8 retries; | 37 | u8 retries; |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 3486bc7fbb64..39fc5b2b96c5 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -1263,6 +1263,16 @@ static int mmc_select_hs400es(struct mmc_card *card) | |||
1263 | goto out_err; | 1263 | goto out_err; |
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V) | ||
1267 | err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); | ||
1268 | |||
1269 | if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V) | ||
1270 | err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); | ||
1271 | |||
1272 | /* If fails try again during next card power cycle */ | ||
1273 | if (err) | ||
1274 | goto out_err; | ||
1275 | |||
1266 | err = mmc_select_bus_width(card); | 1276 | err = mmc_select_bus_width(card); |
1267 | if (err < 0) | 1277 | if (err < 0) |
1268 | goto out_err; | 1278 | goto out_err; |
@@ -1272,6 +1282,8 @@ static int mmc_select_hs400es(struct mmc_card *card) | |||
1272 | if (err) | 1282 | if (err) |
1273 | goto out_err; | 1283 | goto out_err; |
1274 | 1284 | ||
1285 | mmc_set_clock(host, card->ext_csd.hs_max_dtr); | ||
1286 | |||
1275 | err = mmc_switch_status(card); | 1287 | err = mmc_switch_status(card); |
1276 | if (err) | 1288 | if (err) |
1277 | goto out_err; | 1289 | goto out_err; |
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 4106295527b9..6e9c0f8fddb1 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c | |||
@@ -1138,11 +1138,6 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1138 | dev_dbg(sdmmc_dev(host), "%s\n", __func__); | 1138 | dev_dbg(sdmmc_dev(host), "%s\n", __func__); |
1139 | mutex_lock(&ucr->dev_mutex); | 1139 | mutex_lock(&ucr->dev_mutex); |
1140 | 1140 | ||
1141 | if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) { | ||
1142 | mutex_unlock(&ucr->dev_mutex); | ||
1143 | return; | ||
1144 | } | ||
1145 | |||
1146 | sd_set_power_mode(host, ios->power_mode); | 1141 | sd_set_power_mode(host, ios->power_mode); |
1147 | sd_set_bus_width(host, ios->bus_width); | 1142 | sd_set_bus_width(host, ios->bus_width); |
1148 | sd_set_timing(host, ios->timing, &host->ddr_mode); | 1143 | sd_set_timing(host, ios->timing, &host->ddr_mode); |
@@ -1314,6 +1309,7 @@ static void rtsx_usb_update_led(struct work_struct *work) | |||
1314 | container_of(work, struct rtsx_usb_sdmmc, led_work); | 1309 | container_of(work, struct rtsx_usb_sdmmc, led_work); |
1315 | struct rtsx_ucr *ucr = host->ucr; | 1310 | struct rtsx_ucr *ucr = host->ucr; |
1316 | 1311 | ||
1312 | pm_runtime_get_sync(sdmmc_dev(host)); | ||
1317 | mutex_lock(&ucr->dev_mutex); | 1313 | mutex_lock(&ucr->dev_mutex); |
1318 | 1314 | ||
1319 | if (host->led.brightness == LED_OFF) | 1315 | if (host->led.brightness == LED_OFF) |
@@ -1322,6 +1318,7 @@ static void rtsx_usb_update_led(struct work_struct *work) | |||
1322 | rtsx_usb_turn_on_led(ucr); | 1318 | rtsx_usb_turn_on_led(ucr); |
1323 | 1319 | ||
1324 | mutex_unlock(&ucr->dev_mutex); | 1320 | mutex_unlock(&ucr->dev_mutex); |
1321 | pm_runtime_put(sdmmc_dev(host)); | ||
1325 | } | 1322 | } |
1326 | #endif | 1323 | #endif |
1327 | 1324 | ||
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1f54fd8755c8..7123ef96ed18 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -346,7 +346,8 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) | |||
346 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); | 346 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
347 | u32 data; | 347 | u32 data; |
348 | 348 | ||
349 | if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { | 349 | if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE || |
350 | reg == SDHCI_INT_STATUS)) { | ||
350 | if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) { | 351 | if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) { |
351 | /* | 352 | /* |
352 | * Clear and then set D3CD bit to avoid missing the | 353 | * Clear and then set D3CD bit to avoid missing the |
@@ -555,6 +556,25 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
555 | esdhc_clrset_le(host, 0xffff, val, reg); | 556 | esdhc_clrset_le(host, 0xffff, val, reg); |
556 | } | 557 | } |
557 | 558 | ||
559 | static u8 esdhc_readb_le(struct sdhci_host *host, int reg) | ||
560 | { | ||
561 | u8 ret; | ||
562 | u32 val; | ||
563 | |||
564 | switch (reg) { | ||
565 | case SDHCI_HOST_CONTROL: | ||
566 | val = readl(host->ioaddr + reg); | ||
567 | |||
568 | ret = val & SDHCI_CTRL_LED; | ||
569 | ret |= (val >> 5) & SDHCI_CTRL_DMA_MASK; | ||
570 | ret |= (val & ESDHC_CTRL_4BITBUS); | ||
571 | ret |= (val & ESDHC_CTRL_8BITBUS) << 3; | ||
572 | return ret; | ||
573 | } | ||
574 | |||
575 | return readb(host->ioaddr + reg); | ||
576 | } | ||
577 | |||
558 | static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) | 578 | static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) |
559 | { | 579 | { |
560 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 580 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
@@ -947,6 +967,7 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) | |||
947 | static struct sdhci_ops sdhci_esdhc_ops = { | 967 | static struct sdhci_ops sdhci_esdhc_ops = { |
948 | .read_l = esdhc_readl_le, | 968 | .read_l = esdhc_readl_le, |
949 | .read_w = esdhc_readw_le, | 969 | .read_w = esdhc_readw_le, |
970 | .read_b = esdhc_readb_le, | ||
950 | .write_l = esdhc_writel_le, | 971 | .write_l = esdhc_writel_le, |
951 | .write_w = esdhc_writew_le, | 972 | .write_w = esdhc_writew_le, |
952 | .write_b = esdhc_writeb_le, | 973 | .write_b = esdhc_writeb_le, |
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index da8e40af6f85..410a55b1c25f 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c | |||
@@ -250,7 +250,7 @@ static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc, | |||
250 | writel(vendor, host->ioaddr + SDHCI_ARASAN_VENDOR_REGISTER); | 250 | writel(vendor, host->ioaddr + SDHCI_ARASAN_VENDOR_REGISTER); |
251 | } | 251 | } |
252 | 252 | ||
253 | void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) | 253 | static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) |
254 | { | 254 | { |
255 | u8 ctrl; | 255 | u8 ctrl; |
256 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 256 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
@@ -265,6 +265,28 @@ void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) | |||
265 | } | 265 | } |
266 | } | 266 | } |
267 | 267 | ||
268 | static int sdhci_arasan_voltage_switch(struct mmc_host *mmc, | ||
269 | struct mmc_ios *ios) | ||
270 | { | ||
271 | switch (ios->signal_voltage) { | ||
272 | case MMC_SIGNAL_VOLTAGE_180: | ||
273 | /* | ||
274 | * Plese don't switch to 1V8 as arasan,5.1 doesn't | ||
275 | * actually refer to this setting to indicate the | ||
276 | * signal voltage and the state machine will be broken | ||
277 | * actually if we force to enable 1V8. That's something | ||
278 | * like broken quirk but we could work around here. | ||
279 | */ | ||
280 | return 0; | ||
281 | case MMC_SIGNAL_VOLTAGE_330: | ||
282 | case MMC_SIGNAL_VOLTAGE_120: | ||
283 | /* We don't support 3V3 and 1V2 */ | ||
284 | break; | ||
285 | } | ||
286 | |||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
268 | static struct sdhci_ops sdhci_arasan_ops = { | 290 | static struct sdhci_ops sdhci_arasan_ops = { |
269 | .set_clock = sdhci_arasan_set_clock, | 291 | .set_clock = sdhci_arasan_set_clock, |
270 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | 292 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, |
@@ -661,6 +683,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev) | |||
661 | 683 | ||
662 | host->mmc_host_ops.hs400_enhanced_strobe = | 684 | host->mmc_host_ops.hs400_enhanced_strobe = |
663 | sdhci_arasan_hs400_enhanced_strobe; | 685 | sdhci_arasan_hs400_enhanced_strobe; |
686 | host->mmc_host_ops.start_signal_voltage_switch = | ||
687 | sdhci_arasan_voltage_switch; | ||
664 | } | 688 | } |
665 | 689 | ||
666 | ret = sdhci_add_host(host); | 690 | ret = sdhci_add_host(host); |
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 72a1f1f5180a..1d9e00a00e9f 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c | |||
@@ -32,6 +32,14 @@ | |||
32 | #include "sdhci-pci.h" | 32 | #include "sdhci-pci.h" |
33 | #include "sdhci-pci-o2micro.h" | 33 | #include "sdhci-pci-o2micro.h" |
34 | 34 | ||
35 | static int sdhci_pci_enable_dma(struct sdhci_host *host); | ||
36 | static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width); | ||
37 | static void sdhci_pci_hw_reset(struct sdhci_host *host); | ||
38 | static int sdhci_pci_select_drive_strength(struct sdhci_host *host, | ||
39 | struct mmc_card *card, | ||
40 | unsigned int max_dtr, int host_drv, | ||
41 | int card_drv, int *drv_type); | ||
42 | |||
35 | /*****************************************************************************\ | 43 | /*****************************************************************************\ |
36 | * * | 44 | * * |
37 | * Hardware specific quirk handling * | 45 | * Hardware specific quirk handling * |
@@ -390,6 +398,45 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) | |||
390 | return 0; | 398 | return 0; |
391 | } | 399 | } |
392 | 400 | ||
401 | #define SDHCI_INTEL_PWR_TIMEOUT_CNT 20 | ||
402 | #define SDHCI_INTEL_PWR_TIMEOUT_UDELAY 100 | ||
403 | |||
404 | static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, | ||
405 | unsigned short vdd) | ||
406 | { | ||
407 | int cntr; | ||
408 | u8 reg; | ||
409 | |||
410 | sdhci_set_power(host, mode, vdd); | ||
411 | |||
412 | if (mode == MMC_POWER_OFF) | ||
413 | return; | ||
414 | |||
415 | /* | ||
416 | * Bus power might not enable after D3 -> D0 transition due to the | ||
417 | * present state not yet having propagated. Retry for up to 2ms. | ||
418 | */ | ||
419 | for (cntr = 0; cntr < SDHCI_INTEL_PWR_TIMEOUT_CNT; cntr++) { | ||
420 | reg = sdhci_readb(host, SDHCI_POWER_CONTROL); | ||
421 | if (reg & SDHCI_POWER_ON) | ||
422 | break; | ||
423 | udelay(SDHCI_INTEL_PWR_TIMEOUT_UDELAY); | ||
424 | reg |= SDHCI_POWER_ON; | ||
425 | sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | static const struct sdhci_ops sdhci_intel_byt_ops = { | ||
430 | .set_clock = sdhci_set_clock, | ||
431 | .set_power = sdhci_intel_set_power, | ||
432 | .enable_dma = sdhci_pci_enable_dma, | ||
433 | .set_bus_width = sdhci_pci_set_bus_width, | ||
434 | .reset = sdhci_reset, | ||
435 | .set_uhs_signaling = sdhci_set_uhs_signaling, | ||
436 | .hw_reset = sdhci_pci_hw_reset, | ||
437 | .select_drive_strength = sdhci_pci_select_drive_strength, | ||
438 | }; | ||
439 | |||
393 | static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { | 440 | static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { |
394 | .allow_runtime_pm = true, | 441 | .allow_runtime_pm = true, |
395 | .probe_slot = byt_emmc_probe_slot, | 442 | .probe_slot = byt_emmc_probe_slot, |
@@ -397,6 +444,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { | |||
397 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | 444 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
398 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | | 445 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | |
399 | SDHCI_QUIRK2_STOP_WITH_TC, | 446 | SDHCI_QUIRK2_STOP_WITH_TC, |
447 | .ops = &sdhci_intel_byt_ops, | ||
400 | }; | 448 | }; |
401 | 449 | ||
402 | static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | 450 | static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { |
@@ -405,6 +453,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | |||
405 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN, | 453 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN, |
406 | .allow_runtime_pm = true, | 454 | .allow_runtime_pm = true, |
407 | .probe_slot = byt_sdio_probe_slot, | 455 | .probe_slot = byt_sdio_probe_slot, |
456 | .ops = &sdhci_intel_byt_ops, | ||
408 | }; | 457 | }; |
409 | 458 | ||
410 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 459 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
@@ -415,6 +464,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | |||
415 | .allow_runtime_pm = true, | 464 | .allow_runtime_pm = true, |
416 | .own_cd_for_runtime_pm = true, | 465 | .own_cd_for_runtime_pm = true, |
417 | .probe_slot = byt_sd_probe_slot, | 466 | .probe_slot = byt_sd_probe_slot, |
467 | .ops = &sdhci_intel_byt_ops, | ||
418 | }; | 468 | }; |
419 | 469 | ||
420 | /* Define Host controllers for Intel Merrifield platform */ | 470 | /* Define Host controllers for Intel Merrifield platform */ |
@@ -1648,7 +1698,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( | |||
1648 | } | 1698 | } |
1649 | 1699 | ||
1650 | host->hw_name = "PCI"; | 1700 | host->hw_name = "PCI"; |
1651 | host->ops = &sdhci_pci_ops; | 1701 | host->ops = chip->fixes && chip->fixes->ops ? |
1702 | chip->fixes->ops : | ||
1703 | &sdhci_pci_ops; | ||
1652 | host->quirks = chip->quirks; | 1704 | host->quirks = chip->quirks; |
1653 | host->quirks2 = chip->quirks2; | 1705 | host->quirks2 = chip->quirks2; |
1654 | 1706 | ||
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 9c7c08b93223..6bccf56bc5ff 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h | |||
@@ -65,6 +65,8 @@ struct sdhci_pci_fixes { | |||
65 | 65 | ||
66 | int (*suspend) (struct sdhci_pci_chip *); | 66 | int (*suspend) (struct sdhci_pci_chip *); |
67 | int (*resume) (struct sdhci_pci_chip *); | 67 | int (*resume) (struct sdhci_pci_chip *); |
68 | |||
69 | const struct sdhci_ops *ops; | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | struct sdhci_pci_slot { | 72 | struct sdhci_pci_slot { |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index dd1938d341f7..d0f5c05fbc19 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
@@ -315,7 +315,7 @@ static void pxav3_set_power(struct sdhci_host *host, unsigned char mode, | |||
315 | struct mmc_host *mmc = host->mmc; | 315 | struct mmc_host *mmc = host->mmc; |
316 | u8 pwr = host->pwr; | 316 | u8 pwr = host->pwr; |
317 | 317 | ||
318 | sdhci_set_power(host, mode, vdd); | 318 | sdhci_set_power_noreg(host, mode, vdd); |
319 | 319 | ||
320 | if (host->pwr == pwr) | 320 | if (host->pwr == pwr) |
321 | return; | 321 | return; |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 48055666c655..71654b90227f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -687,7 +687,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) | |||
687 | * host->clock is in Hz. target_timeout is in us. | 687 | * host->clock is in Hz. target_timeout is in us. |
688 | * Hence, us = 1000000 * cycles / Hz. Round up. | 688 | * Hence, us = 1000000 * cycles / Hz. Round up. |
689 | */ | 689 | */ |
690 | val = 1000000 * data->timeout_clks; | 690 | val = 1000000ULL * data->timeout_clks; |
691 | if (do_div(val, host->clock)) | 691 | if (do_div(val, host->clock)) |
692 | target_timeout++; | 692 | target_timeout++; |
693 | target_timeout += val; | 693 | target_timeout += val; |
@@ -1077,6 +1077,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
1077 | /* Initially, a command has no error */ | 1077 | /* Initially, a command has no error */ |
1078 | cmd->error = 0; | 1078 | cmd->error = 0; |
1079 | 1079 | ||
1080 | if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && | ||
1081 | cmd->opcode == MMC_STOP_TRANSMISSION) | ||
1082 | cmd->flags |= MMC_RSP_BUSY; | ||
1083 | |||
1080 | /* Wait max 10 ms */ | 1084 | /* Wait max 10 ms */ |
1081 | timeout = 10; | 1085 | timeout = 10; |
1082 | 1086 | ||
@@ -1390,8 +1394,8 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, | |||
1390 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); | 1394 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); |
1391 | } | 1395 | } |
1392 | 1396 | ||
1393 | void sdhci_set_power(struct sdhci_host *host, unsigned char mode, | 1397 | void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, |
1394 | unsigned short vdd) | 1398 | unsigned short vdd) |
1395 | { | 1399 | { |
1396 | u8 pwr = 0; | 1400 | u8 pwr = 0; |
1397 | 1401 | ||
@@ -1455,20 +1459,17 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char mode, | |||
1455 | mdelay(10); | 1459 | mdelay(10); |
1456 | } | 1460 | } |
1457 | } | 1461 | } |
1458 | EXPORT_SYMBOL_GPL(sdhci_set_power); | 1462 | EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); |
1459 | 1463 | ||
1460 | static void __sdhci_set_power(struct sdhci_host *host, unsigned char mode, | 1464 | void sdhci_set_power(struct sdhci_host *host, unsigned char mode, |
1461 | unsigned short vdd) | 1465 | unsigned short vdd) |
1462 | { | 1466 | { |
1463 | struct mmc_host *mmc = host->mmc; | 1467 | if (IS_ERR(host->mmc->supply.vmmc)) |
1464 | 1468 | sdhci_set_power_noreg(host, mode, vdd); | |
1465 | if (host->ops->set_power) | ||
1466 | host->ops->set_power(host, mode, vdd); | ||
1467 | else if (!IS_ERR(mmc->supply.vmmc)) | ||
1468 | sdhci_set_power_reg(host, mode, vdd); | ||
1469 | else | 1469 | else |
1470 | sdhci_set_power(host, mode, vdd); | 1470 | sdhci_set_power_reg(host, mode, vdd); |
1471 | } | 1471 | } |
1472 | EXPORT_SYMBOL_GPL(sdhci_set_power); | ||
1472 | 1473 | ||
1473 | /*****************************************************************************\ | 1474 | /*****************************************************************************\ |
1474 | * * | 1475 | * * |
@@ -1609,7 +1610,10 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1609 | } | 1610 | } |
1610 | } | 1611 | } |
1611 | 1612 | ||
1612 | __sdhci_set_power(host, ios->power_mode, ios->vdd); | 1613 | if (host->ops->set_power) |
1614 | host->ops->set_power(host, ios->power_mode, ios->vdd); | ||
1615 | else | ||
1616 | sdhci_set_power(host, ios->power_mode, ios->vdd); | ||
1613 | 1617 | ||
1614 | if (host->ops->platform_send_init_74_clocks) | 1618 | if (host->ops->platform_send_init_74_clocks) |
1615 | host->ops->platform_send_init_74_clocks(host, ios->power_mode); | 1619 | host->ops->platform_send_init_74_clocks(host, ios->power_mode); |
@@ -2409,7 +2413,7 @@ static void sdhci_timeout_data_timer(unsigned long data) | |||
2409 | * * | 2413 | * * |
2410 | \*****************************************************************************/ | 2414 | \*****************************************************************************/ |
2411 | 2415 | ||
2412 | static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) | 2416 | static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) |
2413 | { | 2417 | { |
2414 | if (!host->cmd) { | 2418 | if (!host->cmd) { |
2415 | /* | 2419 | /* |
@@ -2453,11 +2457,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) | |||
2453 | return; | 2457 | return; |
2454 | } | 2458 | } |
2455 | 2459 | ||
2456 | if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && | ||
2457 | !(host->cmd->flags & MMC_RSP_BUSY) && !host->data && | ||
2458 | host->cmd->opcode == MMC_STOP_TRANSMISSION) | ||
2459 | *mask &= ~SDHCI_INT_DATA_END; | ||
2460 | |||
2461 | if (intmask & SDHCI_INT_RESPONSE) | 2460 | if (intmask & SDHCI_INT_RESPONSE) |
2462 | sdhci_finish_command(host); | 2461 | sdhci_finish_command(host); |
2463 | } | 2462 | } |
@@ -2680,8 +2679,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
2680 | } | 2679 | } |
2681 | 2680 | ||
2682 | if (intmask & SDHCI_INT_CMD_MASK) | 2681 | if (intmask & SDHCI_INT_CMD_MASK) |
2683 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, | 2682 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); |
2684 | &intmask); | ||
2685 | 2683 | ||
2686 | if (intmask & SDHCI_INT_DATA_MASK) | 2684 | if (intmask & SDHCI_INT_DATA_MASK) |
2687 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); | 2685 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c722cd23205c..766df17fb7eb 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -683,6 +683,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, | |||
683 | void sdhci_set_clock(struct sdhci_host *host, unsigned int clock); | 683 | void sdhci_set_clock(struct sdhci_host *host, unsigned int clock); |
684 | void sdhci_set_power(struct sdhci_host *host, unsigned char mode, | 684 | void sdhci_set_power(struct sdhci_host *host, unsigned char mode, |
685 | unsigned short vdd); | 685 | unsigned short vdd); |
686 | void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, | ||
687 | unsigned short vdd); | ||
686 | void sdhci_set_bus_width(struct sdhci_host *host, int width); | 688 | void sdhci_set_bus_width(struct sdhci_host *host, int width); |
687 | void sdhci_reset(struct sdhci_host *host, u8 mask); | 689 | void sdhci_reset(struct sdhci_host *host, u8 mask); |
688 | void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing); | 690 | void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing); |