summaryrefslogtreecommitdiff
path: root/drivers/mmc/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-04 13:45:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-04 13:45:17 -0700
commit173192958d06b8d1eb44f56d74373052ad6a9a60 (patch)
tree838a4f063c994d4d0a6259a85f21005c4098b752 /drivers/mmc/core
parente72a5d1ceb1c5cbe39c35c1c7a7f5909cbe8451a (diff)
parente4404fab2e0b70287a471a1e760c9338ce683fde (diff)
Merge tag 'mmc-updates-for-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC update from Chris Ball: "MMC highlights for 3.10: Core: - Introduce MMC_CAP2_NO_PRESCAN_POWERUP to allow skipping mmc_power_up() at boot/initialization time if it's already happened, for performance (faster boot time) reasons. - Fix a bit width test failure that resulted in old eMMC cards being put into 1-bit mode when 4-bit mode was available. - Expose fwrev/hwrev for MMCv4 parts. - Improve card removal logic in the case where the card's removed slowly; we were missing card removal events if the card retained contact with the slot pads for long enough to reply to a CMD13 while being removed. Drivers: - davinci_mmc: Support using PIO instead of DMA. - dw_mmc: Add support for Exynos4412. - mxcmmc: DT support, use slot-gpio API. - mxs-mmc: Add broken-cd/cd-inverted/non-removable DT property support. - sdhci-sirf: New sdhci-pltfm driver for CSR SiRF SoCs: SiRFprimaII: unicore ARM Cortex-A9 SiRFatlas6: unicore ARM Cortex-A9 SiRFmarco: dual core ARM Cortex-A9 SMP - sdhci-tegra: Add support for Tegra114 platforms, use mmc_of_parse()" * tag 'mmc-updates-for-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (66 commits) mmc: sdhci-tegra: fix MODULE_DEVICE_TABLE mmc: core: fix init controller performance regression, updated patch mmc: mxcmmc: enable DMA support on mpc512x mmc: mxcmmc: constify mxcmci_devtype mmc: mxcmmc: use slot-gpio API for write-protect detection mmc: mxcmmc: add mpc512x SDHC support mmc: mxcmmc: fix race conditions for host->req and host->data access mmc: mxcmmc: DT support mmc: dw_mmc: let device core setup the default pin configuration mmc: mxs-mmc: add broken-cd property mmc: mxs-mmc: add non-removable property mmc: mxs-mmc: add cd-inverted property mmc: core: call pm_runtime_put_noidle in pm_runtime_get_sync failed case mmc: mxcmmc: Fix bug when card is present during boot mmc: core: fix performance regression initializing MMC host controllers Revert "mmc: core: wait while adding MMC host to ensure root mounts successfully" mmc: atmel-mci: pio hang on block errors mmc: core: Fix bit width test failing on old eMMC cards mmc: dw_mmc: Use pr_info instead of printk mmc: dw_mmc: Check return value of regulator_enable ...
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/core.c18
-rw-r--r--drivers/mmc/core/mmc.c5
-rw-r--r--drivers/mmc/core/sdio.c4
-rw-r--r--drivers/mmc/core/sdio_bus.c23
4 files changed, 44 insertions, 6 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9290bb51a06a..c40396f23202 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2289,6 +2289,19 @@ int _mmc_detect_card_removed(struct mmc_host *host)
return 1;
ret = host->bus_ops->alive(host);
+
+ /*
+ * Card detect status and alive check may be out of sync if card is
+ * removed slowly, when card detect switch changes while card/slot
+ * pads are still contacted in hardware (refer to "SD Card Mechanical
+ * Addendum, Appendix C: Card Detection Switch"). So reschedule a
+ * detect work 200ms later for this case.
+ */
+ if (!ret && host->ops->get_cd && !host->ops->get_cd(host)) {
+ mmc_detect_change(host, msecs_to_jiffies(200));
+ pr_debug("%s: card removed too slowly\n", mmc_hostname(host));
+ }
+
if (ret) {
mmc_card_set_removed(host->card);
pr_debug("%s: card remove detected\n", mmc_hostname(host));
@@ -2403,7 +2416,10 @@ void mmc_start_host(struct mmc_host *host)
{
host->f_init = max(freqs[0], host->f_min);
host->rescan_disable = 0;
- mmc_power_up(host);
+ if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
+ mmc_power_off(host);
+ else
+ mmc_power_up(host);
mmc_detect_change(host, 0);
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index c8f3d6e0684e..0cbd1effe960 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -96,6 +96,7 @@ static int mmc_decode_cid(struct mmc_card *card)
card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
+ card->cid.prv = UNSTUFF_BITS(resp, 48, 8);
card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
@@ -368,13 +369,13 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
card->ext_csd.raw_trim_mult =
ext_csd[EXT_CSD_TRIM_MULT];
+ card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if (card->ext_csd.rev >= 4) {
/*
* Enhanced area feature support -- check whether the eMMC
* card has the Enhanced area enabled. If so, export enhanced
* area offset and size to user by adding sysfs interface.
*/
- card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
hc_erase_grp_sz =
@@ -627,6 +628,7 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
card->ext_csd.enhanced_area_offset);
@@ -645,6 +647,7 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_manfid.attr,
&dev_attr_name.attr,
&dev_attr_oemid.attr,
+ &dev_attr_prv.attr,
&dev_attr_serial.attr,
&dev_attr_enhanced_area_offset.attr,
&dev_attr_enhanced_area_size.attr,
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index aa0719a4dfd1..6889a821c1da 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -861,8 +861,10 @@ static void mmc_sdio_detect(struct mmc_host *host)
/* Make sure card is powered before detecting it */
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
err = pm_runtime_get_sync(&host->card->dev);
- if (err < 0)
+ if (err < 0) {
+ pm_runtime_put_noidle(&host->card->dev);
goto out;
+ }
}
mmc_claim_host(host);
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 5e57048e2c1d..546c67c2bbbf 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
+#include <linux/acpi.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -137,7 +138,7 @@ static int sdio_bus_probe(struct device *dev)
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
ret = pm_runtime_get_sync(dev);
if (ret < 0)
- goto out;
+ goto disable_runtimepm;
}
/* Set the default block size so the driver is sure it's something
@@ -157,7 +158,6 @@ static int sdio_bus_probe(struct device *dev)
disable_runtimepm:
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_noidle(dev);
-out:
return ret;
}
@@ -299,6 +299,19 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
return func;
}
+#ifdef CONFIG_ACPI
+static void sdio_acpi_set_handle(struct sdio_func *func)
+{
+ struct mmc_host *host = func->card->host;
+ u64 addr = (host->slotno << 16) | func->num;
+
+ ACPI_HANDLE_SET(&func->dev,
+ acpi_get_child(ACPI_HANDLE(host->parent), addr));
+}
+#else
+static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
+#endif
+
/*
* Register a new SDIO function with the driver model.
*/
@@ -308,9 +321,12 @@ int sdio_add_func(struct sdio_func *func)
dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
+ sdio_acpi_set_handle(func);
ret = device_add(&func->dev);
- if (ret == 0)
+ if (ret == 0) {
sdio_func_set_present(func);
+ acpi_dev_pm_attach(&func->dev, false);
+ }
return ret;
}
@@ -326,6 +342,7 @@ void sdio_remove_func(struct sdio_func *func)
if (!sdio_func_present(func))
return;
+ acpi_dev_pm_detach(&func->dev, false);
device_del(&func->dev);
put_device(&func->dev);
}