diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-18 17:47:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-18 17:47:30 -0500 |
commit | c2ac2ae44d4c32382d001672021116e771bef4c9 (patch) | |
tree | 39a6ab0a118f562bb58ebc9e4c9cb709ac6ce29a | |
parent | 2d3c627502f2a9b0a7de06a5a2df2365542a72c9 (diff) | |
parent | e395c4387c746b4cc7aace4c44baecd7e69a3249 (diff) |
Merge tag 'mmc-updates-for-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC updates from Chris Ball:
"MMC highlights for 3.13:
Core:
- Improve runtime PM support, remove mmc_{suspend,resume}_host().
- Add MMC_CAP_RUNTIME_RESUME, for delaying MMC resume until we're
outside of the resume sequence (in runtime_resume) to decrease
system resume time.
Drivers:
- dw_mmc: Support HS200 mode.
- sdhci-eshdc-imx: Support SD3.0 SDR clock tuning, DDR on IMX6.
- sdhci-pci: Add support for Intel Clovertrail and Merrifield"
* tag 'mmc-updates-for-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (108 commits)
mmc: wbsd: Silence compiler warning
mmc: core: Silence compiler warning in __mmc_switch
mmc: sh_mmcif: Convert to clk_prepare|unprepare
mmc: sh_mmcif: Convert to PM macros when defining dev_pm_ops
mmc: dw_mmc: exynos: Revert the sdr_timing assignment
mmc: sdhci: Avoid needless loop while handling SDIO interrupts in sdhci_irq
mmc: core: Add MMC_CAP_RUNTIME_RESUME to resume at runtime_resume
mmc: core: Improve runtime PM support during suspend/resume for sd/mmc
mmc: core: Remove redundant mmc_power_up|off at runtime callbacks
mmc: Don't force card to active state when entering suspend/shutdown
MIPS: db1235: Don't use MMC_CLKGATE
mmc: core: Remove deprecated mmc_suspend|resume_host APIs
mmc: mmci: Move away from using deprecated APIs
mmc: via-sdmmc: Move away from using deprecated APIs
mmc: tmio: Move away from using deprecated APIs
mmc: sh_mmcif: Move away from using deprecated APIs
mmc: sdricoh_cs: Move away from using deprecated APIs
mmc: rtsx: Remove redundant suspend and resume callbacks
mmc: wbsd: Move away from using deprecated APIs
mmc: pxamci: Remove redundant suspend and resume callbacks
...
54 files changed, 1818 insertions, 1240 deletions
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt index 1dd622546d06..9046ba06c47a 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt | |||
@@ -12,6 +12,11 @@ Required properties: | |||
12 | Optional properties: | 12 | Optional properties: |
13 | - fsl,cd-controller : Indicate to use controller internal card detection | 13 | - fsl,cd-controller : Indicate to use controller internal card detection |
14 | - fsl,wp-controller : Indicate to use controller internal write protection | 14 | - fsl,wp-controller : Indicate to use controller internal write protection |
15 | - fsl,delay-line : Specify the number of delay cells for override mode. | ||
16 | This is used to set the clock delay for DLL(Delay Line) on override mode | ||
17 | to select a proper data sampling window in case the clock quality is not good | ||
18 | due to signal path is too long on the board. Please refer to eSDHC/uSDHC | ||
19 | chapter, DLL (Delay Line) section in RM for details. | ||
15 | 20 | ||
16 | Examples: | 21 | Examples: |
17 | 22 | ||
diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt index 066a78b034ca..8f3f13315358 100644 --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | |||
@@ -52,6 +52,9 @@ Optional properties: | |||
52 | is specified and the ciu clock is specified then we'll try to set the ciu | 52 | is specified and the ciu clock is specified then we'll try to set the ciu |
53 | clock to this at probe time. | 53 | clock to this at probe time. |
54 | 54 | ||
55 | * clock-freq-min-max: Minimum and Maximum clock frequency for card output | ||
56 | clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default. | ||
57 | |||
55 | * num-slots: specifies the number of slots supported by the controller. | 58 | * num-slots: specifies the number of slots supported by the controller. |
56 | The number of physical slots actually used could be equal or less than the | 59 | The number of physical slots actually used could be equal or less than the |
57 | value specified by num-slots. If this property is not specified, the value | 60 | value specified by num-slots. If this property is not specified, the value |
@@ -66,6 +69,10 @@ Optional properties: | |||
66 | 69 | ||
67 | * supports-highspeed: Enables support for high speed cards (up to 50MHz) | 70 | * supports-highspeed: Enables support for high speed cards (up to 50MHz) |
68 | 71 | ||
72 | * caps2-mmc-hs200-1_8v: Supports mmc HS200 SDR 1.8V mode | ||
73 | |||
74 | * caps2-mmc-hs200-1_2v: Supports mmc HS200 SDR 1.2V mode | ||
75 | |||
69 | * broken-cd: as documented in mmc core bindings. | 76 | * broken-cd: as documented in mmc core bindings. |
70 | 77 | ||
71 | * vmmc-supply: The phandle to the regulator to use for vmmc. If this is | 78 | * vmmc-supply: The phandle to the regulator to use for vmmc. If this is |
@@ -93,8 +100,10 @@ board specific portions as listed below. | |||
93 | 100 | ||
94 | dwmmc0@12200000 { | 101 | dwmmc0@12200000 { |
95 | clock-frequency = <400000000>; | 102 | clock-frequency = <400000000>; |
103 | clock-freq-min-max = <400000 200000000>; | ||
96 | num-slots = <1>; | 104 | num-slots = <1>; |
97 | supports-highspeed; | 105 | supports-highspeed; |
106 | caps2-mmc-hs200-1_8v; | ||
98 | broken-cd; | 107 | broken-cd; |
99 | fifo-depth = <0x80>; | 108 | fifo-depth = <0x80>; |
100 | card-detect-delay = <200>; | 109 | card-detect-delay = <200>; |
diff --git a/arch/mips/configs/db1235_defconfig b/arch/mips/configs/db1235_defconfig index e2b4ad55462f..28e49f226dc0 100644 --- a/arch/mips/configs/db1235_defconfig +++ b/arch/mips/configs/db1235_defconfig | |||
@@ -351,7 +351,6 @@ CONFIG_USB_OHCI_HCD=y | |||
351 | CONFIG_USB_OHCI_HCD_PLATFORM=y | 351 | CONFIG_USB_OHCI_HCD_PLATFORM=y |
352 | CONFIG_USB_STORAGE=y | 352 | CONFIG_USB_STORAGE=y |
353 | CONFIG_MMC=y | 353 | CONFIG_MMC=y |
354 | CONFIG_MMC_CLKGATE=y | ||
355 | CONFIG_MMC_AU1X=y | 354 | CONFIG_MMC_AU1X=y |
356 | CONFIG_NEW_LEDS=y | 355 | CONFIG_NEW_LEDS=y |
357 | CONFIG_LEDS_CLASS=y | 356 | CONFIG_LEDS_CLASS=y |
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 1fa8be409771..122f737a901f 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/mmc/sh_mmcif.h> | 15 | #include <linux/mmc/sh_mmcif.h> |
16 | #include <linux/mmc/sh_mobile_sdhi.h> | 16 | #include <linux/mmc/sh_mobile_sdhi.h> |
17 | #include <linux/mtd/physmap.h> | 17 | #include <linux/mtd/physmap.h> |
18 | #include <linux/mfd/tmio.h> | ||
18 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | #include <linux/io.h> | 21 | #include <linux/io.h> |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 1a3163f1407e..29d5d988a51c 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -2448,7 +2448,6 @@ static int _mmc_blk_suspend(struct mmc_card *card) | |||
2448 | struct mmc_blk_data *md = mmc_get_drvdata(card); | 2448 | struct mmc_blk_data *md = mmc_get_drvdata(card); |
2449 | 2449 | ||
2450 | if (md) { | 2450 | if (md) { |
2451 | pm_runtime_get_sync(&card->dev); | ||
2452 | mmc_queue_suspend(&md->queue); | 2451 | mmc_queue_suspend(&md->queue); |
2453 | list_for_each_entry(part_md, &md->part, part) { | 2452 | list_for_each_entry(part_md, &md->part, part) { |
2454 | mmc_queue_suspend(&part_md->queue); | 2453 | mmc_queue_suspend(&part_md->queue); |
@@ -2483,7 +2482,6 @@ static int mmc_blk_resume(struct mmc_card *card) | |||
2483 | list_for_each_entry(part_md, &md->part, part) { | 2482 | list_for_each_entry(part_md, &md->part, part) { |
2484 | mmc_queue_resume(&part_md->queue); | 2483 | mmc_queue_resume(&part_md->queue); |
2485 | } | 2484 | } |
2486 | pm_runtime_put(&card->dev); | ||
2487 | } | 2485 | } |
2488 | return 0; | 2486 | return 0; |
2489 | } | 2487 | } |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 3e227bd91e81..64145a32b917 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -342,7 +342,7 @@ int mmc_add_card(struct mmc_card *card) | |||
342 | break; | 342 | break; |
343 | } | 343 | } |
344 | 344 | ||
345 | if (mmc_sd_card_uhs(card) && | 345 | if (mmc_card_uhs(card) && |
346 | (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) | 346 | (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) |
347 | uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; | 347 | uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; |
348 | 348 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index bf18b6bfce48..57a2b403bf8e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
24 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
25 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
26 | #include <linux/pm_wakeup.h> | ||
26 | #include <linux/suspend.h> | 27 | #include <linux/suspend.h> |
27 | #include <linux/fault-inject.h> | 28 | #include <linux/fault-inject.h> |
28 | #include <linux/random.h> | 29 | #include <linux/random.h> |
@@ -301,7 +302,7 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) | |||
301 | } | 302 | } |
302 | 303 | ||
303 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 304 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
304 | EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal); | 305 | EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true); |
305 | if (err) { | 306 | if (err) { |
306 | pr_warn("%s: Error %d starting bkops\n", | 307 | pr_warn("%s: Error %d starting bkops\n", |
307 | mmc_hostname(card->host), err); | 308 | mmc_hostname(card->host), err); |
@@ -918,31 +919,6 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) | |||
918 | EXPORT_SYMBOL(__mmc_claim_host); | 919 | EXPORT_SYMBOL(__mmc_claim_host); |
919 | 920 | ||
920 | /** | 921 | /** |
921 | * mmc_try_claim_host - try exclusively to claim a host | ||
922 | * @host: mmc host to claim | ||
923 | * | ||
924 | * Returns %1 if the host is claimed, %0 otherwise. | ||
925 | */ | ||
926 | int mmc_try_claim_host(struct mmc_host *host) | ||
927 | { | ||
928 | int claimed_host = 0; | ||
929 | unsigned long flags; | ||
930 | |||
931 | spin_lock_irqsave(&host->lock, flags); | ||
932 | if (!host->claimed || host->claimer == current) { | ||
933 | host->claimed = 1; | ||
934 | host->claimer = current; | ||
935 | host->claim_cnt += 1; | ||
936 | claimed_host = 1; | ||
937 | } | ||
938 | spin_unlock_irqrestore(&host->lock, flags); | ||
939 | if (host->ops->enable && claimed_host && host->claim_cnt == 1) | ||
940 | host->ops->enable(host); | ||
941 | return claimed_host; | ||
942 | } | ||
943 | EXPORT_SYMBOL(mmc_try_claim_host); | ||
944 | |||
945 | /** | ||
946 | * mmc_release_host - release a host | 922 | * mmc_release_host - release a host |
947 | * @host: mmc host to release | 923 | * @host: mmc host to release |
948 | * | 924 | * |
@@ -1382,22 +1358,31 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) | |||
1382 | { | 1358 | { |
1383 | int bit; | 1359 | int bit; |
1384 | 1360 | ||
1385 | ocr &= host->ocr_avail; | 1361 | /* |
1362 | * Sanity check the voltages that the card claims to | ||
1363 | * support. | ||
1364 | */ | ||
1365 | if (ocr & 0x7F) { | ||
1366 | dev_warn(mmc_dev(host), | ||
1367 | "card claims to support voltages below defined range\n"); | ||
1368 | ocr &= ~0x7F; | ||
1369 | } | ||
1386 | 1370 | ||
1387 | bit = ffs(ocr); | 1371 | ocr &= host->ocr_avail; |
1388 | if (bit) { | 1372 | if (!ocr) { |
1389 | bit -= 1; | 1373 | dev_warn(mmc_dev(host), "no support for card's volts\n"); |
1374 | return 0; | ||
1375 | } | ||
1390 | 1376 | ||
1377 | if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { | ||
1378 | bit = ffs(ocr) - 1; | ||
1391 | ocr &= 3 << bit; | 1379 | ocr &= 3 << bit; |
1392 | 1380 | mmc_power_cycle(host, ocr); | |
1393 | mmc_host_clk_hold(host); | ||
1394 | host->ios.vdd = bit; | ||
1395 | mmc_set_ios(host); | ||
1396 | mmc_host_clk_release(host); | ||
1397 | } else { | 1381 | } else { |
1398 | pr_warning("%s: host doesn't support card's voltages\n", | 1382 | bit = fls(ocr) - 1; |
1399 | mmc_hostname(host)); | 1383 | ocr &= 3 << bit; |
1400 | ocr = 0; | 1384 | if (bit != host->ios.vdd) |
1385 | dev_warn(mmc_dev(host), "exceeding card's volts\n"); | ||
1401 | } | 1386 | } |
1402 | 1387 | ||
1403 | return ocr; | 1388 | return ocr; |
@@ -1422,7 +1407,7 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) | |||
1422 | 1407 | ||
1423 | } | 1408 | } |
1424 | 1409 | ||
1425 | int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) | 1410 | int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) |
1426 | { | 1411 | { |
1427 | struct mmc_command cmd = {0}; | 1412 | struct mmc_command cmd = {0}; |
1428 | int err = 0; | 1413 | int err = 0; |
@@ -1504,7 +1489,7 @@ power_cycle: | |||
1504 | if (err) { | 1489 | if (err) { |
1505 | pr_debug("%s: Signal voltage switch failed, " | 1490 | pr_debug("%s: Signal voltage switch failed, " |
1506 | "power cycling card\n", mmc_hostname(host)); | 1491 | "power cycling card\n", mmc_hostname(host)); |
1507 | mmc_power_cycle(host); | 1492 | mmc_power_cycle(host, ocr); |
1508 | } | 1493 | } |
1509 | 1494 | ||
1510 | mmc_host_clk_release(host); | 1495 | mmc_host_clk_release(host); |
@@ -1545,22 +1530,14 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) | |||
1545 | * If a host does all the power sequencing itself, ignore the | 1530 | * If a host does all the power sequencing itself, ignore the |
1546 | * initial MMC_POWER_UP stage. | 1531 | * initial MMC_POWER_UP stage. |
1547 | */ | 1532 | */ |
1548 | void mmc_power_up(struct mmc_host *host) | 1533 | void mmc_power_up(struct mmc_host *host, u32 ocr) |
1549 | { | 1534 | { |
1550 | int bit; | ||
1551 | |||
1552 | if (host->ios.power_mode == MMC_POWER_ON) | 1535 | if (host->ios.power_mode == MMC_POWER_ON) |
1553 | return; | 1536 | return; |
1554 | 1537 | ||
1555 | mmc_host_clk_hold(host); | 1538 | mmc_host_clk_hold(host); |
1556 | 1539 | ||
1557 | /* If ocr is set, we use it */ | 1540 | host->ios.vdd = fls(ocr) - 1; |
1558 | if (host->ocr) | ||
1559 | bit = ffs(host->ocr) - 1; | ||
1560 | else | ||
1561 | bit = fls(host->ocr_avail) - 1; | ||
1562 | |||
1563 | host->ios.vdd = bit; | ||
1564 | if (mmc_host_is_spi(host)) | 1541 | if (mmc_host_is_spi(host)) |
1565 | host->ios.chip_select = MMC_CS_HIGH; | 1542 | host->ios.chip_select = MMC_CS_HIGH; |
1566 | else | 1543 | else |
@@ -1604,13 +1581,6 @@ void mmc_power_off(struct mmc_host *host) | |||
1604 | host->ios.clock = 0; | 1581 | host->ios.clock = 0; |
1605 | host->ios.vdd = 0; | 1582 | host->ios.vdd = 0; |
1606 | 1583 | ||
1607 | |||
1608 | /* | ||
1609 | * Reset ocr mask to be the highest possible voltage supported for | ||
1610 | * this mmc host. This value will be used at next power up. | ||
1611 | */ | ||
1612 | host->ocr = 1 << (fls(host->ocr_avail) - 1); | ||
1613 | |||
1614 | if (!mmc_host_is_spi(host)) { | 1584 | if (!mmc_host_is_spi(host)) { |
1615 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 1585 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
1616 | host->ios.chip_select = MMC_CS_DONTCARE; | 1586 | host->ios.chip_select = MMC_CS_DONTCARE; |
@@ -1630,12 +1600,12 @@ void mmc_power_off(struct mmc_host *host) | |||
1630 | mmc_host_clk_release(host); | 1600 | mmc_host_clk_release(host); |
1631 | } | 1601 | } |
1632 | 1602 | ||
1633 | void mmc_power_cycle(struct mmc_host *host) | 1603 | void mmc_power_cycle(struct mmc_host *host, u32 ocr) |
1634 | { | 1604 | { |
1635 | mmc_power_off(host); | 1605 | mmc_power_off(host); |
1636 | /* Wait at least 1 ms according to SD spec */ | 1606 | /* Wait at least 1 ms according to SD spec */ |
1637 | mmc_delay(1); | 1607 | mmc_delay(1); |
1638 | mmc_power_up(host); | 1608 | mmc_power_up(host, ocr); |
1639 | } | 1609 | } |
1640 | 1610 | ||
1641 | /* | 1611 | /* |
@@ -1723,6 +1693,28 @@ void mmc_detach_bus(struct mmc_host *host) | |||
1723 | mmc_bus_put(host); | 1693 | mmc_bus_put(host); |
1724 | } | 1694 | } |
1725 | 1695 | ||
1696 | static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, | ||
1697 | bool cd_irq) | ||
1698 | { | ||
1699 | #ifdef CONFIG_MMC_DEBUG | ||
1700 | unsigned long flags; | ||
1701 | spin_lock_irqsave(&host->lock, flags); | ||
1702 | WARN_ON(host->removed); | ||
1703 | spin_unlock_irqrestore(&host->lock, flags); | ||
1704 | #endif | ||
1705 | |||
1706 | /* | ||
1707 | * If the device is configured as wakeup, we prevent a new sleep for | ||
1708 | * 5 s to give provision for user space to consume the event. | ||
1709 | */ | ||
1710 | if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) && | ||
1711 | device_can_wakeup(mmc_dev(host))) | ||
1712 | pm_wakeup_event(mmc_dev(host), 5000); | ||
1713 | |||
1714 | host->detect_change = 1; | ||
1715 | mmc_schedule_delayed_work(&host->detect, delay); | ||
1716 | } | ||
1717 | |||
1726 | /** | 1718 | /** |
1727 | * mmc_detect_change - process change of state on a MMC socket | 1719 | * mmc_detect_change - process change of state on a MMC socket |
1728 | * @host: host which changed state. | 1720 | * @host: host which changed state. |
@@ -1735,16 +1727,8 @@ void mmc_detach_bus(struct mmc_host *host) | |||
1735 | */ | 1727 | */ |
1736 | void mmc_detect_change(struct mmc_host *host, unsigned long delay) | 1728 | void mmc_detect_change(struct mmc_host *host, unsigned long delay) |
1737 | { | 1729 | { |
1738 | #ifdef CONFIG_MMC_DEBUG | 1730 | _mmc_detect_change(host, delay, true); |
1739 | unsigned long flags; | ||
1740 | spin_lock_irqsave(&host->lock, flags); | ||
1741 | WARN_ON(host->removed); | ||
1742 | spin_unlock_irqrestore(&host->lock, flags); | ||
1743 | #endif | ||
1744 | host->detect_change = 1; | ||
1745 | mmc_schedule_delayed_work(&host->detect, delay); | ||
1746 | } | 1731 | } |
1747 | |||
1748 | EXPORT_SYMBOL(mmc_detect_change); | 1732 | EXPORT_SYMBOL(mmc_detect_change); |
1749 | 1733 | ||
1750 | void mmc_init_erase(struct mmc_card *card) | 1734 | void mmc_init_erase(struct mmc_card *card) |
@@ -2334,7 +2318,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) | |||
2334 | pr_info("%s: %s: trying to init card at %u Hz\n", | 2318 | pr_info("%s: %s: trying to init card at %u Hz\n", |
2335 | mmc_hostname(host), __func__, host->f_init); | 2319 | mmc_hostname(host), __func__, host->f_init); |
2336 | #endif | 2320 | #endif |
2337 | mmc_power_up(host); | 2321 | mmc_power_up(host, host->ocr_avail); |
2338 | 2322 | ||
2339 | /* | 2323 | /* |
2340 | * Some eMMCs (with VCCQ always on) may not be reset after power up, so | 2324 | * Some eMMCs (with VCCQ always on) may not be reset after power up, so |
@@ -2423,7 +2407,7 @@ int mmc_detect_card_removed(struct mmc_host *host) | |||
2423 | * rescan handle the card removal. | 2407 | * rescan handle the card removal. |
2424 | */ | 2408 | */ |
2425 | cancel_delayed_work(&host->detect); | 2409 | cancel_delayed_work(&host->detect); |
2426 | mmc_detect_change(host, 0); | 2410 | _mmc_detect_change(host, 0, false); |
2427 | } | 2411 | } |
2428 | } | 2412 | } |
2429 | 2413 | ||
@@ -2504,8 +2488,8 @@ void mmc_start_host(struct mmc_host *host) | |||
2504 | if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP) | 2488 | if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP) |
2505 | mmc_power_off(host); | 2489 | mmc_power_off(host); |
2506 | else | 2490 | else |
2507 | mmc_power_up(host); | 2491 | mmc_power_up(host, host->ocr_avail); |
2508 | mmc_detect_change(host, 0); | 2492 | _mmc_detect_change(host, 0, false); |
2509 | } | 2493 | } |
2510 | 2494 | ||
2511 | void mmc_stop_host(struct mmc_host *host) | 2495 | void mmc_stop_host(struct mmc_host *host) |
@@ -2583,7 +2567,7 @@ int mmc_power_restore_host(struct mmc_host *host) | |||
2583 | return -EINVAL; | 2567 | return -EINVAL; |
2584 | } | 2568 | } |
2585 | 2569 | ||
2586 | mmc_power_up(host); | 2570 | mmc_power_up(host, host->card->ocr); |
2587 | ret = host->bus_ops->power_restore(host); | 2571 | ret = host->bus_ops->power_restore(host); |
2588 | 2572 | ||
2589 | mmc_bus_put(host); | 2573 | mmc_bus_put(host); |
@@ -2657,28 +2641,6 @@ EXPORT_SYMBOL(mmc_cache_ctrl); | |||
2657 | 2641 | ||
2658 | #ifdef CONFIG_PM | 2642 | #ifdef CONFIG_PM |
2659 | 2643 | ||
2660 | /** | ||
2661 | * mmc_suspend_host - suspend a host | ||
2662 | * @host: mmc host | ||
2663 | */ | ||
2664 | int mmc_suspend_host(struct mmc_host *host) | ||
2665 | { | ||
2666 | /* This function is deprecated */ | ||
2667 | return 0; | ||
2668 | } | ||
2669 | EXPORT_SYMBOL(mmc_suspend_host); | ||
2670 | |||
2671 | /** | ||
2672 | * mmc_resume_host - resume a previously suspended host | ||
2673 | * @host: mmc host | ||
2674 | */ | ||
2675 | int mmc_resume_host(struct mmc_host *host) | ||
2676 | { | ||
2677 | /* This function is deprecated */ | ||
2678 | return 0; | ||
2679 | } | ||
2680 | EXPORT_SYMBOL(mmc_resume_host); | ||
2681 | |||
2682 | /* Do the card removal on suspend if card is assumed removeable | 2644 | /* Do the card removal on suspend if card is assumed removeable |
2683 | * Do that in pm notifier while userspace isn't yet frozen, so we will be able | 2645 | * Do that in pm notifier while userspace isn't yet frozen, so we will be able |
2684 | to sync the card. | 2646 | to sync the card. |
@@ -2724,7 +2686,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
2724 | spin_lock_irqsave(&host->lock, flags); | 2686 | spin_lock_irqsave(&host->lock, flags); |
2725 | host->rescan_disable = 0; | 2687 | host->rescan_disable = 0; |
2726 | spin_unlock_irqrestore(&host->lock, flags); | 2688 | spin_unlock_irqrestore(&host->lock, flags); |
2727 | mmc_detect_change(host, 0); | 2689 | _mmc_detect_change(host, 0, false); |
2728 | 2690 | ||
2729 | } | 2691 | } |
2730 | 2692 | ||
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 5345d156493e..443a584660f0 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
@@ -42,13 +42,13 @@ void mmc_set_ungated(struct mmc_host *host); | |||
42 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); | 42 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); |
43 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); | 43 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); |
44 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); | 44 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); |
45 | int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); | 45 | int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr); |
46 | int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); | 46 | int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); |
47 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); | 47 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); |
48 | void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); | 48 | void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); |
49 | void mmc_power_up(struct mmc_host *host); | 49 | void mmc_power_up(struct mmc_host *host, u32 ocr); |
50 | void mmc_power_off(struct mmc_host *host); | 50 | void mmc_power_off(struct mmc_host *host); |
51 | void mmc_power_cycle(struct mmc_host *host); | 51 | void mmc_power_cycle(struct mmc_host *host, u32 ocr); |
52 | 52 | ||
53 | static inline void mmc_delay(unsigned int ms) | 53 | static inline void mmc_delay(unsigned int ms) |
54 | { | 54 | { |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6d02012a1d0b..f631f5a9bf79 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/stat.h> | 15 | #include <linux/stat.h> |
16 | #include <linux/pm_runtime.h> | ||
16 | 17 | ||
17 | #include <linux/mmc/host.h> | 18 | #include <linux/mmc/host.h> |
18 | #include <linux/mmc/card.h> | 19 | #include <linux/mmc/card.h> |
@@ -934,6 +935,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
934 | goto err; | 935 | goto err; |
935 | } | 936 | } |
936 | 937 | ||
938 | card->ocr = ocr; | ||
937 | card->type = MMC_TYPE_MMC; | 939 | card->type = MMC_TYPE_MMC; |
938 | card->rca = 1; | 940 | card->rca = 1; |
939 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); | 941 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); |
@@ -1404,9 +1406,9 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) | |||
1404 | if (notify_type == EXT_CSD_POWER_OFF_LONG) | 1406 | if (notify_type == EXT_CSD_POWER_OFF_LONG) |
1405 | timeout = card->ext_csd.power_off_longtime; | 1407 | timeout = card->ext_csd.power_off_longtime; |
1406 | 1408 | ||
1407 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1409 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
1408 | EXT_CSD_POWER_OFF_NOTIFICATION, | 1410 | EXT_CSD_POWER_OFF_NOTIFICATION, |
1409 | notify_type, timeout); | 1411 | notify_type, timeout, true, false); |
1410 | if (err) | 1412 | if (err) |
1411 | pr_err("%s: Power Off Notification timed out, %u\n", | 1413 | pr_err("%s: Power Off Notification timed out, %u\n", |
1412 | mmc_hostname(card->host), timeout); | 1414 | mmc_hostname(card->host), timeout); |
@@ -1477,6 +1479,9 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) | |||
1477 | 1479 | ||
1478 | mmc_claim_host(host); | 1480 | mmc_claim_host(host); |
1479 | 1481 | ||
1482 | if (mmc_card_suspended(host->card)) | ||
1483 | goto out; | ||
1484 | |||
1480 | if (mmc_card_doing_bkops(host->card)) { | 1485 | if (mmc_card_doing_bkops(host->card)) { |
1481 | err = mmc_stop_bkops(host->card); | 1486 | err = mmc_stop_bkops(host->card); |
1482 | if (err) | 1487 | if (err) |
@@ -1496,51 +1501,93 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) | |||
1496 | err = mmc_deselect_cards(host); | 1501 | err = mmc_deselect_cards(host); |
1497 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); | 1502 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
1498 | 1503 | ||
1499 | if (!err) | 1504 | if (!err) { |
1500 | mmc_power_off(host); | 1505 | mmc_power_off(host); |
1506 | mmc_card_set_suspended(host->card); | ||
1507 | } | ||
1501 | out: | 1508 | out: |
1502 | mmc_release_host(host); | 1509 | mmc_release_host(host); |
1503 | return err; | 1510 | return err; |
1504 | } | 1511 | } |
1505 | 1512 | ||
1506 | /* | 1513 | /* |
1507 | * Suspend callback from host. | 1514 | * Suspend callback |
1508 | */ | 1515 | */ |
1509 | static int mmc_suspend(struct mmc_host *host) | 1516 | static int mmc_suspend(struct mmc_host *host) |
1510 | { | 1517 | { |
1511 | return _mmc_suspend(host, true); | 1518 | int err; |
1512 | } | ||
1513 | 1519 | ||
1514 | /* | 1520 | err = _mmc_suspend(host, true); |
1515 | * Shutdown callback | 1521 | if (!err) { |
1516 | */ | 1522 | pm_runtime_disable(&host->card->dev); |
1517 | static int mmc_shutdown(struct mmc_host *host) | 1523 | pm_runtime_set_suspended(&host->card->dev); |
1518 | { | 1524 | } |
1519 | return _mmc_suspend(host, false); | 1525 | |
1526 | return err; | ||
1520 | } | 1527 | } |
1521 | 1528 | ||
1522 | /* | 1529 | /* |
1523 | * Resume callback from host. | ||
1524 | * | ||
1525 | * This function tries to determine if the same card is still present | 1530 | * This function tries to determine if the same card is still present |
1526 | * and, if so, restore all state to it. | 1531 | * and, if so, restore all state to it. |
1527 | */ | 1532 | */ |
1528 | static int mmc_resume(struct mmc_host *host) | 1533 | static int _mmc_resume(struct mmc_host *host) |
1529 | { | 1534 | { |
1530 | int err; | 1535 | int err = 0; |
1531 | 1536 | ||
1532 | BUG_ON(!host); | 1537 | BUG_ON(!host); |
1533 | BUG_ON(!host->card); | 1538 | BUG_ON(!host->card); |
1534 | 1539 | ||
1535 | mmc_claim_host(host); | 1540 | mmc_claim_host(host); |
1536 | mmc_power_up(host); | 1541 | |
1537 | mmc_select_voltage(host, host->ocr); | 1542 | if (!mmc_card_suspended(host->card)) |
1538 | err = mmc_init_card(host, host->ocr, host->card); | 1543 | goto out; |
1544 | |||
1545 | mmc_power_up(host, host->card->ocr); | ||
1546 | err = mmc_init_card(host, host->card->ocr, host->card); | ||
1547 | mmc_card_clr_suspended(host->card); | ||
1548 | |||
1549 | out: | ||
1539 | mmc_release_host(host); | 1550 | mmc_release_host(host); |
1551 | return err; | ||
1552 | } | ||
1553 | |||
1554 | /* | ||
1555 | * Shutdown callback | ||
1556 | */ | ||
1557 | static int mmc_shutdown(struct mmc_host *host) | ||
1558 | { | ||
1559 | int err = 0; | ||
1560 | |||
1561 | /* | ||
1562 | * In a specific case for poweroff notify, we need to resume the card | ||
1563 | * before we can shutdown it properly. | ||
1564 | */ | ||
1565 | if (mmc_can_poweroff_notify(host->card) && | ||
1566 | !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE)) | ||
1567 | err = _mmc_resume(host); | ||
1568 | |||
1569 | if (!err) | ||
1570 | err = _mmc_suspend(host, false); | ||
1540 | 1571 | ||
1541 | return err; | 1572 | return err; |
1542 | } | 1573 | } |
1543 | 1574 | ||
1575 | /* | ||
1576 | * Callback for resume. | ||
1577 | */ | ||
1578 | static int mmc_resume(struct mmc_host *host) | ||
1579 | { | ||
1580 | int err = 0; | ||
1581 | |||
1582 | if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) { | ||
1583 | err = _mmc_resume(host); | ||
1584 | pm_runtime_set_active(&host->card->dev); | ||
1585 | pm_runtime_mark_last_busy(&host->card->dev); | ||
1586 | } | ||
1587 | pm_runtime_enable(&host->card->dev); | ||
1588 | |||
1589 | return err; | ||
1590 | } | ||
1544 | 1591 | ||
1545 | /* | 1592 | /* |
1546 | * Callback for runtime_suspend. | 1593 | * Callback for runtime_suspend. |
@@ -1552,18 +1599,11 @@ static int mmc_runtime_suspend(struct mmc_host *host) | |||
1552 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) | 1599 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) |
1553 | return 0; | 1600 | return 0; |
1554 | 1601 | ||
1555 | mmc_claim_host(host); | 1602 | err = _mmc_suspend(host, true); |
1556 | 1603 | if (err) | |
1557 | err = mmc_suspend(host); | ||
1558 | if (err) { | ||
1559 | pr_err("%s: error %d doing aggessive suspend\n", | 1604 | pr_err("%s: error %d doing aggessive suspend\n", |
1560 | mmc_hostname(host), err); | 1605 | mmc_hostname(host), err); |
1561 | goto out; | ||
1562 | } | ||
1563 | mmc_power_off(host); | ||
1564 | 1606 | ||
1565 | out: | ||
1566 | mmc_release_host(host); | ||
1567 | return err; | 1607 | return err; |
1568 | } | 1608 | } |
1569 | 1609 | ||
@@ -1574,18 +1614,14 @@ static int mmc_runtime_resume(struct mmc_host *host) | |||
1574 | { | 1614 | { |
1575 | int err; | 1615 | int err; |
1576 | 1616 | ||
1577 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) | 1617 | if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME))) |
1578 | return 0; | 1618 | return 0; |
1579 | 1619 | ||
1580 | mmc_claim_host(host); | 1620 | err = _mmc_resume(host); |
1581 | |||
1582 | mmc_power_up(host); | ||
1583 | err = mmc_resume(host); | ||
1584 | if (err) | 1621 | if (err) |
1585 | pr_err("%s: error %d doing aggessive resume\n", | 1622 | pr_err("%s: error %d doing aggessive resume\n", |
1586 | mmc_hostname(host), err); | 1623 | mmc_hostname(host), err); |
1587 | 1624 | ||
1588 | mmc_release_host(host); | ||
1589 | return 0; | 1625 | return 0; |
1590 | } | 1626 | } |
1591 | 1627 | ||
@@ -1595,7 +1631,7 @@ static int mmc_power_restore(struct mmc_host *host) | |||
1595 | 1631 | ||
1596 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); | 1632 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
1597 | mmc_claim_host(host); | 1633 | mmc_claim_host(host); |
1598 | ret = mmc_init_card(host, host->ocr, host->card); | 1634 | ret = mmc_init_card(host, host->card->ocr, host->card); |
1599 | mmc_release_host(host); | 1635 | mmc_release_host(host); |
1600 | 1636 | ||
1601 | return ret; | 1637 | return ret; |
@@ -1640,7 +1676,7 @@ static void mmc_attach_bus_ops(struct mmc_host *host) | |||
1640 | int mmc_attach_mmc(struct mmc_host *host) | 1676 | int mmc_attach_mmc(struct mmc_host *host) |
1641 | { | 1677 | { |
1642 | int err; | 1678 | int err; |
1643 | u32 ocr; | 1679 | u32 ocr, rocr; |
1644 | 1680 | ||
1645 | BUG_ON(!host); | 1681 | BUG_ON(!host); |
1646 | WARN_ON(!host->claimed); | 1682 | WARN_ON(!host->claimed); |
@@ -1666,23 +1702,12 @@ int mmc_attach_mmc(struct mmc_host *host) | |||
1666 | goto err; | 1702 | goto err; |
1667 | } | 1703 | } |
1668 | 1704 | ||
1669 | /* | 1705 | rocr = mmc_select_voltage(host, ocr); |
1670 | * Sanity check the voltages that the card claims to | ||
1671 | * support. | ||
1672 | */ | ||
1673 | if (ocr & 0x7F) { | ||
1674 | pr_warning("%s: card claims to support voltages " | ||
1675 | "below the defined range. These will be ignored.\n", | ||
1676 | mmc_hostname(host)); | ||
1677 | ocr &= ~0x7F; | ||
1678 | } | ||
1679 | |||
1680 | host->ocr = mmc_select_voltage(host, ocr); | ||
1681 | 1706 | ||
1682 | /* | 1707 | /* |
1683 | * Can we support the voltage of the card? | 1708 | * Can we support the voltage of the card? |
1684 | */ | 1709 | */ |
1685 | if (!host->ocr) { | 1710 | if (!rocr) { |
1686 | err = -EINVAL; | 1711 | err = -EINVAL; |
1687 | goto err; | 1712 | goto err; |
1688 | } | 1713 | } |
@@ -1690,7 +1715,7 @@ int mmc_attach_mmc(struct mmc_host *host) | |||
1690 | /* | 1715 | /* |
1691 | * Detect and init the card. | 1716 | * Detect and init the card. |
1692 | */ | 1717 | */ |
1693 | err = mmc_init_card(host, host->ocr, NULL); | 1718 | err = mmc_init_card(host, rocr, NULL); |
1694 | if (err) | 1719 | if (err) |
1695 | goto err; | 1720 | goto err; |
1696 | 1721 | ||
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index ef183483d5b6..e5b5eeb548d1 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
@@ -23,6 +23,40 @@ | |||
23 | 23 | ||
24 | #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ | 24 | #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ |
25 | 25 | ||
26 | static inline int __mmc_send_status(struct mmc_card *card, u32 *status, | ||
27 | bool ignore_crc) | ||
28 | { | ||
29 | int err; | ||
30 | struct mmc_command cmd = {0}; | ||
31 | |||
32 | BUG_ON(!card); | ||
33 | BUG_ON(!card->host); | ||
34 | |||
35 | cmd.opcode = MMC_SEND_STATUS; | ||
36 | if (!mmc_host_is_spi(card->host)) | ||
37 | cmd.arg = card->rca << 16; | ||
38 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; | ||
39 | if (ignore_crc) | ||
40 | cmd.flags &= ~MMC_RSP_CRC; | ||
41 | |||
42 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | ||
43 | if (err) | ||
44 | return err; | ||
45 | |||
46 | /* NOTE: callers are required to understand the difference | ||
47 | * between "native" and SPI format status words! | ||
48 | */ | ||
49 | if (status) | ||
50 | *status = cmd.resp[0]; | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | int mmc_send_status(struct mmc_card *card, u32 *status) | ||
56 | { | ||
57 | return __mmc_send_status(card, status, false); | ||
58 | } | ||
59 | |||
26 | static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) | 60 | static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) |
27 | { | 61 | { |
28 | int err; | 62 | int err; |
@@ -370,16 +404,18 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc) | |||
370 | * @timeout_ms: timeout (ms) for operation performed by register write, | 404 | * @timeout_ms: timeout (ms) for operation performed by register write, |
371 | * timeout of zero implies maximum possible timeout | 405 | * timeout of zero implies maximum possible timeout |
372 | * @use_busy_signal: use the busy signal as response type | 406 | * @use_busy_signal: use the busy signal as response type |
407 | * @send_status: send status cmd to poll for busy | ||
373 | * | 408 | * |
374 | * Modifies the EXT_CSD register for selected card. | 409 | * Modifies the EXT_CSD register for selected card. |
375 | */ | 410 | */ |
376 | int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | 411 | int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, |
377 | unsigned int timeout_ms, bool use_busy_signal) | 412 | unsigned int timeout_ms, bool use_busy_signal, bool send_status) |
378 | { | 413 | { |
379 | int err; | 414 | int err; |
380 | struct mmc_command cmd = {0}; | 415 | struct mmc_command cmd = {0}; |
381 | unsigned long timeout; | 416 | unsigned long timeout; |
382 | u32 status; | 417 | u32 status = 0; |
418 | bool ignore_crc = false; | ||
383 | 419 | ||
384 | BUG_ON(!card); | 420 | BUG_ON(!card); |
385 | BUG_ON(!card->host); | 421 | BUG_ON(!card->host); |
@@ -408,17 +444,37 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
408 | if (!use_busy_signal) | 444 | if (!use_busy_signal) |
409 | return 0; | 445 | return 0; |
410 | 446 | ||
411 | /* Must check status to be sure of no errors */ | 447 | /* |
448 | * Must check status to be sure of no errors | ||
449 | * If CMD13 is to check the busy completion of the timing change, | ||
450 | * disable the check of CRC error. | ||
451 | */ | ||
452 | if (index == EXT_CSD_HS_TIMING && | ||
453 | !(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)) | ||
454 | ignore_crc = true; | ||
455 | |||
412 | timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); | 456 | timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); |
413 | do { | 457 | do { |
414 | err = mmc_send_status(card, &status); | 458 | if (send_status) { |
415 | if (err) | 459 | err = __mmc_send_status(card, &status, ignore_crc); |
416 | return err; | 460 | if (err) |
461 | return err; | ||
462 | } | ||
417 | if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) | 463 | if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) |
418 | break; | 464 | break; |
419 | if (mmc_host_is_spi(card->host)) | 465 | if (mmc_host_is_spi(card->host)) |
420 | break; | 466 | break; |
421 | 467 | ||
468 | /* | ||
469 | * We are not allowed to issue a status command and the host | ||
470 | * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only | ||
471 | * rely on waiting for the stated timeout to be sufficient. | ||
472 | */ | ||
473 | if (!send_status) { | ||
474 | mmc_delay(timeout_ms); | ||
475 | return 0; | ||
476 | } | ||
477 | |||
422 | /* Timeout if the device never leaves the program state. */ | 478 | /* Timeout if the device never leaves the program state. */ |
423 | if (time_after(jiffies, timeout)) { | 479 | if (time_after(jiffies, timeout)) { |
424 | pr_err("%s: Card stuck in programming state! %s\n", | 480 | pr_err("%s: Card stuck in programming state! %s\n", |
@@ -445,36 +501,10 @@ EXPORT_SYMBOL_GPL(__mmc_switch); | |||
445 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | 501 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, |
446 | unsigned int timeout_ms) | 502 | unsigned int timeout_ms) |
447 | { | 503 | { |
448 | return __mmc_switch(card, set, index, value, timeout_ms, true); | 504 | return __mmc_switch(card, set, index, value, timeout_ms, true, true); |
449 | } | 505 | } |
450 | EXPORT_SYMBOL_GPL(mmc_switch); | 506 | EXPORT_SYMBOL_GPL(mmc_switch); |
451 | 507 | ||
452 | int mmc_send_status(struct mmc_card *card, u32 *status) | ||
453 | { | ||
454 | int err; | ||
455 | struct mmc_command cmd = {0}; | ||
456 | |||
457 | BUG_ON(!card); | ||
458 | BUG_ON(!card->host); | ||
459 | |||
460 | cmd.opcode = MMC_SEND_STATUS; | ||
461 | if (!mmc_host_is_spi(card->host)) | ||
462 | cmd.arg = card->rca << 16; | ||
463 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; | ||
464 | |||
465 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | ||
466 | if (err) | ||
467 | return err; | ||
468 | |||
469 | /* NOTE: callers are required to understand the difference | ||
470 | * between "native" and SPI format status words! | ||
471 | */ | ||
472 | if (status) | ||
473 | *status = cmd.resp[0]; | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static int | 508 | static int |
479 | mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, | 509 | mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, |
480 | u8 len) | 510 | u8 len) |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5e8823dc3ef6..6f42050b7ccc 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/stat.h> | 15 | #include <linux/stat.h> |
16 | #include <linux/pm_runtime.h> | ||
16 | 17 | ||
17 | #include <linux/mmc/host.h> | 18 | #include <linux/mmc/host.h> |
18 | #include <linux/mmc/card.h> | 19 | #include <linux/mmc/card.h> |
@@ -721,6 +722,7 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr) | |||
721 | int err; | 722 | int err; |
722 | u32 max_current; | 723 | u32 max_current; |
723 | int retries = 10; | 724 | int retries = 10; |
725 | u32 pocr = ocr; | ||
724 | 726 | ||
725 | try_again: | 727 | try_again: |
726 | if (!retries) { | 728 | if (!retries) { |
@@ -773,7 +775,8 @@ try_again: | |||
773 | */ | 775 | */ |
774 | if (!mmc_host_is_spi(host) && rocr && | 776 | if (!mmc_host_is_spi(host) && rocr && |
775 | ((*rocr & 0x41000000) == 0x41000000)) { | 777 | ((*rocr & 0x41000000) == 0x41000000)) { |
776 | err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); | 778 | err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, |
779 | pocr); | ||
777 | if (err == -EAGAIN) { | 780 | if (err == -EAGAIN) { |
778 | retries--; | 781 | retries--; |
779 | goto try_again; | 782 | goto try_again; |
@@ -935,6 +938,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
935 | if (IS_ERR(card)) | 938 | if (IS_ERR(card)) |
936 | return PTR_ERR(card); | 939 | return PTR_ERR(card); |
937 | 940 | ||
941 | card->ocr = ocr; | ||
938 | card->type = MMC_TYPE_SD; | 942 | card->type = MMC_TYPE_SD; |
939 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); | 943 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); |
940 | } | 944 | } |
@@ -1064,10 +1068,7 @@ static void mmc_sd_detect(struct mmc_host *host) | |||
1064 | } | 1068 | } |
1065 | } | 1069 | } |
1066 | 1070 | ||
1067 | /* | 1071 | static int _mmc_sd_suspend(struct mmc_host *host) |
1068 | * Suspend callback from host. | ||
1069 | */ | ||
1070 | static int mmc_sd_suspend(struct mmc_host *host) | ||
1071 | { | 1072 | { |
1072 | int err = 0; | 1073 | int err = 0; |
1073 | 1074 | ||
@@ -1075,34 +1076,77 @@ static int mmc_sd_suspend(struct mmc_host *host) | |||
1075 | BUG_ON(!host->card); | 1076 | BUG_ON(!host->card); |
1076 | 1077 | ||
1077 | mmc_claim_host(host); | 1078 | mmc_claim_host(host); |
1079 | |||
1080 | if (mmc_card_suspended(host->card)) | ||
1081 | goto out; | ||
1082 | |||
1078 | if (!mmc_host_is_spi(host)) | 1083 | if (!mmc_host_is_spi(host)) |
1079 | err = mmc_deselect_cards(host); | 1084 | err = mmc_deselect_cards(host); |
1080 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 1085 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
1081 | if (!err) | 1086 | if (!err) { |
1082 | mmc_power_off(host); | 1087 | mmc_power_off(host); |
1088 | mmc_card_set_suspended(host->card); | ||
1089 | } | ||
1090 | |||
1091 | out: | ||
1083 | mmc_release_host(host); | 1092 | mmc_release_host(host); |
1093 | return err; | ||
1094 | } | ||
1095 | |||
1096 | /* | ||
1097 | * Callback for suspend | ||
1098 | */ | ||
1099 | static int mmc_sd_suspend(struct mmc_host *host) | ||
1100 | { | ||
1101 | int err; | ||
1102 | |||
1103 | err = _mmc_sd_suspend(host); | ||
1104 | if (!err) { | ||
1105 | pm_runtime_disable(&host->card->dev); | ||
1106 | pm_runtime_set_suspended(&host->card->dev); | ||
1107 | } | ||
1084 | 1108 | ||
1085 | return err; | 1109 | return err; |
1086 | } | 1110 | } |
1087 | 1111 | ||
1088 | /* | 1112 | /* |
1089 | * Resume callback from host. | ||
1090 | * | ||
1091 | * This function tries to determine if the same card is still present | 1113 | * This function tries to determine if the same card is still present |
1092 | * and, if so, restore all state to it. | 1114 | * and, if so, restore all state to it. |
1093 | */ | 1115 | */ |
1094 | static int mmc_sd_resume(struct mmc_host *host) | 1116 | static int _mmc_sd_resume(struct mmc_host *host) |
1095 | { | 1117 | { |
1096 | int err; | 1118 | int err = 0; |
1097 | 1119 | ||
1098 | BUG_ON(!host); | 1120 | BUG_ON(!host); |
1099 | BUG_ON(!host->card); | 1121 | BUG_ON(!host->card); |
1100 | 1122 | ||
1101 | mmc_claim_host(host); | 1123 | mmc_claim_host(host); |
1102 | mmc_power_up(host); | 1124 | |
1103 | mmc_select_voltage(host, host->ocr); | 1125 | if (!mmc_card_suspended(host->card)) |
1104 | err = mmc_sd_init_card(host, host->ocr, host->card); | 1126 | goto out; |
1127 | |||
1128 | mmc_power_up(host, host->card->ocr); | ||
1129 | err = mmc_sd_init_card(host, host->card->ocr, host->card); | ||
1130 | mmc_card_clr_suspended(host->card); | ||
1131 | |||
1132 | out: | ||
1105 | mmc_release_host(host); | 1133 | mmc_release_host(host); |
1134 | return err; | ||
1135 | } | ||
1136 | |||
1137 | /* | ||
1138 | * Callback for resume | ||
1139 | */ | ||
1140 | static int mmc_sd_resume(struct mmc_host *host) | ||
1141 | { | ||
1142 | int err = 0; | ||
1143 | |||
1144 | if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) { | ||
1145 | err = _mmc_sd_resume(host); | ||
1146 | pm_runtime_set_active(&host->card->dev); | ||
1147 | pm_runtime_mark_last_busy(&host->card->dev); | ||
1148 | } | ||
1149 | pm_runtime_enable(&host->card->dev); | ||
1106 | 1150 | ||
1107 | return err; | 1151 | return err; |
1108 | } | 1152 | } |
@@ -1117,18 +1161,11 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host) | |||
1117 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) | 1161 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) |
1118 | return 0; | 1162 | return 0; |
1119 | 1163 | ||
1120 | mmc_claim_host(host); | 1164 | err = _mmc_sd_suspend(host); |
1121 | 1165 | if (err) | |
1122 | err = mmc_sd_suspend(host); | ||
1123 | if (err) { | ||
1124 | pr_err("%s: error %d doing aggessive suspend\n", | 1166 | pr_err("%s: error %d doing aggessive suspend\n", |
1125 | mmc_hostname(host), err); | 1167 | mmc_hostname(host), err); |
1126 | goto out; | ||
1127 | } | ||
1128 | mmc_power_off(host); | ||
1129 | 1168 | ||
1130 | out: | ||
1131 | mmc_release_host(host); | ||
1132 | return err; | 1169 | return err; |
1133 | } | 1170 | } |
1134 | 1171 | ||
@@ -1139,18 +1176,14 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) | |||
1139 | { | 1176 | { |
1140 | int err; | 1177 | int err; |
1141 | 1178 | ||
1142 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) | 1179 | if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME))) |
1143 | return 0; | 1180 | return 0; |
1144 | 1181 | ||
1145 | mmc_claim_host(host); | 1182 | err = _mmc_sd_resume(host); |
1146 | |||
1147 | mmc_power_up(host); | ||
1148 | err = mmc_sd_resume(host); | ||
1149 | if (err) | 1183 | if (err) |
1150 | pr_err("%s: error %d doing aggessive resume\n", | 1184 | pr_err("%s: error %d doing aggessive resume\n", |
1151 | mmc_hostname(host), err); | 1185 | mmc_hostname(host), err); |
1152 | 1186 | ||
1153 | mmc_release_host(host); | ||
1154 | return 0; | 1187 | return 0; |
1155 | } | 1188 | } |
1156 | 1189 | ||
@@ -1160,7 +1193,7 @@ static int mmc_sd_power_restore(struct mmc_host *host) | |||
1160 | 1193 | ||
1161 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 1194 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
1162 | mmc_claim_host(host); | 1195 | mmc_claim_host(host); |
1163 | ret = mmc_sd_init_card(host, host->ocr, host->card); | 1196 | ret = mmc_sd_init_card(host, host->card->ocr, host->card); |
1164 | mmc_release_host(host); | 1197 | mmc_release_host(host); |
1165 | 1198 | ||
1166 | return ret; | 1199 | return ret; |
@@ -1205,7 +1238,7 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) | |||
1205 | int mmc_attach_sd(struct mmc_host *host) | 1238 | int mmc_attach_sd(struct mmc_host *host) |
1206 | { | 1239 | { |
1207 | int err; | 1240 | int err; |
1208 | u32 ocr; | 1241 | u32 ocr, rocr; |
1209 | 1242 | ||
1210 | BUG_ON(!host); | 1243 | BUG_ON(!host); |
1211 | WARN_ON(!host->claimed); | 1244 | WARN_ON(!host->claimed); |
@@ -1229,31 +1262,12 @@ int mmc_attach_sd(struct mmc_host *host) | |||
1229 | goto err; | 1262 | goto err; |
1230 | } | 1263 | } |
1231 | 1264 | ||
1232 | /* | 1265 | rocr = mmc_select_voltage(host, ocr); |
1233 | * Sanity check the voltages that the card claims to | ||
1234 | * support. | ||
1235 | */ | ||
1236 | if (ocr & 0x7F) { | ||
1237 | pr_warning("%s: card claims to support voltages " | ||
1238 | "below the defined range. These will be ignored.\n", | ||
1239 | mmc_hostname(host)); | ||
1240 | ocr &= ~0x7F; | ||
1241 | } | ||
1242 | |||
1243 | if ((ocr & MMC_VDD_165_195) && | ||
1244 | !(host->ocr_avail_sd & MMC_VDD_165_195)) { | ||
1245 | pr_warning("%s: SD card claims to support the " | ||
1246 | "incompletely defined 'low voltage range'. This " | ||
1247 | "will be ignored.\n", mmc_hostname(host)); | ||
1248 | ocr &= ~MMC_VDD_165_195; | ||
1249 | } | ||
1250 | |||
1251 | host->ocr = mmc_select_voltage(host, ocr); | ||
1252 | 1266 | ||
1253 | /* | 1267 | /* |
1254 | * Can we support the voltage(s) of the card(s)? | 1268 | * Can we support the voltage(s) of the card(s)? |
1255 | */ | 1269 | */ |
1256 | if (!host->ocr) { | 1270 | if (!rocr) { |
1257 | err = -EINVAL; | 1271 | err = -EINVAL; |
1258 | goto err; | 1272 | goto err; |
1259 | } | 1273 | } |
@@ -1261,7 +1275,7 @@ int mmc_attach_sd(struct mmc_host *host) | |||
1261 | /* | 1275 | /* |
1262 | * Detect and init the card. | 1276 | * Detect and init the card. |
1263 | */ | 1277 | */ |
1264 | err = mmc_sd_init_card(host, host->ocr, NULL); | 1278 | err = mmc_sd_init_card(host, rocr, NULL); |
1265 | if (err) | 1279 | if (err) |
1266 | goto err; | 1280 | goto err; |
1267 | 1281 | ||
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 80d89cff7306..4d721c6e2af0 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -593,23 +593,28 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
593 | struct mmc_card *card; | 593 | struct mmc_card *card; |
594 | int err; | 594 | int err; |
595 | int retries = 10; | 595 | int retries = 10; |
596 | u32 rocr = 0; | ||
597 | u32 ocr_card = ocr; | ||
596 | 598 | ||
597 | BUG_ON(!host); | 599 | BUG_ON(!host); |
598 | WARN_ON(!host->claimed); | 600 | WARN_ON(!host->claimed); |
599 | 601 | ||
602 | /* to query card if 1.8V signalling is supported */ | ||
603 | if (mmc_host_uhs(host)) | ||
604 | ocr |= R4_18V_PRESENT; | ||
605 | |||
600 | try_again: | 606 | try_again: |
601 | if (!retries) { | 607 | if (!retries) { |
602 | pr_warning("%s: Skipping voltage switch\n", | 608 | pr_warning("%s: Skipping voltage switch\n", |
603 | mmc_hostname(host)); | 609 | mmc_hostname(host)); |
604 | ocr &= ~R4_18V_PRESENT; | 610 | ocr &= ~R4_18V_PRESENT; |
605 | host->ocr &= ~R4_18V_PRESENT; | ||
606 | } | 611 | } |
607 | 612 | ||
608 | /* | 613 | /* |
609 | * Inform the card of the voltage | 614 | * Inform the card of the voltage |
610 | */ | 615 | */ |
611 | if (!powered_resume) { | 616 | if (!powered_resume) { |
612 | err = mmc_send_io_op_cond(host, host->ocr, &ocr); | 617 | err = mmc_send_io_op_cond(host, ocr, &rocr); |
613 | if (err) | 618 | if (err) |
614 | goto err; | 619 | goto err; |
615 | } | 620 | } |
@@ -632,8 +637,8 @@ try_again: | |||
632 | goto err; | 637 | goto err; |
633 | } | 638 | } |
634 | 639 | ||
635 | if ((ocr & R4_MEMORY_PRESENT) && | 640 | if ((rocr & R4_MEMORY_PRESENT) && |
636 | mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid, NULL) == 0) { | 641 | mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) { |
637 | card->type = MMC_TYPE_SD_COMBO; | 642 | card->type = MMC_TYPE_SD_COMBO; |
638 | 643 | ||
639 | if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || | 644 | if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || |
@@ -663,8 +668,9 @@ try_again: | |||
663 | * systems that claim 1.8v signalling in fact do not support | 668 | * systems that claim 1.8v signalling in fact do not support |
664 | * it. | 669 | * it. |
665 | */ | 670 | */ |
666 | if (!powered_resume && (ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) { | 671 | if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { |
667 | err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); | 672 | err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, |
673 | ocr); | ||
668 | if (err == -EAGAIN) { | 674 | if (err == -EAGAIN) { |
669 | sdio_reset(host); | 675 | sdio_reset(host); |
670 | mmc_go_idle(host); | 676 | mmc_go_idle(host); |
@@ -674,12 +680,10 @@ try_again: | |||
674 | goto try_again; | 680 | goto try_again; |
675 | } else if (err) { | 681 | } else if (err) { |
676 | ocr &= ~R4_18V_PRESENT; | 682 | ocr &= ~R4_18V_PRESENT; |
677 | host->ocr &= ~R4_18V_PRESENT; | ||
678 | } | 683 | } |
679 | err = 0; | 684 | err = 0; |
680 | } else { | 685 | } else { |
681 | ocr &= ~R4_18V_PRESENT; | 686 | ocr &= ~R4_18V_PRESENT; |
682 | host->ocr &= ~R4_18V_PRESENT; | ||
683 | } | 687 | } |
684 | 688 | ||
685 | /* | 689 | /* |
@@ -759,6 +763,7 @@ try_again: | |||
759 | 763 | ||
760 | card = oldcard; | 764 | card = oldcard; |
761 | } | 765 | } |
766 | card->ocr = ocr_card; | ||
762 | mmc_fixup_device(card, NULL); | 767 | mmc_fixup_device(card, NULL); |
763 | 768 | ||
764 | if (card->type == MMC_TYPE_SD_COMBO) { | 769 | if (card->type == MMC_TYPE_SD_COMBO) { |
@@ -981,8 +986,7 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
981 | 986 | ||
982 | /* Restore power if needed */ | 987 | /* Restore power if needed */ |
983 | if (!mmc_card_keep_power(host)) { | 988 | if (!mmc_card_keep_power(host)) { |
984 | mmc_power_up(host); | 989 | mmc_power_up(host, host->card->ocr); |
985 | mmc_select_voltage(host, host->ocr); | ||
986 | /* | 990 | /* |
987 | * Tell runtime PM core we just powered up the card, | 991 | * Tell runtime PM core we just powered up the card, |
988 | * since it still believes the card is powered off. | 992 | * since it still believes the card is powered off. |
@@ -1000,7 +1004,7 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
1000 | if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { | 1004 | if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { |
1001 | sdio_reset(host); | 1005 | sdio_reset(host); |
1002 | mmc_go_idle(host); | 1006 | mmc_go_idle(host); |
1003 | err = mmc_sdio_init_card(host, host->ocr, host->card, | 1007 | err = mmc_sdio_init_card(host, host->card->ocr, host->card, |
1004 | mmc_card_keep_power(host)); | 1008 | mmc_card_keep_power(host)); |
1005 | } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { | 1009 | } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { |
1006 | /* We may have switched to 1-bit mode during suspend */ | 1010 | /* We may have switched to 1-bit mode during suspend */ |
@@ -1040,7 +1044,6 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
1040 | static int mmc_sdio_power_restore(struct mmc_host *host) | 1044 | static int mmc_sdio_power_restore(struct mmc_host *host) |
1041 | { | 1045 | { |
1042 | int ret; | 1046 | int ret; |
1043 | u32 ocr; | ||
1044 | 1047 | ||
1045 | BUG_ON(!host); | 1048 | BUG_ON(!host); |
1046 | BUG_ON(!host->card); | 1049 | BUG_ON(!host->card); |
@@ -1062,32 +1065,17 @@ static int mmc_sdio_power_restore(struct mmc_host *host) | |||
1062 | * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and | 1065 | * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and |
1063 | * harmless in other situations. | 1066 | * harmless in other situations. |
1064 | * | 1067 | * |
1065 | * With these steps taken, mmc_select_voltage() is also required to | ||
1066 | * restore the correct voltage setting of the card. | ||
1067 | */ | 1068 | */ |
1068 | 1069 | ||
1069 | sdio_reset(host); | 1070 | sdio_reset(host); |
1070 | mmc_go_idle(host); | 1071 | mmc_go_idle(host); |
1071 | mmc_send_if_cond(host, host->ocr_avail); | 1072 | mmc_send_if_cond(host, host->ocr_avail); |
1072 | 1073 | ||
1073 | ret = mmc_send_io_op_cond(host, 0, &ocr); | 1074 | ret = mmc_send_io_op_cond(host, 0, NULL); |
1074 | if (ret) | 1075 | if (ret) |
1075 | goto out; | 1076 | goto out; |
1076 | 1077 | ||
1077 | if (host->ocr_avail_sdio) | 1078 | ret = mmc_sdio_init_card(host, host->card->ocr, host->card, |
1078 | host->ocr_avail = host->ocr_avail_sdio; | ||
1079 | |||
1080 | host->ocr = mmc_select_voltage(host, ocr & ~0x7F); | ||
1081 | if (!host->ocr) { | ||
1082 | ret = -EINVAL; | ||
1083 | goto out; | ||
1084 | } | ||
1085 | |||
1086 | if (mmc_host_uhs(host)) | ||
1087 | /* to query card if 1.8V signalling is supported */ | ||
1088 | host->ocr |= R4_18V_PRESENT; | ||
1089 | |||
1090 | ret = mmc_sdio_init_card(host, host->ocr, host->card, | ||
1091 | mmc_card_keep_power(host)); | 1079 | mmc_card_keep_power(host)); |
1092 | if (!ret && host->sdio_irqs) | 1080 | if (!ret && host->sdio_irqs) |
1093 | mmc_signal_sdio_irq(host); | 1081 | mmc_signal_sdio_irq(host); |
@@ -1108,7 +1096,7 @@ static int mmc_sdio_runtime_suspend(struct mmc_host *host) | |||
1108 | static int mmc_sdio_runtime_resume(struct mmc_host *host) | 1096 | static int mmc_sdio_runtime_resume(struct mmc_host *host) |
1109 | { | 1097 | { |
1110 | /* Restore power and re-initialize. */ | 1098 | /* Restore power and re-initialize. */ |
1111 | mmc_power_up(host); | 1099 | mmc_power_up(host, host->card->ocr); |
1112 | return mmc_sdio_power_restore(host); | 1100 | return mmc_sdio_power_restore(host); |
1113 | } | 1101 | } |
1114 | 1102 | ||
@@ -1131,7 +1119,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = { | |||
1131 | int mmc_attach_sdio(struct mmc_host *host) | 1119 | int mmc_attach_sdio(struct mmc_host *host) |
1132 | { | 1120 | { |
1133 | int err, i, funcs; | 1121 | int err, i, funcs; |
1134 | u32 ocr; | 1122 | u32 ocr, rocr; |
1135 | struct mmc_card *card; | 1123 | struct mmc_card *card; |
1136 | 1124 | ||
1137 | BUG_ON(!host); | 1125 | BUG_ON(!host); |
@@ -1145,23 +1133,13 @@ int mmc_attach_sdio(struct mmc_host *host) | |||
1145 | if (host->ocr_avail_sdio) | 1133 | if (host->ocr_avail_sdio) |
1146 | host->ocr_avail = host->ocr_avail_sdio; | 1134 | host->ocr_avail = host->ocr_avail_sdio; |
1147 | 1135 | ||
1148 | /* | ||
1149 | * Sanity check the voltages that the card claims to | ||
1150 | * support. | ||
1151 | */ | ||
1152 | if (ocr & 0x7F) { | ||
1153 | pr_warning("%s: card claims to support voltages " | ||
1154 | "below the defined range. These will be ignored.\n", | ||
1155 | mmc_hostname(host)); | ||
1156 | ocr &= ~0x7F; | ||
1157 | } | ||
1158 | 1136 | ||
1159 | host->ocr = mmc_select_voltage(host, ocr); | 1137 | rocr = mmc_select_voltage(host, ocr); |
1160 | 1138 | ||
1161 | /* | 1139 | /* |
1162 | * Can we support the voltage(s) of the card(s)? | 1140 | * Can we support the voltage(s) of the card(s)? |
1163 | */ | 1141 | */ |
1164 | if (!host->ocr) { | 1142 | if (!rocr) { |
1165 | err = -EINVAL; | 1143 | err = -EINVAL; |
1166 | goto err; | 1144 | goto err; |
1167 | } | 1145 | } |
@@ -1169,22 +1147,10 @@ int mmc_attach_sdio(struct mmc_host *host) | |||
1169 | /* | 1147 | /* |
1170 | * Detect and init the card. | 1148 | * Detect and init the card. |
1171 | */ | 1149 | */ |
1172 | if (mmc_host_uhs(host)) | 1150 | err = mmc_sdio_init_card(host, rocr, NULL, 0); |
1173 | /* to query card if 1.8V signalling is supported */ | 1151 | if (err) |
1174 | host->ocr |= R4_18V_PRESENT; | 1152 | goto err; |
1175 | 1153 | ||
1176 | err = mmc_sdio_init_card(host, host->ocr, NULL, 0); | ||
1177 | if (err) { | ||
1178 | if (err == -EAGAIN) { | ||
1179 | /* | ||
1180 | * Retry initialization with S18R set to 0. | ||
1181 | */ | ||
1182 | host->ocr &= ~R4_18V_PRESENT; | ||
1183 | err = mmc_sdio_init_card(host, host->ocr, NULL, 0); | ||
1184 | } | ||
1185 | if (err) | ||
1186 | goto err; | ||
1187 | } | ||
1188 | card = host->card; | 1154 | card = host->card; |
1189 | 1155 | ||
1190 | /* | 1156 | /* |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 69e438ee043e..2cbb4516d353 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -255,7 +255,6 @@ struct atmel_mci_slot { | |||
255 | #define ATMCI_CARD_PRESENT 0 | 255 | #define ATMCI_CARD_PRESENT 0 |
256 | #define ATMCI_CARD_NEED_INIT 1 | 256 | #define ATMCI_CARD_NEED_INIT 1 |
257 | #define ATMCI_SHUTDOWN 2 | 257 | #define ATMCI_SHUTDOWN 2 |
258 | #define ATMCI_SUSPENDED 3 | ||
259 | 258 | ||
260 | int detect_pin; | 259 | int detect_pin; |
261 | int wp_pin; | 260 | int wp_pin; |
@@ -589,6 +588,13 @@ static void atmci_timeout_timer(unsigned long data) | |||
589 | if (host->mrq->cmd->data) { | 588 | if (host->mrq->cmd->data) { |
590 | host->mrq->cmd->data->error = -ETIMEDOUT; | 589 | host->mrq->cmd->data->error = -ETIMEDOUT; |
591 | host->data = NULL; | 590 | host->data = NULL; |
591 | /* | ||
592 | * With some SDIO modules, sometimes DMA transfer hangs. If | ||
593 | * stop_transfer() is not called then the DMA request is not | ||
594 | * removed, following ones are queued and never computed. | ||
595 | */ | ||
596 | if (host->state == STATE_DATA_XFER) | ||
597 | host->stop_transfer(host); | ||
592 | } else { | 598 | } else { |
593 | host->mrq->cmd->error = -ETIMEDOUT; | 599 | host->mrq->cmd->error = -ETIMEDOUT; |
594 | host->cmd = NULL; | 600 | host->cmd = NULL; |
@@ -1803,12 +1809,14 @@ static void atmci_tasklet_func(unsigned long priv) | |||
1803 | if (unlikely(status)) { | 1809 | if (unlikely(status)) { |
1804 | host->stop_transfer(host); | 1810 | host->stop_transfer(host); |
1805 | host->data = NULL; | 1811 | host->data = NULL; |
1806 | if (status & ATMCI_DTOE) { | 1812 | if (data) { |
1807 | data->error = -ETIMEDOUT; | 1813 | if (status & ATMCI_DTOE) { |
1808 | } else if (status & ATMCI_DCRCE) { | 1814 | data->error = -ETIMEDOUT; |
1809 | data->error = -EILSEQ; | 1815 | } else if (status & ATMCI_DCRCE) { |
1810 | } else { | 1816 | data->error = -EILSEQ; |
1811 | data->error = -EIO; | 1817 | } else { |
1818 | data->error = -EIO; | ||
1819 | } | ||
1812 | } | 1820 | } |
1813 | } | 1821 | } |
1814 | 1822 | ||
@@ -2520,70 +2528,10 @@ static int __exit atmci_remove(struct platform_device *pdev) | |||
2520 | return 0; | 2528 | return 0; |
2521 | } | 2529 | } |
2522 | 2530 | ||
2523 | #ifdef CONFIG_PM_SLEEP | ||
2524 | static int atmci_suspend(struct device *dev) | ||
2525 | { | ||
2526 | struct atmel_mci *host = dev_get_drvdata(dev); | ||
2527 | int i; | ||
2528 | |||
2529 | for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { | ||
2530 | struct atmel_mci_slot *slot = host->slot[i]; | ||
2531 | int ret; | ||
2532 | |||
2533 | if (!slot) | ||
2534 | continue; | ||
2535 | ret = mmc_suspend_host(slot->mmc); | ||
2536 | if (ret < 0) { | ||
2537 | while (--i >= 0) { | ||
2538 | slot = host->slot[i]; | ||
2539 | if (slot | ||
2540 | && test_bit(ATMCI_SUSPENDED, &slot->flags)) { | ||
2541 | mmc_resume_host(host->slot[i]->mmc); | ||
2542 | clear_bit(ATMCI_SUSPENDED, &slot->flags); | ||
2543 | } | ||
2544 | } | ||
2545 | return ret; | ||
2546 | } else { | ||
2547 | set_bit(ATMCI_SUSPENDED, &slot->flags); | ||
2548 | } | ||
2549 | } | ||
2550 | |||
2551 | return 0; | ||
2552 | } | ||
2553 | |||
2554 | static int atmci_resume(struct device *dev) | ||
2555 | { | ||
2556 | struct atmel_mci *host = dev_get_drvdata(dev); | ||
2557 | int i; | ||
2558 | int ret = 0; | ||
2559 | |||
2560 | for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { | ||
2561 | struct atmel_mci_slot *slot = host->slot[i]; | ||
2562 | int err; | ||
2563 | |||
2564 | slot = host->slot[i]; | ||
2565 | if (!slot) | ||
2566 | continue; | ||
2567 | if (!test_bit(ATMCI_SUSPENDED, &slot->flags)) | ||
2568 | continue; | ||
2569 | err = mmc_resume_host(slot->mmc); | ||
2570 | if (err < 0) | ||
2571 | ret = err; | ||
2572 | else | ||
2573 | clear_bit(ATMCI_SUSPENDED, &slot->flags); | ||
2574 | } | ||
2575 | |||
2576 | return ret; | ||
2577 | } | ||
2578 | #endif | ||
2579 | |||
2580 | static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); | ||
2581 | |||
2582 | static struct platform_driver atmci_driver = { | 2531 | static struct platform_driver atmci_driver = { |
2583 | .remove = __exit_p(atmci_remove), | 2532 | .remove = __exit_p(atmci_remove), |
2584 | .driver = { | 2533 | .driver = { |
2585 | .name = "atmel_mci", | 2534 | .name = "atmel_mci", |
2586 | .pm = &atmci_pm, | ||
2587 | .of_match_table = of_match_ptr(atmci_dt_ids), | 2535 | .of_match_table = of_match_ptr(atmci_dt_ids), |
2588 | }, | 2536 | }, |
2589 | }; | 2537 | }; |
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index df9becdd2e99..f5443a6c4915 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c | |||
@@ -1157,11 +1157,6 @@ static int au1xmmc_remove(struct platform_device *pdev) | |||
1157 | static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state) | 1157 | static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state) |
1158 | { | 1158 | { |
1159 | struct au1xmmc_host *host = platform_get_drvdata(pdev); | 1159 | struct au1xmmc_host *host = platform_get_drvdata(pdev); |
1160 | int ret; | ||
1161 | |||
1162 | ret = mmc_suspend_host(host->mmc); | ||
1163 | if (ret) | ||
1164 | return ret; | ||
1165 | 1160 | ||
1166 | au_writel(0, HOST_CONFIG2(host)); | 1161 | au_writel(0, HOST_CONFIG2(host)); |
1167 | au_writel(0, HOST_CONFIG(host)); | 1162 | au_writel(0, HOST_CONFIG(host)); |
@@ -1178,7 +1173,7 @@ static int au1xmmc_resume(struct platform_device *pdev) | |||
1178 | 1173 | ||
1179 | au1xmmc_reset_controller(host); | 1174 | au1xmmc_reset_controller(host); |
1180 | 1175 | ||
1181 | return mmc_resume_host(host->mmc); | 1176 | return 0; |
1182 | } | 1177 | } |
1183 | #else | 1178 | #else |
1184 | #define au1xmmc_suspend NULL | 1179 | #define au1xmmc_suspend NULL |
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 94fae2f1baaf..2b7f37e82ca9 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
@@ -391,6 +391,7 @@ static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
391 | /* Disable 4 bit SDIO */ | 391 | /* Disable 4 bit SDIO */ |
392 | cfg &= ~SD4E; | 392 | cfg &= ~SD4E; |
393 | } | 393 | } |
394 | bfin_write_SDH_CFG(cfg); | ||
394 | 395 | ||
395 | host->power_mode = ios->power_mode; | 396 | host->power_mode = ios->power_mode; |
396 | #ifndef RSI_BLKSZ | 397 | #ifndef RSI_BLKSZ |
@@ -415,7 +416,6 @@ static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
415 | cfg &= ~SD_CMD_OD; | 416 | cfg &= ~SD_CMD_OD; |
416 | # endif | 417 | # endif |
417 | 418 | ||
418 | |||
419 | if (ios->power_mode != MMC_POWER_OFF) | 419 | if (ios->power_mode != MMC_POWER_OFF) |
420 | cfg |= PWR_ON; | 420 | cfg |= PWR_ON; |
421 | else | 421 | else |
@@ -433,7 +433,6 @@ static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
433 | clk_ctl |= CLK_E; | 433 | clk_ctl |= CLK_E; |
434 | host->clk_div = clk_div; | 434 | host->clk_div = clk_div; |
435 | bfin_write_SDH_CLK_CTL(clk_ctl); | 435 | bfin_write_SDH_CLK_CTL(clk_ctl); |
436 | |||
437 | } else | 436 | } else |
438 | sdh_stop_clock(host); | 437 | sdh_stop_clock(host); |
439 | 438 | ||
@@ -640,21 +639,15 @@ static int sdh_remove(struct platform_device *pdev) | |||
640 | #ifdef CONFIG_PM | 639 | #ifdef CONFIG_PM |
641 | static int sdh_suspend(struct platform_device *dev, pm_message_t state) | 640 | static int sdh_suspend(struct platform_device *dev, pm_message_t state) |
642 | { | 641 | { |
643 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
644 | struct bfin_sd_host *drv_data = get_sdh_data(dev); | 642 | struct bfin_sd_host *drv_data = get_sdh_data(dev); |
645 | int ret = 0; | ||
646 | |||
647 | if (mmc) | ||
648 | ret = mmc_suspend_host(mmc); | ||
649 | 643 | ||
650 | peripheral_free_list(drv_data->pin_req); | 644 | peripheral_free_list(drv_data->pin_req); |
651 | 645 | ||
652 | return ret; | 646 | return 0; |
653 | } | 647 | } |
654 | 648 | ||
655 | static int sdh_resume(struct platform_device *dev) | 649 | static int sdh_resume(struct platform_device *dev) |
656 | { | 650 | { |
657 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
658 | struct bfin_sd_host *drv_data = get_sdh_data(dev); | 651 | struct bfin_sd_host *drv_data = get_sdh_data(dev); |
659 | int ret = 0; | 652 | int ret = 0; |
660 | 653 | ||
@@ -665,10 +658,6 @@ static int sdh_resume(struct platform_device *dev) | |||
665 | } | 658 | } |
666 | 659 | ||
667 | sdh_reset(); | 660 | sdh_reset(); |
668 | |||
669 | if (mmc) | ||
670 | ret = mmc_resume_host(mmc); | ||
671 | |||
672 | return ret; | 661 | return ret; |
673 | } | 662 | } |
674 | #else | 663 | #else |
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 9d6e2b844404..1087b4c79cd6 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c | |||
@@ -667,12 +667,6 @@ static const struct mmc_host_ops cb710_mmc_host = { | |||
667 | static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state) | 667 | static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state) |
668 | { | 668 | { |
669 | struct cb710_slot *slot = cb710_pdev_to_slot(pdev); | 669 | struct cb710_slot *slot = cb710_pdev_to_slot(pdev); |
670 | struct mmc_host *mmc = cb710_slot_to_mmc(slot); | ||
671 | int err; | ||
672 | |||
673 | err = mmc_suspend_host(mmc); | ||
674 | if (err) | ||
675 | return err; | ||
676 | 670 | ||
677 | cb710_mmc_enable_irq(slot, 0, ~0); | 671 | cb710_mmc_enable_irq(slot, 0, ~0); |
678 | return 0; | 672 | return 0; |
@@ -681,11 +675,9 @@ static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
681 | static int cb710_mmc_resume(struct platform_device *pdev) | 675 | static int cb710_mmc_resume(struct platform_device *pdev) |
682 | { | 676 | { |
683 | struct cb710_slot *slot = cb710_pdev_to_slot(pdev); | 677 | struct cb710_slot *slot = cb710_pdev_to_slot(pdev); |
684 | struct mmc_host *mmc = cb710_slot_to_mmc(slot); | ||
685 | 678 | ||
686 | cb710_mmc_enable_irq(slot, 0, ~0); | 679 | cb710_mmc_enable_irq(slot, 0, ~0); |
687 | 680 | return 0; | |
688 | return mmc_resume_host(mmc); | ||
689 | } | 681 | } |
690 | 682 | ||
691 | #endif /* CONFIG_PM */ | 683 | #endif /* CONFIG_PM */ |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index e9fa87df909c..d6153740b77f 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
@@ -193,7 +193,6 @@ struct mmc_davinci_host { | |||
193 | #define DAVINCI_MMC_DATADIR_READ 1 | 193 | #define DAVINCI_MMC_DATADIR_READ 1 |
194 | #define DAVINCI_MMC_DATADIR_WRITE 2 | 194 | #define DAVINCI_MMC_DATADIR_WRITE 2 |
195 | unsigned char data_dir; | 195 | unsigned char data_dir; |
196 | unsigned char suspended; | ||
197 | 196 | ||
198 | /* buffer is used during PIO of one scatterlist segment, and | 197 | /* buffer is used during PIO of one scatterlist segment, and |
199 | * is updated along with buffer_bytes_left. bytes_left applies | 198 | * is updated along with buffer_bytes_left. bytes_left applies |
@@ -1435,38 +1434,23 @@ static int davinci_mmcsd_suspend(struct device *dev) | |||
1435 | { | 1434 | { |
1436 | struct platform_device *pdev = to_platform_device(dev); | 1435 | struct platform_device *pdev = to_platform_device(dev); |
1437 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | 1436 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); |
1438 | int ret; | ||
1439 | 1437 | ||
1440 | ret = mmc_suspend_host(host->mmc); | 1438 | writel(0, host->base + DAVINCI_MMCIM); |
1441 | if (!ret) { | 1439 | mmc_davinci_reset_ctrl(host, 1); |
1442 | writel(0, host->base + DAVINCI_MMCIM); | 1440 | clk_disable(host->clk); |
1443 | mmc_davinci_reset_ctrl(host, 1); | ||
1444 | clk_disable(host->clk); | ||
1445 | host->suspended = 1; | ||
1446 | } else { | ||
1447 | host->suspended = 0; | ||
1448 | } | ||
1449 | 1441 | ||
1450 | return ret; | 1442 | return 0; |
1451 | } | 1443 | } |
1452 | 1444 | ||
1453 | static int davinci_mmcsd_resume(struct device *dev) | 1445 | static int davinci_mmcsd_resume(struct device *dev) |
1454 | { | 1446 | { |
1455 | struct platform_device *pdev = to_platform_device(dev); | 1447 | struct platform_device *pdev = to_platform_device(dev); |
1456 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | 1448 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); |
1457 | int ret; | ||
1458 | |||
1459 | if (!host->suspended) | ||
1460 | return 0; | ||
1461 | 1449 | ||
1462 | clk_enable(host->clk); | 1450 | clk_enable(host->clk); |
1463 | |||
1464 | mmc_davinci_reset_ctrl(host, 0); | 1451 | mmc_davinci_reset_ctrl(host, 0); |
1465 | ret = mmc_resume_host(host->mmc); | ||
1466 | if (!ret) | ||
1467 | host->suspended = 0; | ||
1468 | 1452 | ||
1469 | return ret; | 1453 | return 0; |
1470 | } | 1454 | } |
1471 | 1455 | ||
1472 | static const struct dev_pm_ops davinci_mmcsd_pm = { | 1456 | static const struct dev_pm_ops davinci_mmcsd_pm = { |
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 6a1fa2110a05..3423c5ed50c7 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c | |||
@@ -14,8 +14,10 @@ | |||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/mmc/host.h> | 15 | #include <linux/mmc/host.h> |
16 | #include <linux/mmc/dw_mmc.h> | 16 | #include <linux/mmc/dw_mmc.h> |
17 | #include <linux/mmc/mmc.h> | ||
17 | #include <linux/of.h> | 18 | #include <linux/of.h> |
18 | #include <linux/of_gpio.h> | 19 | #include <linux/of_gpio.h> |
20 | #include <linux/slab.h> | ||
19 | 21 | ||
20 | #include "dw_mmc.h" | 22 | #include "dw_mmc.h" |
21 | #include "dw_mmc-pltfm.h" | 23 | #include "dw_mmc-pltfm.h" |
@@ -30,16 +32,39 @@ | |||
30 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ | 32 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ |
31 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ | 33 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ |
32 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) | 34 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) |
35 | #define SDMMC_CLKSEL_WAKEUP_INT BIT(11) | ||
33 | 36 | ||
34 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 | 37 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 |
35 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 | 38 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 |
36 | 39 | ||
40 | /* Block number in eMMC */ | ||
41 | #define DWMCI_BLOCK_NUM 0xFFFFFFFF | ||
42 | |||
43 | #define SDMMC_EMMCP_BASE 0x1000 | ||
44 | #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) | ||
45 | #define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) | ||
46 | #define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) | ||
47 | #define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) | ||
48 | |||
49 | /* SMU control bits */ | ||
50 | #define DWMCI_MPSCTRL_SECURE_READ_BIT BIT(7) | ||
51 | #define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) | ||
52 | #define DWMCI_MPSCTRL_NON_SECURE_READ_BIT BIT(5) | ||
53 | #define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) | ||
54 | #define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) | ||
55 | #define DWMCI_MPSCTRL_ECB_MODE BIT(2) | ||
56 | #define DWMCI_MPSCTRL_ENCRYPTION BIT(1) | ||
57 | #define DWMCI_MPSCTRL_VALID BIT(0) | ||
58 | |||
59 | #define EXYNOS_CCLKIN_MIN 50000000 /* unit: HZ */ | ||
60 | |||
37 | /* Variations in Exynos specific dw-mshc controller */ | 61 | /* Variations in Exynos specific dw-mshc controller */ |
38 | enum dw_mci_exynos_type { | 62 | enum dw_mci_exynos_type { |
39 | DW_MCI_TYPE_EXYNOS4210, | 63 | DW_MCI_TYPE_EXYNOS4210, |
40 | DW_MCI_TYPE_EXYNOS4412, | 64 | DW_MCI_TYPE_EXYNOS4412, |
41 | DW_MCI_TYPE_EXYNOS5250, | 65 | DW_MCI_TYPE_EXYNOS5250, |
42 | DW_MCI_TYPE_EXYNOS5420, | 66 | DW_MCI_TYPE_EXYNOS5420, |
67 | DW_MCI_TYPE_EXYNOS5420_SMU, | ||
43 | }; | 68 | }; |
44 | 69 | ||
45 | /* Exynos implementation specific driver private data */ | 70 | /* Exynos implementation specific driver private data */ |
@@ -48,6 +73,7 @@ struct dw_mci_exynos_priv_data { | |||
48 | u8 ciu_div; | 73 | u8 ciu_div; |
49 | u32 sdr_timing; | 74 | u32 sdr_timing; |
50 | u32 ddr_timing; | 75 | u32 ddr_timing; |
76 | u32 cur_speed; | ||
51 | }; | 77 | }; |
52 | 78 | ||
53 | static struct dw_mci_exynos_compatible { | 79 | static struct dw_mci_exynos_compatible { |
@@ -66,44 +92,80 @@ static struct dw_mci_exynos_compatible { | |||
66 | }, { | 92 | }, { |
67 | .compatible = "samsung,exynos5420-dw-mshc", | 93 | .compatible = "samsung,exynos5420-dw-mshc", |
68 | .ctrl_type = DW_MCI_TYPE_EXYNOS5420, | 94 | .ctrl_type = DW_MCI_TYPE_EXYNOS5420, |
95 | }, { | ||
96 | .compatible = "samsung,exynos5420-dw-mshc-smu", | ||
97 | .ctrl_type = DW_MCI_TYPE_EXYNOS5420_SMU, | ||
69 | }, | 98 | }, |
70 | }; | 99 | }; |
71 | 100 | ||
72 | static int dw_mci_exynos_priv_init(struct dw_mci *host) | 101 | static int dw_mci_exynos_priv_init(struct dw_mci *host) |
73 | { | 102 | { |
74 | struct dw_mci_exynos_priv_data *priv; | 103 | struct dw_mci_exynos_priv_data *priv = host->priv; |
75 | int idx; | ||
76 | |||
77 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
78 | if (!priv) { | ||
79 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
80 | return -ENOMEM; | ||
81 | } | ||
82 | 104 | ||
83 | for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { | 105 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU) { |
84 | if (of_device_is_compatible(host->dev->of_node, | 106 | mci_writel(host, MPSBEGIN0, 0); |
85 | exynos_compat[idx].compatible)) | 107 | mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); |
86 | priv->ctrl_type = exynos_compat[idx].ctrl_type; | 108 | mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | |
109 | DWMCI_MPSCTRL_NON_SECURE_READ_BIT | | ||
110 | DWMCI_MPSCTRL_VALID | | ||
111 | DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); | ||
87 | } | 112 | } |
88 | 113 | ||
89 | host->priv = priv; | ||
90 | return 0; | 114 | return 0; |
91 | } | 115 | } |
92 | 116 | ||
93 | static int dw_mci_exynos_setup_clock(struct dw_mci *host) | 117 | static int dw_mci_exynos_setup_clock(struct dw_mci *host) |
94 | { | 118 | { |
95 | struct dw_mci_exynos_priv_data *priv = host->priv; | 119 | struct dw_mci_exynos_priv_data *priv = host->priv; |
120 | unsigned long rate = clk_get_rate(host->ciu_clk); | ||
96 | 121 | ||
97 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250 || | 122 | host->bus_hz = rate / (priv->ciu_div + 1); |
98 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420) | 123 | return 0; |
99 | host->bus_hz /= (priv->ciu_div + 1); | 124 | } |
100 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) | 125 | |
101 | host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV; | 126 | #ifdef CONFIG_PM_SLEEP |
102 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) | 127 | static int dw_mci_exynos_suspend(struct device *dev) |
103 | host->bus_hz /= EXYNOS4210_FIXED_CIU_CLK_DIV; | 128 | { |
129 | struct dw_mci *host = dev_get_drvdata(dev); | ||
130 | |||
131 | return dw_mci_suspend(host); | ||
132 | } | ||
133 | |||
134 | static int dw_mci_exynos_resume(struct device *dev) | ||
135 | { | ||
136 | struct dw_mci *host = dev_get_drvdata(dev); | ||
137 | |||
138 | dw_mci_exynos_priv_init(host); | ||
139 | return dw_mci_resume(host); | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * dw_mci_exynos_resume_noirq - Exynos-specific resume code | ||
144 | * | ||
145 | * On exynos5420 there is a silicon errata that will sometimes leave the | ||
146 | * WAKEUP_INT bit in the CLKSEL register asserted. This bit is 1 to indicate | ||
147 | * that it fired and we can clear it by writing a 1 back. Clear it to prevent | ||
148 | * interrupts from going off constantly. | ||
149 | * | ||
150 | * We run this code on all exynos variants because it doesn't hurt. | ||
151 | */ | ||
152 | |||
153 | static int dw_mci_exynos_resume_noirq(struct device *dev) | ||
154 | { | ||
155 | struct dw_mci *host = dev_get_drvdata(dev); | ||
156 | u32 clksel; | ||
157 | |||
158 | clksel = mci_readl(host, CLKSEL); | ||
159 | if (clksel & SDMMC_CLKSEL_WAKEUP_INT) | ||
160 | mci_writel(host, CLKSEL, clksel); | ||
104 | 161 | ||
105 | return 0; | 162 | return 0; |
106 | } | 163 | } |
164 | #else | ||
165 | #define dw_mci_exynos_suspend NULL | ||
166 | #define dw_mci_exynos_resume NULL | ||
167 | #define dw_mci_exynos_resume_noirq NULL | ||
168 | #endif /* CONFIG_PM_SLEEP */ | ||
107 | 169 | ||
108 | static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) | 170 | static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) |
109 | { | 171 | { |
@@ -121,23 +183,68 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) | |||
121 | static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) | 183 | static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) |
122 | { | 184 | { |
123 | struct dw_mci_exynos_priv_data *priv = host->priv; | 185 | struct dw_mci_exynos_priv_data *priv = host->priv; |
186 | unsigned int wanted = ios->clock; | ||
187 | unsigned long actual; | ||
188 | u8 div = priv->ciu_div + 1; | ||
124 | 189 | ||
125 | if (ios->timing == MMC_TIMING_UHS_DDR50) | 190 | if (ios->timing == MMC_TIMING_UHS_DDR50) { |
126 | mci_writel(host, CLKSEL, priv->ddr_timing); | 191 | mci_writel(host, CLKSEL, priv->ddr_timing); |
127 | else | 192 | /* Should be double rate for DDR mode */ |
193 | if (ios->bus_width == MMC_BUS_WIDTH_8) | ||
194 | wanted <<= 1; | ||
195 | } else { | ||
128 | mci_writel(host, CLKSEL, priv->sdr_timing); | 196 | mci_writel(host, CLKSEL, priv->sdr_timing); |
197 | } | ||
198 | |||
199 | /* Don't care if wanted clock is zero */ | ||
200 | if (!wanted) | ||
201 | return; | ||
202 | |||
203 | /* Guaranteed minimum frequency for cclkin */ | ||
204 | if (wanted < EXYNOS_CCLKIN_MIN) | ||
205 | wanted = EXYNOS_CCLKIN_MIN; | ||
206 | |||
207 | if (wanted != priv->cur_speed) { | ||
208 | int ret = clk_set_rate(host->ciu_clk, wanted * div); | ||
209 | if (ret) | ||
210 | dev_warn(host->dev, | ||
211 | "failed to set clk-rate %u error: %d\n", | ||
212 | wanted * div, ret); | ||
213 | actual = clk_get_rate(host->ciu_clk); | ||
214 | host->bus_hz = actual / div; | ||
215 | priv->cur_speed = wanted; | ||
216 | host->current_speed = 0; | ||
217 | } | ||
129 | } | 218 | } |
130 | 219 | ||
131 | static int dw_mci_exynos_parse_dt(struct dw_mci *host) | 220 | static int dw_mci_exynos_parse_dt(struct dw_mci *host) |
132 | { | 221 | { |
133 | struct dw_mci_exynos_priv_data *priv = host->priv; | 222 | struct dw_mci_exynos_priv_data *priv; |
134 | struct device_node *np = host->dev->of_node; | 223 | struct device_node *np = host->dev->of_node; |
135 | u32 timing[2]; | 224 | u32 timing[2]; |
136 | u32 div = 0; | 225 | u32 div = 0; |
226 | int idx; | ||
137 | int ret; | 227 | int ret; |
138 | 228 | ||
139 | of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div); | 229 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); |
140 | priv->ciu_div = div; | 230 | if (!priv) { |
231 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
232 | return -ENOMEM; | ||
233 | } | ||
234 | |||
235 | for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { | ||
236 | if (of_device_is_compatible(np, exynos_compat[idx].compatible)) | ||
237 | priv->ctrl_type = exynos_compat[idx].ctrl_type; | ||
238 | } | ||
239 | |||
240 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) | ||
241 | priv->ciu_div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1; | ||
242 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) | ||
243 | priv->ciu_div = EXYNOS4210_FIXED_CIU_CLK_DIV - 1; | ||
244 | else { | ||
245 | of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div); | ||
246 | priv->ciu_div = div; | ||
247 | } | ||
141 | 248 | ||
142 | ret = of_property_read_u32_array(np, | 249 | ret = of_property_read_u32_array(np, |
143 | "samsung,dw-mshc-sdr-timing", timing, 2); | 250 | "samsung,dw-mshc-sdr-timing", timing, 2); |
@@ -152,9 +259,131 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) | |||
152 | return ret; | 259 | return ret; |
153 | 260 | ||
154 | priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); | 261 | priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); |
262 | host->priv = priv; | ||
155 | return 0; | 263 | return 0; |
156 | } | 264 | } |
157 | 265 | ||
266 | static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host) | ||
267 | { | ||
268 | return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL)); | ||
269 | } | ||
270 | |||
271 | static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) | ||
272 | { | ||
273 | u32 clksel; | ||
274 | clksel = mci_readl(host, CLKSEL); | ||
275 | clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample); | ||
276 | mci_writel(host, CLKSEL, clksel); | ||
277 | } | ||
278 | |||
279 | static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) | ||
280 | { | ||
281 | u32 clksel; | ||
282 | u8 sample; | ||
283 | |||
284 | clksel = mci_readl(host, CLKSEL); | ||
285 | sample = (clksel + 1) & 0x7; | ||
286 | clksel = (clksel & ~0x7) | sample; | ||
287 | mci_writel(host, CLKSEL, clksel); | ||
288 | return sample; | ||
289 | } | ||
290 | |||
291 | static s8 dw_mci_exynos_get_best_clksmpl(u8 candiates) | ||
292 | { | ||
293 | const u8 iter = 8; | ||
294 | u8 __c; | ||
295 | s8 i, loc = -1; | ||
296 | |||
297 | for (i = 0; i < iter; i++) { | ||
298 | __c = ror8(candiates, i); | ||
299 | if ((__c & 0xc7) == 0xc7) { | ||
300 | loc = i; | ||
301 | goto out; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | for (i = 0; i < iter; i++) { | ||
306 | __c = ror8(candiates, i); | ||
307 | if ((__c & 0x83) == 0x83) { | ||
308 | loc = i; | ||
309 | goto out; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | out: | ||
314 | return loc; | ||
315 | } | ||
316 | |||
317 | static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode, | ||
318 | struct dw_mci_tuning_data *tuning_data) | ||
319 | { | ||
320 | struct dw_mci *host = slot->host; | ||
321 | struct mmc_host *mmc = slot->mmc; | ||
322 | const u8 *blk_pattern = tuning_data->blk_pattern; | ||
323 | u8 *blk_test; | ||
324 | unsigned int blksz = tuning_data->blksz; | ||
325 | u8 start_smpl, smpl, candiates = 0; | ||
326 | s8 found = -1; | ||
327 | int ret = 0; | ||
328 | |||
329 | blk_test = kmalloc(blksz, GFP_KERNEL); | ||
330 | if (!blk_test) | ||
331 | return -ENOMEM; | ||
332 | |||
333 | start_smpl = dw_mci_exynos_get_clksmpl(host); | ||
334 | |||
335 | do { | ||
336 | struct mmc_request mrq = {NULL}; | ||
337 | struct mmc_command cmd = {0}; | ||
338 | struct mmc_command stop = {0}; | ||
339 | struct mmc_data data = {0}; | ||
340 | struct scatterlist sg; | ||
341 | |||
342 | cmd.opcode = opcode; | ||
343 | cmd.arg = 0; | ||
344 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
345 | |||
346 | stop.opcode = MMC_STOP_TRANSMISSION; | ||
347 | stop.arg = 0; | ||
348 | stop.flags = MMC_RSP_R1B | MMC_CMD_AC; | ||
349 | |||
350 | data.blksz = blksz; | ||
351 | data.blocks = 1; | ||
352 | data.flags = MMC_DATA_READ; | ||
353 | data.sg = &sg; | ||
354 | data.sg_len = 1; | ||
355 | |||
356 | sg_init_one(&sg, blk_test, blksz); | ||
357 | mrq.cmd = &cmd; | ||
358 | mrq.stop = &stop; | ||
359 | mrq.data = &data; | ||
360 | host->mrq = &mrq; | ||
361 | |||
362 | mci_writel(host, TMOUT, ~0); | ||
363 | smpl = dw_mci_exynos_move_next_clksmpl(host); | ||
364 | |||
365 | mmc_wait_for_req(mmc, &mrq); | ||
366 | |||
367 | if (!cmd.error && !data.error) { | ||
368 | if (!memcmp(blk_pattern, blk_test, blksz)) | ||
369 | candiates |= (1 << smpl); | ||
370 | } else { | ||
371 | dev_dbg(host->dev, | ||
372 | "Tuning error: cmd.error:%d, data.error:%d\n", | ||
373 | cmd.error, data.error); | ||
374 | } | ||
375 | } while (start_smpl != smpl); | ||
376 | |||
377 | found = dw_mci_exynos_get_best_clksmpl(candiates); | ||
378 | if (found >= 0) | ||
379 | dw_mci_exynos_set_clksmpl(host, found); | ||
380 | else | ||
381 | ret = -EIO; | ||
382 | |||
383 | kfree(blk_test); | ||
384 | return ret; | ||
385 | } | ||
386 | |||
158 | /* Common capabilities of Exynos4/Exynos5 SoC */ | 387 | /* Common capabilities of Exynos4/Exynos5 SoC */ |
159 | static unsigned long exynos_dwmmc_caps[4] = { | 388 | static unsigned long exynos_dwmmc_caps[4] = { |
160 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | | 389 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | |
@@ -171,6 +400,7 @@ static const struct dw_mci_drv_data exynos_drv_data = { | |||
171 | .prepare_command = dw_mci_exynos_prepare_command, | 400 | .prepare_command = dw_mci_exynos_prepare_command, |
172 | .set_ios = dw_mci_exynos_set_ios, | 401 | .set_ios = dw_mci_exynos_set_ios, |
173 | .parse_dt = dw_mci_exynos_parse_dt, | 402 | .parse_dt = dw_mci_exynos_parse_dt, |
403 | .execute_tuning = dw_mci_exynos_execute_tuning, | ||
174 | }; | 404 | }; |
175 | 405 | ||
176 | static const struct of_device_id dw_mci_exynos_match[] = { | 406 | static const struct of_device_id dw_mci_exynos_match[] = { |
@@ -180,6 +410,8 @@ static const struct of_device_id dw_mci_exynos_match[] = { | |||
180 | .data = &exynos_drv_data, }, | 410 | .data = &exynos_drv_data, }, |
181 | { .compatible = "samsung,exynos5420-dw-mshc", | 411 | { .compatible = "samsung,exynos5420-dw-mshc", |
182 | .data = &exynos_drv_data, }, | 412 | .data = &exynos_drv_data, }, |
413 | { .compatible = "samsung,exynos5420-dw-mshc-smu", | ||
414 | .data = &exynos_drv_data, }, | ||
183 | {}, | 415 | {}, |
184 | }; | 416 | }; |
185 | MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); | 417 | MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); |
@@ -194,13 +426,20 @@ static int dw_mci_exynos_probe(struct platform_device *pdev) | |||
194 | return dw_mci_pltfm_register(pdev, drv_data); | 426 | return dw_mci_pltfm_register(pdev, drv_data); |
195 | } | 427 | } |
196 | 428 | ||
429 | const struct dev_pm_ops dw_mci_exynos_pmops = { | ||
430 | SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume) | ||
431 | .resume_noirq = dw_mci_exynos_resume_noirq, | ||
432 | .thaw_noirq = dw_mci_exynos_resume_noirq, | ||
433 | .restore_noirq = dw_mci_exynos_resume_noirq, | ||
434 | }; | ||
435 | |||
197 | static struct platform_driver dw_mci_exynos_pltfm_driver = { | 436 | static struct platform_driver dw_mci_exynos_pltfm_driver = { |
198 | .probe = dw_mci_exynos_probe, | 437 | .probe = dw_mci_exynos_probe, |
199 | .remove = __exit_p(dw_mci_pltfm_remove), | 438 | .remove = __exit_p(dw_mci_pltfm_remove), |
200 | .driver = { | 439 | .driver = { |
201 | .name = "dwmmc_exynos", | 440 | .name = "dwmmc_exynos", |
202 | .of_match_table = dw_mci_exynos_match, | 441 | .of_match_table = dw_mci_exynos_match, |
203 | .pm = &dw_mci_pltfm_pmops, | 442 | .pm = &dw_mci_exynos_pmops, |
204 | }, | 443 | }, |
205 | }; | 444 | }; |
206 | 445 | ||
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 20897529ea5e..5c4965655297 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c | |||
@@ -39,7 +39,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev, | |||
39 | { | 39 | { |
40 | struct dw_mci *host; | 40 | struct dw_mci *host; |
41 | struct resource *regs; | 41 | struct resource *regs; |
42 | int ret; | ||
43 | 42 | ||
44 | host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); | 43 | host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); |
45 | if (!host) | 44 | if (!host) |
@@ -59,12 +58,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev, | |||
59 | if (IS_ERR(host->regs)) | 58 | if (IS_ERR(host->regs)) |
60 | return PTR_ERR(host->regs); | 59 | return PTR_ERR(host->regs); |
61 | 60 | ||
62 | if (drv_data && drv_data->init) { | ||
63 | ret = drv_data->init(host); | ||
64 | if (ret) | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | platform_set_drvdata(pdev, host); | 61 | platform_set_drvdata(pdev, host); |
69 | return dw_mci_probe(host); | 62 | return dw_mci_probe(host); |
70 | } | 63 | } |
diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c index 14b5961a851c..3e8e53ae3302 100644 --- a/drivers/mmc/host/dw_mmc-socfpga.c +++ b/drivers/mmc/host/dw_mmc-socfpga.c | |||
@@ -38,21 +38,6 @@ struct dw_mci_socfpga_priv_data { | |||
38 | 38 | ||
39 | static int dw_mci_socfpga_priv_init(struct dw_mci *host) | 39 | static int dw_mci_socfpga_priv_init(struct dw_mci *host) |
40 | { | 40 | { |
41 | struct dw_mci_socfpga_priv_data *priv; | ||
42 | |||
43 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
44 | if (!priv) { | ||
45 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
46 | return -ENOMEM; | ||
47 | } | ||
48 | |||
49 | priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); | ||
50 | if (IS_ERR(priv->sysreg)) { | ||
51 | dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n"); | ||
52 | return PTR_ERR(priv->sysreg); | ||
53 | } | ||
54 | host->priv = priv; | ||
55 | |||
56 | return 0; | 41 | return 0; |
57 | } | 42 | } |
58 | 43 | ||
@@ -79,12 +64,24 @@ static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr) | |||
79 | 64 | ||
80 | static int dw_mci_socfpga_parse_dt(struct dw_mci *host) | 65 | static int dw_mci_socfpga_parse_dt(struct dw_mci *host) |
81 | { | 66 | { |
82 | struct dw_mci_socfpga_priv_data *priv = host->priv; | 67 | struct dw_mci_socfpga_priv_data *priv; |
83 | struct device_node *np = host->dev->of_node; | 68 | struct device_node *np = host->dev->of_node; |
84 | u32 timing[2]; | 69 | u32 timing[2]; |
85 | u32 div = 0; | 70 | u32 div = 0; |
86 | int ret; | 71 | int ret; |
87 | 72 | ||
73 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
74 | if (!priv) { | ||
75 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
76 | return -ENOMEM; | ||
77 | } | ||
78 | |||
79 | priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); | ||
80 | if (IS_ERR(priv->sysreg)) { | ||
81 | dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n"); | ||
82 | return PTR_ERR(priv->sysreg); | ||
83 | } | ||
84 | |||
88 | ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div); | 85 | ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div); |
89 | if (ret) | 86 | if (ret) |
90 | dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1"); | 87 | dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1"); |
@@ -96,6 +93,7 @@ static int dw_mci_socfpga_parse_dt(struct dw_mci *host) | |||
96 | return ret; | 93 | return ret; |
97 | 94 | ||
98 | priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]); | 95 | priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]); |
96 | host->priv = priv; | ||
99 | return 0; | 97 | return 0; |
100 | } | 98 | } |
101 | 99 | ||
@@ -113,7 +111,7 @@ static const struct of_device_id dw_mci_socfpga_match[] = { | |||
113 | }; | 111 | }; |
114 | MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match); | 112 | MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match); |
115 | 113 | ||
116 | int dw_mci_socfpga_probe(struct platform_device *pdev) | 114 | static int dw_mci_socfpga_probe(struct platform_device *pdev) |
117 | { | 115 | { |
118 | const struct dw_mci_drv_data *drv_data; | 116 | const struct dw_mci_drv_data *drv_data; |
119 | const struct of_device_id *match; | 117 | const struct of_device_id *match; |
@@ -128,7 +126,7 @@ static struct platform_driver dw_mci_socfpga_pltfm_driver = { | |||
128 | .remove = __exit_p(dw_mci_pltfm_remove), | 126 | .remove = __exit_p(dw_mci_pltfm_remove), |
129 | .driver = { | 127 | .driver = { |
130 | .name = "dwmmc_socfpga", | 128 | .name = "dwmmc_socfpga", |
131 | .of_match_table = of_match_ptr(dw_mci_socfpga_match), | 129 | .of_match_table = dw_mci_socfpga_match, |
132 | .pm = &dw_mci_pltfm_pmops, | 130 | .pm = &dw_mci_pltfm_pmops, |
133 | }, | 131 | }, |
134 | }; | 132 | }; |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 018f365e5ae4..4bce0deec362 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/irq.h> | 29 | #include <linux/irq.h> |
30 | #include <linux/mmc/host.h> | 30 | #include <linux/mmc/host.h> |
31 | #include <linux/mmc/mmc.h> | 31 | #include <linux/mmc/mmc.h> |
32 | #include <linux/mmc/sdio.h> | ||
32 | #include <linux/mmc/dw_mmc.h> | 33 | #include <linux/mmc/dw_mmc.h> |
33 | #include <linux/bitops.h> | 34 | #include <linux/bitops.h> |
34 | #include <linux/regulator/consumer.h> | 35 | #include <linux/regulator/consumer.h> |
@@ -50,6 +51,9 @@ | |||
50 | #define DW_MCI_RECV_STATUS 2 | 51 | #define DW_MCI_RECV_STATUS 2 |
51 | #define DW_MCI_DMA_THRESHOLD 16 | 52 | #define DW_MCI_DMA_THRESHOLD 16 |
52 | 53 | ||
54 | #define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */ | ||
55 | #define DW_MCI_FREQ_MIN 400000 /* unit: HZ */ | ||
56 | |||
53 | #ifdef CONFIG_MMC_DW_IDMAC | 57 | #ifdef CONFIG_MMC_DW_IDMAC |
54 | #define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ | 58 | #define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ |
55 | SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ | 59 | SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ |
@@ -76,42 +80,39 @@ struct idmac_desc { | |||
76 | }; | 80 | }; |
77 | #endif /* CONFIG_MMC_DW_IDMAC */ | 81 | #endif /* CONFIG_MMC_DW_IDMAC */ |
78 | 82 | ||
79 | /** | 83 | static const u8 tuning_blk_pattern_4bit[] = { |
80 | * struct dw_mci_slot - MMC slot state | 84 | 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, |
81 | * @mmc: The mmc_host representing this slot. | 85 | 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, |
82 | * @host: The MMC controller this slot is using. | 86 | 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, |
83 | * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) | 87 | 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, |
84 | * @wp_gpio: If gpio_is_valid() we'll use this to read write protect. | 88 | 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, |
85 | * @ctype: Card type for this slot. | 89 | 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, |
86 | * @mrq: mmc_request currently being processed or waiting to be | 90 | 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, |
87 | * processed, or NULL when the slot is idle. | 91 | 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, |
88 | * @queue_node: List node for placing this node in the @queue list of | 92 | }; |
89 | * &struct dw_mci. | ||
90 | * @clock: Clock rate configured by set_ios(). Protected by host->lock. | ||
91 | * @flags: Random state bits associated with the slot. | ||
92 | * @id: Number of this slot. | ||
93 | * @last_detect_state: Most recently observed card detect state. | ||
94 | */ | ||
95 | struct dw_mci_slot { | ||
96 | struct mmc_host *mmc; | ||
97 | struct dw_mci *host; | ||
98 | |||
99 | int quirks; | ||
100 | int wp_gpio; | ||
101 | |||
102 | u32 ctype; | ||
103 | |||
104 | struct mmc_request *mrq; | ||
105 | struct list_head queue_node; | ||
106 | 93 | ||
107 | unsigned int clock; | 94 | static const u8 tuning_blk_pattern_8bit[] = { |
108 | unsigned long flags; | 95 | 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, |
109 | #define DW_MMC_CARD_PRESENT 0 | 96 | 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, |
110 | #define DW_MMC_CARD_NEED_INIT 1 | 97 | 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, |
111 | int id; | 98 | 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, |
112 | int last_detect_state; | 99 | 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, |
100 | 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, | ||
101 | 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, | ||
102 | 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, | ||
103 | 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, | ||
104 | 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, | ||
105 | 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, | ||
106 | 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, | ||
107 | 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, | ||
108 | 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, | ||
109 | 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, | ||
110 | 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, | ||
113 | }; | 111 | }; |
114 | 112 | ||
113 | static inline bool dw_mci_fifo_reset(struct dw_mci *host); | ||
114 | static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host); | ||
115 | |||
115 | #if defined(CONFIG_DEBUG_FS) | 116 | #if defined(CONFIG_DEBUG_FS) |
116 | static int dw_mci_req_show(struct seq_file *s, void *v) | 117 | static int dw_mci_req_show(struct seq_file *s, void *v) |
117 | { | 118 | { |
@@ -249,10 +250,15 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | |||
249 | 250 | ||
250 | cmdr = cmd->opcode; | 251 | cmdr = cmd->opcode; |
251 | 252 | ||
252 | if (cmdr == MMC_STOP_TRANSMISSION) | 253 | if (cmd->opcode == MMC_STOP_TRANSMISSION || |
254 | cmd->opcode == MMC_GO_IDLE_STATE || | ||
255 | cmd->opcode == MMC_GO_INACTIVE_STATE || | ||
256 | (cmd->opcode == SD_IO_RW_DIRECT && | ||
257 | ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT)) | ||
253 | cmdr |= SDMMC_CMD_STOP; | 258 | cmdr |= SDMMC_CMD_STOP; |
254 | else | 259 | else |
255 | cmdr |= SDMMC_CMD_PRV_DAT_WAIT; | 260 | if (cmd->opcode != MMC_SEND_STATUS && cmd->data) |
261 | cmdr |= SDMMC_CMD_PRV_DAT_WAIT; | ||
256 | 262 | ||
257 | if (cmd->flags & MMC_RSP_PRESENT) { | 263 | if (cmd->flags & MMC_RSP_PRESENT) { |
258 | /* We expect a response, so set this bit */ | 264 | /* We expect a response, so set this bit */ |
@@ -279,6 +285,40 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | |||
279 | return cmdr; | 285 | return cmdr; |
280 | } | 286 | } |
281 | 287 | ||
288 | static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) | ||
289 | { | ||
290 | struct mmc_command *stop; | ||
291 | u32 cmdr; | ||
292 | |||
293 | if (!cmd->data) | ||
294 | return 0; | ||
295 | |||
296 | stop = &host->stop_abort; | ||
297 | cmdr = cmd->opcode; | ||
298 | memset(stop, 0, sizeof(struct mmc_command)); | ||
299 | |||
300 | if (cmdr == MMC_READ_SINGLE_BLOCK || | ||
301 | cmdr == MMC_READ_MULTIPLE_BLOCK || | ||
302 | cmdr == MMC_WRITE_BLOCK || | ||
303 | cmdr == MMC_WRITE_MULTIPLE_BLOCK) { | ||
304 | stop->opcode = MMC_STOP_TRANSMISSION; | ||
305 | stop->arg = 0; | ||
306 | stop->flags = MMC_RSP_R1B | MMC_CMD_AC; | ||
307 | } else if (cmdr == SD_IO_RW_EXTENDED) { | ||
308 | stop->opcode = SD_IO_RW_DIRECT; | ||
309 | stop->arg |= (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | | ||
310 | ((cmd->arg >> 28) & 0x7); | ||
311 | stop->flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; | ||
312 | } else { | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | cmdr = stop->opcode | SDMMC_CMD_STOP | | ||
317 | SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP; | ||
318 | |||
319 | return cmdr; | ||
320 | } | ||
321 | |||
282 | static void dw_mci_start_command(struct dw_mci *host, | 322 | static void dw_mci_start_command(struct dw_mci *host, |
283 | struct mmc_command *cmd, u32 cmd_flags) | 323 | struct mmc_command *cmd, u32 cmd_flags) |
284 | { | 324 | { |
@@ -293,9 +333,10 @@ static void dw_mci_start_command(struct dw_mci *host, | |||
293 | mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); | 333 | mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); |
294 | } | 334 | } |
295 | 335 | ||
296 | static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data) | 336 | static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data) |
297 | { | 337 | { |
298 | dw_mci_start_command(host, data->stop, host->stop_cmdr); | 338 | struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort; |
339 | dw_mci_start_command(host, stop, host->stop_cmdr); | ||
299 | } | 340 | } |
300 | 341 | ||
301 | /* DMA interface functions */ | 342 | /* DMA interface functions */ |
@@ -304,10 +345,10 @@ static void dw_mci_stop_dma(struct dw_mci *host) | |||
304 | if (host->using_dma) { | 345 | if (host->using_dma) { |
305 | host->dma_ops->stop(host); | 346 | host->dma_ops->stop(host); |
306 | host->dma_ops->cleanup(host); | 347 | host->dma_ops->cleanup(host); |
307 | } else { | ||
308 | /* Data transfer was stopped by the interrupt handler */ | ||
309 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | ||
310 | } | 348 | } |
349 | |||
350 | /* Data transfer was stopped by the interrupt handler */ | ||
351 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | ||
311 | } | 352 | } |
312 | 353 | ||
313 | static int dw_mci_get_dma_dir(struct mmc_data *data) | 354 | static int dw_mci_get_dma_dir(struct mmc_data *data) |
@@ -331,6 +372,14 @@ static void dw_mci_dma_cleanup(struct dw_mci *host) | |||
331 | dw_mci_get_dma_dir(data)); | 372 | dw_mci_get_dma_dir(data)); |
332 | } | 373 | } |
333 | 374 | ||
375 | static void dw_mci_idmac_reset(struct dw_mci *host) | ||
376 | { | ||
377 | u32 bmod = mci_readl(host, BMOD); | ||
378 | /* Software reset of DMA */ | ||
379 | bmod |= SDMMC_IDMAC_SWRESET; | ||
380 | mci_writel(host, BMOD, bmod); | ||
381 | } | ||
382 | |||
334 | static void dw_mci_idmac_stop_dma(struct dw_mci *host) | 383 | static void dw_mci_idmac_stop_dma(struct dw_mci *host) |
335 | { | 384 | { |
336 | u32 temp; | 385 | u32 temp; |
@@ -344,6 +393,7 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host) | |||
344 | /* Stop the IDMAC running */ | 393 | /* Stop the IDMAC running */ |
345 | temp = mci_readl(host, BMOD); | 394 | temp = mci_readl(host, BMOD); |
346 | temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB); | 395 | temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB); |
396 | temp |= SDMMC_IDMAC_SWRESET; | ||
347 | mci_writel(host, BMOD, temp); | 397 | mci_writel(host, BMOD, temp); |
348 | } | 398 | } |
349 | 399 | ||
@@ -435,7 +485,7 @@ static int dw_mci_idmac_init(struct dw_mci *host) | |||
435 | p->des3 = host->sg_dma; | 485 | p->des3 = host->sg_dma; |
436 | p->des0 = IDMAC_DES0_ER; | 486 | p->des0 = IDMAC_DES0_ER; |
437 | 487 | ||
438 | mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET); | 488 | dw_mci_idmac_reset(host); |
439 | 489 | ||
440 | /* Mask out interrupts - get Tx & Rx complete only */ | 490 | /* Mask out interrupts - get Tx & Rx complete only */ |
441 | mci_writel(host, IDSTS, IDMAC_INT_CLR); | 491 | mci_writel(host, IDSTS, IDMAC_INT_CLR); |
@@ -532,6 +582,78 @@ static void dw_mci_post_req(struct mmc_host *mmc, | |||
532 | data->host_cookie = 0; | 582 | data->host_cookie = 0; |
533 | } | 583 | } |
534 | 584 | ||
585 | static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data) | ||
586 | { | ||
587 | #ifdef CONFIG_MMC_DW_IDMAC | ||
588 | unsigned int blksz = data->blksz; | ||
589 | const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; | ||
590 | u32 fifo_width = 1 << host->data_shift; | ||
591 | u32 blksz_depth = blksz / fifo_width, fifoth_val; | ||
592 | u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers; | ||
593 | int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1; | ||
594 | |||
595 | tx_wmark = (host->fifo_depth) / 2; | ||
596 | tx_wmark_invers = host->fifo_depth - tx_wmark; | ||
597 | |||
598 | /* | ||
599 | * MSIZE is '1', | ||
600 | * if blksz is not a multiple of the FIFO width | ||
601 | */ | ||
602 | if (blksz % fifo_width) { | ||
603 | msize = 0; | ||
604 | rx_wmark = 1; | ||
605 | goto done; | ||
606 | } | ||
607 | |||
608 | do { | ||
609 | if (!((blksz_depth % mszs[idx]) || | ||
610 | (tx_wmark_invers % mszs[idx]))) { | ||
611 | msize = idx; | ||
612 | rx_wmark = mszs[idx] - 1; | ||
613 | break; | ||
614 | } | ||
615 | } while (--idx > 0); | ||
616 | /* | ||
617 | * If idx is '0', it won't be tried | ||
618 | * Thus, initial values are uesed | ||
619 | */ | ||
620 | done: | ||
621 | fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark); | ||
622 | mci_writel(host, FIFOTH, fifoth_val); | ||
623 | #endif | ||
624 | } | ||
625 | |||
626 | static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) | ||
627 | { | ||
628 | unsigned int blksz = data->blksz; | ||
629 | u32 blksz_depth, fifo_depth; | ||
630 | u16 thld_size; | ||
631 | |||
632 | WARN_ON(!(data->flags & MMC_DATA_READ)); | ||
633 | |||
634 | if (host->timing != MMC_TIMING_MMC_HS200 && | ||
635 | host->timing != MMC_TIMING_UHS_SDR104) | ||
636 | goto disable; | ||
637 | |||
638 | blksz_depth = blksz / (1 << host->data_shift); | ||
639 | fifo_depth = host->fifo_depth; | ||
640 | |||
641 | if (blksz_depth > fifo_depth) | ||
642 | goto disable; | ||
643 | |||
644 | /* | ||
645 | * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz' | ||
646 | * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz | ||
647 | * Currently just choose blksz. | ||
648 | */ | ||
649 | thld_size = blksz; | ||
650 | mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1)); | ||
651 | return; | ||
652 | |||
653 | disable: | ||
654 | mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0)); | ||
655 | } | ||
656 | |||
535 | static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | 657 | static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) |
536 | { | 658 | { |
537 | int sg_len; | 659 | int sg_len; |
@@ -556,6 +678,14 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | |||
556 | (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, | 678 | (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, |
557 | sg_len); | 679 | sg_len); |
558 | 680 | ||
681 | /* | ||
682 | * Decide the MSIZE and RX/TX Watermark. | ||
683 | * If current block size is same with previous size, | ||
684 | * no need to update fifoth. | ||
685 | */ | ||
686 | if (host->prev_blksz != data->blksz) | ||
687 | dw_mci_adjust_fifoth(host, data); | ||
688 | |||
559 | /* Enable the DMA interface */ | 689 | /* Enable the DMA interface */ |
560 | temp = mci_readl(host, CTRL); | 690 | temp = mci_readl(host, CTRL); |
561 | temp |= SDMMC_CTRL_DMA_ENABLE; | 691 | temp |= SDMMC_CTRL_DMA_ENABLE; |
@@ -581,10 +711,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) | |||
581 | host->sg = NULL; | 711 | host->sg = NULL; |
582 | host->data = data; | 712 | host->data = data; |
583 | 713 | ||
584 | if (data->flags & MMC_DATA_READ) | 714 | if (data->flags & MMC_DATA_READ) { |
585 | host->dir_status = DW_MCI_RECV_STATUS; | 715 | host->dir_status = DW_MCI_RECV_STATUS; |
586 | else | 716 | dw_mci_ctrl_rd_thld(host, data); |
717 | } else { | ||
587 | host->dir_status = DW_MCI_SEND_STATUS; | 718 | host->dir_status = DW_MCI_SEND_STATUS; |
719 | } | ||
588 | 720 | ||
589 | if (dw_mci_submit_data_dma(host, data)) { | 721 | if (dw_mci_submit_data_dma(host, data)) { |
590 | int flags = SG_MITER_ATOMIC; | 722 | int flags = SG_MITER_ATOMIC; |
@@ -606,6 +738,21 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) | |||
606 | temp = mci_readl(host, CTRL); | 738 | temp = mci_readl(host, CTRL); |
607 | temp &= ~SDMMC_CTRL_DMA_ENABLE; | 739 | temp &= ~SDMMC_CTRL_DMA_ENABLE; |
608 | mci_writel(host, CTRL, temp); | 740 | mci_writel(host, CTRL, temp); |
741 | |||
742 | /* | ||
743 | * Use the initial fifoth_val for PIO mode. | ||
744 | * If next issued data may be transfered by DMA mode, | ||
745 | * prev_blksz should be invalidated. | ||
746 | */ | ||
747 | mci_writel(host, FIFOTH, host->fifoth_val); | ||
748 | host->prev_blksz = 0; | ||
749 | } else { | ||
750 | /* | ||
751 | * Keep the current block size. | ||
752 | * It will be used to decide whether to update | ||
753 | * fifoth register next time. | ||
754 | */ | ||
755 | host->prev_blksz = data->blksz; | ||
609 | } | 756 | } |
610 | } | 757 | } |
611 | 758 | ||
@@ -632,24 +779,31 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) | |||
632 | static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) | 779 | static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) |
633 | { | 780 | { |
634 | struct dw_mci *host = slot->host; | 781 | struct dw_mci *host = slot->host; |
782 | unsigned int clock = slot->clock; | ||
635 | u32 div; | 783 | u32 div; |
636 | u32 clk_en_a; | 784 | u32 clk_en_a; |
637 | 785 | ||
638 | if (slot->clock != host->current_speed || force_clkinit) { | 786 | if (!clock) { |
639 | div = host->bus_hz / slot->clock; | 787 | mci_writel(host, CLKENA, 0); |
640 | if (host->bus_hz % slot->clock && host->bus_hz > slot->clock) | 788 | mci_send_cmd(slot, |
789 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
790 | } else if (clock != host->current_speed || force_clkinit) { | ||
791 | div = host->bus_hz / clock; | ||
792 | if (host->bus_hz % clock && host->bus_hz > clock) | ||
641 | /* | 793 | /* |
642 | * move the + 1 after the divide to prevent | 794 | * move the + 1 after the divide to prevent |
643 | * over-clocking the card. | 795 | * over-clocking the card. |
644 | */ | 796 | */ |
645 | div += 1; | 797 | div += 1; |
646 | 798 | ||
647 | div = (host->bus_hz != slot->clock) ? DIV_ROUND_UP(div, 2) : 0; | 799 | div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0; |
648 | 800 | ||
649 | dev_info(&slot->mmc->class_dev, | 801 | if ((clock << div) != slot->__clk_old || force_clkinit) |
650 | "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ" | 802 | dev_info(&slot->mmc->class_dev, |
651 | " div = %d)\n", slot->id, host->bus_hz, slot->clock, | 803 | "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n", |
652 | div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div); | 804 | slot->id, host->bus_hz, clock, |
805 | div ? ((host->bus_hz / div) >> 1) : | ||
806 | host->bus_hz, div); | ||
653 | 807 | ||
654 | /* disable clock */ | 808 | /* disable clock */ |
655 | mci_writel(host, CLKENA, 0); | 809 | mci_writel(host, CLKENA, 0); |
@@ -676,9 +830,12 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) | |||
676 | mci_send_cmd(slot, | 830 | mci_send_cmd(slot, |
677 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | 831 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); |
678 | 832 | ||
679 | host->current_speed = slot->clock; | 833 | /* keep the clock with reflecting clock dividor */ |
834 | slot->__clk_old = clock << div; | ||
680 | } | 835 | } |
681 | 836 | ||
837 | host->current_speed = clock; | ||
838 | |||
682 | /* Set the current slot bus width */ | 839 | /* Set the current slot bus width */ |
683 | mci_writel(host, CTYPE, (slot->ctype << slot->id)); | 840 | mci_writel(host, CTYPE, (slot->ctype << slot->id)); |
684 | } | 841 | } |
@@ -700,7 +857,9 @@ static void __dw_mci_start_request(struct dw_mci *host, | |||
700 | 857 | ||
701 | host->pending_events = 0; | 858 | host->pending_events = 0; |
702 | host->completed_events = 0; | 859 | host->completed_events = 0; |
860 | host->cmd_status = 0; | ||
703 | host->data_status = 0; | 861 | host->data_status = 0; |
862 | host->dir_status = 0; | ||
704 | 863 | ||
705 | data = cmd->data; | 864 | data = cmd->data; |
706 | if (data) { | 865 | if (data) { |
@@ -724,6 +883,8 @@ static void __dw_mci_start_request(struct dw_mci *host, | |||
724 | 883 | ||
725 | if (mrq->stop) | 884 | if (mrq->stop) |
726 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); | 885 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); |
886 | else | ||
887 | host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd); | ||
727 | } | 888 | } |
728 | 889 | ||
729 | static void dw_mci_start_request(struct dw_mci *host, | 890 | static void dw_mci_start_request(struct dw_mci *host, |
@@ -806,14 +967,13 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
806 | regs &= ~((0x1 << slot->id) << 16); | 967 | regs &= ~((0x1 << slot->id) << 16); |
807 | 968 | ||
808 | mci_writel(slot->host, UHS_REG, regs); | 969 | mci_writel(slot->host, UHS_REG, regs); |
970 | slot->host->timing = ios->timing; | ||
809 | 971 | ||
810 | if (ios->clock) { | 972 | /* |
811 | /* | 973 | * Use mirror of ios->clock to prevent race with mmc |
812 | * Use mirror of ios->clock to prevent race with mmc | 974 | * core ios update when finding the minimum. |
813 | * core ios update when finding the minimum. | 975 | */ |
814 | */ | 976 | slot->clock = ios->clock; |
815 | slot->clock = ios->clock; | ||
816 | } | ||
817 | 977 | ||
818 | if (drv_data && drv_data->set_ios) | 978 | if (drv_data && drv_data->set_ios) |
819 | drv_data->set_ios(slot->host, ios); | 979 | drv_data->set_ios(slot->host, ios); |
@@ -939,6 +1099,38 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) | |||
939 | } | 1099 | } |
940 | } | 1100 | } |
941 | 1101 | ||
1102 | static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) | ||
1103 | { | ||
1104 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
1105 | struct dw_mci *host = slot->host; | ||
1106 | const struct dw_mci_drv_data *drv_data = host->drv_data; | ||
1107 | struct dw_mci_tuning_data tuning_data; | ||
1108 | int err = -ENOSYS; | ||
1109 | |||
1110 | if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { | ||
1111 | if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { | ||
1112 | tuning_data.blk_pattern = tuning_blk_pattern_8bit; | ||
1113 | tuning_data.blksz = sizeof(tuning_blk_pattern_8bit); | ||
1114 | } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) { | ||
1115 | tuning_data.blk_pattern = tuning_blk_pattern_4bit; | ||
1116 | tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); | ||
1117 | } else { | ||
1118 | return -EINVAL; | ||
1119 | } | ||
1120 | } else if (opcode == MMC_SEND_TUNING_BLOCK) { | ||
1121 | tuning_data.blk_pattern = tuning_blk_pattern_4bit; | ||
1122 | tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); | ||
1123 | } else { | ||
1124 | dev_err(host->dev, | ||
1125 | "Undefined command(%d) for tuning\n", opcode); | ||
1126 | return -EINVAL; | ||
1127 | } | ||
1128 | |||
1129 | if (drv_data && drv_data->execute_tuning) | ||
1130 | err = drv_data->execute_tuning(slot, opcode, &tuning_data); | ||
1131 | return err; | ||
1132 | } | ||
1133 | |||
942 | static const struct mmc_host_ops dw_mci_ops = { | 1134 | static const struct mmc_host_ops dw_mci_ops = { |
943 | .request = dw_mci_request, | 1135 | .request = dw_mci_request, |
944 | .pre_req = dw_mci_pre_req, | 1136 | .pre_req = dw_mci_pre_req, |
@@ -947,6 +1139,7 @@ static const struct mmc_host_ops dw_mci_ops = { | |||
947 | .get_ro = dw_mci_get_ro, | 1139 | .get_ro = dw_mci_get_ro, |
948 | .get_cd = dw_mci_get_cd, | 1140 | .get_cd = dw_mci_get_cd, |
949 | .enable_sdio_irq = dw_mci_enable_sdio_irq, | 1141 | .enable_sdio_irq = dw_mci_enable_sdio_irq, |
1142 | .execute_tuning = dw_mci_execute_tuning, | ||
950 | }; | 1143 | }; |
951 | 1144 | ||
952 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | 1145 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) |
@@ -978,7 +1171,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | |||
978 | spin_lock(&host->lock); | 1171 | spin_lock(&host->lock); |
979 | } | 1172 | } |
980 | 1173 | ||
981 | static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd) | 1174 | static int dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd) |
982 | { | 1175 | { |
983 | u32 status = host->cmd_status; | 1176 | u32 status = host->cmd_status; |
984 | 1177 | ||
@@ -1012,12 +1205,52 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd | |||
1012 | /* newer ip versions need a delay between retries */ | 1205 | /* newer ip versions need a delay between retries */ |
1013 | if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY) | 1206 | if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY) |
1014 | mdelay(20); | 1207 | mdelay(20); |
1208 | } | ||
1015 | 1209 | ||
1016 | if (cmd->data) { | 1210 | return cmd->error; |
1017 | dw_mci_stop_dma(host); | 1211 | } |
1018 | host->data = NULL; | 1212 | |
1213 | static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data) | ||
1214 | { | ||
1215 | u32 status = host->data_status; | ||
1216 | |||
1217 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
1218 | if (status & SDMMC_INT_DRTO) { | ||
1219 | data->error = -ETIMEDOUT; | ||
1220 | } else if (status & SDMMC_INT_DCRC) { | ||
1221 | data->error = -EILSEQ; | ||
1222 | } else if (status & SDMMC_INT_EBE) { | ||
1223 | if (host->dir_status == | ||
1224 | DW_MCI_SEND_STATUS) { | ||
1225 | /* | ||
1226 | * No data CRC status was returned. | ||
1227 | * The number of bytes transferred | ||
1228 | * will be exaggerated in PIO mode. | ||
1229 | */ | ||
1230 | data->bytes_xfered = 0; | ||
1231 | data->error = -ETIMEDOUT; | ||
1232 | } else if (host->dir_status == | ||
1233 | DW_MCI_RECV_STATUS) { | ||
1234 | data->error = -EIO; | ||
1235 | } | ||
1236 | } else { | ||
1237 | /* SDMMC_INT_SBE is included */ | ||
1238 | data->error = -EIO; | ||
1019 | } | 1239 | } |
1240 | |||
1241 | dev_err(host->dev, "data error, status 0x%08x\n", status); | ||
1242 | |||
1243 | /* | ||
1244 | * After an error, there may be data lingering | ||
1245 | * in the FIFO | ||
1246 | */ | ||
1247 | dw_mci_fifo_reset(host); | ||
1248 | } else { | ||
1249 | data->bytes_xfered = data->blocks * data->blksz; | ||
1250 | data->error = 0; | ||
1020 | } | 1251 | } |
1252 | |||
1253 | return data->error; | ||
1021 | } | 1254 | } |
1022 | 1255 | ||
1023 | static void dw_mci_tasklet_func(unsigned long priv) | 1256 | static void dw_mci_tasklet_func(unsigned long priv) |
@@ -1025,14 +1258,16 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1025 | struct dw_mci *host = (struct dw_mci *)priv; | 1258 | struct dw_mci *host = (struct dw_mci *)priv; |
1026 | struct mmc_data *data; | 1259 | struct mmc_data *data; |
1027 | struct mmc_command *cmd; | 1260 | struct mmc_command *cmd; |
1261 | struct mmc_request *mrq; | ||
1028 | enum dw_mci_state state; | 1262 | enum dw_mci_state state; |
1029 | enum dw_mci_state prev_state; | 1263 | enum dw_mci_state prev_state; |
1030 | u32 status, ctrl; | 1264 | unsigned int err; |
1031 | 1265 | ||
1032 | spin_lock(&host->lock); | 1266 | spin_lock(&host->lock); |
1033 | 1267 | ||
1034 | state = host->state; | 1268 | state = host->state; |
1035 | data = host->data; | 1269 | data = host->data; |
1270 | mrq = host->mrq; | ||
1036 | 1271 | ||
1037 | do { | 1272 | do { |
1038 | prev_state = state; | 1273 | prev_state = state; |
@@ -1049,16 +1284,23 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1049 | cmd = host->cmd; | 1284 | cmd = host->cmd; |
1050 | host->cmd = NULL; | 1285 | host->cmd = NULL; |
1051 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); | 1286 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); |
1052 | dw_mci_command_complete(host, cmd); | 1287 | err = dw_mci_command_complete(host, cmd); |
1053 | if (cmd == host->mrq->sbc && !cmd->error) { | 1288 | if (cmd == mrq->sbc && !err) { |
1054 | prev_state = state = STATE_SENDING_CMD; | 1289 | prev_state = state = STATE_SENDING_CMD; |
1055 | __dw_mci_start_request(host, host->cur_slot, | 1290 | __dw_mci_start_request(host, host->cur_slot, |
1056 | host->mrq->cmd); | 1291 | mrq->cmd); |
1057 | goto unlock; | 1292 | goto unlock; |
1058 | } | 1293 | } |
1059 | 1294 | ||
1060 | if (!host->mrq->data || cmd->error) { | 1295 | if (cmd->data && err) { |
1061 | dw_mci_request_end(host, host->mrq); | 1296 | dw_mci_stop_dma(host); |
1297 | send_stop_abort(host, data); | ||
1298 | state = STATE_SENDING_STOP; | ||
1299 | break; | ||
1300 | } | ||
1301 | |||
1302 | if (!cmd->data || err) { | ||
1303 | dw_mci_request_end(host, mrq); | ||
1062 | goto unlock; | 1304 | goto unlock; |
1063 | } | 1305 | } |
1064 | 1306 | ||
@@ -1069,8 +1311,7 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1069 | if (test_and_clear_bit(EVENT_DATA_ERROR, | 1311 | if (test_and_clear_bit(EVENT_DATA_ERROR, |
1070 | &host->pending_events)) { | 1312 | &host->pending_events)) { |
1071 | dw_mci_stop_dma(host); | 1313 | dw_mci_stop_dma(host); |
1072 | if (data->stop) | 1314 | send_stop_abort(host, data); |
1073 | send_stop_cmd(host, data); | ||
1074 | state = STATE_DATA_ERROR; | 1315 | state = STATE_DATA_ERROR; |
1075 | break; | 1316 | break; |
1076 | } | 1317 | } |
@@ -1090,60 +1331,27 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1090 | 1331 | ||
1091 | host->data = NULL; | 1332 | host->data = NULL; |
1092 | set_bit(EVENT_DATA_COMPLETE, &host->completed_events); | 1333 | set_bit(EVENT_DATA_COMPLETE, &host->completed_events); |
1093 | status = host->data_status; | 1334 | err = dw_mci_data_complete(host, data); |
1094 | |||
1095 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
1096 | if (status & SDMMC_INT_DRTO) { | ||
1097 | data->error = -ETIMEDOUT; | ||
1098 | } else if (status & SDMMC_INT_DCRC) { | ||
1099 | data->error = -EILSEQ; | ||
1100 | } else if (status & SDMMC_INT_EBE && | ||
1101 | host->dir_status == | ||
1102 | DW_MCI_SEND_STATUS) { | ||
1103 | /* | ||
1104 | * No data CRC status was returned. | ||
1105 | * The number of bytes transferred will | ||
1106 | * be exaggerated in PIO mode. | ||
1107 | */ | ||
1108 | data->bytes_xfered = 0; | ||
1109 | data->error = -ETIMEDOUT; | ||
1110 | } else { | ||
1111 | dev_err(host->dev, | ||
1112 | "data FIFO error " | ||
1113 | "(status=%08x)\n", | ||
1114 | status); | ||
1115 | data->error = -EIO; | ||
1116 | } | ||
1117 | /* | ||
1118 | * After an error, there may be data lingering | ||
1119 | * in the FIFO, so reset it - doing so | ||
1120 | * generates a block interrupt, hence setting | ||
1121 | * the scatter-gather pointer to NULL. | ||
1122 | */ | ||
1123 | sg_miter_stop(&host->sg_miter); | ||
1124 | host->sg = NULL; | ||
1125 | ctrl = mci_readl(host, CTRL); | ||
1126 | ctrl |= SDMMC_CTRL_FIFO_RESET; | ||
1127 | mci_writel(host, CTRL, ctrl); | ||
1128 | } else { | ||
1129 | data->bytes_xfered = data->blocks * data->blksz; | ||
1130 | data->error = 0; | ||
1131 | } | ||
1132 | 1335 | ||
1133 | if (!data->stop) { | 1336 | if (!err) { |
1134 | dw_mci_request_end(host, host->mrq); | 1337 | if (!data->stop || mrq->sbc) { |
1135 | goto unlock; | 1338 | if (mrq->sbc) |
1136 | } | 1339 | data->stop->error = 0; |
1340 | dw_mci_request_end(host, mrq); | ||
1341 | goto unlock; | ||
1342 | } | ||
1137 | 1343 | ||
1138 | if (host->mrq->sbc && !data->error) { | 1344 | /* stop command for open-ended transfer*/ |
1139 | data->stop->error = 0; | 1345 | if (data->stop) |
1140 | dw_mci_request_end(host, host->mrq); | 1346 | send_stop_abort(host, data); |
1141 | goto unlock; | ||
1142 | } | 1347 | } |
1143 | 1348 | ||
1349 | /* | ||
1350 | * If err has non-zero, | ||
1351 | * stop-abort command has been already issued. | ||
1352 | */ | ||
1144 | prev_state = state = STATE_SENDING_STOP; | 1353 | prev_state = state = STATE_SENDING_STOP; |
1145 | if (!data->error) | 1354 | |
1146 | send_stop_cmd(host, data); | ||
1147 | /* fall through */ | 1355 | /* fall through */ |
1148 | 1356 | ||
1149 | case STATE_SENDING_STOP: | 1357 | case STATE_SENDING_STOP: |
@@ -1151,9 +1359,19 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1151 | &host->pending_events)) | 1359 | &host->pending_events)) |
1152 | break; | 1360 | break; |
1153 | 1361 | ||
1362 | /* CMD error in data command */ | ||
1363 | if (mrq->cmd->error && mrq->data) | ||
1364 | dw_mci_fifo_reset(host); | ||
1365 | |||
1154 | host->cmd = NULL; | 1366 | host->cmd = NULL; |
1155 | dw_mci_command_complete(host, host->mrq->stop); | 1367 | host->data = NULL; |
1156 | dw_mci_request_end(host, host->mrq); | 1368 | |
1369 | if (mrq->stop) | ||
1370 | dw_mci_command_complete(host, mrq->stop); | ||
1371 | else | ||
1372 | host->cmd_status = 0; | ||
1373 | |||
1374 | dw_mci_request_end(host, mrq); | ||
1157 | goto unlock; | 1375 | goto unlock; |
1158 | 1376 | ||
1159 | case STATE_DATA_ERROR: | 1377 | case STATE_DATA_ERROR: |
@@ -1697,7 +1915,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1697 | struct mmc_host *mmc = slot->mmc; | 1915 | struct mmc_host *mmc = slot->mmc; |
1698 | struct mmc_request *mrq; | 1916 | struct mmc_request *mrq; |
1699 | int present; | 1917 | int present; |
1700 | u32 ctrl; | ||
1701 | 1918 | ||
1702 | present = dw_mci_get_cd(mmc); | 1919 | present = dw_mci_get_cd(mmc); |
1703 | while (present != slot->last_detect_state) { | 1920 | while (present != slot->last_detect_state) { |
@@ -1736,11 +1953,10 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1736 | case STATE_DATA_ERROR: | 1953 | case STATE_DATA_ERROR: |
1737 | if (mrq->data->error == -EINPROGRESS) | 1954 | if (mrq->data->error == -EINPROGRESS) |
1738 | mrq->data->error = -ENOMEDIUM; | 1955 | mrq->data->error = -ENOMEDIUM; |
1739 | if (!mrq->stop) | ||
1740 | break; | ||
1741 | /* fall through */ | 1956 | /* fall through */ |
1742 | case STATE_SENDING_STOP: | 1957 | case STATE_SENDING_STOP: |
1743 | mrq->stop->error = -ENOMEDIUM; | 1958 | if (mrq->stop) |
1959 | mrq->stop->error = -ENOMEDIUM; | ||
1744 | break; | 1960 | break; |
1745 | } | 1961 | } |
1746 | 1962 | ||
@@ -1763,23 +1979,10 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1763 | if (present == 0) { | 1979 | if (present == 0) { |
1764 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | 1980 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); |
1765 | 1981 | ||
1766 | /* | 1982 | /* Clear down the FIFO */ |
1767 | * Clear down the FIFO - doing so generates a | 1983 | dw_mci_fifo_reset(host); |
1768 | * block interrupt, hence setting the | ||
1769 | * scatter-gather pointer to NULL. | ||
1770 | */ | ||
1771 | sg_miter_stop(&host->sg_miter); | ||
1772 | host->sg = NULL; | ||
1773 | |||
1774 | ctrl = mci_readl(host, CTRL); | ||
1775 | ctrl |= SDMMC_CTRL_FIFO_RESET; | ||
1776 | mci_writel(host, CTRL, ctrl); | ||
1777 | |||
1778 | #ifdef CONFIG_MMC_DW_IDMAC | 1984 | #ifdef CONFIG_MMC_DW_IDMAC |
1779 | ctrl = mci_readl(host, BMOD); | 1985 | dw_mci_idmac_reset(host); |
1780 | /* Software reset of DMA */ | ||
1781 | ctrl |= SDMMC_IDMAC_SWRESET; | ||
1782 | mci_writel(host, BMOD, ctrl); | ||
1783 | #endif | 1986 | #endif |
1784 | 1987 | ||
1785 | } | 1988 | } |
@@ -1901,6 +2104,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1901 | struct dw_mci_slot *slot; | 2104 | struct dw_mci_slot *slot; |
1902 | const struct dw_mci_drv_data *drv_data = host->drv_data; | 2105 | const struct dw_mci_drv_data *drv_data = host->drv_data; |
1903 | int ctrl_id, ret; | 2106 | int ctrl_id, ret; |
2107 | u32 freq[2]; | ||
1904 | u8 bus_width; | 2108 | u8 bus_width; |
1905 | 2109 | ||
1906 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); | 2110 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); |
@@ -1916,8 +2120,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1916 | slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id); | 2120 | slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id); |
1917 | 2121 | ||
1918 | mmc->ops = &dw_mci_ops; | 2122 | mmc->ops = &dw_mci_ops; |
1919 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); | 2123 | if (of_property_read_u32_array(host->dev->of_node, |
1920 | mmc->f_max = host->bus_hz; | 2124 | "clock-freq-min-max", freq, 2)) { |
2125 | mmc->f_min = DW_MCI_FREQ_MIN; | ||
2126 | mmc->f_max = DW_MCI_FREQ_MAX; | ||
2127 | } else { | ||
2128 | mmc->f_min = freq[0]; | ||
2129 | mmc->f_max = freq[1]; | ||
2130 | } | ||
1921 | 2131 | ||
1922 | if (host->pdata->get_ocr) | 2132 | if (host->pdata->get_ocr) |
1923 | mmc->ocr_avail = host->pdata->get_ocr(id); | 2133 | mmc->ocr_avail = host->pdata->get_ocr(id); |
@@ -1964,9 +2174,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1964 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 2174 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1965 | } | 2175 | } |
1966 | 2176 | ||
1967 | if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) | ||
1968 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | ||
1969 | |||
1970 | if (host->pdata->blk_settings) { | 2177 | if (host->pdata->blk_settings) { |
1971 | mmc->max_segs = host->pdata->blk_settings->max_segs; | 2178 | mmc->max_segs = host->pdata->blk_settings->max_segs; |
1972 | mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; | 2179 | mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; |
@@ -2008,12 +2215,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
2008 | /* Card initially undetected */ | 2215 | /* Card initially undetected */ |
2009 | slot->last_detect_state = 0; | 2216 | slot->last_detect_state = 0; |
2010 | 2217 | ||
2011 | /* | ||
2012 | * Card may have been plugged in prior to boot so we | ||
2013 | * need to run the detect tasklet | ||
2014 | */ | ||
2015 | queue_work(host->card_workqueue, &host->card_work); | ||
2016 | |||
2017 | return 0; | 2218 | return 0; |
2018 | 2219 | ||
2019 | err_setup_bus: | 2220 | err_setup_bus: |
@@ -2074,36 +2275,57 @@ no_dma: | |||
2074 | return; | 2275 | return; |
2075 | } | 2276 | } |
2076 | 2277 | ||
2077 | static bool mci_wait_reset(struct device *dev, struct dw_mci *host) | 2278 | static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) |
2078 | { | 2279 | { |
2079 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | 2280 | unsigned long timeout = jiffies + msecs_to_jiffies(500); |
2080 | unsigned int ctrl; | 2281 | u32 ctrl; |
2081 | 2282 | ||
2082 | mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | | 2283 | ctrl = mci_readl(host, CTRL); |
2083 | SDMMC_CTRL_DMA_RESET)); | 2284 | ctrl |= reset; |
2285 | mci_writel(host, CTRL, ctrl); | ||
2084 | 2286 | ||
2085 | /* wait till resets clear */ | 2287 | /* wait till resets clear */ |
2086 | do { | 2288 | do { |
2087 | ctrl = mci_readl(host, CTRL); | 2289 | ctrl = mci_readl(host, CTRL); |
2088 | if (!(ctrl & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | | 2290 | if (!(ctrl & reset)) |
2089 | SDMMC_CTRL_DMA_RESET))) | ||
2090 | return true; | 2291 | return true; |
2091 | } while (time_before(jiffies, timeout)); | 2292 | } while (time_before(jiffies, timeout)); |
2092 | 2293 | ||
2093 | dev_err(dev, "Timeout resetting block (ctrl %#x)\n", ctrl); | 2294 | dev_err(host->dev, |
2295 | "Timeout resetting block (ctrl reset %#x)\n", | ||
2296 | ctrl & reset); | ||
2094 | 2297 | ||
2095 | return false; | 2298 | return false; |
2096 | } | 2299 | } |
2097 | 2300 | ||
2301 | static inline bool dw_mci_fifo_reset(struct dw_mci *host) | ||
2302 | { | ||
2303 | /* | ||
2304 | * Reseting generates a block interrupt, hence setting | ||
2305 | * the scatter-gather pointer to NULL. | ||
2306 | */ | ||
2307 | if (host->sg) { | ||
2308 | sg_miter_stop(&host->sg_miter); | ||
2309 | host->sg = NULL; | ||
2310 | } | ||
2311 | |||
2312 | return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); | ||
2313 | } | ||
2314 | |||
2315 | static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) | ||
2316 | { | ||
2317 | return dw_mci_ctrl_reset(host, | ||
2318 | SDMMC_CTRL_FIFO_RESET | | ||
2319 | SDMMC_CTRL_RESET | | ||
2320 | SDMMC_CTRL_DMA_RESET); | ||
2321 | } | ||
2322 | |||
2098 | #ifdef CONFIG_OF | 2323 | #ifdef CONFIG_OF |
2099 | static struct dw_mci_of_quirks { | 2324 | static struct dw_mci_of_quirks { |
2100 | char *quirk; | 2325 | char *quirk; |
2101 | int id; | 2326 | int id; |
2102 | } of_quirks[] = { | 2327 | } of_quirks[] = { |
2103 | { | 2328 | { |
2104 | .quirk = "supports-highspeed", | ||
2105 | .id = DW_MCI_QUIRK_HIGHSPEED, | ||
2106 | }, { | ||
2107 | .quirk = "broken-cd", | 2329 | .quirk = "broken-cd", |
2108 | .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, | 2330 | .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, |
2109 | }, | 2331 | }, |
@@ -2158,6 +2380,15 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
2158 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) | 2380 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) |
2159 | pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | 2381 | pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; |
2160 | 2382 | ||
2383 | if (of_find_property(np, "supports-highspeed", NULL)) | ||
2384 | pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | ||
2385 | |||
2386 | if (of_find_property(np, "caps2-mmc-hs200-1_8v", NULL)) | ||
2387 | pdata->caps2 |= MMC_CAP2_HS200_1_8V_SDR; | ||
2388 | |||
2389 | if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL)) | ||
2390 | pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR; | ||
2391 | |||
2161 | return pdata; | 2392 | return pdata; |
2162 | } | 2393 | } |
2163 | 2394 | ||
@@ -2221,6 +2452,15 @@ int dw_mci_probe(struct dw_mci *host) | |||
2221 | host->bus_hz = clk_get_rate(host->ciu_clk); | 2452 | host->bus_hz = clk_get_rate(host->ciu_clk); |
2222 | } | 2453 | } |
2223 | 2454 | ||
2455 | if (drv_data && drv_data->init) { | ||
2456 | ret = drv_data->init(host); | ||
2457 | if (ret) { | ||
2458 | dev_err(host->dev, | ||
2459 | "implementation specific init failed\n"); | ||
2460 | goto err_clk_ciu; | ||
2461 | } | ||
2462 | } | ||
2463 | |||
2224 | if (drv_data && drv_data->setup_clock) { | 2464 | if (drv_data && drv_data->setup_clock) { |
2225 | ret = drv_data->setup_clock(host); | 2465 | ret = drv_data->setup_clock(host); |
2226 | if (ret) { | 2466 | if (ret) { |
@@ -2287,7 +2527,7 @@ int dw_mci_probe(struct dw_mci *host) | |||
2287 | } | 2527 | } |
2288 | 2528 | ||
2289 | /* Reset all blocks */ | 2529 | /* Reset all blocks */ |
2290 | if (!mci_wait_reset(host->dev, host)) | 2530 | if (!dw_mci_ctrl_all_reset(host)) |
2291 | return -ENODEV; | 2531 | return -ENODEV; |
2292 | 2532 | ||
2293 | host->dma_ops = host->pdata->dma_ops; | 2533 | host->dma_ops = host->pdata->dma_ops; |
@@ -2317,8 +2557,8 @@ int dw_mci_probe(struct dw_mci *host) | |||
2317 | fifo_size = host->pdata->fifo_depth; | 2557 | fifo_size = host->pdata->fifo_depth; |
2318 | } | 2558 | } |
2319 | host->fifo_depth = fifo_size; | 2559 | host->fifo_depth = fifo_size; |
2320 | host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | | 2560 | host->fifoth_val = |
2321 | ((fifo_size/2) << 0)); | 2561 | SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2); |
2322 | mci_writel(host, FIFOTH, host->fifoth_val); | 2562 | mci_writel(host, FIFOTH, host->fifoth_val); |
2323 | 2563 | ||
2324 | /* disable clock to CIU */ | 2564 | /* disable clock to CIU */ |
@@ -2456,23 +2696,6 @@ EXPORT_SYMBOL(dw_mci_remove); | |||
2456 | */ | 2696 | */ |
2457 | int dw_mci_suspend(struct dw_mci *host) | 2697 | int dw_mci_suspend(struct dw_mci *host) |
2458 | { | 2698 | { |
2459 | int i, ret = 0; | ||
2460 | |||
2461 | for (i = 0; i < host->num_slots; i++) { | ||
2462 | struct dw_mci_slot *slot = host->slot[i]; | ||
2463 | if (!slot) | ||
2464 | continue; | ||
2465 | ret = mmc_suspend_host(slot->mmc); | ||
2466 | if (ret < 0) { | ||
2467 | while (--i >= 0) { | ||
2468 | slot = host->slot[i]; | ||
2469 | if (slot) | ||
2470 | mmc_resume_host(host->slot[i]->mmc); | ||
2471 | } | ||
2472 | return ret; | ||
2473 | } | ||
2474 | } | ||
2475 | |||
2476 | if (host->vmmc) | 2699 | if (host->vmmc) |
2477 | regulator_disable(host->vmmc); | 2700 | regulator_disable(host->vmmc); |
2478 | 2701 | ||
@@ -2493,7 +2716,7 @@ int dw_mci_resume(struct dw_mci *host) | |||
2493 | } | 2716 | } |
2494 | } | 2717 | } |
2495 | 2718 | ||
2496 | if (!mci_wait_reset(host->dev, host)) { | 2719 | if (!dw_mci_ctrl_all_reset(host)) { |
2497 | ret = -ENODEV; | 2720 | ret = -ENODEV; |
2498 | return ret; | 2721 | return ret; |
2499 | } | 2722 | } |
@@ -2501,8 +2724,15 @@ int dw_mci_resume(struct dw_mci *host) | |||
2501 | if (host->use_dma && host->dma_ops->init) | 2724 | if (host->use_dma && host->dma_ops->init) |
2502 | host->dma_ops->init(host); | 2725 | host->dma_ops->init(host); |
2503 | 2726 | ||
2504 | /* Restore the old value at FIFOTH register */ | 2727 | /* |
2728 | * Restore the initial value at FIFOTH register | ||
2729 | * And Invalidate the prev_blksz with zero | ||
2730 | */ | ||
2505 | mci_writel(host, FIFOTH, host->fifoth_val); | 2731 | mci_writel(host, FIFOTH, host->fifoth_val); |
2732 | host->prev_blksz = 0; | ||
2733 | |||
2734 | /* Put in max timeout */ | ||
2735 | mci_writel(host, TMOUT, 0xFFFFFFFF); | ||
2506 | 2736 | ||
2507 | mci_writel(host, RINTSTS, 0xFFFFFFFF); | 2737 | mci_writel(host, RINTSTS, 0xFFFFFFFF); |
2508 | mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | | 2738 | mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | |
@@ -2518,10 +2748,6 @@ int dw_mci_resume(struct dw_mci *host) | |||
2518 | dw_mci_set_ios(slot->mmc, &slot->mmc->ios); | 2748 | dw_mci_set_ios(slot->mmc, &slot->mmc->ios); |
2519 | dw_mci_setup_bus(slot, true); | 2749 | dw_mci_setup_bus(slot, true); |
2520 | } | 2750 | } |
2521 | |||
2522 | ret = mmc_resume_host(host->slot[i]->mmc); | ||
2523 | if (ret < 0) | ||
2524 | return ret; | ||
2525 | } | 2751 | } |
2526 | return 0; | 2752 | return 0; |
2527 | } | 2753 | } |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 81b29941c5b9..6bf24ab917e6 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define SDMMC_IDINTEN 0x090 | 53 | #define SDMMC_IDINTEN 0x090 |
54 | #define SDMMC_DSCADDR 0x094 | 54 | #define SDMMC_DSCADDR 0x094 |
55 | #define SDMMC_BUFADDR 0x098 | 55 | #define SDMMC_BUFADDR 0x098 |
56 | #define SDMMC_CDTHRCTL 0x100 | ||
56 | #define SDMMC_DATA(x) (x) | 57 | #define SDMMC_DATA(x) (x) |
57 | 58 | ||
58 | /* | 59 | /* |
@@ -128,6 +129,10 @@ | |||
128 | #define SDMMC_CMD_INDX(n) ((n) & 0x1F) | 129 | #define SDMMC_CMD_INDX(n) ((n) & 0x1F) |
129 | /* Status register defines */ | 130 | /* Status register defines */ |
130 | #define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) | 131 | #define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) |
132 | /* FIFOTH register defines */ | ||
133 | #define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ | ||
134 | ((r) & 0xFFF) << 16 | \ | ||
135 | ((t) & 0xFFF)) | ||
131 | /* Internal DMAC interrupt defines */ | 136 | /* Internal DMAC interrupt defines */ |
132 | #define SDMMC_IDMAC_INT_AI BIT(9) | 137 | #define SDMMC_IDMAC_INT_AI BIT(9) |
133 | #define SDMMC_IDMAC_INT_NI BIT(8) | 138 | #define SDMMC_IDMAC_INT_NI BIT(8) |
@@ -142,6 +147,8 @@ | |||
142 | #define SDMMC_IDMAC_SWRESET BIT(0) | 147 | #define SDMMC_IDMAC_SWRESET BIT(0) |
143 | /* Version ID register define */ | 148 | /* Version ID register define */ |
144 | #define SDMMC_GET_VERID(x) ((x) & 0xFFFF) | 149 | #define SDMMC_GET_VERID(x) ((x) & 0xFFFF) |
150 | /* Card read threshold */ | ||
151 | #define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x)) | ||
145 | 152 | ||
146 | /* Register access macros */ | 153 | /* Register access macros */ |
147 | #define mci_readl(dev, reg) \ | 154 | #define mci_readl(dev, reg) \ |
@@ -184,6 +191,52 @@ extern int dw_mci_resume(struct dw_mci *host); | |||
184 | #endif | 191 | #endif |
185 | 192 | ||
186 | /** | 193 | /** |
194 | * struct dw_mci_slot - MMC slot state | ||
195 | * @mmc: The mmc_host representing this slot. | ||
196 | * @host: The MMC controller this slot is using. | ||
197 | * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) | ||
198 | * @wp_gpio: If gpio_is_valid() we'll use this to read write protect. | ||
199 | * @ctype: Card type for this slot. | ||
200 | * @mrq: mmc_request currently being processed or waiting to be | ||
201 | * processed, or NULL when the slot is idle. | ||
202 | * @queue_node: List node for placing this node in the @queue list of | ||
203 | * &struct dw_mci. | ||
204 | * @clock: Clock rate configured by set_ios(). Protected by host->lock. | ||
205 | * @__clk_old: The last updated clock with reflecting clock divider. | ||
206 | * Keeping track of this helps us to avoid spamming the console | ||
207 | * with CONFIG_MMC_CLKGATE. | ||
208 | * @flags: Random state bits associated with the slot. | ||
209 | * @id: Number of this slot. | ||
210 | * @last_detect_state: Most recently observed card detect state. | ||
211 | */ | ||
212 | struct dw_mci_slot { | ||
213 | struct mmc_host *mmc; | ||
214 | struct dw_mci *host; | ||
215 | |||
216 | int quirks; | ||
217 | int wp_gpio; | ||
218 | |||
219 | u32 ctype; | ||
220 | |||
221 | struct mmc_request *mrq; | ||
222 | struct list_head queue_node; | ||
223 | |||
224 | unsigned int clock; | ||
225 | unsigned int __clk_old; | ||
226 | |||
227 | unsigned long flags; | ||
228 | #define DW_MMC_CARD_PRESENT 0 | ||
229 | #define DW_MMC_CARD_NEED_INIT 1 | ||
230 | int id; | ||
231 | int last_detect_state; | ||
232 | }; | ||
233 | |||
234 | struct dw_mci_tuning_data { | ||
235 | const u8 *blk_pattern; | ||
236 | unsigned int blksz; | ||
237 | }; | ||
238 | |||
239 | /** | ||
187 | * dw_mci driver data - dw-mshc implementation specific driver data. | 240 | * dw_mci driver data - dw-mshc implementation specific driver data. |
188 | * @caps: mmc subsystem specified capabilities of the controller(s). | 241 | * @caps: mmc subsystem specified capabilities of the controller(s). |
189 | * @init: early implementation specific initialization. | 242 | * @init: early implementation specific initialization. |
@@ -203,5 +256,7 @@ struct dw_mci_drv_data { | |||
203 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); | 256 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); |
204 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); | 257 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); |
205 | int (*parse_dt)(struct dw_mci *host); | 258 | int (*parse_dt)(struct dw_mci *host); |
259 | int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode, | ||
260 | struct dw_mci_tuning_data *tuning_data); | ||
206 | }; | 261 | }; |
207 | #endif /* _DW_MMC_H_ */ | 262 | #endif /* _DW_MMC_H_ */ |
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 66516339e3a0..de2139cf3444 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c | |||
@@ -880,8 +880,6 @@ static int jz4740_mmc_suspend(struct device *dev) | |||
880 | { | 880 | { |
881 | struct jz4740_mmc_host *host = dev_get_drvdata(dev); | 881 | struct jz4740_mmc_host *host = dev_get_drvdata(dev); |
882 | 882 | ||
883 | mmc_suspend_host(host->mmc); | ||
884 | |||
885 | jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); | 883 | jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); |
886 | 884 | ||
887 | return 0; | 885 | return 0; |
@@ -893,8 +891,6 @@ static int jz4740_mmc_resume(struct device *dev) | |||
893 | 891 | ||
894 | jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); | 892 | jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); |
895 | 893 | ||
896 | mmc_resume_host(host->mmc); | ||
897 | |||
898 | return 0; | 894 | return 0; |
899 | } | 895 | } |
900 | 896 | ||
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index d135c76c4855..f32057972dd7 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -1730,37 +1730,28 @@ static int mmci_suspend(struct device *dev) | |||
1730 | { | 1730 | { |
1731 | struct amba_device *adev = to_amba_device(dev); | 1731 | struct amba_device *adev = to_amba_device(dev); |
1732 | struct mmc_host *mmc = amba_get_drvdata(adev); | 1732 | struct mmc_host *mmc = amba_get_drvdata(adev); |
1733 | int ret = 0; | ||
1734 | 1733 | ||
1735 | if (mmc) { | 1734 | if (mmc) { |
1736 | struct mmci_host *host = mmc_priv(mmc); | 1735 | struct mmci_host *host = mmc_priv(mmc); |
1737 | 1736 | pm_runtime_get_sync(dev); | |
1738 | ret = mmc_suspend_host(mmc); | 1737 | writel(0, host->base + MMCIMASK0); |
1739 | if (ret == 0) { | ||
1740 | pm_runtime_get_sync(dev); | ||
1741 | writel(0, host->base + MMCIMASK0); | ||
1742 | } | ||
1743 | } | 1738 | } |
1744 | 1739 | ||
1745 | return ret; | 1740 | return 0; |
1746 | } | 1741 | } |
1747 | 1742 | ||
1748 | static int mmci_resume(struct device *dev) | 1743 | static int mmci_resume(struct device *dev) |
1749 | { | 1744 | { |
1750 | struct amba_device *adev = to_amba_device(dev); | 1745 | struct amba_device *adev = to_amba_device(dev); |
1751 | struct mmc_host *mmc = amba_get_drvdata(adev); | 1746 | struct mmc_host *mmc = amba_get_drvdata(adev); |
1752 | int ret = 0; | ||
1753 | 1747 | ||
1754 | if (mmc) { | 1748 | if (mmc) { |
1755 | struct mmci_host *host = mmc_priv(mmc); | 1749 | struct mmci_host *host = mmc_priv(mmc); |
1756 | |||
1757 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); | 1750 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); |
1758 | pm_runtime_put(dev); | 1751 | pm_runtime_put(dev); |
1759 | |||
1760 | ret = mmc_resume_host(mmc); | ||
1761 | } | 1752 | } |
1762 | 1753 | ||
1763 | return ret; | 1754 | return 0; |
1764 | } | 1755 | } |
1765 | #endif | 1756 | #endif |
1766 | 1757 | ||
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index b900de4e7e94..9405ecdaf6cf 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -1416,28 +1416,10 @@ ioremap_free: | |||
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | #ifdef CONFIG_PM | 1418 | #ifdef CONFIG_PM |
1419 | #ifdef CONFIG_MMC_MSM7X00A_RESUME_IN_WQ | ||
1420 | static void | ||
1421 | do_resume_work(struct work_struct *work) | ||
1422 | { | ||
1423 | struct msmsdcc_host *host = | ||
1424 | container_of(work, struct msmsdcc_host, resume_task); | ||
1425 | struct mmc_host *mmc = host->mmc; | ||
1426 | |||
1427 | if (mmc) { | ||
1428 | mmc_resume_host(mmc); | ||
1429 | if (host->stat_irq) | ||
1430 | enable_irq(host->stat_irq); | ||
1431 | } | ||
1432 | } | ||
1433 | #endif | ||
1434 | |||
1435 | |||
1436 | static int | 1419 | static int |
1437 | msmsdcc_suspend(struct platform_device *dev, pm_message_t state) | 1420 | msmsdcc_suspend(struct platform_device *dev, pm_message_t state) |
1438 | { | 1421 | { |
1439 | struct mmc_host *mmc = mmc_get_drvdata(dev); | 1422 | struct mmc_host *mmc = mmc_get_drvdata(dev); |
1440 | int rc = 0; | ||
1441 | 1423 | ||
1442 | if (mmc) { | 1424 | if (mmc) { |
1443 | struct msmsdcc_host *host = mmc_priv(mmc); | 1425 | struct msmsdcc_host *host = mmc_priv(mmc); |
@@ -1445,14 +1427,11 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state) | |||
1445 | if (host->stat_irq) | 1427 | if (host->stat_irq) |
1446 | disable_irq(host->stat_irq); | 1428 | disable_irq(host->stat_irq); |
1447 | 1429 | ||
1448 | if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) | 1430 | msmsdcc_writel(host, 0, MMCIMASK0); |
1449 | rc = mmc_suspend_host(mmc); | ||
1450 | if (!rc) | ||
1451 | msmsdcc_writel(host, 0, MMCIMASK0); | ||
1452 | if (host->clks_on) | 1431 | if (host->clks_on) |
1453 | msmsdcc_disable_clocks(host, 0); | 1432 | msmsdcc_disable_clocks(host, 0); |
1454 | } | 1433 | } |
1455 | return rc; | 1434 | return 0; |
1456 | } | 1435 | } |
1457 | 1436 | ||
1458 | static int | 1437 | static int |
@@ -1467,8 +1446,6 @@ msmsdcc_resume(struct platform_device *dev) | |||
1467 | 1446 | ||
1468 | msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0); | 1447 | msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0); |
1469 | 1448 | ||
1470 | if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) | ||
1471 | mmc_resume_host(mmc); | ||
1472 | if (host->stat_irq) | 1449 | if (host->stat_irq) |
1473 | enable_irq(host->stat_irq); | 1450 | enable_irq(host->stat_irq); |
1474 | #if BUSCLK_PWRSAVE | 1451 | #if BUSCLK_PWRSAVE |
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index deecee08c288..45aa2206741d 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -775,9 +775,9 @@ static int mvsd_probe(struct platform_device *pdev) | |||
775 | 775 | ||
776 | spin_lock_init(&host->lock); | 776 | spin_lock_init(&host->lock); |
777 | 777 | ||
778 | host->base = devm_request_and_ioremap(&pdev->dev, r); | 778 | host->base = devm_ioremap_resource(&pdev->dev, r); |
779 | if (!host->base) { | 779 | if (IS_ERR(host->base)) { |
780 | ret = -ENOMEM; | 780 | ret = PTR_ERR(host->base); |
781 | goto out; | 781 | goto out; |
782 | } | 782 | } |
783 | 783 | ||
@@ -838,33 +838,6 @@ static int mvsd_remove(struct platform_device *pdev) | |||
838 | return 0; | 838 | return 0; |
839 | } | 839 | } |
840 | 840 | ||
841 | #ifdef CONFIG_PM | ||
842 | static int mvsd_suspend(struct platform_device *dev, pm_message_t state) | ||
843 | { | ||
844 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
845 | int ret = 0; | ||
846 | |||
847 | if (mmc) | ||
848 | ret = mmc_suspend_host(mmc); | ||
849 | |||
850 | return ret; | ||
851 | } | ||
852 | |||
853 | static int mvsd_resume(struct platform_device *dev) | ||
854 | { | ||
855 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
856 | int ret = 0; | ||
857 | |||
858 | if (mmc) | ||
859 | ret = mmc_resume_host(mmc); | ||
860 | |||
861 | return ret; | ||
862 | } | ||
863 | #else | ||
864 | #define mvsd_suspend NULL | ||
865 | #define mvsd_resume NULL | ||
866 | #endif | ||
867 | |||
868 | static const struct of_device_id mvsdio_dt_ids[] = { | 841 | static const struct of_device_id mvsdio_dt_ids[] = { |
869 | { .compatible = "marvell,orion-sdio" }, | 842 | { .compatible = "marvell,orion-sdio" }, |
870 | { /* sentinel */ } | 843 | { /* sentinel */ } |
@@ -874,8 +847,6 @@ MODULE_DEVICE_TABLE(of, mvsdio_dt_ids); | |||
874 | static struct platform_driver mvsd_driver = { | 847 | static struct platform_driver mvsd_driver = { |
875 | .probe = mvsd_probe, | 848 | .probe = mvsd_probe, |
876 | .remove = mvsd_remove, | 849 | .remove = mvsd_remove, |
877 | .suspend = mvsd_suspend, | ||
878 | .resume = mvsd_resume, | ||
879 | .driver = { | 850 | .driver = { |
880 | .name = DRIVER_NAME, | 851 | .name = DRIVER_NAME, |
881 | .of_match_table = mvsdio_dt_ids, | 852 | .of_match_table = mvsdio_dt_ids, |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index c174c6a0d224..f7199c83f5cf 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -1250,28 +1250,20 @@ static int mxcmci_suspend(struct device *dev) | |||
1250 | { | 1250 | { |
1251 | struct mmc_host *mmc = dev_get_drvdata(dev); | 1251 | struct mmc_host *mmc = dev_get_drvdata(dev); |
1252 | struct mxcmci_host *host = mmc_priv(mmc); | 1252 | struct mxcmci_host *host = mmc_priv(mmc); |
1253 | int ret = 0; | ||
1254 | 1253 | ||
1255 | if (mmc) | ||
1256 | ret = mmc_suspend_host(mmc); | ||
1257 | clk_disable_unprepare(host->clk_per); | 1254 | clk_disable_unprepare(host->clk_per); |
1258 | clk_disable_unprepare(host->clk_ipg); | 1255 | clk_disable_unprepare(host->clk_ipg); |
1259 | 1256 | return 0; | |
1260 | return ret; | ||
1261 | } | 1257 | } |
1262 | 1258 | ||
1263 | static int mxcmci_resume(struct device *dev) | 1259 | static int mxcmci_resume(struct device *dev) |
1264 | { | 1260 | { |
1265 | struct mmc_host *mmc = dev_get_drvdata(dev); | 1261 | struct mmc_host *mmc = dev_get_drvdata(dev); |
1266 | struct mxcmci_host *host = mmc_priv(mmc); | 1262 | struct mxcmci_host *host = mmc_priv(mmc); |
1267 | int ret = 0; | ||
1268 | 1263 | ||
1269 | clk_prepare_enable(host->clk_per); | 1264 | clk_prepare_enable(host->clk_per); |
1270 | clk_prepare_enable(host->clk_ipg); | 1265 | clk_prepare_enable(host->clk_ipg); |
1271 | if (mmc) | 1266 | return 0; |
1272 | ret = mmc_resume_host(mmc); | ||
1273 | |||
1274 | return ret; | ||
1275 | } | 1267 | } |
1276 | 1268 | ||
1277 | static const struct dev_pm_ops mxcmci_pm_ops = { | 1269 | static const struct dev_pm_ops mxcmci_pm_ops = { |
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index e1fa3ef735e0..50fc9df791b2 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
@@ -724,13 +724,9 @@ static int mxs_mmc_suspend(struct device *dev) | |||
724 | struct mmc_host *mmc = dev_get_drvdata(dev); | 724 | struct mmc_host *mmc = dev_get_drvdata(dev); |
725 | struct mxs_mmc_host *host = mmc_priv(mmc); | 725 | struct mxs_mmc_host *host = mmc_priv(mmc); |
726 | struct mxs_ssp *ssp = &host->ssp; | 726 | struct mxs_ssp *ssp = &host->ssp; |
727 | int ret = 0; | ||
728 | |||
729 | ret = mmc_suspend_host(mmc); | ||
730 | 727 | ||
731 | clk_disable_unprepare(ssp->clk); | 728 | clk_disable_unprepare(ssp->clk); |
732 | 729 | return 0; | |
733 | return ret; | ||
734 | } | 730 | } |
735 | 731 | ||
736 | static int mxs_mmc_resume(struct device *dev) | 732 | static int mxs_mmc_resume(struct device *dev) |
@@ -738,13 +734,9 @@ static int mxs_mmc_resume(struct device *dev) | |||
738 | struct mmc_host *mmc = dev_get_drvdata(dev); | 734 | struct mmc_host *mmc = dev_get_drvdata(dev); |
739 | struct mxs_mmc_host *host = mmc_priv(mmc); | 735 | struct mxs_mmc_host *host = mmc_priv(mmc); |
740 | struct mxs_ssp *ssp = &host->ssp; | 736 | struct mxs_ssp *ssp = &host->ssp; |
741 | int ret = 0; | ||
742 | 737 | ||
743 | clk_prepare_enable(ssp->clk); | 738 | clk_prepare_enable(ssp->clk); |
744 | 739 | return 0; | |
745 | ret = mmc_resume_host(mmc); | ||
746 | |||
747 | return ret; | ||
748 | } | 740 | } |
749 | 741 | ||
750 | static const struct dev_pm_ops mxs_mmc_pm_ops = { | 742 | static const struct dev_pm_ops mxs_mmc_pm_ops = { |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index b94f38ec2a83..0b10a9030f4e 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -128,7 +128,6 @@ struct mmc_omap_slot { | |||
128 | 128 | ||
129 | struct mmc_omap_host { | 129 | struct mmc_omap_host { |
130 | int initialized; | 130 | int initialized; |
131 | int suspended; | ||
132 | struct mmc_request * mrq; | 131 | struct mmc_request * mrq; |
133 | struct mmc_command * cmd; | 132 | struct mmc_command * cmd; |
134 | struct mmc_data * data; | 133 | struct mmc_data * data; |
@@ -1513,61 +1512,9 @@ static int mmc_omap_remove(struct platform_device *pdev) | |||
1513 | return 0; | 1512 | return 0; |
1514 | } | 1513 | } |
1515 | 1514 | ||
1516 | #ifdef CONFIG_PM | ||
1517 | static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
1518 | { | ||
1519 | int i, ret = 0; | ||
1520 | struct mmc_omap_host *host = platform_get_drvdata(pdev); | ||
1521 | |||
1522 | if (host == NULL || host->suspended) | ||
1523 | return 0; | ||
1524 | |||
1525 | for (i = 0; i < host->nr_slots; i++) { | ||
1526 | struct mmc_omap_slot *slot; | ||
1527 | |||
1528 | slot = host->slots[i]; | ||
1529 | ret = mmc_suspend_host(slot->mmc); | ||
1530 | if (ret < 0) { | ||
1531 | while (--i >= 0) { | ||
1532 | slot = host->slots[i]; | ||
1533 | mmc_resume_host(slot->mmc); | ||
1534 | } | ||
1535 | return ret; | ||
1536 | } | ||
1537 | } | ||
1538 | host->suspended = 1; | ||
1539 | return 0; | ||
1540 | } | ||
1541 | |||
1542 | static int mmc_omap_resume(struct platform_device *pdev) | ||
1543 | { | ||
1544 | int i, ret = 0; | ||
1545 | struct mmc_omap_host *host = platform_get_drvdata(pdev); | ||
1546 | |||
1547 | if (host == NULL || !host->suspended) | ||
1548 | return 0; | ||
1549 | |||
1550 | for (i = 0; i < host->nr_slots; i++) { | ||
1551 | struct mmc_omap_slot *slot; | ||
1552 | slot = host->slots[i]; | ||
1553 | ret = mmc_resume_host(slot->mmc); | ||
1554 | if (ret < 0) | ||
1555 | return ret; | ||
1556 | |||
1557 | host->suspended = 0; | ||
1558 | } | ||
1559 | return 0; | ||
1560 | } | ||
1561 | #else | ||
1562 | #define mmc_omap_suspend NULL | ||
1563 | #define mmc_omap_resume NULL | ||
1564 | #endif | ||
1565 | |||
1566 | static struct platform_driver mmc_omap_driver = { | 1515 | static struct platform_driver mmc_omap_driver = { |
1567 | .probe = mmc_omap_probe, | 1516 | .probe = mmc_omap_probe, |
1568 | .remove = mmc_omap_remove, | 1517 | .remove = mmc_omap_remove, |
1569 | .suspend = mmc_omap_suspend, | ||
1570 | .resume = mmc_omap_resume, | ||
1571 | .driver = { | 1518 | .driver = { |
1572 | .name = DRIVER_NAME, | 1519 | .name = DRIVER_NAME, |
1573 | .owner = THIS_MODULE, | 1520 | .owner = THIS_MODULE, |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 6ac63df645c4..dbd32ad3b749 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #define ICE 0x1 | 75 | #define ICE 0x1 |
76 | #define ICS 0x2 | 76 | #define ICS 0x2 |
77 | #define CEN (1 << 2) | 77 | #define CEN (1 << 2) |
78 | #define CLKD_MAX 0x3FF /* max clock divisor: 1023 */ | ||
78 | #define CLKD_MASK 0x0000FFC0 | 79 | #define CLKD_MASK 0x0000FFC0 |
79 | #define CLKD_SHIFT 6 | 80 | #define CLKD_SHIFT 6 |
80 | #define DTO_MASK 0x000F0000 | 81 | #define DTO_MASK 0x000F0000 |
@@ -119,7 +120,8 @@ | |||
119 | BRR_EN | BWR_EN | TC_EN | CC_EN) | 120 | BRR_EN | BWR_EN | TC_EN | CC_EN) |
120 | 121 | ||
121 | #define MMC_AUTOSUSPEND_DELAY 100 | 122 | #define MMC_AUTOSUSPEND_DELAY 100 |
122 | #define MMC_TIMEOUT_MS 20 | 123 | #define MMC_TIMEOUT_MS 20 /* 20 mSec */ |
124 | #define MMC_TIMEOUT_US 20000 /* 20000 micro Sec */ | ||
123 | #define OMAP_MMC_MIN_CLOCK 400000 | 125 | #define OMAP_MMC_MIN_CLOCK 400000 |
124 | #define OMAP_MMC_MAX_CLOCK 52000000 | 126 | #define OMAP_MMC_MAX_CLOCK 52000000 |
125 | #define DRIVER_NAME "omap_hsmmc" | 127 | #define DRIVER_NAME "omap_hsmmc" |
@@ -171,6 +173,10 @@ struct omap_hsmmc_host { | |||
171 | unsigned char bus_mode; | 173 | unsigned char bus_mode; |
172 | unsigned char power_mode; | 174 | unsigned char power_mode; |
173 | int suspended; | 175 | int suspended; |
176 | u32 con; | ||
177 | u32 hctl; | ||
178 | u32 sysctl; | ||
179 | u32 capa; | ||
174 | int irq; | 180 | int irq; |
175 | int use_dma, dma_ch; | 181 | int use_dma, dma_ch; |
176 | struct dma_chan *tx_chan; | 182 | struct dma_chan *tx_chan; |
@@ -183,7 +189,6 @@ struct omap_hsmmc_host { | |||
183 | int use_reg; | 189 | int use_reg; |
184 | int req_in_progress; | 190 | int req_in_progress; |
185 | struct omap_hsmmc_next next_data; | 191 | struct omap_hsmmc_next next_data; |
186 | |||
187 | struct omap_mmc_platform_data *pdata; | 192 | struct omap_mmc_platform_data *pdata; |
188 | }; | 193 | }; |
189 | 194 | ||
@@ -493,8 +498,8 @@ static u16 calc_divisor(struct omap_hsmmc_host *host, struct mmc_ios *ios) | |||
493 | 498 | ||
494 | if (ios->clock) { | 499 | if (ios->clock) { |
495 | dsor = DIV_ROUND_UP(clk_get_rate(host->fclk), ios->clock); | 500 | dsor = DIV_ROUND_UP(clk_get_rate(host->fclk), ios->clock); |
496 | if (dsor > 250) | 501 | if (dsor > CLKD_MAX) |
497 | dsor = 250; | 502 | dsor = CLKD_MAX; |
498 | } | 503 | } |
499 | 504 | ||
500 | return dsor; | 505 | return dsor; |
@@ -597,25 +602,20 @@ static void omap_hsmmc_set_bus_mode(struct omap_hsmmc_host *host) | |||
597 | static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | 602 | static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) |
598 | { | 603 | { |
599 | struct mmc_ios *ios = &host->mmc->ios; | 604 | struct mmc_ios *ios = &host->mmc->ios; |
600 | struct omap_mmc_platform_data *pdata = host->pdata; | ||
601 | int context_loss = 0; | ||
602 | u32 hctl, capa; | 605 | u32 hctl, capa; |
603 | unsigned long timeout; | 606 | unsigned long timeout; |
604 | 607 | ||
605 | if (pdata->get_context_loss_count) { | ||
606 | context_loss = pdata->get_context_loss_count(host->dev); | ||
607 | if (context_loss < 0) | ||
608 | return 1; | ||
609 | } | ||
610 | |||
611 | dev_dbg(mmc_dev(host->mmc), "context was %slost\n", | ||
612 | context_loss == host->context_loss ? "not " : ""); | ||
613 | if (host->context_loss == context_loss) | ||
614 | return 1; | ||
615 | |||
616 | if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) | 608 | if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) |
617 | return 1; | 609 | return 1; |
618 | 610 | ||
611 | if (host->con == OMAP_HSMMC_READ(host->base, CON) && | ||
612 | host->hctl == OMAP_HSMMC_READ(host->base, HCTL) && | ||
613 | host->sysctl == OMAP_HSMMC_READ(host->base, SYSCTL) && | ||
614 | host->capa == OMAP_HSMMC_READ(host->base, CAPA)) | ||
615 | return 0; | ||
616 | |||
617 | host->context_loss++; | ||
618 | |||
619 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { | 619 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
620 | if (host->power_mode != MMC_POWER_OFF && | 620 | if (host->power_mode != MMC_POWER_OFF && |
621 | (1 << ios->vdd) <= MMC_VDD_23_24) | 621 | (1 << ios->vdd) <= MMC_VDD_23_24) |
@@ -655,9 +655,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | |||
655 | omap_hsmmc_set_bus_mode(host); | 655 | omap_hsmmc_set_bus_mode(host); |
656 | 656 | ||
657 | out: | 657 | out: |
658 | host->context_loss = context_loss; | 658 | dev_dbg(mmc_dev(host->mmc), "context is restored: restore count %d\n", |
659 | 659 | host->context_loss); | |
660 | dev_dbg(mmc_dev(host->mmc), "context is restored\n"); | ||
661 | return 0; | 660 | return 0; |
662 | } | 661 | } |
663 | 662 | ||
@@ -666,15 +665,10 @@ out: | |||
666 | */ | 665 | */ |
667 | static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) | 666 | static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) |
668 | { | 667 | { |
669 | struct omap_mmc_platform_data *pdata = host->pdata; | 668 | host->con = OMAP_HSMMC_READ(host->base, CON); |
670 | int context_loss; | 669 | host->hctl = OMAP_HSMMC_READ(host->base, HCTL); |
671 | 670 | host->sysctl = OMAP_HSMMC_READ(host->base, SYSCTL); | |
672 | if (pdata->get_context_loss_count) { | 671 | host->capa = OMAP_HSMMC_READ(host->base, CAPA); |
673 | context_loss = pdata->get_context_loss_count(host->dev); | ||
674 | if (context_loss < 0) | ||
675 | return; | ||
676 | host->context_loss = context_loss; | ||
677 | } | ||
678 | } | 672 | } |
679 | 673 | ||
680 | #else | 674 | #else |
@@ -975,8 +969,7 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | |||
975 | unsigned long bit) | 969 | unsigned long bit) |
976 | { | 970 | { |
977 | unsigned long i = 0; | 971 | unsigned long i = 0; |
978 | unsigned long limit = (loops_per_jiffy * | 972 | unsigned long limit = MMC_TIMEOUT_US; |
979 | msecs_to_jiffies(MMC_TIMEOUT_MS)); | ||
980 | 973 | ||
981 | OMAP_HSMMC_WRITE(host->base, SYSCTL, | 974 | OMAP_HSMMC_WRITE(host->base, SYSCTL, |
982 | OMAP_HSMMC_READ(host->base, SYSCTL) | bit); | 975 | OMAP_HSMMC_READ(host->base, SYSCTL) | bit); |
@@ -988,13 +981,13 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | |||
988 | if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { | 981 | if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { |
989 | while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) | 982 | while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) |
990 | && (i++ < limit)) | 983 | && (i++ < limit)) |
991 | cpu_relax(); | 984 | udelay(1); |
992 | } | 985 | } |
993 | i = 0; | 986 | i = 0; |
994 | 987 | ||
995 | while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) && | 988 | while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) && |
996 | (i++ < limit)) | 989 | (i++ < limit)) |
997 | cpu_relax(); | 990 | udelay(1); |
998 | 991 | ||
999 | if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit) | 992 | if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit) |
1000 | dev_err(mmc_dev(host->mmc), | 993 | dev_err(mmc_dev(host->mmc), |
@@ -1178,9 +1171,6 @@ static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) | |||
1178 | struct omap_mmc_slot_data *slot = &mmc_slot(host); | 1171 | struct omap_mmc_slot_data *slot = &mmc_slot(host); |
1179 | int carddetect; | 1172 | int carddetect; |
1180 | 1173 | ||
1181 | if (host->suspended) | ||
1182 | return IRQ_HANDLED; | ||
1183 | |||
1184 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); | 1174 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); |
1185 | 1175 | ||
1186 | if (slot->card_detect) | 1176 | if (slot->card_detect) |
@@ -1635,18 +1625,9 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) | |||
1635 | { | 1625 | { |
1636 | struct mmc_host *mmc = s->private; | 1626 | struct mmc_host *mmc = s->private; |
1637 | struct omap_hsmmc_host *host = mmc_priv(mmc); | 1627 | struct omap_hsmmc_host *host = mmc_priv(mmc); |
1638 | int context_loss = 0; | ||
1639 | |||
1640 | if (host->pdata->get_context_loss_count) | ||
1641 | context_loss = host->pdata->get_context_loss_count(host->dev); | ||
1642 | 1628 | ||
1643 | seq_printf(s, "mmc%d:\n ctx_loss:\t%d:%d\n\nregs:\n", | 1629 | seq_printf(s, "mmc%d:\n ctx_loss:\t%d\n\nregs:\n", |
1644 | mmc->index, host->context_loss, context_loss); | 1630 | mmc->index, host->context_loss); |
1645 | |||
1646 | if (host->suspended) { | ||
1647 | seq_printf(s, "host suspended, can't read registers\n"); | ||
1648 | return 0; | ||
1649 | } | ||
1650 | 1631 | ||
1651 | pm_runtime_get_sync(host->dev); | 1632 | pm_runtime_get_sync(host->dev); |
1652 | 1633 | ||
@@ -1838,13 +1819,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
1838 | 1819 | ||
1839 | mmc->ops = &omap_hsmmc_ops; | 1820 | mmc->ops = &omap_hsmmc_ops; |
1840 | 1821 | ||
1841 | /* | ||
1842 | * If regulator_disable can only put vcc_aux to sleep then there is | ||
1843 | * no off state. | ||
1844 | */ | ||
1845 | if (mmc_slot(host).vcc_aux_disable_is_sleep) | ||
1846 | mmc_slot(host).no_off = 1; | ||
1847 | |||
1848 | mmc->f_min = OMAP_MMC_MIN_CLOCK; | 1822 | mmc->f_min = OMAP_MMC_MIN_CLOCK; |
1849 | 1823 | ||
1850 | if (pdata->max_freq > 0) | 1824 | if (pdata->max_freq > 0) |
@@ -1874,7 +1848,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
1874 | omap_hsmmc_context_save(host); | 1848 | omap_hsmmc_context_save(host); |
1875 | 1849 | ||
1876 | /* This can be removed once we support PBIAS with DT */ | 1850 | /* This can be removed once we support PBIAS with DT */ |
1877 | if (host->dev->of_node && host->mapbase == 0x4809c000) | 1851 | if (host->dev->of_node && res->start == 0x4809c000) |
1878 | host->pbias_disable = 1; | 1852 | host->pbias_disable = 1; |
1879 | 1853 | ||
1880 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); | 1854 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); |
@@ -2119,23 +2093,12 @@ static void omap_hsmmc_complete(struct device *dev) | |||
2119 | 2093 | ||
2120 | static int omap_hsmmc_suspend(struct device *dev) | 2094 | static int omap_hsmmc_suspend(struct device *dev) |
2121 | { | 2095 | { |
2122 | int ret = 0; | ||
2123 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 2096 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
2124 | 2097 | ||
2125 | if (!host) | 2098 | if (!host) |
2126 | return 0; | 2099 | return 0; |
2127 | 2100 | ||
2128 | if (host && host->suspended) | ||
2129 | return 0; | ||
2130 | |||
2131 | pm_runtime_get_sync(host->dev); | 2101 | pm_runtime_get_sync(host->dev); |
2132 | host->suspended = 1; | ||
2133 | ret = mmc_suspend_host(host->mmc); | ||
2134 | |||
2135 | if (ret) { | ||
2136 | host->suspended = 0; | ||
2137 | goto err; | ||
2138 | } | ||
2139 | 2102 | ||
2140 | if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { | 2103 | if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { |
2141 | omap_hsmmc_disable_irq(host); | 2104 | omap_hsmmc_disable_irq(host); |
@@ -2145,23 +2108,19 @@ static int omap_hsmmc_suspend(struct device *dev) | |||
2145 | 2108 | ||
2146 | if (host->dbclk) | 2109 | if (host->dbclk) |
2147 | clk_disable_unprepare(host->dbclk); | 2110 | clk_disable_unprepare(host->dbclk); |
2148 | err: | 2111 | |
2149 | pm_runtime_put_sync(host->dev); | 2112 | pm_runtime_put_sync(host->dev); |
2150 | return ret; | 2113 | return 0; |
2151 | } | 2114 | } |
2152 | 2115 | ||
2153 | /* Routine to resume the MMC device */ | 2116 | /* Routine to resume the MMC device */ |
2154 | static int omap_hsmmc_resume(struct device *dev) | 2117 | static int omap_hsmmc_resume(struct device *dev) |
2155 | { | 2118 | { |
2156 | int ret = 0; | ||
2157 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 2119 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
2158 | 2120 | ||
2159 | if (!host) | 2121 | if (!host) |
2160 | return 0; | 2122 | return 0; |
2161 | 2123 | ||
2162 | if (host && !host->suspended) | ||
2163 | return 0; | ||
2164 | |||
2165 | pm_runtime_get_sync(host->dev); | 2124 | pm_runtime_get_sync(host->dev); |
2166 | 2125 | ||
2167 | if (host->dbclk) | 2126 | if (host->dbclk) |
@@ -2172,16 +2131,9 @@ static int omap_hsmmc_resume(struct device *dev) | |||
2172 | 2131 | ||
2173 | omap_hsmmc_protect_card(host); | 2132 | omap_hsmmc_protect_card(host); |
2174 | 2133 | ||
2175 | /* Notify the core to resume the host */ | ||
2176 | ret = mmc_resume_host(host->mmc); | ||
2177 | if (ret == 0) | ||
2178 | host->suspended = 0; | ||
2179 | |||
2180 | pm_runtime_mark_last_busy(host->dev); | 2134 | pm_runtime_mark_last_busy(host->dev); |
2181 | pm_runtime_put_autosuspend(host->dev); | 2135 | pm_runtime_put_autosuspend(host->dev); |
2182 | 2136 | return 0; | |
2183 | return ret; | ||
2184 | |||
2185 | } | 2137 | } |
2186 | 2138 | ||
2187 | #else | 2139 | #else |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 1956a3df7cf3..32fe11323f39 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -880,35 +880,6 @@ static int pxamci_remove(struct platform_device *pdev) | |||
880 | return 0; | 880 | return 0; |
881 | } | 881 | } |
882 | 882 | ||
883 | #ifdef CONFIG_PM | ||
884 | static int pxamci_suspend(struct device *dev) | ||
885 | { | ||
886 | struct mmc_host *mmc = dev_get_drvdata(dev); | ||
887 | int ret = 0; | ||
888 | |||
889 | if (mmc) | ||
890 | ret = mmc_suspend_host(mmc); | ||
891 | |||
892 | return ret; | ||
893 | } | ||
894 | |||
895 | static int pxamci_resume(struct device *dev) | ||
896 | { | ||
897 | struct mmc_host *mmc = dev_get_drvdata(dev); | ||
898 | int ret = 0; | ||
899 | |||
900 | if (mmc) | ||
901 | ret = mmc_resume_host(mmc); | ||
902 | |||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | static const struct dev_pm_ops pxamci_pm_ops = { | ||
907 | .suspend = pxamci_suspend, | ||
908 | .resume = pxamci_resume, | ||
909 | }; | ||
910 | #endif | ||
911 | |||
912 | static struct platform_driver pxamci_driver = { | 883 | static struct platform_driver pxamci_driver = { |
913 | .probe = pxamci_probe, | 884 | .probe = pxamci_probe, |
914 | .remove = pxamci_remove, | 885 | .remove = pxamci_remove, |
@@ -916,9 +887,6 @@ static struct platform_driver pxamci_driver = { | |||
916 | .name = DRIVER_NAME, | 887 | .name = DRIVER_NAME, |
917 | .owner = THIS_MODULE, | 888 | .owner = THIS_MODULE, |
918 | .of_match_table = of_match_ptr(pxa_mmc_dt_ids), | 889 | .of_match_table = of_match_ptr(pxa_mmc_dt_ids), |
919 | #ifdef CONFIG_PM | ||
920 | .pm = &pxamci_pm_ops, | ||
921 | #endif | ||
922 | }, | 890 | }, |
923 | }; | 891 | }; |
924 | 892 | ||
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 375a880e0c5f..c46feda07d56 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
@@ -364,7 +364,7 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) | |||
364 | struct mmc_host *mmc = host->mmc; | 364 | struct mmc_host *mmc = host->mmc; |
365 | struct mmc_card *card = mmc->card; | 365 | struct mmc_card *card = mmc->card; |
366 | struct mmc_data *data = mrq->data; | 366 | struct mmc_data *data = mrq->data; |
367 | int uhs = mmc_sd_card_uhs(card); | 367 | int uhs = mmc_card_uhs(card); |
368 | int read = (data->flags & MMC_DATA_READ) ? 1 : 0; | 368 | int read = (data->flags & MMC_DATA_READ) ? 1 : 0; |
369 | u8 cfg2, trans_mode; | 369 | u8 cfg2, trans_mode; |
370 | int err; | 370 | int err; |
@@ -1197,37 +1197,6 @@ static const struct mmc_host_ops realtek_pci_sdmmc_ops = { | |||
1197 | .execute_tuning = sdmmc_execute_tuning, | 1197 | .execute_tuning = sdmmc_execute_tuning, |
1198 | }; | 1198 | }; |
1199 | 1199 | ||
1200 | #ifdef CONFIG_PM | ||
1201 | static int rtsx_pci_sdmmc_suspend(struct platform_device *pdev, | ||
1202 | pm_message_t state) | ||
1203 | { | ||
1204 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); | ||
1205 | struct mmc_host *mmc = host->mmc; | ||
1206 | int err; | ||
1207 | |||
1208 | dev_dbg(sdmmc_dev(host), "--> %s\n", __func__); | ||
1209 | |||
1210 | err = mmc_suspend_host(mmc); | ||
1211 | if (err) | ||
1212 | return err; | ||
1213 | |||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static int rtsx_pci_sdmmc_resume(struct platform_device *pdev) | ||
1218 | { | ||
1219 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); | ||
1220 | struct mmc_host *mmc = host->mmc; | ||
1221 | |||
1222 | dev_dbg(sdmmc_dev(host), "--> %s\n", __func__); | ||
1223 | |||
1224 | return mmc_resume_host(mmc); | ||
1225 | } | ||
1226 | #else /* CONFIG_PM */ | ||
1227 | #define rtsx_pci_sdmmc_suspend NULL | ||
1228 | #define rtsx_pci_sdmmc_resume NULL | ||
1229 | #endif /* CONFIG_PM */ | ||
1230 | |||
1231 | static void init_extra_caps(struct realtek_pci_sdmmc *host) | 1200 | static void init_extra_caps(struct realtek_pci_sdmmc *host) |
1232 | { | 1201 | { |
1233 | struct mmc_host *mmc = host->mmc; | 1202 | struct mmc_host *mmc = host->mmc; |
@@ -1367,8 +1336,6 @@ static struct platform_driver rtsx_pci_sdmmc_driver = { | |||
1367 | .probe = rtsx_pci_sdmmc_drv_probe, | 1336 | .probe = rtsx_pci_sdmmc_drv_probe, |
1368 | .remove = rtsx_pci_sdmmc_drv_remove, | 1337 | .remove = rtsx_pci_sdmmc_drv_remove, |
1369 | .id_table = rtsx_pci_sdmmc_ids, | 1338 | .id_table = rtsx_pci_sdmmc_ids, |
1370 | .suspend = rtsx_pci_sdmmc_suspend, | ||
1371 | .resume = rtsx_pci_sdmmc_resume, | ||
1372 | .driver = { | 1339 | .driver = { |
1373 | .owner = THIS_MODULE, | 1340 | .owner = THIS_MODULE, |
1374 | .name = DRV_NAME_RTSX_PCI_SDMMC, | 1341 | .name = DRV_NAME_RTSX_PCI_SDMMC, |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 8d6794cdf899..2fce5ea5eb39 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -1949,39 +1949,10 @@ static struct platform_device_id s3cmci_driver_ids[] = { | |||
1949 | 1949 | ||
1950 | MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids); | 1950 | MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids); |
1951 | 1951 | ||
1952 | |||
1953 | #ifdef CONFIG_PM | ||
1954 | |||
1955 | static int s3cmci_suspend(struct device *dev) | ||
1956 | { | ||
1957 | struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev)); | ||
1958 | |||
1959 | return mmc_suspend_host(mmc); | ||
1960 | } | ||
1961 | |||
1962 | static int s3cmci_resume(struct device *dev) | ||
1963 | { | ||
1964 | struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev)); | ||
1965 | |||
1966 | return mmc_resume_host(mmc); | ||
1967 | } | ||
1968 | |||
1969 | static const struct dev_pm_ops s3cmci_pm = { | ||
1970 | .suspend = s3cmci_suspend, | ||
1971 | .resume = s3cmci_resume, | ||
1972 | }; | ||
1973 | |||
1974 | #define s3cmci_pm_ops &s3cmci_pm | ||
1975 | #else /* CONFIG_PM */ | ||
1976 | #define s3cmci_pm_ops NULL | ||
1977 | #endif /* CONFIG_PM */ | ||
1978 | |||
1979 | |||
1980 | static struct platform_driver s3cmci_driver = { | 1952 | static struct platform_driver s3cmci_driver = { |
1981 | .driver = { | 1953 | .driver = { |
1982 | .name = "s3c-sdi", | 1954 | .name = "s3c-sdi", |
1983 | .owner = THIS_MODULE, | 1955 | .owner = THIS_MODULE, |
1984 | .pm = s3cmci_pm_ops, | ||
1985 | }, | 1956 | }, |
1986 | .id_table = s3cmci_driver_ids, | 1957 | .id_table = s3cmci_driver_ids, |
1987 | .probe = s3cmci_probe, | 1958 | .probe = s3cmci_probe, |
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 85472d3fd37f..7a190fe4dff1 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c | |||
@@ -316,19 +316,7 @@ err_pltfm_free: | |||
316 | 316 | ||
317 | static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev) | 317 | static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev) |
318 | { | 318 | { |
319 | struct sdhci_host *host = platform_get_drvdata(pdev); | 319 | return sdhci_pltfm_unregister(pdev); |
320 | int dead; | ||
321 | u32 scratch; | ||
322 | |||
323 | dead = 0; | ||
324 | scratch = readl(host->ioaddr + SDHCI_INT_STATUS); | ||
325 | if (scratch == (u32)-1) | ||
326 | dead = 1; | ||
327 | sdhci_remove_host(host, dead); | ||
328 | |||
329 | sdhci_free_host(host); | ||
330 | |||
331 | return 0; | ||
332 | } | 320 | } |
333 | 321 | ||
334 | static struct platform_driver sdhci_bcm_kona_driver = { | 322 | static struct platform_driver sdhci_bcm_kona_driver = { |
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c index 36fa2df04660..f6d8d67c545f 100644 --- a/drivers/mmc/host/sdhci-bcm2835.c +++ b/drivers/mmc/host/sdhci-bcm2835.c | |||
@@ -178,13 +178,7 @@ err: | |||
178 | 178 | ||
179 | static int bcm2835_sdhci_remove(struct platform_device *pdev) | 179 | static int bcm2835_sdhci_remove(struct platform_device *pdev) |
180 | { | 180 | { |
181 | struct sdhci_host *host = platform_get_drvdata(pdev); | 181 | return sdhci_pltfm_unregister(pdev); |
182 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | ||
183 | |||
184 | sdhci_remove_host(host, dead); | ||
185 | sdhci_pltfm_free(pdev); | ||
186 | |||
187 | return 0; | ||
188 | } | 182 | } |
189 | 183 | ||
190 | static const struct of_device_id bcm2835_sdhci_of_match[] = { | 184 | static const struct of_device_id bcm2835_sdhci_of_match[] = { |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index abc8cf01e6e3..461a4c3f4ef7 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -34,12 +34,40 @@ | |||
34 | /* VENDOR SPEC register */ | 34 | /* VENDOR SPEC register */ |
35 | #define ESDHC_VENDOR_SPEC 0xc0 | 35 | #define ESDHC_VENDOR_SPEC 0xc0 |
36 | #define ESDHC_VENDOR_SPEC_SDIO_QUIRK (1 << 1) | 36 | #define ESDHC_VENDOR_SPEC_SDIO_QUIRK (1 << 1) |
37 | #define ESDHC_VENDOR_SPEC_VSELECT (1 << 1) | ||
38 | #define ESDHC_VENDOR_SPEC_FRC_SDCLK_ON (1 << 8) | ||
37 | #define ESDHC_WTMK_LVL 0x44 | 39 | #define ESDHC_WTMK_LVL 0x44 |
38 | #define ESDHC_MIX_CTRL 0x48 | 40 | #define ESDHC_MIX_CTRL 0x48 |
41 | #define ESDHC_MIX_CTRL_DDREN (1 << 3) | ||
39 | #define ESDHC_MIX_CTRL_AC23EN (1 << 7) | 42 | #define ESDHC_MIX_CTRL_AC23EN (1 << 7) |
43 | #define ESDHC_MIX_CTRL_EXE_TUNE (1 << 22) | ||
44 | #define ESDHC_MIX_CTRL_SMPCLK_SEL (1 << 23) | ||
45 | #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) | ||
40 | /* Bits 3 and 6 are not SDHCI standard definitions */ | 46 | /* Bits 3 and 6 are not SDHCI standard definitions */ |
41 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 | 47 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 |
42 | 48 | ||
49 | /* dll control register */ | ||
50 | #define ESDHC_DLL_CTRL 0x60 | ||
51 | #define ESDHC_DLL_OVERRIDE_VAL_SHIFT 9 | ||
52 | #define ESDHC_DLL_OVERRIDE_EN_SHIFT 8 | ||
53 | |||
54 | /* tune control register */ | ||
55 | #define ESDHC_TUNE_CTRL_STATUS 0x68 | ||
56 | #define ESDHC_TUNE_CTRL_STEP 1 | ||
57 | #define ESDHC_TUNE_CTRL_MIN 0 | ||
58 | #define ESDHC_TUNE_CTRL_MAX ((1 << 7) - 1) | ||
59 | |||
60 | #define ESDHC_TUNING_CTRL 0xcc | ||
61 | #define ESDHC_STD_TUNING_EN (1 << 24) | ||
62 | /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ | ||
63 | #define ESDHC_TUNING_START_TAP 0x1 | ||
64 | |||
65 | #define ESDHC_TUNING_BLOCK_PATTERN_LEN 64 | ||
66 | |||
67 | /* pinctrl state */ | ||
68 | #define ESDHC_PINCTRL_STATE_100MHZ "state_100mhz" | ||
69 | #define ESDHC_PINCTRL_STATE_200MHZ "state_200mhz" | ||
70 | |||
43 | /* | 71 | /* |
44 | * Our interpretation of the SDHCI_HOST_CONTROL register | 72 | * Our interpretation of the SDHCI_HOST_CONTROL register |
45 | */ | 73 | */ |
@@ -66,21 +94,60 @@ | |||
66 | * As a result, the TC flag is not asserted and SW received timeout | 94 | * As a result, the TC flag is not asserted and SW received timeout |
67 | * exeception. Bit1 of Vendor Spec registor is used to fix it. | 95 | * exeception. Bit1 of Vendor Spec registor is used to fix it. |
68 | */ | 96 | */ |
69 | #define ESDHC_FLAG_MULTIBLK_NO_INT (1 << 1) | 97 | #define ESDHC_FLAG_MULTIBLK_NO_INT BIT(1) |
70 | 98 | /* | |
71 | enum imx_esdhc_type { | 99 | * The flag enables the workaround for ESDHC errata ENGcm07207 which |
72 | IMX25_ESDHC, | 100 | * affects i.MX25 and i.MX35. |
73 | IMX35_ESDHC, | 101 | */ |
74 | IMX51_ESDHC, | 102 | #define ESDHC_FLAG_ENGCM07207 BIT(2) |
75 | IMX53_ESDHC, | 103 | /* |
76 | IMX6Q_USDHC, | 104 | * The flag tells that the ESDHC controller is an USDHC block that is |
105 | * integrated on the i.MX6 series. | ||
106 | */ | ||
107 | #define ESDHC_FLAG_USDHC BIT(3) | ||
108 | /* The IP supports manual tuning process */ | ||
109 | #define ESDHC_FLAG_MAN_TUNING BIT(4) | ||
110 | /* The IP supports standard tuning process */ | ||
111 | #define ESDHC_FLAG_STD_TUNING BIT(5) | ||
112 | /* The IP has SDHCI_CAPABILITIES_1 register */ | ||
113 | #define ESDHC_FLAG_HAVE_CAP1 BIT(6) | ||
114 | |||
115 | struct esdhc_soc_data { | ||
116 | u32 flags; | ||
117 | }; | ||
118 | |||
119 | static struct esdhc_soc_data esdhc_imx25_data = { | ||
120 | .flags = ESDHC_FLAG_ENGCM07207, | ||
121 | }; | ||
122 | |||
123 | static struct esdhc_soc_data esdhc_imx35_data = { | ||
124 | .flags = ESDHC_FLAG_ENGCM07207, | ||
125 | }; | ||
126 | |||
127 | static struct esdhc_soc_data esdhc_imx51_data = { | ||
128 | .flags = 0, | ||
129 | }; | ||
130 | |||
131 | static struct esdhc_soc_data esdhc_imx53_data = { | ||
132 | .flags = ESDHC_FLAG_MULTIBLK_NO_INT, | ||
133 | }; | ||
134 | |||
135 | static struct esdhc_soc_data usdhc_imx6q_data = { | ||
136 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING, | ||
137 | }; | ||
138 | |||
139 | static struct esdhc_soc_data usdhc_imx6sl_data = { | ||
140 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | ||
141 | | ESDHC_FLAG_HAVE_CAP1, | ||
77 | }; | 142 | }; |
78 | 143 | ||
79 | struct pltfm_imx_data { | 144 | struct pltfm_imx_data { |
80 | int flags; | ||
81 | u32 scratchpad; | 145 | u32 scratchpad; |
82 | enum imx_esdhc_type devtype; | ||
83 | struct pinctrl *pinctrl; | 146 | struct pinctrl *pinctrl; |
147 | struct pinctrl_state *pins_default; | ||
148 | struct pinctrl_state *pins_100mhz; | ||
149 | struct pinctrl_state *pins_200mhz; | ||
150 | const struct esdhc_soc_data *socdata; | ||
84 | struct esdhc_platform_data boarddata; | 151 | struct esdhc_platform_data boarddata; |
85 | struct clk *clk_ipg; | 152 | struct clk *clk_ipg; |
86 | struct clk *clk_ahb; | 153 | struct clk *clk_ahb; |
@@ -90,25 +157,20 @@ struct pltfm_imx_data { | |||
90 | MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */ | 157 | MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */ |
91 | WAIT_FOR_INT, /* sent CMD12, waiting for response INT */ | 158 | WAIT_FOR_INT, /* sent CMD12, waiting for response INT */ |
92 | } multiblock_status; | 159 | } multiblock_status; |
93 | 160 | u32 uhs_mode; | |
161 | u32 is_ddr; | ||
94 | }; | 162 | }; |
95 | 163 | ||
96 | static struct platform_device_id imx_esdhc_devtype[] = { | 164 | static struct platform_device_id imx_esdhc_devtype[] = { |
97 | { | 165 | { |
98 | .name = "sdhci-esdhc-imx25", | 166 | .name = "sdhci-esdhc-imx25", |
99 | .driver_data = IMX25_ESDHC, | 167 | .driver_data = (kernel_ulong_t) &esdhc_imx25_data, |
100 | }, { | 168 | }, { |
101 | .name = "sdhci-esdhc-imx35", | 169 | .name = "sdhci-esdhc-imx35", |
102 | .driver_data = IMX35_ESDHC, | 170 | .driver_data = (kernel_ulong_t) &esdhc_imx35_data, |
103 | }, { | 171 | }, { |
104 | .name = "sdhci-esdhc-imx51", | 172 | .name = "sdhci-esdhc-imx51", |
105 | .driver_data = IMX51_ESDHC, | 173 | .driver_data = (kernel_ulong_t) &esdhc_imx51_data, |
106 | }, { | ||
107 | .name = "sdhci-esdhc-imx53", | ||
108 | .driver_data = IMX53_ESDHC, | ||
109 | }, { | ||
110 | .name = "sdhci-usdhc-imx6q", | ||
111 | .driver_data = IMX6Q_USDHC, | ||
112 | }, { | 174 | }, { |
113 | /* sentinel */ | 175 | /* sentinel */ |
114 | } | 176 | } |
@@ -116,38 +178,34 @@ static struct platform_device_id imx_esdhc_devtype[] = { | |||
116 | MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); | 178 | MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); |
117 | 179 | ||
118 | static const struct of_device_id imx_esdhc_dt_ids[] = { | 180 | static const struct of_device_id imx_esdhc_dt_ids[] = { |
119 | { .compatible = "fsl,imx25-esdhc", .data = &imx_esdhc_devtype[IMX25_ESDHC], }, | 181 | { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, }, |
120 | { .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], }, | 182 | { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, }, |
121 | { .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], }, | 183 | { .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, }, |
122 | { .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], }, | 184 | { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, }, |
123 | { .compatible = "fsl,imx6q-usdhc", .data = &imx_esdhc_devtype[IMX6Q_USDHC], }, | 185 | { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, }, |
186 | { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, }, | ||
124 | { /* sentinel */ } | 187 | { /* sentinel */ } |
125 | }; | 188 | }; |
126 | MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); | 189 | MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); |
127 | 190 | ||
128 | static inline int is_imx25_esdhc(struct pltfm_imx_data *data) | 191 | static inline int is_imx25_esdhc(struct pltfm_imx_data *data) |
129 | { | 192 | { |
130 | return data->devtype == IMX25_ESDHC; | 193 | return data->socdata == &esdhc_imx25_data; |
131 | } | ||
132 | |||
133 | static inline int is_imx35_esdhc(struct pltfm_imx_data *data) | ||
134 | { | ||
135 | return data->devtype == IMX35_ESDHC; | ||
136 | } | 194 | } |
137 | 195 | ||
138 | static inline int is_imx51_esdhc(struct pltfm_imx_data *data) | 196 | static inline int is_imx53_esdhc(struct pltfm_imx_data *data) |
139 | { | 197 | { |
140 | return data->devtype == IMX51_ESDHC; | 198 | return data->socdata == &esdhc_imx53_data; |
141 | } | 199 | } |
142 | 200 | ||
143 | static inline int is_imx53_esdhc(struct pltfm_imx_data *data) | 201 | static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) |
144 | { | 202 | { |
145 | return data->devtype == IMX53_ESDHC; | 203 | return data->socdata == &usdhc_imx6q_data; |
146 | } | 204 | } |
147 | 205 | ||
148 | static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) | 206 | static inline int esdhc_is_usdhc(struct pltfm_imx_data *data) |
149 | { | 207 | { |
150 | return data->devtype == IMX6Q_USDHC; | 208 | return !!(data->socdata->flags & ESDHC_FLAG_USDHC); |
151 | } | 209 | } |
152 | 210 | ||
153 | static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) | 211 | static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) |
@@ -164,7 +222,21 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | |||
164 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 222 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
165 | u32 val = readl(host->ioaddr + reg); | 223 | u32 val = readl(host->ioaddr + reg); |
166 | 224 | ||
225 | if (unlikely(reg == SDHCI_PRESENT_STATE)) { | ||
226 | u32 fsl_prss = val; | ||
227 | /* save the least 20 bits */ | ||
228 | val = fsl_prss & 0x000FFFFF; | ||
229 | /* move dat[0-3] bits */ | ||
230 | val |= (fsl_prss & 0x0F000000) >> 4; | ||
231 | /* move cmd line bit */ | ||
232 | val |= (fsl_prss & 0x00800000) << 1; | ||
233 | } | ||
234 | |||
167 | if (unlikely(reg == SDHCI_CAPABILITIES)) { | 235 | if (unlikely(reg == SDHCI_CAPABILITIES)) { |
236 | /* ignore bit[0-15] as it stores cap_1 register val for mx6sl */ | ||
237 | if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) | ||
238 | val &= 0xffff0000; | ||
239 | |||
168 | /* In FSL esdhc IC module, only bit20 is used to indicate the | 240 | /* In FSL esdhc IC module, only bit20 is used to indicate the |
169 | * ADMA2 capability of esdhc, but this bit is messed up on | 241 | * ADMA2 capability of esdhc, but this bit is messed up on |
170 | * some SOCs (e.g. on MX25, MX35 this bit is set, but they | 242 | * some SOCs (e.g. on MX25, MX35 this bit is set, but they |
@@ -178,6 +250,25 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | |||
178 | } | 250 | } |
179 | } | 251 | } |
180 | 252 | ||
253 | if (unlikely(reg == SDHCI_CAPABILITIES_1)) { | ||
254 | if (esdhc_is_usdhc(imx_data)) { | ||
255 | if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) | ||
256 | val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF; | ||
257 | else | ||
258 | /* imx6q/dl does not have cap_1 register, fake one */ | ||
259 | val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 | ||
260 | | SDHCI_SUPPORT_SDR50 | ||
261 | | SDHCI_USE_SDR50_TUNING; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) { | ||
266 | val = 0; | ||
267 | val |= 0xFF << SDHCI_MAX_CURRENT_330_SHIFT; | ||
268 | val |= 0xFF << SDHCI_MAX_CURRENT_300_SHIFT; | ||
269 | val |= 0xFF << SDHCI_MAX_CURRENT_180_SHIFT; | ||
270 | } | ||
271 | |||
181 | if (unlikely(reg == SDHCI_INT_STATUS)) { | 272 | if (unlikely(reg == SDHCI_INT_STATUS)) { |
182 | if (val & ESDHC_INT_VENDOR_SPEC_DMA_ERR) { | 273 | if (val & ESDHC_INT_VENDOR_SPEC_DMA_ERR) { |
183 | val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR; | 274 | val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR; |
@@ -224,7 +315,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) | |||
224 | } | 315 | } |
225 | } | 316 | } |
226 | 317 | ||
227 | if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT) | 318 | if (unlikely((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) |
228 | && (reg == SDHCI_INT_STATUS) | 319 | && (reg == SDHCI_INT_STATUS) |
229 | && (val & SDHCI_INT_DATA_END))) { | 320 | && (val & SDHCI_INT_DATA_END))) { |
230 | u32 v; | 321 | u32 v; |
@@ -256,10 +347,12 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) | |||
256 | { | 347 | { |
257 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 348 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
258 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 349 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
350 | u16 ret = 0; | ||
351 | u32 val; | ||
259 | 352 | ||
260 | if (unlikely(reg == SDHCI_HOST_VERSION)) { | 353 | if (unlikely(reg == SDHCI_HOST_VERSION)) { |
261 | reg ^= 2; | 354 | reg ^= 2; |
262 | if (is_imx6q_usdhc(imx_data)) { | 355 | if (esdhc_is_usdhc(imx_data)) { |
263 | /* | 356 | /* |
264 | * The usdhc register returns a wrong host version. | 357 | * The usdhc register returns a wrong host version. |
265 | * Correct it here. | 358 | * Correct it here. |
@@ -268,6 +361,30 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) | |||
268 | } | 361 | } |
269 | } | 362 | } |
270 | 363 | ||
364 | if (unlikely(reg == SDHCI_HOST_CONTROL2)) { | ||
365 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | ||
366 | if (val & ESDHC_VENDOR_SPEC_VSELECT) | ||
367 | ret |= SDHCI_CTRL_VDD_180; | ||
368 | |||
369 | if (esdhc_is_usdhc(imx_data)) { | ||
370 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) | ||
371 | val = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
372 | else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) | ||
373 | /* the std tuning bits is in ACMD12_ERR for imx6sl */ | ||
374 | val = readl(host->ioaddr + SDHCI_ACMD12_ERR); | ||
375 | } | ||
376 | |||
377 | if (val & ESDHC_MIX_CTRL_EXE_TUNE) | ||
378 | ret |= SDHCI_CTRL_EXEC_TUNING; | ||
379 | if (val & ESDHC_MIX_CTRL_SMPCLK_SEL) | ||
380 | ret |= SDHCI_CTRL_TUNED_CLK; | ||
381 | |||
382 | ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK); | ||
383 | ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
271 | return readw(host->ioaddr + reg); | 388 | return readw(host->ioaddr + reg); |
272 | } | 389 | } |
273 | 390 | ||
@@ -275,10 +392,59 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
275 | { | 392 | { |
276 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 393 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
277 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 394 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
395 | u32 new_val = 0; | ||
278 | 396 | ||
279 | switch (reg) { | 397 | switch (reg) { |
398 | case SDHCI_CLOCK_CONTROL: | ||
399 | new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | ||
400 | if (val & SDHCI_CLOCK_CARD_EN) | ||
401 | new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; | ||
402 | else | ||
403 | new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; | ||
404 | writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); | ||
405 | return; | ||
406 | case SDHCI_HOST_CONTROL2: | ||
407 | new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | ||
408 | if (val & SDHCI_CTRL_VDD_180) | ||
409 | new_val |= ESDHC_VENDOR_SPEC_VSELECT; | ||
410 | else | ||
411 | new_val &= ~ESDHC_VENDOR_SPEC_VSELECT; | ||
412 | writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); | ||
413 | imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK; | ||
414 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { | ||
415 | new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
416 | if (val & SDHCI_CTRL_TUNED_CLK) | ||
417 | new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
418 | else | ||
419 | new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
420 | writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); | ||
421 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { | ||
422 | u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); | ||
423 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
424 | new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL); | ||
425 | if (val & SDHCI_CTRL_EXEC_TUNING) { | ||
426 | new_val |= ESDHC_STD_TUNING_EN | | ||
427 | ESDHC_TUNING_START_TAP; | ||
428 | v |= ESDHC_MIX_CTRL_EXE_TUNE; | ||
429 | m |= ESDHC_MIX_CTRL_FBCLK_SEL; | ||
430 | } else { | ||
431 | new_val &= ~ESDHC_STD_TUNING_EN; | ||
432 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; | ||
433 | m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; | ||
434 | } | ||
435 | |||
436 | if (val & SDHCI_CTRL_TUNED_CLK) | ||
437 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
438 | else | ||
439 | v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
440 | |||
441 | writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL); | ||
442 | writel(v, host->ioaddr + SDHCI_ACMD12_ERR); | ||
443 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); | ||
444 | } | ||
445 | return; | ||
280 | case SDHCI_TRANSFER_MODE: | 446 | case SDHCI_TRANSFER_MODE: |
281 | if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT) | 447 | if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) |
282 | && (host->cmd->opcode == SD_IO_RW_EXTENDED) | 448 | && (host->cmd->opcode == SD_IO_RW_EXTENDED) |
283 | && (host->cmd->data->blocks > 1) | 449 | && (host->cmd->data->blocks > 1) |
284 | && (host->cmd->data->flags & MMC_DATA_READ)) { | 450 | && (host->cmd->data->flags & MMC_DATA_READ)) { |
@@ -288,7 +454,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
288 | writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); | 454 | writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); |
289 | } | 455 | } |
290 | 456 | ||
291 | if (is_imx6q_usdhc(imx_data)) { | 457 | if (esdhc_is_usdhc(imx_data)) { |
292 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | 458 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); |
293 | /* Swap AC23 bit */ | 459 | /* Swap AC23 bit */ |
294 | if (val & SDHCI_TRNS_AUTO_CMD23) { | 460 | if (val & SDHCI_TRNS_AUTO_CMD23) { |
@@ -310,10 +476,10 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
310 | val |= SDHCI_CMD_ABORTCMD; | 476 | val |= SDHCI_CMD_ABORTCMD; |
311 | 477 | ||
312 | if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) && | 478 | if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) && |
313 | (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) | 479 | (imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) |
314 | imx_data->multiblock_status = MULTIBLK_IN_PROCESS; | 480 | imx_data->multiblock_status = MULTIBLK_IN_PROCESS; |
315 | 481 | ||
316 | if (is_imx6q_usdhc(imx_data)) | 482 | if (esdhc_is_usdhc(imx_data)) |
317 | writel(val << 16, | 483 | writel(val << 16, |
318 | host->ioaddr + SDHCI_TRANSFER_MODE); | 484 | host->ioaddr + SDHCI_TRANSFER_MODE); |
319 | else | 485 | else |
@@ -379,8 +545,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) | |||
379 | * The reset on usdhc fails to clear MIX_CTRL register. | 545 | * The reset on usdhc fails to clear MIX_CTRL register. |
380 | * Do it manually here. | 546 | * Do it manually here. |
381 | */ | 547 | */ |
382 | if (is_imx6q_usdhc(imx_data)) | 548 | if (esdhc_is_usdhc(imx_data)) { |
383 | writel(0, host->ioaddr + ESDHC_MIX_CTRL); | 549 | writel(0, host->ioaddr + ESDHC_MIX_CTRL); |
550 | imx_data->is_ddr = 0; | ||
551 | } | ||
384 | } | 552 | } |
385 | } | 553 | } |
386 | 554 | ||
@@ -409,8 +577,60 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | |||
409 | unsigned int clock) | 577 | unsigned int clock) |
410 | { | 578 | { |
411 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 579 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
580 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
581 | unsigned int host_clock = clk_get_rate(pltfm_host->clk); | ||
582 | int pre_div = 2; | ||
583 | int div = 1; | ||
584 | u32 temp, val; | ||
585 | |||
586 | if (clock == 0) { | ||
587 | if (esdhc_is_usdhc(imx_data)) { | ||
588 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | ||
589 | writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, | ||
590 | host->ioaddr + ESDHC_VENDOR_SPEC); | ||
591 | } | ||
592 | goto out; | ||
593 | } | ||
594 | |||
595 | if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr) | ||
596 | pre_div = 1; | ||
597 | |||
598 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
599 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ||
600 | | ESDHC_CLOCK_MASK); | ||
601 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
602 | |||
603 | while (host_clock / pre_div / 16 > clock && pre_div < 256) | ||
604 | pre_div *= 2; | ||
605 | |||
606 | while (host_clock / pre_div / div > clock && div < 16) | ||
607 | div++; | ||
412 | 608 | ||
413 | esdhc_set_clock(host, clock, clk_get_rate(pltfm_host->clk)); | 609 | host->mmc->actual_clock = host_clock / pre_div / div; |
610 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | ||
611 | clock, host->mmc->actual_clock); | ||
612 | |||
613 | if (imx_data->is_ddr) | ||
614 | pre_div >>= 2; | ||
615 | else | ||
616 | pre_div >>= 1; | ||
617 | div--; | ||
618 | |||
619 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
620 | temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ||
621 | | (div << ESDHC_DIVIDER_SHIFT) | ||
622 | | (pre_div << ESDHC_PREDIV_SHIFT)); | ||
623 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
624 | |||
625 | if (esdhc_is_usdhc(imx_data)) { | ||
626 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | ||
627 | writel(val | ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, | ||
628 | host->ioaddr + ESDHC_VENDOR_SPEC); | ||
629 | } | ||
630 | |||
631 | mdelay(1); | ||
632 | out: | ||
633 | host->clock = clock; | ||
414 | } | 634 | } |
415 | 635 | ||
416 | static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) | 636 | static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) |
@@ -454,7 +674,192 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) | |||
454 | return 0; | 674 | return 0; |
455 | } | 675 | } |
456 | 676 | ||
457 | static const struct sdhci_ops sdhci_esdhc_ops = { | 677 | static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) |
678 | { | ||
679 | u32 reg; | ||
680 | |||
681 | /* FIXME: delay a bit for card to be ready for next tuning due to errors */ | ||
682 | mdelay(1); | ||
683 | |||
684 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
685 | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | | ||
686 | ESDHC_MIX_CTRL_FBCLK_SEL; | ||
687 | writel(reg, host->ioaddr + ESDHC_MIX_CTRL); | ||
688 | writel(val << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); | ||
689 | dev_dbg(mmc_dev(host->mmc), | ||
690 | "tunning with delay 0x%x ESDHC_TUNE_CTRL_STATUS 0x%x\n", | ||
691 | val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS)); | ||
692 | } | ||
693 | |||
694 | static void esdhc_request_done(struct mmc_request *mrq) | ||
695 | { | ||
696 | complete(&mrq->completion); | ||
697 | } | ||
698 | |||
699 | static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) | ||
700 | { | ||
701 | struct mmc_command cmd = {0}; | ||
702 | struct mmc_request mrq = {0}; | ||
703 | struct mmc_data data = {0}; | ||
704 | struct scatterlist sg; | ||
705 | char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN]; | ||
706 | |||
707 | cmd.opcode = opcode; | ||
708 | cmd.arg = 0; | ||
709 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
710 | |||
711 | data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN; | ||
712 | data.blocks = 1; | ||
713 | data.flags = MMC_DATA_READ; | ||
714 | data.sg = &sg; | ||
715 | data.sg_len = 1; | ||
716 | |||
717 | sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern)); | ||
718 | |||
719 | mrq.cmd = &cmd; | ||
720 | mrq.cmd->mrq = &mrq; | ||
721 | mrq.data = &data; | ||
722 | mrq.data->mrq = &mrq; | ||
723 | mrq.cmd->data = mrq.data; | ||
724 | |||
725 | mrq.done = esdhc_request_done; | ||
726 | init_completion(&(mrq.completion)); | ||
727 | |||
728 | disable_irq(host->irq); | ||
729 | spin_lock(&host->lock); | ||
730 | host->mrq = &mrq; | ||
731 | |||
732 | sdhci_send_command(host, mrq.cmd); | ||
733 | |||
734 | spin_unlock(&host->lock); | ||
735 | enable_irq(host->irq); | ||
736 | |||
737 | wait_for_completion(&mrq.completion); | ||
738 | |||
739 | if (cmd.error) | ||
740 | return cmd.error; | ||
741 | if (data.error) | ||
742 | return data.error; | ||
743 | |||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | static void esdhc_post_tuning(struct sdhci_host *host) | ||
748 | { | ||
749 | u32 reg; | ||
750 | |||
751 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
752 | reg &= ~ESDHC_MIX_CTRL_EXE_TUNE; | ||
753 | writel(reg, host->ioaddr + ESDHC_MIX_CTRL); | ||
754 | } | ||
755 | |||
756 | static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) | ||
757 | { | ||
758 | int min, max, avg, ret; | ||
759 | |||
760 | /* find the mininum delay first which can pass tuning */ | ||
761 | min = ESDHC_TUNE_CTRL_MIN; | ||
762 | while (min < ESDHC_TUNE_CTRL_MAX) { | ||
763 | esdhc_prepare_tuning(host, min); | ||
764 | if (!esdhc_send_tuning_cmd(host, opcode)) | ||
765 | break; | ||
766 | min += ESDHC_TUNE_CTRL_STEP; | ||
767 | } | ||
768 | |||
769 | /* find the maxinum delay which can not pass tuning */ | ||
770 | max = min + ESDHC_TUNE_CTRL_STEP; | ||
771 | while (max < ESDHC_TUNE_CTRL_MAX) { | ||
772 | esdhc_prepare_tuning(host, max); | ||
773 | if (esdhc_send_tuning_cmd(host, opcode)) { | ||
774 | max -= ESDHC_TUNE_CTRL_STEP; | ||
775 | break; | ||
776 | } | ||
777 | max += ESDHC_TUNE_CTRL_STEP; | ||
778 | } | ||
779 | |||
780 | /* use average delay to get the best timing */ | ||
781 | avg = (min + max) / 2; | ||
782 | esdhc_prepare_tuning(host, avg); | ||
783 | ret = esdhc_send_tuning_cmd(host, opcode); | ||
784 | esdhc_post_tuning(host); | ||
785 | |||
786 | dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n", | ||
787 | ret ? "failed" : "passed", avg, ret); | ||
788 | |||
789 | return ret; | ||
790 | } | ||
791 | |||
792 | static int esdhc_change_pinstate(struct sdhci_host *host, | ||
793 | unsigned int uhs) | ||
794 | { | ||
795 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
796 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
797 | struct pinctrl_state *pinctrl; | ||
798 | |||
799 | dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs); | ||
800 | |||
801 | if (IS_ERR(imx_data->pinctrl) || | ||
802 | IS_ERR(imx_data->pins_default) || | ||
803 | IS_ERR(imx_data->pins_100mhz) || | ||
804 | IS_ERR(imx_data->pins_200mhz)) | ||
805 | return -EINVAL; | ||
806 | |||
807 | switch (uhs) { | ||
808 | case MMC_TIMING_UHS_SDR50: | ||
809 | pinctrl = imx_data->pins_100mhz; | ||
810 | break; | ||
811 | case MMC_TIMING_UHS_SDR104: | ||
812 | pinctrl = imx_data->pins_200mhz; | ||
813 | break; | ||
814 | default: | ||
815 | /* back to default state for other legacy timing */ | ||
816 | pinctrl = imx_data->pins_default; | ||
817 | } | ||
818 | |||
819 | return pinctrl_select_state(imx_data->pinctrl, pinctrl); | ||
820 | } | ||
821 | |||
822 | static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) | ||
823 | { | ||
824 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
825 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
826 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; | ||
827 | |||
828 | switch (uhs) { | ||
829 | case MMC_TIMING_UHS_SDR12: | ||
830 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12; | ||
831 | break; | ||
832 | case MMC_TIMING_UHS_SDR25: | ||
833 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25; | ||
834 | break; | ||
835 | case MMC_TIMING_UHS_SDR50: | ||
836 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50; | ||
837 | break; | ||
838 | case MMC_TIMING_UHS_SDR104: | ||
839 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104; | ||
840 | break; | ||
841 | case MMC_TIMING_UHS_DDR50: | ||
842 | imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50; | ||
843 | writel(readl(host->ioaddr + ESDHC_MIX_CTRL) | | ||
844 | ESDHC_MIX_CTRL_DDREN, | ||
845 | host->ioaddr + ESDHC_MIX_CTRL); | ||
846 | imx_data->is_ddr = 1; | ||
847 | if (boarddata->delay_line) { | ||
848 | u32 v; | ||
849 | v = boarddata->delay_line << | ||
850 | ESDHC_DLL_OVERRIDE_VAL_SHIFT | | ||
851 | (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT); | ||
852 | if (is_imx53_esdhc(imx_data)) | ||
853 | v <<= 1; | ||
854 | writel(v, host->ioaddr + ESDHC_DLL_CTRL); | ||
855 | } | ||
856 | break; | ||
857 | } | ||
858 | |||
859 | return esdhc_change_pinstate(host, uhs); | ||
860 | } | ||
861 | |||
862 | static struct sdhci_ops sdhci_esdhc_ops = { | ||
458 | .read_l = esdhc_readl_le, | 863 | .read_l = esdhc_readl_le, |
459 | .read_w = esdhc_readw_le, | 864 | .read_w = esdhc_readw_le, |
460 | .write_l = esdhc_writel_le, | 865 | .write_l = esdhc_writel_le, |
@@ -465,6 +870,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { | |||
465 | .get_min_clock = esdhc_pltfm_get_min_clock, | 870 | .get_min_clock = esdhc_pltfm_get_min_clock, |
466 | .get_ro = esdhc_pltfm_get_ro, | 871 | .get_ro = esdhc_pltfm_get_ro, |
467 | .platform_bus_width = esdhc_pltfm_bus_width, | 872 | .platform_bus_width = esdhc_pltfm_bus_width, |
873 | .set_uhs_signaling = esdhc_set_uhs_signaling, | ||
468 | }; | 874 | }; |
469 | 875 | ||
470 | static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { | 876 | static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { |
@@ -506,6 +912,14 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | |||
506 | 912 | ||
507 | of_property_read_u32(np, "max-frequency", &boarddata->f_max); | 913 | of_property_read_u32(np, "max-frequency", &boarddata->f_max); |
508 | 914 | ||
915 | if (of_find_property(np, "no-1-8-v", NULL)) | ||
916 | boarddata->support_vsel = false; | ||
917 | else | ||
918 | boarddata->support_vsel = true; | ||
919 | |||
920 | if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) | ||
921 | boarddata->delay_line = 0; | ||
922 | |||
509 | return 0; | 923 | return 0; |
510 | } | 924 | } |
511 | #else | 925 | #else |
@@ -539,9 +953,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
539 | goto free_sdhci; | 953 | goto free_sdhci; |
540 | } | 954 | } |
541 | 955 | ||
542 | if (of_id) | 956 | imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *) |
543 | pdev->id_entry = of_id->data; | 957 | pdev->id_entry->driver_data; |
544 | imx_data->devtype = pdev->id_entry->driver_data; | ||
545 | pltfm_host->priv = imx_data; | 958 | pltfm_host->priv = imx_data; |
546 | 959 | ||
547 | imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); | 960 | imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
@@ -568,29 +981,39 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
568 | clk_prepare_enable(imx_data->clk_ipg); | 981 | clk_prepare_enable(imx_data->clk_ipg); |
569 | clk_prepare_enable(imx_data->clk_ahb); | 982 | clk_prepare_enable(imx_data->clk_ahb); |
570 | 983 | ||
571 | imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | 984 | imx_data->pinctrl = devm_pinctrl_get(&pdev->dev); |
572 | if (IS_ERR(imx_data->pinctrl)) { | 985 | if (IS_ERR(imx_data->pinctrl)) { |
573 | err = PTR_ERR(imx_data->pinctrl); | 986 | err = PTR_ERR(imx_data->pinctrl); |
574 | goto disable_clk; | 987 | goto disable_clk; |
575 | } | 988 | } |
576 | 989 | ||
990 | imx_data->pins_default = pinctrl_lookup_state(imx_data->pinctrl, | ||
991 | PINCTRL_STATE_DEFAULT); | ||
992 | if (IS_ERR(imx_data->pins_default)) { | ||
993 | err = PTR_ERR(imx_data->pins_default); | ||
994 | dev_err(mmc_dev(host->mmc), "could not get default state\n"); | ||
995 | goto disable_clk; | ||
996 | } | ||
997 | |||
577 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | 998 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; |
578 | 999 | ||
579 | if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data)) | 1000 | if (imx_data->socdata->flags & ESDHC_FLAG_ENGCM07207) |
580 | /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */ | 1001 | /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */ |
581 | host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK | 1002 | host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK |
582 | | SDHCI_QUIRK_BROKEN_ADMA; | 1003 | | SDHCI_QUIRK_BROKEN_ADMA; |
583 | 1004 | ||
584 | if (is_imx53_esdhc(imx_data)) | ||
585 | imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; | ||
586 | |||
587 | /* | 1005 | /* |
588 | * The imx6q ROM code will change the default watermark level setting | 1006 | * The imx6q ROM code will change the default watermark level setting |
589 | * to something insane. Change it back here. | 1007 | * to something insane. Change it back here. |
590 | */ | 1008 | */ |
591 | if (is_imx6q_usdhc(imx_data)) | 1009 | if (esdhc_is_usdhc(imx_data)) { |
592 | writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); | 1010 | writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); |
1011 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; | ||
1012 | } | ||
593 | 1013 | ||
1014 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) | ||
1015 | sdhci_esdhc_ops.platform_execute_tuning = | ||
1016 | esdhc_executing_tuning; | ||
594 | boarddata = &imx_data->boarddata; | 1017 | boarddata = &imx_data->boarddata; |
595 | if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { | 1018 | if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { |
596 | if (!host->mmc->parent->platform_data) { | 1019 | if (!host->mmc->parent->platform_data) { |
@@ -650,6 +1073,23 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
650 | break; | 1073 | break; |
651 | } | 1074 | } |
652 | 1075 | ||
1076 | /* sdr50 and sdr104 needs work on 1.8v signal voltage */ | ||
1077 | if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data)) { | ||
1078 | imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, | ||
1079 | ESDHC_PINCTRL_STATE_100MHZ); | ||
1080 | imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, | ||
1081 | ESDHC_PINCTRL_STATE_200MHZ); | ||
1082 | if (IS_ERR(imx_data->pins_100mhz) || | ||
1083 | IS_ERR(imx_data->pins_200mhz)) { | ||
1084 | dev_warn(mmc_dev(host->mmc), | ||
1085 | "could not get ultra high speed state, work on normal mode\n"); | ||
1086 | /* fall back to not support uhs by specify no 1.8v quirk */ | ||
1087 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; | ||
1088 | } | ||
1089 | } else { | ||
1090 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; | ||
1091 | } | ||
1092 | |||
653 | err = sdhci_add_host(host); | 1093 | err = sdhci_add_host(host); |
654 | if (err) | 1094 | if (err) |
655 | goto disable_clk; | 1095 | goto disable_clk; |
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index a2a06420e463..a7d9f95a7b03 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h | |||
@@ -49,41 +49,4 @@ | |||
49 | 49 | ||
50 | #define ESDHC_HOST_CONTROL_RES 0x05 | 50 | #define ESDHC_HOST_CONTROL_RES 0x05 |
51 | 51 | ||
52 | static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock, | ||
53 | unsigned int host_clock) | ||
54 | { | ||
55 | int pre_div = 2; | ||
56 | int div = 1; | ||
57 | u32 temp; | ||
58 | |||
59 | if (clock == 0) | ||
60 | goto out; | ||
61 | |||
62 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
63 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ||
64 | | ESDHC_CLOCK_MASK); | ||
65 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
66 | |||
67 | while (host_clock / pre_div / 16 > clock && pre_div < 256) | ||
68 | pre_div *= 2; | ||
69 | |||
70 | while (host_clock / pre_div / div > clock && div < 16) | ||
71 | div++; | ||
72 | |||
73 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | ||
74 | clock, host_clock / pre_div / div); | ||
75 | |||
76 | pre_div >>= 1; | ||
77 | div--; | ||
78 | |||
79 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
80 | temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ||
81 | | (div << ESDHC_DIVIDER_SHIFT) | ||
82 | | (pre_div << ESDHC_PREDIV_SHIFT)); | ||
83 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
84 | mdelay(1); | ||
85 | out: | ||
86 | host->clock = clock; | ||
87 | } | ||
88 | |||
89 | #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ | 52 | #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index e328252ebf2a..0b249970b119 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -199,6 +199,14 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) | |||
199 | 199 | ||
200 | static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | 200 | static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) |
201 | { | 201 | { |
202 | |||
203 | int pre_div = 2; | ||
204 | int div = 1; | ||
205 | u32 temp; | ||
206 | |||
207 | if (clock == 0) | ||
208 | goto out; | ||
209 | |||
202 | /* Workaround to reduce the clock frequency for p1010 esdhc */ | 210 | /* Workaround to reduce the clock frequency for p1010 esdhc */ |
203 | if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) { | 211 | if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) { |
204 | if (clock > 20000000) | 212 | if (clock > 20000000) |
@@ -207,8 +215,31 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
207 | clock -= 5000000; | 215 | clock -= 5000000; |
208 | } | 216 | } |
209 | 217 | ||
210 | /* Set the clock */ | 218 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); |
211 | esdhc_set_clock(host, clock, host->max_clk); | 219 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
220 | | ESDHC_CLOCK_MASK); | ||
221 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
222 | |||
223 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) | ||
224 | pre_div *= 2; | ||
225 | |||
226 | while (host->max_clk / pre_div / div > clock && div < 16) | ||
227 | div++; | ||
228 | |||
229 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | ||
230 | clock, host->max_clk / pre_div / div); | ||
231 | |||
232 | pre_div >>= 1; | ||
233 | div--; | ||
234 | |||
235 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
236 | temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ||
237 | | (div << ESDHC_DIVIDER_SHIFT) | ||
238 | | (pre_div << ESDHC_PREDIV_SHIFT)); | ||
239 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
240 | mdelay(1); | ||
241 | out: | ||
242 | host->clock = clock; | ||
212 | } | 243 | } |
213 | 244 | ||
214 | #ifdef CONFIG_PM | 245 | #ifdef CONFIG_PM |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index d7d6bc8968d2..8f753811fc7a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -37,6 +37,12 @@ | |||
37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | 37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 |
38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | 38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 |
39 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 | 39 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 |
40 | #define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190 | ||
41 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO0 0x08f9 | ||
42 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO1 0x08fa | ||
43 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb | ||
44 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 | ||
45 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 | ||
40 | 46 | ||
41 | /* | 47 | /* |
42 | * PCI registers | 48 | * PCI registers |
@@ -356,6 +362,28 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | |||
356 | .allow_runtime_pm = true, | 362 | .allow_runtime_pm = true, |
357 | }; | 363 | }; |
358 | 364 | ||
365 | /* Define Host controllers for Intel Merrifield platform */ | ||
366 | #define INTEL_MRFL_EMMC_0 0 | ||
367 | #define INTEL_MRFL_EMMC_1 1 | ||
368 | |||
369 | static int intel_mrfl_mmc_probe_slot(struct sdhci_pci_slot *slot) | ||
370 | { | ||
371 | if ((PCI_FUNC(slot->chip->pdev->devfn) != INTEL_MRFL_EMMC_0) && | ||
372 | (PCI_FUNC(slot->chip->pdev->devfn) != INTEL_MRFL_EMMC_1)) | ||
373 | /* SD support is not ready yet */ | ||
374 | return -ENODEV; | ||
375 | |||
376 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | | ||
377 | MMC_CAP_1_8V_DDR; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { | ||
383 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
384 | .probe_slot = intel_mrfl_mmc_probe_slot, | ||
385 | }; | ||
386 | |||
359 | /* O2Micro extra registers */ | 387 | /* O2Micro extra registers */ |
360 | #define O2_SD_LOCK_WP 0xD3 | 388 | #define O2_SD_LOCK_WP 0xD3 |
361 | #define O2_SD_MULTI_VCC3V 0xEE | 389 | #define O2_SD_MULTI_VCC3V 0xEE |
@@ -939,6 +967,54 @@ static const struct pci_device_id pci_ids[] = { | |||
939 | .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc, | 967 | .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc, |
940 | }, | 968 | }, |
941 | 969 | ||
970 | |||
971 | { | ||
972 | .vendor = PCI_VENDOR_ID_INTEL, | ||
973 | .device = PCI_DEVICE_ID_INTEL_CLV_SDIO0, | ||
974 | .subvendor = PCI_ANY_ID, | ||
975 | .subdevice = PCI_ANY_ID, | ||
976 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sd, | ||
977 | }, | ||
978 | |||
979 | { | ||
980 | .vendor = PCI_VENDOR_ID_INTEL, | ||
981 | .device = PCI_DEVICE_ID_INTEL_CLV_SDIO1, | ||
982 | .subvendor = PCI_ANY_ID, | ||
983 | .subdevice = PCI_ANY_ID, | ||
984 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sdio, | ||
985 | }, | ||
986 | |||
987 | { | ||
988 | .vendor = PCI_VENDOR_ID_INTEL, | ||
989 | .device = PCI_DEVICE_ID_INTEL_CLV_SDIO2, | ||
990 | .subvendor = PCI_ANY_ID, | ||
991 | .subdevice = PCI_ANY_ID, | ||
992 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sdio, | ||
993 | }, | ||
994 | |||
995 | { | ||
996 | .vendor = PCI_VENDOR_ID_INTEL, | ||
997 | .device = PCI_DEVICE_ID_INTEL_CLV_EMMC0, | ||
998 | .subvendor = PCI_ANY_ID, | ||
999 | .subdevice = PCI_ANY_ID, | ||
1000 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc, | ||
1001 | }, | ||
1002 | |||
1003 | { | ||
1004 | .vendor = PCI_VENDOR_ID_INTEL, | ||
1005 | .device = PCI_DEVICE_ID_INTEL_CLV_EMMC1, | ||
1006 | .subvendor = PCI_ANY_ID, | ||
1007 | .subdevice = PCI_ANY_ID, | ||
1008 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc, | ||
1009 | }, | ||
1010 | |||
1011 | { | ||
1012 | .vendor = PCI_VENDOR_ID_INTEL, | ||
1013 | .device = PCI_DEVICE_ID_INTEL_MRFL_MMC, | ||
1014 | .subvendor = PCI_ANY_ID, | ||
1015 | .subdevice = PCI_ANY_ID, | ||
1016 | .driver_data = (kernel_ulong_t)&sdhci_intel_mrfl_mmc, | ||
1017 | }, | ||
942 | { | 1018 | { |
943 | .vendor = PCI_VENDOR_ID_O2, | 1019 | .vendor = PCI_VENDOR_ID_O2, |
944 | .device = PCI_DEVICE_ID_O2_8120, | 1020 | .device = PCI_DEVICE_ID_O2_8120, |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7a7fb4f0d5a4..bd8a0982aec3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -49,7 +49,6 @@ static unsigned int debug_quirks2; | |||
49 | 49 | ||
50 | static void sdhci_finish_data(struct sdhci_host *); | 50 | static void sdhci_finish_data(struct sdhci_host *); |
51 | 51 | ||
52 | static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); | ||
53 | static void sdhci_finish_command(struct sdhci_host *); | 52 | static void sdhci_finish_command(struct sdhci_host *); |
54 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); | 53 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); |
55 | static void sdhci_tuning_timer(unsigned long data); | 54 | static void sdhci_tuning_timer(unsigned long data); |
@@ -981,7 +980,7 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
981 | tasklet_schedule(&host->finish_tasklet); | 980 | tasklet_schedule(&host->finish_tasklet); |
982 | } | 981 | } |
983 | 982 | ||
984 | static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | 983 | void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) |
985 | { | 984 | { |
986 | int flags; | 985 | int flags; |
987 | u32 mask; | 986 | u32 mask; |
@@ -1053,6 +1052,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
1053 | 1052 | ||
1054 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); | 1053 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); |
1055 | } | 1054 | } |
1055 | EXPORT_SYMBOL_GPL(sdhci_send_command); | ||
1056 | 1056 | ||
1057 | static void sdhci_finish_command(struct sdhci_host *host) | 1057 | static void sdhci_finish_command(struct sdhci_host *host) |
1058 | { | 1058 | { |
@@ -1435,7 +1435,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | if (host->version >= SDHCI_SPEC_300 && | 1437 | if (host->version >= SDHCI_SPEC_300 && |
1438 | (ios->power_mode == MMC_POWER_UP)) | 1438 | (ios->power_mode == MMC_POWER_UP) && |
1439 | !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) | ||
1439 | sdhci_enable_preset_value(host, false); | 1440 | sdhci_enable_preset_value(host, false); |
1440 | 1441 | ||
1441 | sdhci_set_clock(host, ios->clock); | 1442 | sdhci_set_clock(host, ios->clock); |
@@ -1875,6 +1876,14 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1875 | return 0; | 1876 | return 0; |
1876 | } | 1877 | } |
1877 | 1878 | ||
1879 | if (host->ops->platform_execute_tuning) { | ||
1880 | spin_unlock(&host->lock); | ||
1881 | enable_irq(host->irq); | ||
1882 | err = host->ops->platform_execute_tuning(host, opcode); | ||
1883 | sdhci_runtime_pm_put(host); | ||
1884 | return err; | ||
1885 | } | ||
1886 | |||
1878 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1887 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
1879 | 1888 | ||
1880 | /* | 1889 | /* |
@@ -1981,6 +1990,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1981 | if (!tuning_loop_counter || !timeout) { | 1990 | if (!tuning_loop_counter || !timeout) { |
1982 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | 1991 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; |
1983 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1992 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
1993 | err = -EIO; | ||
1984 | } else { | 1994 | } else { |
1985 | if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { | 1995 | if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { |
1986 | pr_info(DRIVER_NAME ": Tuning procedure" | 1996 | pr_info(DRIVER_NAME ": Tuning procedure" |
@@ -2491,6 +2501,14 @@ again: | |||
2491 | result = IRQ_HANDLED; | 2501 | result = IRQ_HANDLED; |
2492 | 2502 | ||
2493 | intmask = sdhci_readl(host, SDHCI_INT_STATUS); | 2503 | intmask = sdhci_readl(host, SDHCI_INT_STATUS); |
2504 | |||
2505 | /* | ||
2506 | * If we know we'll call the driver to signal SDIO IRQ, disregard | ||
2507 | * further indications of Card Interrupt in the status to avoid a | ||
2508 | * needless loop. | ||
2509 | */ | ||
2510 | if (cardint) | ||
2511 | intmask &= ~SDHCI_INT_CARD_INT; | ||
2494 | if (intmask && --max_loops) | 2512 | if (intmask && --max_loops) |
2495 | goto again; | 2513 | goto again; |
2496 | out: | 2514 | out: |
@@ -2546,8 +2564,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups); | |||
2546 | 2564 | ||
2547 | int sdhci_suspend_host(struct sdhci_host *host) | 2565 | int sdhci_suspend_host(struct sdhci_host *host) |
2548 | { | 2566 | { |
2549 | int ret; | ||
2550 | |||
2551 | if (host->ops->platform_suspend) | 2567 | if (host->ops->platform_suspend) |
2552 | host->ops->platform_suspend(host); | 2568 | host->ops->platform_suspend(host); |
2553 | 2569 | ||
@@ -2559,19 +2575,6 @@ int sdhci_suspend_host(struct sdhci_host *host) | |||
2559 | host->flags &= ~SDHCI_NEEDS_RETUNING; | 2575 | host->flags &= ~SDHCI_NEEDS_RETUNING; |
2560 | } | 2576 | } |
2561 | 2577 | ||
2562 | ret = mmc_suspend_host(host->mmc); | ||
2563 | if (ret) { | ||
2564 | if (host->flags & SDHCI_USING_RETUNING_TIMER) { | ||
2565 | host->flags |= SDHCI_NEEDS_RETUNING; | ||
2566 | mod_timer(&host->tuning_timer, jiffies + | ||
2567 | host->tuning_count * HZ); | ||
2568 | } | ||
2569 | |||
2570 | sdhci_enable_card_detection(host); | ||
2571 | |||
2572 | return ret; | ||
2573 | } | ||
2574 | |||
2575 | if (!device_may_wakeup(mmc_dev(host->mmc))) { | 2578 | if (!device_may_wakeup(mmc_dev(host->mmc))) { |
2576 | sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); | 2579 | sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); |
2577 | free_irq(host->irq, host); | 2580 | free_irq(host->irq, host); |
@@ -2579,14 +2582,14 @@ int sdhci_suspend_host(struct sdhci_host *host) | |||
2579 | sdhci_enable_irq_wakeups(host); | 2582 | sdhci_enable_irq_wakeups(host); |
2580 | enable_irq_wake(host->irq); | 2583 | enable_irq_wake(host->irq); |
2581 | } | 2584 | } |
2582 | return ret; | 2585 | return 0; |
2583 | } | 2586 | } |
2584 | 2587 | ||
2585 | EXPORT_SYMBOL_GPL(sdhci_suspend_host); | 2588 | EXPORT_SYMBOL_GPL(sdhci_suspend_host); |
2586 | 2589 | ||
2587 | int sdhci_resume_host(struct sdhci_host *host) | 2590 | int sdhci_resume_host(struct sdhci_host *host) |
2588 | { | 2591 | { |
2589 | int ret; | 2592 | int ret = 0; |
2590 | 2593 | ||
2591 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { | 2594 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { |
2592 | if (host->ops->enable_dma) | 2595 | if (host->ops->enable_dma) |
@@ -2615,7 +2618,6 @@ int sdhci_resume_host(struct sdhci_host *host) | |||
2615 | mmiowb(); | 2618 | mmiowb(); |
2616 | } | 2619 | } |
2617 | 2620 | ||
2618 | ret = mmc_resume_host(host->mmc); | ||
2619 | sdhci_enable_card_detection(host); | 2621 | sdhci_enable_card_detection(host); |
2620 | 2622 | ||
2621 | if (host->ops->platform_resume) | 2623 | if (host->ops->platform_resume) |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index b037f188fe44..0a3ed01887db 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -288,6 +288,7 @@ struct sdhci_ops { | |||
288 | unsigned int (*get_ro)(struct sdhci_host *host); | 288 | unsigned int (*get_ro)(struct sdhci_host *host); |
289 | void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); | 289 | void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); |
290 | void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); | 290 | void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); |
291 | int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); | ||
291 | int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); | 292 | int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); |
292 | void (*hw_reset)(struct sdhci_host *host); | 293 | void (*hw_reset)(struct sdhci_host *host); |
293 | void (*platform_suspend)(struct sdhci_host *host); | 294 | void (*platform_suspend)(struct sdhci_host *host); |
@@ -393,6 +394,8 @@ static inline void *sdhci_priv(struct sdhci_host *host) | |||
393 | extern void sdhci_card_detect(struct sdhci_host *host); | 394 | extern void sdhci_card_detect(struct sdhci_host *host); |
394 | extern int sdhci_add_host(struct sdhci_host *host); | 395 | extern int sdhci_add_host(struct sdhci_host *host); |
395 | extern void sdhci_remove_host(struct sdhci_host *host, int dead); | 396 | extern void sdhci_remove_host(struct sdhci_host *host, int dead); |
397 | extern void sdhci_send_command(struct sdhci_host *host, | ||
398 | struct mmc_command *cmd); | ||
396 | 399 | ||
397 | #ifdef CONFIG_PM | 400 | #ifdef CONFIG_PM |
398 | extern int sdhci_suspend_host(struct sdhci_host *host); | 401 | extern int sdhci_suspend_host(struct sdhci_host *host); |
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index 50adbd155f35..b7e305775314 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c | |||
@@ -516,9 +516,7 @@ static void sdricoh_pcmcia_detach(struct pcmcia_device *link) | |||
516 | #ifdef CONFIG_PM | 516 | #ifdef CONFIG_PM |
517 | static int sdricoh_pcmcia_suspend(struct pcmcia_device *link) | 517 | static int sdricoh_pcmcia_suspend(struct pcmcia_device *link) |
518 | { | 518 | { |
519 | struct mmc_host *mmc = link->priv; | ||
520 | dev_dbg(&link->dev, "suspend\n"); | 519 | dev_dbg(&link->dev, "suspend\n"); |
521 | mmc_suspend_host(mmc); | ||
522 | return 0; | 520 | return 0; |
523 | } | 521 | } |
524 | 522 | ||
@@ -527,7 +525,6 @@ static int sdricoh_pcmcia_resume(struct pcmcia_device *link) | |||
527 | struct mmc_host *mmc = link->priv; | 525 | struct mmc_host *mmc = link->priv; |
528 | dev_dbg(&link->dev, "resume\n"); | 526 | dev_dbg(&link->dev, "resume\n"); |
529 | sdricoh_reset(mmc_priv(mmc)); | 527 | sdricoh_reset(mmc_priv(mmc)); |
530 | mmc_resume_host(mmc); | ||
531 | return 0; | 528 | return 0; |
532 | } | 529 | } |
533 | #else | 530 | #else |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 36629a024aa1..d032b080ac4d 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -964,7 +964,7 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
964 | 964 | ||
965 | static int sh_mmcif_clk_update(struct sh_mmcif_host *host) | 965 | static int sh_mmcif_clk_update(struct sh_mmcif_host *host) |
966 | { | 966 | { |
967 | int ret = clk_enable(host->hclk); | 967 | int ret = clk_prepare_enable(host->hclk); |
968 | 968 | ||
969 | if (!ret) { | 969 | if (!ret) { |
970 | host->clk = clk_get_rate(host->hclk); | 970 | host->clk = clk_get_rate(host->hclk); |
@@ -1018,7 +1018,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1018 | } | 1018 | } |
1019 | if (host->power) { | 1019 | if (host->power) { |
1020 | pm_runtime_put_sync(&host->pd->dev); | 1020 | pm_runtime_put_sync(&host->pd->dev); |
1021 | clk_disable(host->hclk); | 1021 | clk_disable_unprepare(host->hclk); |
1022 | host->power = false; | 1022 | host->power = false; |
1023 | if (ios->power_mode == MMC_POWER_OFF) | 1023 | if (ios->power_mode == MMC_POWER_OFF) |
1024 | sh_mmcif_set_power(host, ios); | 1024 | sh_mmcif_set_power(host, ios); |
@@ -1466,7 +1466,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) | |||
1466 | 1466 | ||
1467 | mutex_init(&host->thread_lock); | 1467 | mutex_init(&host->thread_lock); |
1468 | 1468 | ||
1469 | clk_disable(host->hclk); | 1469 | clk_disable_unprepare(host->hclk); |
1470 | ret = mmc_add_host(mmc); | 1470 | ret = mmc_add_host(mmc); |
1471 | if (ret < 0) | 1471 | if (ret < 0) |
1472 | goto emmcaddh; | 1472 | goto emmcaddh; |
@@ -1487,7 +1487,7 @@ ereqirq1: | |||
1487 | ereqirq0: | 1487 | ereqirq0: |
1488 | pm_runtime_suspend(&pdev->dev); | 1488 | pm_runtime_suspend(&pdev->dev); |
1489 | eresume: | 1489 | eresume: |
1490 | clk_disable(host->hclk); | 1490 | clk_disable_unprepare(host->hclk); |
1491 | eclkupdate: | 1491 | eclkupdate: |
1492 | clk_put(host->hclk); | 1492 | clk_put(host->hclk); |
1493 | eclkget: | 1493 | eclkget: |
@@ -1505,7 +1505,7 @@ static int sh_mmcif_remove(struct platform_device *pdev) | |||
1505 | int irq[2]; | 1505 | int irq[2]; |
1506 | 1506 | ||
1507 | host->dying = true; | 1507 | host->dying = true; |
1508 | clk_enable(host->hclk); | 1508 | clk_prepare_enable(host->hclk); |
1509 | pm_runtime_get_sync(&pdev->dev); | 1509 | pm_runtime_get_sync(&pdev->dev); |
1510 | 1510 | ||
1511 | dev_pm_qos_hide_latency_limit(&pdev->dev); | 1511 | dev_pm_qos_hide_latency_limit(&pdev->dev); |
@@ -1530,7 +1530,7 @@ static int sh_mmcif_remove(struct platform_device *pdev) | |||
1530 | if (irq[1] >= 0) | 1530 | if (irq[1] >= 0) |
1531 | free_irq(irq[1], host); | 1531 | free_irq(irq[1], host); |
1532 | 1532 | ||
1533 | clk_disable(host->hclk); | 1533 | clk_disable_unprepare(host->hclk); |
1534 | mmc_free_host(host->mmc); | 1534 | mmc_free_host(host->mmc); |
1535 | pm_runtime_put_sync(&pdev->dev); | 1535 | pm_runtime_put_sync(&pdev->dev); |
1536 | pm_runtime_disable(&pdev->dev); | 1536 | pm_runtime_disable(&pdev->dev); |
@@ -1538,28 +1538,21 @@ static int sh_mmcif_remove(struct platform_device *pdev) | |||
1538 | return 0; | 1538 | return 0; |
1539 | } | 1539 | } |
1540 | 1540 | ||
1541 | #ifdef CONFIG_PM | 1541 | #ifdef CONFIG_PM_SLEEP |
1542 | static int sh_mmcif_suspend(struct device *dev) | 1542 | static int sh_mmcif_suspend(struct device *dev) |
1543 | { | 1543 | { |
1544 | struct sh_mmcif_host *host = dev_get_drvdata(dev); | 1544 | struct sh_mmcif_host *host = dev_get_drvdata(dev); |
1545 | int ret = mmc_suspend_host(host->mmc); | ||
1546 | 1545 | ||
1547 | if (!ret) | 1546 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); |
1548 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); | ||
1549 | 1547 | ||
1550 | return ret; | 1548 | return 0; |
1551 | } | 1549 | } |
1552 | 1550 | ||
1553 | static int sh_mmcif_resume(struct device *dev) | 1551 | static int sh_mmcif_resume(struct device *dev) |
1554 | { | 1552 | { |
1555 | struct sh_mmcif_host *host = dev_get_drvdata(dev); | 1553 | return 0; |
1556 | |||
1557 | return mmc_resume_host(host->mmc); | ||
1558 | } | 1554 | } |
1559 | #else | 1555 | #endif |
1560 | #define sh_mmcif_suspend NULL | ||
1561 | #define sh_mmcif_resume NULL | ||
1562 | #endif /* CONFIG_PM */ | ||
1563 | 1556 | ||
1564 | static const struct of_device_id mmcif_of_match[] = { | 1557 | static const struct of_device_id mmcif_of_match[] = { |
1565 | { .compatible = "renesas,sh-mmcif" }, | 1558 | { .compatible = "renesas,sh-mmcif" }, |
@@ -1568,8 +1561,7 @@ static const struct of_device_id mmcif_of_match[] = { | |||
1568 | MODULE_DEVICE_TABLE(of, mmcif_of_match); | 1561 | MODULE_DEVICE_TABLE(of, mmcif_of_match); |
1569 | 1562 | ||
1570 | static const struct dev_pm_ops sh_mmcif_dev_pm_ops = { | 1563 | static const struct dev_pm_ops sh_mmcif_dev_pm_ops = { |
1571 | .suspend = sh_mmcif_suspend, | 1564 | SET_SYSTEM_SLEEP_PM_OPS(sh_mmcif_suspend, sh_mmcif_resume) |
1572 | .resume = sh_mmcif_resume, | ||
1573 | }; | 1565 | }; |
1574 | 1566 | ||
1575 | static struct platform_driver sh_mmcif_driver = { | 1567 | static struct platform_driver sh_mmcif_driver = { |
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 43d962829f8e..d1760ebcac03 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c | |||
@@ -1030,7 +1030,7 @@ static void tifm_sd_remove(struct tifm_dev *sock) | |||
1030 | 1030 | ||
1031 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) | 1031 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) |
1032 | { | 1032 | { |
1033 | return mmc_suspend_host(tifm_get_drvdata(sock)); | 1033 | return 0; |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | static int tifm_sd_resume(struct tifm_dev *sock) | 1036 | static int tifm_sd_resume(struct tifm_dev *sock) |
@@ -1044,8 +1044,6 @@ static int tifm_sd_resume(struct tifm_dev *sock) | |||
1044 | 1044 | ||
1045 | if (rc) | 1045 | if (rc) |
1046 | host->eject = 1; | 1046 | host->eject = 1; |
1047 | else | ||
1048 | rc = mmc_resume_host(mmc); | ||
1049 | 1047 | ||
1050 | return rc; | 1048 | return rc; |
1051 | } | 1049 | } |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index b3802256f954..f3b2d8ca1eca 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -1145,12 +1145,9 @@ int tmio_mmc_host_suspend(struct device *dev) | |||
1145 | { | 1145 | { |
1146 | struct mmc_host *mmc = dev_get_drvdata(dev); | 1146 | struct mmc_host *mmc = dev_get_drvdata(dev); |
1147 | struct tmio_mmc_host *host = mmc_priv(mmc); | 1147 | struct tmio_mmc_host *host = mmc_priv(mmc); |
1148 | int ret = mmc_suspend_host(mmc); | ||
1149 | 1148 | ||
1150 | if (!ret) | 1149 | tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); |
1151 | tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); | 1150 | return 0; |
1152 | |||
1153 | return ret; | ||
1154 | } | 1151 | } |
1155 | EXPORT_SYMBOL(tmio_mmc_host_suspend); | 1152 | EXPORT_SYMBOL(tmio_mmc_host_suspend); |
1156 | 1153 | ||
@@ -1163,7 +1160,7 @@ int tmio_mmc_host_resume(struct device *dev) | |||
1163 | 1160 | ||
1164 | /* The MMC core will perform the complete set up */ | 1161 | /* The MMC core will perform the complete set up */ |
1165 | host->resuming = true; | 1162 | host->resuming = true; |
1166 | return mmc_resume_host(mmc); | 1163 | return 0; |
1167 | } | 1164 | } |
1168 | EXPORT_SYMBOL(tmio_mmc_host_resume); | 1165 | EXPORT_SYMBOL(tmio_mmc_host_resume); |
1169 | 1166 | ||
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 4f84586c6e9e..63fac78b3d46 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c | |||
@@ -1269,21 +1269,18 @@ static void via_init_sdc_pm(struct via_crdr_mmc_host *host) | |||
1269 | static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state) | 1269 | static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state) |
1270 | { | 1270 | { |
1271 | struct via_crdr_mmc_host *host; | 1271 | struct via_crdr_mmc_host *host; |
1272 | int ret = 0; | ||
1273 | 1272 | ||
1274 | host = pci_get_drvdata(pcidev); | 1273 | host = pci_get_drvdata(pcidev); |
1275 | 1274 | ||
1276 | via_save_pcictrlreg(host); | 1275 | via_save_pcictrlreg(host); |
1277 | via_save_sdcreg(host); | 1276 | via_save_sdcreg(host); |
1278 | 1277 | ||
1279 | ret = mmc_suspend_host(host->mmc); | ||
1280 | |||
1281 | pci_save_state(pcidev); | 1278 | pci_save_state(pcidev); |
1282 | pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); | 1279 | pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); |
1283 | pci_disable_device(pcidev); | 1280 | pci_disable_device(pcidev); |
1284 | pci_set_power_state(pcidev, pci_choose_state(pcidev, state)); | 1281 | pci_set_power_state(pcidev, pci_choose_state(pcidev, state)); |
1285 | 1282 | ||
1286 | return ret; | 1283 | return 0; |
1287 | } | 1284 | } |
1288 | 1285 | ||
1289 | static int via_sd_resume(struct pci_dev *pcidev) | 1286 | static int via_sd_resume(struct pci_dev *pcidev) |
@@ -1316,8 +1313,6 @@ static int via_sd_resume(struct pci_dev *pcidev) | |||
1316 | via_restore_pcictrlreg(sdhost); | 1313 | via_restore_pcictrlreg(sdhost); |
1317 | via_init_sdc_pm(sdhost); | 1314 | via_init_sdc_pm(sdhost); |
1318 | 1315 | ||
1319 | ret = mmc_resume_host(sdhost->mmc); | ||
1320 | |||
1321 | return ret; | 1316 | return ret; |
1322 | } | 1317 | } |
1323 | 1318 | ||
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index e9028ad05ffb..4262296c12fa 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c | |||
@@ -2392,26 +2392,12 @@ static void vub300_disconnect(struct usb_interface *interface) | |||
2392 | #ifdef CONFIG_PM | 2392 | #ifdef CONFIG_PM |
2393 | static int vub300_suspend(struct usb_interface *intf, pm_message_t message) | 2393 | static int vub300_suspend(struct usb_interface *intf, pm_message_t message) |
2394 | { | 2394 | { |
2395 | struct vub300_mmc_host *vub300 = usb_get_intfdata(intf); | 2395 | return 0; |
2396 | if (!vub300 || !vub300->mmc) { | ||
2397 | return 0; | ||
2398 | } else { | ||
2399 | struct mmc_host *mmc = vub300->mmc; | ||
2400 | mmc_suspend_host(mmc); | ||
2401 | return 0; | ||
2402 | } | ||
2403 | } | 2396 | } |
2404 | 2397 | ||
2405 | static int vub300_resume(struct usb_interface *intf) | 2398 | static int vub300_resume(struct usb_interface *intf) |
2406 | { | 2399 | { |
2407 | struct vub300_mmc_host *vub300 = usb_get_intfdata(intf); | 2400 | return 0; |
2408 | if (!vub300 || !vub300->mmc) { | ||
2409 | return 0; | ||
2410 | } else { | ||
2411 | struct mmc_host *mmc = vub300->mmc; | ||
2412 | mmc_resume_host(mmc); | ||
2413 | return 0; | ||
2414 | } | ||
2415 | } | 2401 | } |
2416 | #else | 2402 | #else |
2417 | #define vub300_suspend NULL | 2403 | #define vub300_suspend NULL |
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index e954b7758876..1defd5ed3236 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c | |||
@@ -1814,28 +1814,11 @@ static void wbsd_pnp_remove(struct pnp_dev *dev) | |||
1814 | 1814 | ||
1815 | #ifdef CONFIG_PM | 1815 | #ifdef CONFIG_PM |
1816 | 1816 | ||
1817 | static int wbsd_suspend(struct wbsd_host *host, pm_message_t state) | ||
1818 | { | ||
1819 | BUG_ON(host == NULL); | ||
1820 | |||
1821 | return mmc_suspend_host(host->mmc); | ||
1822 | } | ||
1823 | |||
1824 | static int wbsd_resume(struct wbsd_host *host) | ||
1825 | { | ||
1826 | BUG_ON(host == NULL); | ||
1827 | |||
1828 | wbsd_init_device(host); | ||
1829 | |||
1830 | return mmc_resume_host(host->mmc); | ||
1831 | } | ||
1832 | |||
1833 | static int wbsd_platform_suspend(struct platform_device *dev, | 1817 | static int wbsd_platform_suspend(struct platform_device *dev, |
1834 | pm_message_t state) | 1818 | pm_message_t state) |
1835 | { | 1819 | { |
1836 | struct mmc_host *mmc = platform_get_drvdata(dev); | 1820 | struct mmc_host *mmc = platform_get_drvdata(dev); |
1837 | struct wbsd_host *host; | 1821 | struct wbsd_host *host; |
1838 | int ret; | ||
1839 | 1822 | ||
1840 | if (mmc == NULL) | 1823 | if (mmc == NULL) |
1841 | return 0; | 1824 | return 0; |
@@ -1844,12 +1827,7 @@ static int wbsd_platform_suspend(struct platform_device *dev, | |||
1844 | 1827 | ||
1845 | host = mmc_priv(mmc); | 1828 | host = mmc_priv(mmc); |
1846 | 1829 | ||
1847 | ret = wbsd_suspend(host, state); | ||
1848 | if (ret) | ||
1849 | return ret; | ||
1850 | |||
1851 | wbsd_chip_poweroff(host); | 1830 | wbsd_chip_poweroff(host); |
1852 | |||
1853 | return 0; | 1831 | return 0; |
1854 | } | 1832 | } |
1855 | 1833 | ||
@@ -1872,7 +1850,8 @@ static int wbsd_platform_resume(struct platform_device *dev) | |||
1872 | */ | 1850 | */ |
1873 | mdelay(5); | 1851 | mdelay(5); |
1874 | 1852 | ||
1875 | return wbsd_resume(host); | 1853 | wbsd_init_device(host); |
1854 | return 0; | ||
1876 | } | 1855 | } |
1877 | 1856 | ||
1878 | #ifdef CONFIG_PNP | 1857 | #ifdef CONFIG_PNP |
@@ -1880,16 +1859,12 @@ static int wbsd_platform_resume(struct platform_device *dev) | |||
1880 | static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state) | 1859 | static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state) |
1881 | { | 1860 | { |
1882 | struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev); | 1861 | struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev); |
1883 | struct wbsd_host *host; | ||
1884 | 1862 | ||
1885 | if (mmc == NULL) | 1863 | if (mmc == NULL) |
1886 | return 0; | 1864 | return 0; |
1887 | 1865 | ||
1888 | DBGF("Suspending...\n"); | 1866 | DBGF("Suspending...\n"); |
1889 | 1867 | return 0; | |
1890 | host = mmc_priv(mmc); | ||
1891 | |||
1892 | return wbsd_suspend(host, state); | ||
1893 | } | 1868 | } |
1894 | 1869 | ||
1895 | static int wbsd_pnp_resume(struct pnp_dev *pnp_dev) | 1870 | static int wbsd_pnp_resume(struct pnp_dev *pnp_dev) |
@@ -1922,7 +1897,8 @@ static int wbsd_pnp_resume(struct pnp_dev *pnp_dev) | |||
1922 | */ | 1897 | */ |
1923 | mdelay(5); | 1898 | mdelay(5); |
1924 | 1899 | ||
1925 | return wbsd_resume(host); | 1900 | wbsd_init_device(host); |
1901 | return 0; | ||
1926 | } | 1902 | } |
1927 | 1903 | ||
1928 | #endif /* CONFIG_PNP */ | 1904 | #endif /* CONFIG_PNP */ |
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 34231d5168fc..e902ed7846b0 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c | |||
@@ -212,28 +212,14 @@ struct wmt_mci_priv { | |||
212 | 212 | ||
213 | static void wmt_set_sd_power(struct wmt_mci_priv *priv, int enable) | 213 | static void wmt_set_sd_power(struct wmt_mci_priv *priv, int enable) |
214 | { | 214 | { |
215 | u32 reg_tmp; | 215 | u32 reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); |
216 | if (enable) { | 216 | |
217 | if (priv->power_inverted) { | 217 | if (enable ^ priv->power_inverted) |
218 | reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); | 218 | reg_tmp &= ~BM_SD_OFF; |
219 | writeb(reg_tmp | BM_SD_OFF, | 219 | else |
220 | priv->sdmmc_base + SDMMC_BUSMODE); | 220 | reg_tmp |= BM_SD_OFF; |
221 | } else { | 221 | |
222 | reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); | 222 | writeb(reg_tmp, priv->sdmmc_base + SDMMC_BUSMODE); |
223 | writeb(reg_tmp & (~BM_SD_OFF), | ||
224 | priv->sdmmc_base + SDMMC_BUSMODE); | ||
225 | } | ||
226 | } else { | ||
227 | if (priv->power_inverted) { | ||
228 | reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); | ||
229 | writeb(reg_tmp & (~BM_SD_OFF), | ||
230 | priv->sdmmc_base + SDMMC_BUSMODE); | ||
231 | } else { | ||
232 | reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); | ||
233 | writeb(reg_tmp | BM_SD_OFF, | ||
234 | priv->sdmmc_base + SDMMC_BUSMODE); | ||
235 | } | ||
236 | } | ||
237 | } | 223 | } |
238 | 224 | ||
239 | static void wmt_mci_read_response(struct mmc_host *mmc) | 225 | static void wmt_mci_read_response(struct mmc_host *mmc) |
@@ -939,28 +925,23 @@ static int wmt_mci_suspend(struct device *dev) | |||
939 | struct platform_device *pdev = to_platform_device(dev); | 925 | struct platform_device *pdev = to_platform_device(dev); |
940 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 926 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
941 | struct wmt_mci_priv *priv; | 927 | struct wmt_mci_priv *priv; |
942 | int ret; | ||
943 | 928 | ||
944 | if (!mmc) | 929 | if (!mmc) |
945 | return 0; | 930 | return 0; |
946 | 931 | ||
947 | priv = mmc_priv(mmc); | 932 | priv = mmc_priv(mmc); |
948 | ret = mmc_suspend_host(mmc); | 933 | reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); |
949 | 934 | writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + | |
950 | if (!ret) { | 935 | SDMMC_BUSMODE); |
951 | reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); | ||
952 | writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + | ||
953 | SDMMC_BUSMODE); | ||
954 | 936 | ||
955 | reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN); | 937 | reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN); |
956 | writew(reg_tmp & 0x5FFF, priv->sdmmc_base + SDMMC_BLKLEN); | 938 | writew(reg_tmp & 0x5FFF, priv->sdmmc_base + SDMMC_BLKLEN); |
957 | 939 | ||
958 | writeb(0xFF, priv->sdmmc_base + SDMMC_STS0); | 940 | writeb(0xFF, priv->sdmmc_base + SDMMC_STS0); |
959 | writeb(0xFF, priv->sdmmc_base + SDMMC_STS1); | 941 | writeb(0xFF, priv->sdmmc_base + SDMMC_STS1); |
960 | 942 | ||
961 | clk_disable(priv->clk_sdmmc); | 943 | clk_disable(priv->clk_sdmmc); |
962 | } | 944 | return 0; |
963 | return ret; | ||
964 | } | 945 | } |
965 | 946 | ||
966 | static int wmt_mci_resume(struct device *dev) | 947 | static int wmt_mci_resume(struct device *dev) |
@@ -969,7 +950,6 @@ static int wmt_mci_resume(struct device *dev) | |||
969 | struct platform_device *pdev = to_platform_device(dev); | 950 | struct platform_device *pdev = to_platform_device(dev); |
970 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 951 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
971 | struct wmt_mci_priv *priv; | 952 | struct wmt_mci_priv *priv; |
972 | int ret = 0; | ||
973 | 953 | ||
974 | if (mmc) { | 954 | if (mmc) { |
975 | priv = mmc_priv(mmc); | 955 | priv = mmc_priv(mmc); |
@@ -987,10 +967,9 @@ static int wmt_mci_resume(struct device *dev) | |||
987 | writeb(reg_tmp | INT0_DI_INT_EN, priv->sdmmc_base + | 967 | writeb(reg_tmp | INT0_DI_INT_EN, priv->sdmmc_base + |
988 | SDMMC_INTMASK0); | 968 | SDMMC_INTMASK0); |
989 | 969 | ||
990 | ret = mmc_resume_host(mmc); | ||
991 | } | 970 | } |
992 | 971 | ||
993 | return ret; | 972 | return 0; |
994 | } | 973 | } |
995 | 974 | ||
996 | static const struct dev_pm_ops wmt_mci_pm = { | 975 | static const struct dev_pm_ops wmt_mci_pm = { |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 842de3e21e70..176fdf824b14 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -240,6 +240,7 @@ struct mmc_part { | |||
240 | struct mmc_card { | 240 | struct mmc_card { |
241 | struct mmc_host *host; /* the host this device belongs to */ | 241 | struct mmc_host *host; /* the host this device belongs to */ |
242 | struct device dev; /* the device */ | 242 | struct device dev; /* the device */ |
243 | u32 ocr; /* the current OCR setting */ | ||
243 | unsigned int rca; /* relative card address of device */ | 244 | unsigned int rca; /* relative card address of device */ |
244 | unsigned int type; /* card type */ | 245 | unsigned int type; /* card type */ |
245 | #define MMC_TYPE_MMC 0 /* MMC card */ | 246 | #define MMC_TYPE_MMC 0 /* MMC card */ |
@@ -257,6 +258,7 @@ struct mmc_card { | |||
257 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ | 258 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ |
258 | #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ | 259 | #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ |
259 | #define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */ | 260 | #define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */ |
261 | #define MMC_STATE_SUSPENDED (1<<11) /* card is suspended */ | ||
260 | unsigned int quirks; /* card quirks */ | 262 | unsigned int quirks; /* card quirks */ |
261 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ | 263 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ |
262 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ | 264 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ |
@@ -420,10 +422,10 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
420 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) | 422 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) |
421 | #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) | 423 | #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) |
422 | #define mmc_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) | 424 | #define mmc_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) |
423 | #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) | ||
424 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) | 425 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) |
425 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) | 426 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) |
426 | #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) | 427 | #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) |
428 | #define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED) | ||
427 | 429 | ||
428 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 430 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
429 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) | 431 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) |
@@ -432,11 +434,12 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
432 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) | 434 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) |
433 | #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) | 435 | #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) |
434 | #define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) | 436 | #define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) |
435 | #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) | ||
436 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) | 437 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) |
437 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) | 438 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) |
438 | #define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) | 439 | #define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) |
439 | #define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS) | 440 | #define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS) |
441 | #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED) | ||
442 | #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED) | ||
440 | 443 | ||
441 | /* | 444 | /* |
442 | * Quirk add/remove for MMC products. | 445 | * Quirk add/remove for MMC products. |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index da51bec578c3..87079fc38011 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
@@ -151,7 +151,8 @@ extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *); | |||
151 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, | 151 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, |
152 | struct mmc_command *, int); | 152 | struct mmc_command *, int); |
153 | extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); | 153 | extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); |
154 | extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool); | 154 | extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, |
155 | bool); | ||
155 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); | 156 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); |
156 | extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); | 157 | extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); |
157 | 158 | ||
@@ -188,7 +189,6 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); | |||
188 | 189 | ||
189 | extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); | 190 | extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); |
190 | extern void mmc_release_host(struct mmc_host *host); | 191 | extern void mmc_release_host(struct mmc_host *host); |
191 | extern int mmc_try_claim_host(struct mmc_host *host); | ||
192 | 192 | ||
193 | extern void mmc_get_card(struct mmc_card *card); | 193 | extern void mmc_get_card(struct mmc_card *card); |
194 | extern void mmc_put_card(struct mmc_card *card); | 194 | extern void mmc_put_card(struct mmc_card *card); |
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 198f0fa44e9f..6ce7d2cd3c7a 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define LINUX_MMC_DW_MMC_H | 15 | #define LINUX_MMC_DW_MMC_H |
16 | 16 | ||
17 | #include <linux/scatterlist.h> | 17 | #include <linux/scatterlist.h> |
18 | #include <linux/mmc/core.h> | ||
18 | 19 | ||
19 | #define MAX_MCI_SLOTS 2 | 20 | #define MAX_MCI_SLOTS 2 |
20 | 21 | ||
@@ -129,6 +130,9 @@ struct dw_mci { | |||
129 | struct mmc_request *mrq; | 130 | struct mmc_request *mrq; |
130 | struct mmc_command *cmd; | 131 | struct mmc_command *cmd; |
131 | struct mmc_data *data; | 132 | struct mmc_data *data; |
133 | struct mmc_command stop_abort; | ||
134 | unsigned int prev_blksz; | ||
135 | unsigned char timing; | ||
132 | struct workqueue_struct *card_workqueue; | 136 | struct workqueue_struct *card_workqueue; |
133 | 137 | ||
134 | /* DMA interface members*/ | 138 | /* DMA interface members*/ |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 3b0c33ae13e1..99f5709ac343 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -254,6 +254,7 @@ struct mmc_host { | |||
254 | #define MMC_CAP_UHS_SDR50 (1 << 17) /* Host supports UHS SDR50 mode */ | 254 | #define MMC_CAP_UHS_SDR50 (1 << 17) /* Host supports UHS SDR50 mode */ |
255 | #define MMC_CAP_UHS_SDR104 (1 << 18) /* Host supports UHS SDR104 mode */ | 255 | #define MMC_CAP_UHS_SDR104 (1 << 18) /* Host supports UHS SDR104 mode */ |
256 | #define MMC_CAP_UHS_DDR50 (1 << 19) /* Host supports UHS DDR50 mode */ | 256 | #define MMC_CAP_UHS_DDR50 (1 << 19) /* Host supports UHS DDR50 mode */ |
257 | #define MMC_CAP_RUNTIME_RESUME (1 << 20) /* Resume at runtime_resume. */ | ||
257 | #define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ | 258 | #define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ |
258 | #define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ | 259 | #define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ |
259 | #define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ | 260 | #define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ |
@@ -309,7 +310,6 @@ struct mmc_host { | |||
309 | spinlock_t lock; /* lock for claim and bus ops */ | 310 | spinlock_t lock; /* lock for claim and bus ops */ |
310 | 311 | ||
311 | struct mmc_ios ios; /* current io bus settings */ | 312 | struct mmc_ios ios; /* current io bus settings */ |
312 | u32 ocr; /* the current OCR setting */ | ||
313 | 313 | ||
314 | /* group bitfields together to minimize padding */ | 314 | /* group bitfields together to minimize padding */ |
315 | unsigned int use_spi_crc:1; | 315 | unsigned int use_spi_crc:1; |
@@ -382,9 +382,6 @@ static inline void *mmc_priv(struct mmc_host *host) | |||
382 | #define mmc_classdev(x) (&(x)->class_dev) | 382 | #define mmc_classdev(x) (&(x)->class_dev) |
383 | #define mmc_hostname(x) (dev_name(&(x)->class_dev)) | 383 | #define mmc_hostname(x) (dev_name(&(x)->class_dev)) |
384 | 384 | ||
385 | int mmc_suspend_host(struct mmc_host *); | ||
386 | int mmc_resume_host(struct mmc_host *); | ||
387 | |||
388 | int mmc_power_save_host(struct mmc_host *host); | 385 | int mmc_power_save_host(struct mmc_host *host); |
389 | int mmc_power_restore_host(struct mmc_host *host); | 386 | int mmc_power_restore_host(struct mmc_host *host); |
390 | 387 | ||
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index d44912d81578..75f70f6ac137 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h | |||
@@ -10,6 +10,8 @@ | |||
10 | #ifndef __ASM_ARCH_IMX_ESDHC_H | 10 | #ifndef __ASM_ARCH_IMX_ESDHC_H |
11 | #define __ASM_ARCH_IMX_ESDHC_H | 11 | #define __ASM_ARCH_IMX_ESDHC_H |
12 | 12 | ||
13 | #include <linux/types.h> | ||
14 | |||
13 | enum wp_types { | 15 | enum wp_types { |
14 | ESDHC_WP_NONE, /* no WP, neither controller nor gpio */ | 16 | ESDHC_WP_NONE, /* no WP, neither controller nor gpio */ |
15 | ESDHC_WP_CONTROLLER, /* mmc controller internal WP */ | 17 | ESDHC_WP_CONTROLLER, /* mmc controller internal WP */ |
@@ -32,6 +34,7 @@ enum cd_types { | |||
32 | * @cd_gpio: gpio for card_detect interrupt | 34 | * @cd_gpio: gpio for card_detect interrupt |
33 | * @wp_type: type of write_protect method (see wp_types enum above) | 35 | * @wp_type: type of write_protect method (see wp_types enum above) |
34 | * @cd_type: type of card_detect method (see cd_types enum above) | 36 | * @cd_type: type of card_detect method (see cd_types enum above) |
37 | * @support_vsel: indicate it supports 1.8v switching | ||
35 | */ | 38 | */ |
36 | 39 | ||
37 | struct esdhc_platform_data { | 40 | struct esdhc_platform_data { |
@@ -41,5 +44,7 @@ struct esdhc_platform_data { | |||
41 | enum cd_types cd_type; | 44 | enum cd_types cd_type; |
42 | int max_bus_width; | 45 | int max_bus_width; |
43 | unsigned int f_max; | 46 | unsigned int f_max; |
47 | bool support_vsel; | ||
48 | unsigned int delay_line; | ||
44 | }; | 49 | }; |
45 | #endif /* __ASM_ARCH_IMX_ESDHC_H */ | 50 | #endif /* __ASM_ARCH_IMX_ESDHC_H */ |