diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-06 20:22:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-06 20:22:23 -0400 |
commit | 1ddca05743525689421383d2dda1ec34df26157e (patch) | |
tree | 5543764edd03c0bd77cd70ba411c50d5c7859167 | |
parent | f68e556e23d1a4176b563bcb25d8baf2c5313f91 (diff) | |
parent | 3bdc9ba892d6a294d16e9e6e0c4041926aa3d58c (diff) |
Merge tag 'mmc-fixes-for-3.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC fixes from Chris Ball:
- Disable use of MSI in sdhci-pci, which caused multiple chipsets to
stop working in 3.4-rc1. I'll wait to turn this on again until we
have a chipset whitelist for it.
- Fix a libertas SDIO powered-resume regression introduced in 3.3;
thanks to Neil Brown and Rafael Wysocki for this fix.
- Fix module reloading on omap_hsmmc.
- Stop trusting the spec/card's specified maximum data timeout length,
and use three seconds instead. Previously we used 300ms.
Also cleanups and fixes for s3c, atmel, sh_mmcif and omap_hsmmc.
* tag 'mmc-fixes-for-3.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (28 commits)
mmc: use really long write timeout to deal with crappy cards
mmc: sdhci-dove: Fix compile error by including module.h
mmc: Prevent 1.8V switch for SD hosts that don't support UHS modes.
Revert "mmc: sdhci-pci: Add MSI support"
Revert "mmc: sdhci-pci: add quirks for broken MSI on O2Micro controllers"
mmc: core: fix power class selection
mmc: omap_hsmmc: fix module re-insertion
mmc: omap_hsmmc: convert to module_platform_driver
mmc: omap_hsmmc: make it behave well as a module
mmc: omap_hsmmc: trivial cleanups
mmc: omap_hsmmc: context save after enabling runtime pm
mmc: omap_hsmmc: use runtime put sync in probe error patch
mmc: sdio: Use empty system suspend/resume callbacks at the bus level
mmc: bus: print bus speed mode of UHS-I card
mmc: sdhci-pci: add quirks for broken MSI on O2Micro controllers
mmc: sh_mmcif: Simplify calculation of mmc->f_min
mmc: sh_mmcif: mmc->f_max should be half of the bus clock
mmc: sh_mmcif: double clock speed
mmc: block: Remove use of mmc_blk_set_blksize
mmc: atmel-mci: add support for odd clock dividers
...
-rw-r--r-- | drivers/mmc/card/block.c | 27 | ||||
-rw-r--r-- | drivers/mmc/core/bus.c | 17 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 10 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 30 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_bus.c | 12 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci-regs.h | 1 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 55 | ||||
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 181 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-dove.c | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-s3c.c | 159 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 5 | ||||
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 13 |
13 files changed, 299 insertions, 218 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index eed213a5c8cb..b1809650b7aa 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -1623,24 +1623,6 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) | |||
1623 | return ret; | 1623 | return ret; |
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | static int | ||
1627 | mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) | ||
1628 | { | ||
1629 | int err; | ||
1630 | |||
1631 | mmc_claim_host(card->host); | ||
1632 | err = mmc_set_blocklen(card, 512); | ||
1633 | mmc_release_host(card->host); | ||
1634 | |||
1635 | if (err) { | ||
1636 | pr_err("%s: unable to set block size to 512: %d\n", | ||
1637 | md->disk->disk_name, err); | ||
1638 | return -EINVAL; | ||
1639 | } | ||
1640 | |||
1641 | return 0; | ||
1642 | } | ||
1643 | |||
1644 | static void mmc_blk_remove_req(struct mmc_blk_data *md) | 1626 | static void mmc_blk_remove_req(struct mmc_blk_data *md) |
1645 | { | 1627 | { |
1646 | struct mmc_card *card; | 1628 | struct mmc_card *card; |
@@ -1768,7 +1750,6 @@ static const struct mmc_fixup blk_fixups[] = | |||
1768 | static int mmc_blk_probe(struct mmc_card *card) | 1750 | static int mmc_blk_probe(struct mmc_card *card) |
1769 | { | 1751 | { |
1770 | struct mmc_blk_data *md, *part_md; | 1752 | struct mmc_blk_data *md, *part_md; |
1771 | int err; | ||
1772 | char cap_str[10]; | 1753 | char cap_str[10]; |
1773 | 1754 | ||
1774 | /* | 1755 | /* |
@@ -1781,10 +1762,6 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
1781 | if (IS_ERR(md)) | 1762 | if (IS_ERR(md)) |
1782 | return PTR_ERR(md); | 1763 | return PTR_ERR(md); |
1783 | 1764 | ||
1784 | err = mmc_blk_set_blksize(md, card); | ||
1785 | if (err) | ||
1786 | goto out; | ||
1787 | |||
1788 | string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, | 1765 | string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, |
1789 | cap_str, sizeof(cap_str)); | 1766 | cap_str, sizeof(cap_str)); |
1790 | pr_info("%s: %s %s %s %s\n", | 1767 | pr_info("%s: %s %s %s %s\n", |
@@ -1809,7 +1786,7 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
1809 | out: | 1786 | out: |
1810 | mmc_blk_remove_parts(card, md); | 1787 | mmc_blk_remove_parts(card, md); |
1811 | mmc_blk_remove_req(md); | 1788 | mmc_blk_remove_req(md); |
1812 | return err; | 1789 | return 0; |
1813 | } | 1790 | } |
1814 | 1791 | ||
1815 | static void mmc_blk_remove(struct mmc_card *card) | 1792 | static void mmc_blk_remove(struct mmc_card *card) |
@@ -1845,8 +1822,6 @@ static int mmc_blk_resume(struct mmc_card *card) | |||
1845 | struct mmc_blk_data *md = mmc_get_drvdata(card); | 1822 | struct mmc_blk_data *md = mmc_get_drvdata(card); |
1846 | 1823 | ||
1847 | if (md) { | 1824 | if (md) { |
1848 | mmc_blk_set_blksize(md, card); | ||
1849 | |||
1850 | /* | 1825 | /* |
1851 | * Resume involves the card going into idle state, | 1826 | * Resume involves the card going into idle state, |
1852 | * so current partition is always the main one. | 1827 | * so current partition is always the main one. |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 5d011a39dfff..3f606068d552 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -267,6 +267,15 @@ int mmc_add_card(struct mmc_card *card) | |||
267 | { | 267 | { |
268 | int ret; | 268 | int ret; |
269 | const char *type; | 269 | const char *type; |
270 | const char *uhs_bus_speed_mode = ""; | ||
271 | static const char *const uhs_speeds[] = { | ||
272 | [UHS_SDR12_BUS_SPEED] = "SDR12 ", | ||
273 | [UHS_SDR25_BUS_SPEED] = "SDR25 ", | ||
274 | [UHS_SDR50_BUS_SPEED] = "SDR50 ", | ||
275 | [UHS_SDR104_BUS_SPEED] = "SDR104 ", | ||
276 | [UHS_DDR50_BUS_SPEED] = "DDR50 ", | ||
277 | }; | ||
278 | |||
270 | 279 | ||
271 | dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); | 280 | dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); |
272 | 281 | ||
@@ -296,6 +305,10 @@ int mmc_add_card(struct mmc_card *card) | |||
296 | break; | 305 | break; |
297 | } | 306 | } |
298 | 307 | ||
308 | if (mmc_sd_card_uhs(card) && | ||
309 | (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) | ||
310 | uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; | ||
311 | |||
299 | if (mmc_host_is_spi(card->host)) { | 312 | if (mmc_host_is_spi(card->host)) { |
300 | pr_info("%s: new %s%s%s card on SPI\n", | 313 | pr_info("%s: new %s%s%s card on SPI\n", |
301 | mmc_hostname(card->host), | 314 | mmc_hostname(card->host), |
@@ -303,13 +316,13 @@ int mmc_add_card(struct mmc_card *card) | |||
303 | mmc_card_ddr_mode(card) ? "DDR " : "", | 316 | mmc_card_ddr_mode(card) ? "DDR " : "", |
304 | type); | 317 | type); |
305 | } else { | 318 | } else { |
306 | pr_info("%s: new %s%s%s%s card at address %04x\n", | 319 | pr_info("%s: new %s%s%s%s%s card at address %04x\n", |
307 | mmc_hostname(card->host), | 320 | mmc_hostname(card->host), |
308 | mmc_card_uhs(card) ? "ultra high speed " : | 321 | mmc_card_uhs(card) ? "ultra high speed " : |
309 | (mmc_card_highspeed(card) ? "high speed " : ""), | 322 | (mmc_card_highspeed(card) ? "high speed " : ""), |
310 | (mmc_card_hs200(card) ? "HS200 " : ""), | 323 | (mmc_card_hs200(card) ? "HS200 " : ""), |
311 | mmc_card_ddr_mode(card) ? "DDR " : "", | 324 | mmc_card_ddr_mode(card) ? "DDR " : "", |
312 | type, card->rca); | 325 | uhs_bus_speed_mode, type, card->rca); |
313 | } | 326 | } |
314 | 327 | ||
315 | #ifdef CONFIG_DEBUG_FS | 328 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 14f262e9246d..7474c47b9c08 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -527,10 +527,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) | |||
527 | 527 | ||
528 | if (data->flags & MMC_DATA_WRITE) | 528 | if (data->flags & MMC_DATA_WRITE) |
529 | /* | 529 | /* |
530 | * The limit is really 250 ms, but that is | 530 | * The MMC spec "It is strongly recommended |
531 | * insufficient for some crappy cards. | 531 | * for hosts to implement more than 500ms |
532 | * timeout value even if the card indicates | ||
533 | * the 250ms maximum busy length." Even the | ||
534 | * previous value of 300ms is known to be | ||
535 | * insufficient for some cards. | ||
532 | */ | 536 | */ |
533 | limit_us = 300000; | 537 | limit_us = 3000000; |
534 | else | 538 | else |
535 | limit_us = 100000; | 539 | limit_us = 100000; |
536 | 540 | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 02914d609a91..54df5adc0413 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -695,6 +695,11 @@ static int mmc_select_powerclass(struct mmc_card *card, | |||
695 | else if (host->ios.clock <= 200000000) | 695 | else if (host->ios.clock <= 200000000) |
696 | index = EXT_CSD_PWR_CL_200_195; | 696 | index = EXT_CSD_PWR_CL_200_195; |
697 | break; | 697 | break; |
698 | case MMC_VDD_27_28: | ||
699 | case MMC_VDD_28_29: | ||
700 | case MMC_VDD_29_30: | ||
701 | case MMC_VDD_30_31: | ||
702 | case MMC_VDD_31_32: | ||
698 | case MMC_VDD_32_33: | 703 | case MMC_VDD_32_33: |
699 | case MMC_VDD_33_34: | 704 | case MMC_VDD_33_34: |
700 | case MMC_VDD_34_35: | 705 | case MMC_VDD_34_35: |
@@ -1111,11 +1116,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
1111 | ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? | 1116 | ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? |
1112 | EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; | 1117 | EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; |
1113 | err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); | 1118 | err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); |
1114 | if (err) { | 1119 | if (err) |
1115 | pr_err("%s: power class selection to bus width %d failed\n", | 1120 | pr_warning("%s: power class selection to bus width %d" |
1116 | mmc_hostname(card->host), 1 << bus_width); | 1121 | " failed\n", mmc_hostname(card->host), |
1117 | goto err; | 1122 | 1 << bus_width); |
1118 | } | ||
1119 | } | 1123 | } |
1120 | 1124 | ||
1121 | /* | 1125 | /* |
@@ -1147,10 +1151,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
1147 | err = mmc_select_powerclass(card, ext_csd_bits[idx][0], | 1151 | err = mmc_select_powerclass(card, ext_csd_bits[idx][0], |
1148 | ext_csd); | 1152 | ext_csd); |
1149 | if (err) | 1153 | if (err) |
1150 | pr_err("%s: power class selection to " | 1154 | pr_warning("%s: power class selection to " |
1151 | "bus width %d failed\n", | 1155 | "bus width %d failed\n", |
1152 | mmc_hostname(card->host), | 1156 | mmc_hostname(card->host), |
1153 | 1 << bus_width); | 1157 | 1 << bus_width); |
1154 | 1158 | ||
1155 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1159 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
1156 | EXT_CSD_BUS_WIDTH, | 1160 | EXT_CSD_BUS_WIDTH, |
@@ -1178,10 +1182,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
1178 | err = mmc_select_powerclass(card, ext_csd_bits[idx][1], | 1182 | err = mmc_select_powerclass(card, ext_csd_bits[idx][1], |
1179 | ext_csd); | 1183 | ext_csd); |
1180 | if (err) | 1184 | if (err) |
1181 | pr_err("%s: power class selection to " | 1185 | pr_warning("%s: power class selection to " |
1182 | "bus width %d ddr %d failed\n", | 1186 | "bus width %d ddr %d failed\n", |
1183 | mmc_hostname(card->host), | 1187 | mmc_hostname(card->host), |
1184 | 1 << bus_width, ddr); | 1188 | 1 << bus_width, ddr); |
1185 | 1189 | ||
1186 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1190 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
1187 | EXT_CSD_BUS_WIDTH, | 1191 | EXT_CSD_BUS_WIDTH, |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 40989e6bb53a..236842ec955a 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
@@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device *dev) | |||
192 | return ret; | 192 | return ret; |
193 | } | 193 | } |
194 | 194 | ||
195 | #ifdef CONFIG_PM_RUNTIME | 195 | #ifdef CONFIG_PM |
196 | |||
197 | static int pm_no_operation(struct device *dev) | ||
198 | { | ||
199 | return 0; | ||
200 | } | ||
196 | 201 | ||
197 | static const struct dev_pm_ops sdio_bus_pm_ops = { | 202 | static const struct dev_pm_ops sdio_bus_pm_ops = { |
203 | SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation) | ||
198 | SET_RUNTIME_PM_OPS( | 204 | SET_RUNTIME_PM_OPS( |
199 | pm_generic_runtime_suspend, | 205 | pm_generic_runtime_suspend, |
200 | pm_generic_runtime_resume, | 206 | pm_generic_runtime_resume, |
@@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_pm_ops = { | |||
204 | 210 | ||
205 | #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) | 211 | #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) |
206 | 212 | ||
207 | #else /* !CONFIG_PM_RUNTIME */ | 213 | #else /* !CONFIG_PM */ |
208 | 214 | ||
209 | #define SDIO_PM_OPS_PTR NULL | 215 | #define SDIO_PM_OPS_PTR NULL |
210 | 216 | ||
211 | #endif /* !CONFIG_PM_RUNTIME */ | 217 | #endif /* !CONFIG_PM */ |
212 | 218 | ||
213 | static struct bus_type sdio_bus_type = { | 219 | static struct bus_type sdio_bus_type = { |
214 | .name = "sdio", | 220 | .name = "sdio", |
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index 000b3ad0f5ca..787aba1682bb 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h | |||
@@ -31,6 +31,7 @@ | |||
31 | # define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */ | 31 | # define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */ |
32 | # define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */ | 32 | # define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */ |
33 | # define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */ | 33 | # define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */ |
34 | # define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */ | ||
34 | #define ATMCI_DTOR 0x0008 /* Data Timeout */ | 35 | #define ATMCI_DTOR 0x0008 /* Data Timeout */ |
35 | # define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */ | 36 | # define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */ |
36 | # define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */ | 37 | # define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */ |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 9819dc09ce08..e94476beca18 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -77,6 +77,7 @@ struct atmel_mci_caps { | |||
77 | bool has_cstor_reg; | 77 | bool has_cstor_reg; |
78 | bool has_highspeed; | 78 | bool has_highspeed; |
79 | bool has_rwproof; | 79 | bool has_rwproof; |
80 | bool has_odd_clk_div; | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | struct atmel_mci_dma { | 83 | struct atmel_mci_dma { |
@@ -482,7 +483,14 @@ err: | |||
482 | static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, | 483 | static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, |
483 | unsigned int ns) | 484 | unsigned int ns) |
484 | { | 485 | { |
485 | return (ns * (host->bus_hz / 1000000) + 999) / 1000; | 486 | /* |
487 | * It is easier here to use us instead of ns for the timeout, | ||
488 | * it prevents from overflows during calculation. | ||
489 | */ | ||
490 | unsigned int us = DIV_ROUND_UP(ns, 1000); | ||
491 | |||
492 | /* Maximum clock frequency is host->bus_hz/2 */ | ||
493 | return us * (DIV_ROUND_UP(host->bus_hz, 2000000)); | ||
486 | } | 494 | } |
487 | 495 | ||
488 | static void atmci_set_timeout(struct atmel_mci *host, | 496 | static void atmci_set_timeout(struct atmel_mci *host, |
@@ -1127,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1127 | } | 1135 | } |
1128 | 1136 | ||
1129 | /* Calculate clock divider */ | 1137 | /* Calculate clock divider */ |
1130 | clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; | 1138 | if (host->caps.has_odd_clk_div) { |
1131 | if (clkdiv > 255) { | 1139 | clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2; |
1132 | dev_warn(&mmc->class_dev, | 1140 | if (clkdiv > 511) { |
1133 | "clock %u too slow; using %lu\n", | 1141 | dev_warn(&mmc->class_dev, |
1134 | clock_min, host->bus_hz / (2 * 256)); | 1142 | "clock %u too slow; using %lu\n", |
1135 | clkdiv = 255; | 1143 | clock_min, host->bus_hz / (511 + 2)); |
1144 | clkdiv = 511; | ||
1145 | } | ||
1146 | host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1) | ||
1147 | | ATMCI_MR_CLKODD(clkdiv & 1); | ||
1148 | } else { | ||
1149 | clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; | ||
1150 | if (clkdiv > 255) { | ||
1151 | dev_warn(&mmc->class_dev, | ||
1152 | "clock %u too slow; using %lu\n", | ||
1153 | clock_min, host->bus_hz / (2 * 256)); | ||
1154 | clkdiv = 255; | ||
1155 | } | ||
1156 | host->mode_reg = ATMCI_MR_CLKDIV(clkdiv); | ||
1136 | } | 1157 | } |
1137 | 1158 | ||
1138 | host->mode_reg = ATMCI_MR_CLKDIV(clkdiv); | ||
1139 | |||
1140 | /* | 1159 | /* |
1141 | * WRPROOF and RDPROOF prevent overruns/underruns by | 1160 | * WRPROOF and RDPROOF prevent overruns/underruns by |
1142 | * stopping the clock when the FIFO is full/empty. | 1161 | * stopping the clock when the FIFO is full/empty. |
@@ -2007,35 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
2007 | "version: 0x%x\n", version); | 2026 | "version: 0x%x\n", version); |
2008 | 2027 | ||
2009 | host->caps.has_dma = 0; | 2028 | host->caps.has_dma = 0; |
2010 | host->caps.has_pdc = 0; | 2029 | host->caps.has_pdc = 1; |
2011 | host->caps.has_cfg_reg = 0; | 2030 | host->caps.has_cfg_reg = 0; |
2012 | host->caps.has_cstor_reg = 0; | 2031 | host->caps.has_cstor_reg = 0; |
2013 | host->caps.has_highspeed = 0; | 2032 | host->caps.has_highspeed = 0; |
2014 | host->caps.has_rwproof = 0; | 2033 | host->caps.has_rwproof = 0; |
2034 | host->caps.has_odd_clk_div = 0; | ||
2015 | 2035 | ||
2016 | /* keep only major version number */ | 2036 | /* keep only major version number */ |
2017 | switch (version & 0xf00) { | 2037 | switch (version & 0xf00) { |
2018 | case 0x100: | ||
2019 | case 0x200: | ||
2020 | host->caps.has_pdc = 1; | ||
2021 | host->caps.has_rwproof = 1; | ||
2022 | break; | ||
2023 | case 0x300: | ||
2024 | case 0x400: | ||
2025 | case 0x500: | 2038 | case 0x500: |
2039 | host->caps.has_odd_clk_div = 1; | ||
2040 | case 0x400: | ||
2041 | case 0x300: | ||
2026 | #ifdef CONFIG_AT_HDMAC | 2042 | #ifdef CONFIG_AT_HDMAC |
2027 | host->caps.has_dma = 1; | 2043 | host->caps.has_dma = 1; |
2028 | #else | 2044 | #else |
2029 | host->caps.has_dma = 0; | ||
2030 | dev_info(&host->pdev->dev, | 2045 | dev_info(&host->pdev->dev, |
2031 | "has dma capability but dma engine is not selected, then use pio\n"); | 2046 | "has dma capability but dma engine is not selected, then use pio\n"); |
2032 | #endif | 2047 | #endif |
2048 | host->caps.has_pdc = 0; | ||
2033 | host->caps.has_cfg_reg = 1; | 2049 | host->caps.has_cfg_reg = 1; |
2034 | host->caps.has_cstor_reg = 1; | 2050 | host->caps.has_cstor_reg = 1; |
2035 | host->caps.has_highspeed = 1; | 2051 | host->caps.has_highspeed = 1; |
2052 | case 0x200: | ||
2036 | host->caps.has_rwproof = 1; | 2053 | host->caps.has_rwproof = 1; |
2054 | case 0x100: | ||
2037 | break; | 2055 | break; |
2038 | default: | 2056 | default: |
2057 | host->caps.has_pdc = 0; | ||
2039 | dev_warn(&host->pdev->dev, | 2058 | dev_warn(&host->pdev->dev, |
2040 | "Unmanaged mci version, set minimum capabilities\n"); | 2059 | "Unmanaged mci version, set minimum capabilities\n"); |
2041 | break; | 2060 | break; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 47adb161d3ad..5c2b1c10af9c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -1785,7 +1785,7 @@ static inline struct omap_mmc_platform_data | |||
1785 | } | 1785 | } |
1786 | #endif | 1786 | #endif |
1787 | 1787 | ||
1788 | static int __init omap_hsmmc_probe(struct platform_device *pdev) | 1788 | static int __devinit omap_hsmmc_probe(struct platform_device *pdev) |
1789 | { | 1789 | { |
1790 | struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; | 1790 | struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; |
1791 | struct mmc_host *mmc; | 1791 | struct mmc_host *mmc; |
@@ -1818,8 +1818,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1818 | if (res == NULL || irq < 0) | 1818 | if (res == NULL || irq < 0) |
1819 | return -ENXIO; | 1819 | return -ENXIO; |
1820 | 1820 | ||
1821 | res->start += pdata->reg_offset; | ||
1822 | res->end += pdata->reg_offset; | ||
1823 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 1821 | res = request_mem_region(res->start, resource_size(res), pdev->name); |
1824 | if (res == NULL) | 1822 | if (res == NULL) |
1825 | return -EBUSY; | 1823 | return -EBUSY; |
@@ -1843,7 +1841,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1843 | host->dma_ch = -1; | 1841 | host->dma_ch = -1; |
1844 | host->irq = irq; | 1842 | host->irq = irq; |
1845 | host->slot_id = 0; | 1843 | host->slot_id = 0; |
1846 | host->mapbase = res->start; | 1844 | host->mapbase = res->start + pdata->reg_offset; |
1847 | host->base = ioremap(host->mapbase, SZ_4K); | 1845 | host->base = ioremap(host->mapbase, SZ_4K); |
1848 | host->power_mode = MMC_POWER_OFF; | 1846 | host->power_mode = MMC_POWER_OFF; |
1849 | host->next_data.cookie = 1; | 1847 | host->next_data.cookie = 1; |
@@ -1875,8 +1873,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1875 | goto err1; | 1873 | goto err1; |
1876 | } | 1874 | } |
1877 | 1875 | ||
1878 | omap_hsmmc_context_save(host); | ||
1879 | |||
1880 | if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) { | 1876 | if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) { |
1881 | dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n"); | 1877 | dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n"); |
1882 | mmc->caps2 |= MMC_CAP2_NO_MULTI_READ; | 1878 | mmc->caps2 |= MMC_CAP2_NO_MULTI_READ; |
@@ -1887,6 +1883,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1887 | pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY); | 1883 | pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY); |
1888 | pm_runtime_use_autosuspend(host->dev); | 1884 | pm_runtime_use_autosuspend(host->dev); |
1889 | 1885 | ||
1886 | omap_hsmmc_context_save(host); | ||
1887 | |||
1890 | if (cpu_is_omap2430()) { | 1888 | if (cpu_is_omap2430()) { |
1891 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); | 1889 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); |
1892 | /* | 1890 | /* |
@@ -2018,8 +2016,7 @@ err_reg: | |||
2018 | err_irq_cd_init: | 2016 | err_irq_cd_init: |
2019 | free_irq(host->irq, host); | 2017 | free_irq(host->irq, host); |
2020 | err_irq: | 2018 | err_irq: |
2021 | pm_runtime_mark_last_busy(host->dev); | 2019 | pm_runtime_put_sync(host->dev); |
2022 | pm_runtime_put_autosuspend(host->dev); | ||
2023 | pm_runtime_disable(host->dev); | 2020 | pm_runtime_disable(host->dev); |
2024 | clk_put(host->fclk); | 2021 | clk_put(host->fclk); |
2025 | if (host->got_dbclk) { | 2022 | if (host->got_dbclk) { |
@@ -2037,35 +2034,33 @@ err: | |||
2037 | return ret; | 2034 | return ret; |
2038 | } | 2035 | } |
2039 | 2036 | ||
2040 | static int omap_hsmmc_remove(struct platform_device *pdev) | 2037 | static int __devexit omap_hsmmc_remove(struct platform_device *pdev) |
2041 | { | 2038 | { |
2042 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); | 2039 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); |
2043 | struct resource *res; | 2040 | struct resource *res; |
2044 | 2041 | ||
2045 | if (host) { | 2042 | pm_runtime_get_sync(host->dev); |
2046 | pm_runtime_get_sync(host->dev); | 2043 | mmc_remove_host(host->mmc); |
2047 | mmc_remove_host(host->mmc); | 2044 | if (host->use_reg) |
2048 | if (host->use_reg) | 2045 | omap_hsmmc_reg_put(host); |
2049 | omap_hsmmc_reg_put(host); | 2046 | if (host->pdata->cleanup) |
2050 | if (host->pdata->cleanup) | 2047 | host->pdata->cleanup(&pdev->dev); |
2051 | host->pdata->cleanup(&pdev->dev); | 2048 | free_irq(host->irq, host); |
2052 | free_irq(host->irq, host); | 2049 | if (mmc_slot(host).card_detect_irq) |
2053 | if (mmc_slot(host).card_detect_irq) | 2050 | free_irq(mmc_slot(host).card_detect_irq, host); |
2054 | free_irq(mmc_slot(host).card_detect_irq, host); | ||
2055 | |||
2056 | pm_runtime_put_sync(host->dev); | ||
2057 | pm_runtime_disable(host->dev); | ||
2058 | clk_put(host->fclk); | ||
2059 | if (host->got_dbclk) { | ||
2060 | clk_disable(host->dbclk); | ||
2061 | clk_put(host->dbclk); | ||
2062 | } | ||
2063 | 2051 | ||
2064 | mmc_free_host(host->mmc); | 2052 | pm_runtime_put_sync(host->dev); |
2065 | iounmap(host->base); | 2053 | pm_runtime_disable(host->dev); |
2066 | omap_hsmmc_gpio_free(pdev->dev.platform_data); | 2054 | clk_put(host->fclk); |
2055 | if (host->got_dbclk) { | ||
2056 | clk_disable(host->dbclk); | ||
2057 | clk_put(host->dbclk); | ||
2067 | } | 2058 | } |
2068 | 2059 | ||
2060 | mmc_free_host(host->mmc); | ||
2061 | iounmap(host->base); | ||
2062 | omap_hsmmc_gpio_free(pdev->dev.platform_data); | ||
2063 | |||
2069 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2064 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2070 | if (res) | 2065 | if (res) |
2071 | release_mem_region(res->start, resource_size(res)); | 2066 | release_mem_region(res->start, resource_size(res)); |
@@ -2078,49 +2073,45 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2078 | static int omap_hsmmc_suspend(struct device *dev) | 2073 | static int omap_hsmmc_suspend(struct device *dev) |
2079 | { | 2074 | { |
2080 | int ret = 0; | 2075 | int ret = 0; |
2081 | struct platform_device *pdev = to_platform_device(dev); | 2076 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
2082 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); | ||
2083 | 2077 | ||
2084 | if (host && host->suspended) | 2078 | if (!host) |
2085 | return 0; | 2079 | return 0; |
2086 | 2080 | ||
2087 | if (host) { | 2081 | if (host && host->suspended) |
2088 | pm_runtime_get_sync(host->dev); | 2082 | return 0; |
2089 | host->suspended = 1; | ||
2090 | if (host->pdata->suspend) { | ||
2091 | ret = host->pdata->suspend(&pdev->dev, | ||
2092 | host->slot_id); | ||
2093 | if (ret) { | ||
2094 | dev_dbg(mmc_dev(host->mmc), | ||
2095 | "Unable to handle MMC board" | ||
2096 | " level suspend\n"); | ||
2097 | host->suspended = 0; | ||
2098 | return ret; | ||
2099 | } | ||
2100 | } | ||
2101 | ret = mmc_suspend_host(host->mmc); | ||
2102 | 2083 | ||
2084 | pm_runtime_get_sync(host->dev); | ||
2085 | host->suspended = 1; | ||
2086 | if (host->pdata->suspend) { | ||
2087 | ret = host->pdata->suspend(dev, host->slot_id); | ||
2103 | if (ret) { | 2088 | if (ret) { |
2089 | dev_dbg(dev, "Unable to handle MMC board" | ||
2090 | " level suspend\n"); | ||
2104 | host->suspended = 0; | 2091 | host->suspended = 0; |
2105 | if (host->pdata->resume) { | 2092 | return ret; |
2106 | ret = host->pdata->resume(&pdev->dev, | ||
2107 | host->slot_id); | ||
2108 | if (ret) | ||
2109 | dev_dbg(mmc_dev(host->mmc), | ||
2110 | "Unmask interrupt failed\n"); | ||
2111 | } | ||
2112 | goto err; | ||
2113 | } | 2093 | } |
2094 | } | ||
2095 | ret = mmc_suspend_host(host->mmc); | ||
2114 | 2096 | ||
2115 | if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { | 2097 | if (ret) { |
2116 | omap_hsmmc_disable_irq(host); | 2098 | host->suspended = 0; |
2117 | OMAP_HSMMC_WRITE(host->base, HCTL, | 2099 | if (host->pdata->resume) { |
2118 | OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); | 2100 | ret = host->pdata->resume(dev, host->slot_id); |
2101 | if (ret) | ||
2102 | dev_dbg(dev, "Unmask interrupt failed\n"); | ||
2119 | } | 2103 | } |
2120 | if (host->got_dbclk) | 2104 | goto err; |
2121 | clk_disable(host->dbclk); | 2105 | } |
2122 | 2106 | ||
2107 | if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { | ||
2108 | omap_hsmmc_disable_irq(host); | ||
2109 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
2110 | OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); | ||
2123 | } | 2111 | } |
2112 | |||
2113 | if (host->got_dbclk) | ||
2114 | clk_disable(host->dbclk); | ||
2124 | err: | 2115 | err: |
2125 | pm_runtime_put_sync(host->dev); | 2116 | pm_runtime_put_sync(host->dev); |
2126 | return ret; | 2117 | return ret; |
@@ -2130,38 +2121,37 @@ err: | |||
2130 | static int omap_hsmmc_resume(struct device *dev) | 2121 | static int omap_hsmmc_resume(struct device *dev) |
2131 | { | 2122 | { |
2132 | int ret = 0; | 2123 | int ret = 0; |
2133 | struct platform_device *pdev = to_platform_device(dev); | 2124 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
2134 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); | 2125 | |
2126 | if (!host) | ||
2127 | return 0; | ||
2135 | 2128 | ||
2136 | if (host && !host->suspended) | 2129 | if (host && !host->suspended) |
2137 | return 0; | 2130 | return 0; |
2138 | 2131 | ||
2139 | if (host) { | 2132 | pm_runtime_get_sync(host->dev); |
2140 | pm_runtime_get_sync(host->dev); | ||
2141 | 2133 | ||
2142 | if (host->got_dbclk) | 2134 | if (host->got_dbclk) |
2143 | clk_enable(host->dbclk); | 2135 | clk_enable(host->dbclk); |
2144 | 2136 | ||
2145 | if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) | 2137 | if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) |
2146 | omap_hsmmc_conf_bus_power(host); | 2138 | omap_hsmmc_conf_bus_power(host); |
2147 | 2139 | ||
2148 | if (host->pdata->resume) { | 2140 | if (host->pdata->resume) { |
2149 | ret = host->pdata->resume(&pdev->dev, host->slot_id); | 2141 | ret = host->pdata->resume(dev, host->slot_id); |
2150 | if (ret) | 2142 | if (ret) |
2151 | dev_dbg(mmc_dev(host->mmc), | 2143 | dev_dbg(dev, "Unmask interrupt failed\n"); |
2152 | "Unmask interrupt failed\n"); | 2144 | } |
2153 | } | ||
2154 | 2145 | ||
2155 | omap_hsmmc_protect_card(host); | 2146 | omap_hsmmc_protect_card(host); |
2156 | 2147 | ||
2157 | /* Notify the core to resume the host */ | 2148 | /* Notify the core to resume the host */ |
2158 | ret = mmc_resume_host(host->mmc); | 2149 | ret = mmc_resume_host(host->mmc); |
2159 | if (ret == 0) | 2150 | if (ret == 0) |
2160 | host->suspended = 0; | 2151 | host->suspended = 0; |
2161 | 2152 | ||
2162 | pm_runtime_mark_last_busy(host->dev); | 2153 | pm_runtime_mark_last_busy(host->dev); |
2163 | pm_runtime_put_autosuspend(host->dev); | 2154 | pm_runtime_put_autosuspend(host->dev); |
2164 | } | ||
2165 | 2155 | ||
2166 | return ret; | 2156 | return ret; |
2167 | 2157 | ||
@@ -2178,7 +2168,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) | |||
2178 | 2168 | ||
2179 | host = platform_get_drvdata(to_platform_device(dev)); | 2169 | host = platform_get_drvdata(to_platform_device(dev)); |
2180 | omap_hsmmc_context_save(host); | 2170 | omap_hsmmc_context_save(host); |
2181 | dev_dbg(mmc_dev(host->mmc), "disabled\n"); | 2171 | dev_dbg(dev, "disabled\n"); |
2182 | 2172 | ||
2183 | return 0; | 2173 | return 0; |
2184 | } | 2174 | } |
@@ -2189,7 +2179,7 @@ static int omap_hsmmc_runtime_resume(struct device *dev) | |||
2189 | 2179 | ||
2190 | host = platform_get_drvdata(to_platform_device(dev)); | 2180 | host = platform_get_drvdata(to_platform_device(dev)); |
2191 | omap_hsmmc_context_restore(host); | 2181 | omap_hsmmc_context_restore(host); |
2192 | dev_dbg(mmc_dev(host->mmc), "enabled\n"); | 2182 | dev_dbg(dev, "enabled\n"); |
2193 | 2183 | ||
2194 | return 0; | 2184 | return 0; |
2195 | } | 2185 | } |
@@ -2202,7 +2192,8 @@ static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { | |||
2202 | }; | 2192 | }; |
2203 | 2193 | ||
2204 | static struct platform_driver omap_hsmmc_driver = { | 2194 | static struct platform_driver omap_hsmmc_driver = { |
2205 | .remove = omap_hsmmc_remove, | 2195 | .probe = omap_hsmmc_probe, |
2196 | .remove = __devexit_p(omap_hsmmc_remove), | ||
2206 | .driver = { | 2197 | .driver = { |
2207 | .name = DRIVER_NAME, | 2198 | .name = DRIVER_NAME, |
2208 | .owner = THIS_MODULE, | 2199 | .owner = THIS_MODULE, |
@@ -2211,21 +2202,7 @@ static struct platform_driver omap_hsmmc_driver = { | |||
2211 | }, | 2202 | }, |
2212 | }; | 2203 | }; |
2213 | 2204 | ||
2214 | static int __init omap_hsmmc_init(void) | 2205 | module_platform_driver(omap_hsmmc_driver); |
2215 | { | ||
2216 | /* Register the MMC driver */ | ||
2217 | return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe); | ||
2218 | } | ||
2219 | |||
2220 | static void __exit omap_hsmmc_cleanup(void) | ||
2221 | { | ||
2222 | /* Unregister MMC driver */ | ||
2223 | platform_driver_unregister(&omap_hsmmc_driver); | ||
2224 | } | ||
2225 | |||
2226 | module_init(omap_hsmmc_init); | ||
2227 | module_exit(omap_hsmmc_cleanup); | ||
2228 | |||
2229 | MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver"); | 2206 | MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver"); |
2230 | MODULE_LICENSE("GPL"); | 2207 | MODULE_LICENSE("GPL"); |
2231 | MODULE_ALIAS("platform:" DRIVER_NAME); | 2208 | MODULE_ALIAS("platform:" DRIVER_NAME); |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 46fd1fd1b605..177f697b5835 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/module.h> | ||
23 | #include <linux/mmc/host.h> | 24 | #include <linux/mmc/host.h> |
24 | 25 | ||
25 | #include "sdhci-pltfm.h" | 26 | #include "sdhci-pltfm.h" |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index fbbebe251e01..69ef0beae104 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -1418,8 +1418,6 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, | |||
1418 | 1418 | ||
1419 | slots = chip->num_slots; /* Quirk may have changed this */ | 1419 | slots = chip->num_slots; /* Quirk may have changed this */ |
1420 | 1420 | ||
1421 | pci_enable_msi(pdev); | ||
1422 | |||
1423 | for (i = 0; i < slots; i++) { | 1421 | for (i = 0; i < slots; i++) { |
1424 | slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); | 1422 | slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); |
1425 | if (IS_ERR(slot)) { | 1423 | if (IS_ERR(slot)) { |
@@ -1438,8 +1436,6 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, | |||
1438 | return 0; | 1436 | return 0; |
1439 | 1437 | ||
1440 | free: | 1438 | free: |
1441 | pci_disable_msi(pdev); | ||
1442 | |||
1443 | pci_set_drvdata(pdev, NULL); | 1439 | pci_set_drvdata(pdev, NULL); |
1444 | kfree(chip); | 1440 | kfree(chip); |
1445 | 1441 | ||
@@ -1462,8 +1458,6 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev) | |||
1462 | for (i = 0; i < chip->num_slots; i++) | 1458 | for (i = 0; i < chip->num_slots; i++) |
1463 | sdhci_pci_remove_slot(chip->slots[i]); | 1459 | sdhci_pci_remove_slot(chip->slots[i]); |
1464 | 1460 | ||
1465 | pci_disable_msi(pdev); | ||
1466 | |||
1467 | pci_set_drvdata(pdev, NULL); | 1461 | pci_set_drvdata(pdev, NULL); |
1468 | kfree(chip); | 1462 | kfree(chip); |
1469 | } | 1463 | } |
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index b19e7d435f8d..55a164fcaa15 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -20,6 +20,10 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/pm.h> | ||
26 | #include <linux/pm_runtime.h> | ||
23 | 27 | ||
24 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
25 | 29 | ||
@@ -53,6 +57,18 @@ struct sdhci_s3c { | |||
53 | struct clk *clk_bus[MAX_BUS_CLK]; | 57 | struct clk *clk_bus[MAX_BUS_CLK]; |
54 | }; | 58 | }; |
55 | 59 | ||
60 | /** | ||
61 | * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data | ||
62 | * @sdhci_quirks: sdhci host specific quirks. | ||
63 | * | ||
64 | * Specifies platform specific configuration of sdhci controller. | ||
65 | * Note: A structure for driver specific platform data is used for future | ||
66 | * expansion of its usage. | ||
67 | */ | ||
68 | struct sdhci_s3c_drv_data { | ||
69 | unsigned int sdhci_quirks; | ||
70 | }; | ||
71 | |||
56 | static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) | 72 | static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) |
57 | { | 73 | { |
58 | return sdhci_priv(host); | 74 | return sdhci_priv(host); |
@@ -132,10 +148,10 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | |||
132 | return UINT_MAX; | 148 | return UINT_MAX; |
133 | 149 | ||
134 | /* | 150 | /* |
135 | * Clock divider's step is different as 1 from that of host controller | 151 | * If controller uses a non-standard clock division, find the best clock |
136 | * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL. | 152 | * speed possible with selected clock source and skip the division. |
137 | */ | 153 | */ |
138 | if (ourhost->pdata->clk_type) { | 154 | if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { |
139 | rate = clk_round_rate(clksrc, wanted); | 155 | rate = clk_round_rate(clksrc, wanted); |
140 | return wanted - rate; | 156 | return wanted - rate; |
141 | } | 157 | } |
@@ -272,6 +288,8 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) | |||
272 | static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | 288 | static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) |
273 | { | 289 | { |
274 | struct sdhci_s3c *ourhost = to_s3c(host); | 290 | struct sdhci_s3c *ourhost = to_s3c(host); |
291 | unsigned long timeout; | ||
292 | u16 clk = 0; | ||
275 | 293 | ||
276 | /* don't bother if the clock is going off */ | 294 | /* don't bother if the clock is going off */ |
277 | if (clock == 0) | 295 | if (clock == 0) |
@@ -282,6 +300,25 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | |||
282 | clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); | 300 | clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); |
283 | 301 | ||
284 | host->clock = clock; | 302 | host->clock = clock; |
303 | |||
304 | clk = SDHCI_CLOCK_INT_EN; | ||
305 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
306 | |||
307 | /* Wait max 20 ms */ | ||
308 | timeout = 20; | ||
309 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) | ||
310 | & SDHCI_CLOCK_INT_STABLE)) { | ||
311 | if (timeout == 0) { | ||
312 | printk(KERN_ERR "%s: Internal clock never " | ||
313 | "stabilised.\n", mmc_hostname(host->mmc)); | ||
314 | return; | ||
315 | } | ||
316 | timeout--; | ||
317 | mdelay(1); | ||
318 | } | ||
319 | |||
320 | clk |= SDHCI_CLOCK_CARD_EN; | ||
321 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
285 | } | 322 | } |
286 | 323 | ||
287 | /** | 324 | /** |
@@ -382,16 +419,24 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) | |||
382 | } | 419 | } |
383 | } | 420 | } |
384 | 421 | ||
422 | static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( | ||
423 | struct platform_device *pdev) | ||
424 | { | ||
425 | return (struct sdhci_s3c_drv_data *) | ||
426 | platform_get_device_id(pdev)->driver_data; | ||
427 | } | ||
428 | |||
385 | static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | 429 | static int __devinit sdhci_s3c_probe(struct platform_device *pdev) |
386 | { | 430 | { |
387 | struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; | 431 | struct s3c_sdhci_platdata *pdata; |
432 | struct sdhci_s3c_drv_data *drv_data; | ||
388 | struct device *dev = &pdev->dev; | 433 | struct device *dev = &pdev->dev; |
389 | struct sdhci_host *host; | 434 | struct sdhci_host *host; |
390 | struct sdhci_s3c *sc; | 435 | struct sdhci_s3c *sc; |
391 | struct resource *res; | 436 | struct resource *res; |
392 | int ret, irq, ptr, clks; | 437 | int ret, irq, ptr, clks; |
393 | 438 | ||
394 | if (!pdata) { | 439 | if (!pdev->dev.platform_data) { |
395 | dev_err(dev, "no device data specified\n"); | 440 | dev_err(dev, "no device data specified\n"); |
396 | return -ENOENT; | 441 | return -ENOENT; |
397 | } | 442 | } |
@@ -402,18 +447,20 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
402 | return irq; | 447 | return irq; |
403 | } | 448 | } |
404 | 449 | ||
405 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
406 | if (!res) { | ||
407 | dev_err(dev, "no memory specified\n"); | ||
408 | return -ENOENT; | ||
409 | } | ||
410 | |||
411 | host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); | 450 | host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); |
412 | if (IS_ERR(host)) { | 451 | if (IS_ERR(host)) { |
413 | dev_err(dev, "sdhci_alloc_host() failed\n"); | 452 | dev_err(dev, "sdhci_alloc_host() failed\n"); |
414 | return PTR_ERR(host); | 453 | return PTR_ERR(host); |
415 | } | 454 | } |
416 | 455 | ||
456 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
457 | if (!pdata) { | ||
458 | ret = -ENOMEM; | ||
459 | goto err_io_clk; | ||
460 | } | ||
461 | memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); | ||
462 | |||
463 | drv_data = sdhci_s3c_get_driver_data(pdev); | ||
417 | sc = sdhci_priv(host); | 464 | sc = sdhci_priv(host); |
418 | 465 | ||
419 | sc->host = host; | 466 | sc->host = host; |
@@ -464,15 +511,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
464 | goto err_no_busclks; | 511 | goto err_no_busclks; |
465 | } | 512 | } |
466 | 513 | ||
467 | sc->ioarea = request_mem_region(res->start, resource_size(res), | 514 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
468 | mmc_hostname(host->mmc)); | 515 | host->ioaddr = devm_request_and_ioremap(&pdev->dev, res); |
469 | if (!sc->ioarea) { | ||
470 | dev_err(dev, "failed to reserve register area\n"); | ||
471 | ret = -ENXIO; | ||
472 | goto err_req_regs; | ||
473 | } | ||
474 | |||
475 | host->ioaddr = ioremap_nocache(res->start, resource_size(res)); | ||
476 | if (!host->ioaddr) { | 516 | if (!host->ioaddr) { |
477 | dev_err(dev, "failed to map registers\n"); | 517 | dev_err(dev, "failed to map registers\n"); |
478 | ret = -ENXIO; | 518 | ret = -ENXIO; |
@@ -491,6 +531,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
491 | /* Setup quirks for the controller */ | 531 | /* Setup quirks for the controller */ |
492 | host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; | 532 | host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; |
493 | host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; | 533 | host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; |
534 | if (drv_data) | ||
535 | host->quirks |= drv_data->sdhci_quirks; | ||
494 | 536 | ||
495 | #ifndef CONFIG_MMC_SDHCI_S3C_DMA | 537 | #ifndef CONFIG_MMC_SDHCI_S3C_DMA |
496 | 538 | ||
@@ -518,6 +560,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
518 | if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) | 560 | if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) |
519 | host->mmc->caps = MMC_CAP_NONREMOVABLE; | 561 | host->mmc->caps = MMC_CAP_NONREMOVABLE; |
520 | 562 | ||
563 | switch (pdata->max_width) { | ||
564 | case 8: | ||
565 | host->mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
566 | case 4: | ||
567 | host->mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
568 | break; | ||
569 | } | ||
570 | |||
521 | if (pdata->pm_caps) | 571 | if (pdata->pm_caps) |
522 | host->mmc->pm_caps |= pdata->pm_caps; | 572 | host->mmc->pm_caps |= pdata->pm_caps; |
523 | 573 | ||
@@ -531,7 +581,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
531 | * If controller does not have internal clock divider, | 581 | * If controller does not have internal clock divider, |
532 | * we can use overriding functions instead of default. | 582 | * we can use overriding functions instead of default. |
533 | */ | 583 | */ |
534 | if (pdata->clk_type) { | 584 | if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { |
535 | sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; | 585 | sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; |
536 | sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; | 586 | sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; |
537 | sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; | 587 | sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; |
@@ -544,10 +594,17 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
544 | if (pdata->host_caps2) | 594 | if (pdata->host_caps2) |
545 | host->mmc->caps2 |= pdata->host_caps2; | 595 | host->mmc->caps2 |= pdata->host_caps2; |
546 | 596 | ||
597 | pm_runtime_enable(&pdev->dev); | ||
598 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); | ||
599 | pm_runtime_use_autosuspend(&pdev->dev); | ||
600 | pm_suspend_ignore_children(&pdev->dev, 1); | ||
601 | |||
547 | ret = sdhci_add_host(host); | 602 | ret = sdhci_add_host(host); |
548 | if (ret) { | 603 | if (ret) { |
549 | dev_err(dev, "sdhci_add_host() failed\n"); | 604 | dev_err(dev, "sdhci_add_host() failed\n"); |
550 | goto err_add_host; | 605 | pm_runtime_forbid(&pdev->dev); |
606 | pm_runtime_get_noresume(&pdev->dev); | ||
607 | goto err_req_regs; | ||
551 | } | 608 | } |
552 | 609 | ||
553 | /* The following two methods of card detection might call | 610 | /* The following two methods of card detection might call |
@@ -561,10 +618,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
561 | 618 | ||
562 | return 0; | 619 | return 0; |
563 | 620 | ||
564 | err_add_host: | ||
565 | release_resource(sc->ioarea); | ||
566 | kfree(sc->ioarea); | ||
567 | |||
568 | err_req_regs: | 621 | err_req_regs: |
569 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | 622 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { |
570 | if (sc->clk_bus[ptr]) { | 623 | if (sc->clk_bus[ptr]) { |
@@ -601,6 +654,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | |||
601 | 654 | ||
602 | sdhci_remove_host(host, 1); | 655 | sdhci_remove_host(host, 1); |
603 | 656 | ||
657 | pm_runtime_disable(&pdev->dev); | ||
658 | |||
604 | for (ptr = 0; ptr < 3; ptr++) { | 659 | for (ptr = 0; ptr < 3; ptr++) { |
605 | if (sc->clk_bus[ptr]) { | 660 | if (sc->clk_bus[ptr]) { |
606 | clk_disable(sc->clk_bus[ptr]); | 661 | clk_disable(sc->clk_bus[ptr]); |
@@ -610,18 +665,13 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | |||
610 | clk_disable(sc->clk_io); | 665 | clk_disable(sc->clk_io); |
611 | clk_put(sc->clk_io); | 666 | clk_put(sc->clk_io); |
612 | 667 | ||
613 | iounmap(host->ioaddr); | ||
614 | release_resource(sc->ioarea); | ||
615 | kfree(sc->ioarea); | ||
616 | |||
617 | sdhci_free_host(host); | 668 | sdhci_free_host(host); |
618 | platform_set_drvdata(pdev, NULL); | 669 | platform_set_drvdata(pdev, NULL); |
619 | 670 | ||
620 | return 0; | 671 | return 0; |
621 | } | 672 | } |
622 | 673 | ||
623 | #ifdef CONFIG_PM | 674 | #ifdef CONFIG_PM_SLEEP |
624 | |||
625 | static int sdhci_s3c_suspend(struct device *dev) | 675 | static int sdhci_s3c_suspend(struct device *dev) |
626 | { | 676 | { |
627 | struct sdhci_host *host = dev_get_drvdata(dev); | 677 | struct sdhci_host *host = dev_get_drvdata(dev); |
@@ -635,10 +685,29 @@ static int sdhci_s3c_resume(struct device *dev) | |||
635 | 685 | ||
636 | return sdhci_resume_host(host); | 686 | return sdhci_resume_host(host); |
637 | } | 687 | } |
688 | #endif | ||
689 | |||
690 | #ifdef CONFIG_PM_RUNTIME | ||
691 | static int sdhci_s3c_runtime_suspend(struct device *dev) | ||
692 | { | ||
693 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
694 | |||
695 | return sdhci_runtime_suspend_host(host); | ||
696 | } | ||
638 | 697 | ||
698 | static int sdhci_s3c_runtime_resume(struct device *dev) | ||
699 | { | ||
700 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
701 | |||
702 | return sdhci_runtime_resume_host(host); | ||
703 | } | ||
704 | #endif | ||
705 | |||
706 | #ifdef CONFIG_PM | ||
639 | static const struct dev_pm_ops sdhci_s3c_pmops = { | 707 | static const struct dev_pm_ops sdhci_s3c_pmops = { |
640 | .suspend = sdhci_s3c_suspend, | 708 | SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume) |
641 | .resume = sdhci_s3c_resume, | 709 | SET_RUNTIME_PM_OPS(sdhci_s3c_runtime_suspend, sdhci_s3c_runtime_resume, |
710 | NULL) | ||
642 | }; | 711 | }; |
643 | 712 | ||
644 | #define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops) | 713 | #define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops) |
@@ -647,9 +716,31 @@ static const struct dev_pm_ops sdhci_s3c_pmops = { | |||
647 | #define SDHCI_S3C_PMOPS NULL | 716 | #define SDHCI_S3C_PMOPS NULL |
648 | #endif | 717 | #endif |
649 | 718 | ||
719 | #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) | ||
720 | static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { | ||
721 | .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK, | ||
722 | }; | ||
723 | #define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data) | ||
724 | #else | ||
725 | #define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)NULL) | ||
726 | #endif | ||
727 | |||
728 | static struct platform_device_id sdhci_s3c_driver_ids[] = { | ||
729 | { | ||
730 | .name = "s3c-sdhci", | ||
731 | .driver_data = (kernel_ulong_t)NULL, | ||
732 | }, { | ||
733 | .name = "exynos4-sdhci", | ||
734 | .driver_data = EXYNOS4_SDHCI_DRV_DATA, | ||
735 | }, | ||
736 | { } | ||
737 | }; | ||
738 | MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); | ||
739 | |||
650 | static struct platform_driver sdhci_s3c_driver = { | 740 | static struct platform_driver sdhci_s3c_driver = { |
651 | .probe = sdhci_s3c_probe, | 741 | .probe = sdhci_s3c_probe, |
652 | .remove = __devexit_p(sdhci_s3c_remove), | 742 | .remove = __devexit_p(sdhci_s3c_remove), |
743 | .id_table = sdhci_s3c_driver_ids, | ||
653 | .driver = { | 744 | .driver = { |
654 | .owner = THIS_MODULE, | 745 | .owner = THIS_MODULE, |
655 | .name = "s3c-sdhci", | 746 | .name = "s3c-sdhci", |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 8262cadfdab7..9aa77f3f04a8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -2782,8 +2782,9 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2782 | mmc_card_is_removable(mmc)) | 2782 | mmc_card_is_removable(mmc)) |
2783 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 2783 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
2784 | 2784 | ||
2785 | /* UHS-I mode(s) supported by the host controller. */ | 2785 | /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ |
2786 | if (host->version >= SDHCI_SPEC_300) | 2786 | if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | |
2787 | SDHCI_SUPPORT_DDR50)) | ||
2787 | mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; | 2788 | mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; |
2788 | 2789 | ||
2789 | /* SDR104 supports also implies SDR50 support */ | 2790 | /* SDR104 supports also implies SDR50 support */ |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index aafaf0b6eb1c..724b35e85a26 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -454,7 +454,8 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) | |||
454 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); | 454 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); |
455 | else | 455 | else |
456 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & | 456 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & |
457 | ((fls(host->clk / clk) - 1) << 16)); | 457 | ((fls(DIV_ROUND_UP(host->clk, |
458 | clk) - 1) - 1) << 16)); | ||
458 | 459 | ||
459 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); | 460 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); |
460 | } | 461 | } |
@@ -1297,14 +1298,8 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
1297 | spin_lock_init(&host->lock); | 1298 | spin_lock_init(&host->lock); |
1298 | 1299 | ||
1299 | mmc->ops = &sh_mmcif_ops; | 1300 | mmc->ops = &sh_mmcif_ops; |
1300 | mmc->f_max = host->clk; | 1301 | mmc->f_max = host->clk / 2; |
1301 | /* close to 400KHz */ | 1302 | mmc->f_min = host->clk / 512; |
1302 | if (mmc->f_max < 51200000) | ||
1303 | mmc->f_min = mmc->f_max / 128; | ||
1304 | else if (mmc->f_max < 102400000) | ||
1305 | mmc->f_min = mmc->f_max / 256; | ||
1306 | else | ||
1307 | mmc->f_min = mmc->f_max / 512; | ||
1308 | if (pd->ocr) | 1303 | if (pd->ocr) |
1309 | mmc->ocr_avail = pd->ocr; | 1304 | mmc->ocr_avail = pd->ocr; |
1310 | mmc->caps = MMC_CAP_MMC_HIGHSPEED; | 1305 | mmc->caps = MMC_CAP_MMC_HIGHSPEED; |