diff options
Diffstat (limited to 'drivers/mmc/core')
| -rw-r--r-- | drivers/mmc/core/Makefile | 4 | ||||
| -rw-r--r-- | drivers/mmc/core/bus.c | 58 | ||||
| -rw-r--r-- | drivers/mmc/core/bus.h | 2 | ||||
| -rw-r--r-- | drivers/mmc/core/core.c | 179 | ||||
| -rw-r--r-- | drivers/mmc/core/core.h | 7 | ||||
| -rw-r--r-- | drivers/mmc/core/debugfs.c | 35 | ||||
| -rw-r--r-- | drivers/mmc/core/host.c | 3 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc.c | 58 | ||||
| -rw-r--r-- | drivers/mmc/core/sd.c | 10 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio.c | 54 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio_bus.c | 85 |
11 files changed, 386 insertions, 109 deletions
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 889e5f898f6f..86b479119332 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile | |||
| @@ -2,10 +2,6 @@ | |||
| 2 | # Makefile for the kernel mmc core. | 2 | # Makefile for the kernel mmc core. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | ifeq ($(CONFIG_MMC_DEBUG),y) | ||
| 6 | EXTRA_CFLAGS += -DDEBUG | ||
| 7 | endif | ||
| 8 | |||
| 9 | obj-$(CONFIG_MMC) += mmc_core.o | 5 | obj-$(CONFIG_MMC) += mmc_core.o |
| 10 | mmc_core-y := core.o bus.o host.o \ | 6 | mmc_core-y := core.o bus.o host.o \ |
| 11 | mmc.o mmc_ops.o sd.o sd_ops.o \ | 7 | mmc.o mmc_ops.o sd.o sd_ops.o \ |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 7cd9749dc21d..af8dc6a2a317 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/pm_runtime.h> | ||
| 17 | 18 | ||
| 18 | #include <linux/mmc/card.h> | 19 | #include <linux/mmc/card.h> |
| 19 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
| @@ -22,13 +23,12 @@ | |||
| 22 | #include "sdio_cis.h" | 23 | #include "sdio_cis.h" |
| 23 | #include "bus.h" | 24 | #include "bus.h" |
| 24 | 25 | ||
| 25 | #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) | ||
| 26 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) | 26 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) |
| 27 | 27 | ||
| 28 | static ssize_t mmc_type_show(struct device *dev, | 28 | static ssize_t mmc_type_show(struct device *dev, |
| 29 | struct device_attribute *attr, char *buf) | 29 | struct device_attribute *attr, char *buf) |
| 30 | { | 30 | { |
| 31 | struct mmc_card *card = dev_to_mmc_card(dev); | 31 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 32 | 32 | ||
| 33 | switch (card->type) { | 33 | switch (card->type) { |
| 34 | case MMC_TYPE_MMC: | 34 | case MMC_TYPE_MMC: |
| @@ -62,7 +62,7 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv) | |||
| 62 | static int | 62 | static int |
| 63 | mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | 63 | mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 64 | { | 64 | { |
| 65 | struct mmc_card *card = dev_to_mmc_card(dev); | 65 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 66 | const char *type; | 66 | const char *type; |
| 67 | int retval = 0; | 67 | int retval = 0; |
| 68 | 68 | ||
| @@ -105,7 +105,7 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 105 | static int mmc_bus_probe(struct device *dev) | 105 | static int mmc_bus_probe(struct device *dev) |
| 106 | { | 106 | { |
| 107 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 107 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 108 | struct mmc_card *card = dev_to_mmc_card(dev); | 108 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 109 | 109 | ||
| 110 | return drv->probe(card); | 110 | return drv->probe(card); |
| 111 | } | 111 | } |
| @@ -113,7 +113,7 @@ static int mmc_bus_probe(struct device *dev) | |||
| 113 | static int mmc_bus_remove(struct device *dev) | 113 | static int mmc_bus_remove(struct device *dev) |
| 114 | { | 114 | { |
| 115 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 115 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 116 | struct mmc_card *card = dev_to_mmc_card(dev); | 116 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 117 | 117 | ||
| 118 | drv->remove(card); | 118 | drv->remove(card); |
| 119 | 119 | ||
| @@ -123,7 +123,7 @@ static int mmc_bus_remove(struct device *dev) | |||
| 123 | static int mmc_bus_suspend(struct device *dev, pm_message_t state) | 123 | static int mmc_bus_suspend(struct device *dev, pm_message_t state) |
| 124 | { | 124 | { |
| 125 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 125 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 126 | struct mmc_card *card = dev_to_mmc_card(dev); | 126 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 127 | int ret = 0; | 127 | int ret = 0; |
| 128 | 128 | ||
| 129 | if (dev->driver && drv->suspend) | 129 | if (dev->driver && drv->suspend) |
| @@ -134,7 +134,7 @@ static int mmc_bus_suspend(struct device *dev, pm_message_t state) | |||
| 134 | static int mmc_bus_resume(struct device *dev) | 134 | static int mmc_bus_resume(struct device *dev) |
| 135 | { | 135 | { |
| 136 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 136 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 137 | struct mmc_card *card = dev_to_mmc_card(dev); | 137 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 138 | int ret = 0; | 138 | int ret = 0; |
| 139 | 139 | ||
| 140 | if (dev->driver && drv->resume) | 140 | if (dev->driver && drv->resume) |
| @@ -142,6 +142,41 @@ static int mmc_bus_resume(struct device *dev) | |||
| 142 | return ret; | 142 | return ret; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | #ifdef CONFIG_PM_RUNTIME | ||
| 146 | |||
| 147 | static int mmc_runtime_suspend(struct device *dev) | ||
| 148 | { | ||
| 149 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
| 150 | |||
| 151 | return mmc_power_save_host(card->host); | ||
| 152 | } | ||
| 153 | |||
| 154 | static int mmc_runtime_resume(struct device *dev) | ||
| 155 | { | ||
| 156 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
| 157 | |||
| 158 | return mmc_power_restore_host(card->host); | ||
| 159 | } | ||
| 160 | |||
| 161 | static int mmc_runtime_idle(struct device *dev) | ||
| 162 | { | ||
| 163 | return pm_runtime_suspend(dev); | ||
| 164 | } | ||
| 165 | |||
| 166 | static const struct dev_pm_ops mmc_bus_pm_ops = { | ||
| 167 | .runtime_suspend = mmc_runtime_suspend, | ||
| 168 | .runtime_resume = mmc_runtime_resume, | ||
| 169 | .runtime_idle = mmc_runtime_idle, | ||
| 170 | }; | ||
| 171 | |||
| 172 | #define MMC_PM_OPS_PTR (&mmc_bus_pm_ops) | ||
| 173 | |||
| 174 | #else /* !CONFIG_PM_RUNTIME */ | ||
| 175 | |||
| 176 | #define MMC_PM_OPS_PTR NULL | ||
| 177 | |||
| 178 | #endif /* !CONFIG_PM_RUNTIME */ | ||
| 179 | |||
| 145 | static struct bus_type mmc_bus_type = { | 180 | static struct bus_type mmc_bus_type = { |
| 146 | .name = "mmc", | 181 | .name = "mmc", |
| 147 | .dev_attrs = mmc_dev_attrs, | 182 | .dev_attrs = mmc_dev_attrs, |
| @@ -151,6 +186,7 @@ static struct bus_type mmc_bus_type = { | |||
| 151 | .remove = mmc_bus_remove, | 186 | .remove = mmc_bus_remove, |
| 152 | .suspend = mmc_bus_suspend, | 187 | .suspend = mmc_bus_suspend, |
| 153 | .resume = mmc_bus_resume, | 188 | .resume = mmc_bus_resume, |
| 189 | .pm = MMC_PM_OPS_PTR, | ||
| 154 | }; | 190 | }; |
| 155 | 191 | ||
| 156 | int mmc_register_bus(void) | 192 | int mmc_register_bus(void) |
| @@ -189,7 +225,7 @@ EXPORT_SYMBOL(mmc_unregister_driver); | |||
| 189 | 225 | ||
| 190 | static void mmc_release_card(struct device *dev) | 226 | static void mmc_release_card(struct device *dev) |
| 191 | { | 227 | { |
| 192 | struct mmc_card *card = dev_to_mmc_card(dev); | 228 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 193 | 229 | ||
| 194 | sdio_free_common_cis(card); | 230 | sdio_free_common_cis(card); |
| 195 | 231 | ||
| @@ -254,14 +290,16 @@ int mmc_add_card(struct mmc_card *card) | |||
| 254 | } | 290 | } |
| 255 | 291 | ||
| 256 | if (mmc_host_is_spi(card->host)) { | 292 | if (mmc_host_is_spi(card->host)) { |
| 257 | printk(KERN_INFO "%s: new %s%s card on SPI\n", | 293 | printk(KERN_INFO "%s: new %s%s%s card on SPI\n", |
| 258 | mmc_hostname(card->host), | 294 | mmc_hostname(card->host), |
| 259 | mmc_card_highspeed(card) ? "high speed " : "", | 295 | mmc_card_highspeed(card) ? "high speed " : "", |
| 296 | mmc_card_ddr_mode(card) ? "DDR " : "", | ||
| 260 | type); | 297 | type); |
| 261 | } else { | 298 | } else { |
| 262 | printk(KERN_INFO "%s: new %s%s card at address %04x\n", | 299 | printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", |
| 263 | mmc_hostname(card->host), | 300 | mmc_hostname(card->host), |
| 264 | mmc_card_highspeed(card) ? "high speed " : "", | 301 | mmc_card_highspeed(card) ? "high speed " : "", |
| 302 | mmc_card_ddr_mode(card) ? "DDR " : "", | ||
| 265 | type, card->rca); | 303 | type, card->rca); |
| 266 | } | 304 | } |
| 267 | 305 | ||
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h index 18178766ab46..00a19710b6b4 100644 --- a/drivers/mmc/core/bus.h +++ b/drivers/mmc/core/bus.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #define MMC_DEV_ATTR(name, fmt, args...) \ | 14 | #define MMC_DEV_ATTR(name, fmt, args...) \ |
| 15 | static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ | 15 | static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ |
| 16 | { \ | 16 | { \ |
| 17 | struct mmc_card *card = container_of(dev, struct mmc_card, dev); \ | 17 | struct mmc_card *card = mmc_dev_to_card(dev); \ |
| 18 | return sprintf(buf, fmt, args); \ | 18 | return sprintf(buf, fmt, args); \ |
| 19 | } \ | 19 | } \ |
| 20 | static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL) | 20 | static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL) |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 09eee6df0653..8f86d702e46e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -58,6 +58,7 @@ int mmc_assume_removable; | |||
| 58 | #else | 58 | #else |
| 59 | int mmc_assume_removable = 1; | 59 | int mmc_assume_removable = 1; |
| 60 | #endif | 60 | #endif |
| 61 | EXPORT_SYMBOL(mmc_assume_removable); | ||
| 61 | module_param_named(removable, mmc_assume_removable, bool, 0644); | 62 | module_param_named(removable, mmc_assume_removable, bool, 0644); |
| 62 | MODULE_PARM_DESC( | 63 | MODULE_PARM_DESC( |
| 63 | removable, | 64 | removable, |
| @@ -650,14 +651,24 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) | |||
| 650 | } | 651 | } |
| 651 | 652 | ||
| 652 | /* | 653 | /* |
| 653 | * Change data bus width of a host. | 654 | * Change data bus width and DDR mode of a host. |
| 654 | */ | 655 | */ |
| 655 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width) | 656 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, |
| 657 | unsigned int ddr) | ||
| 656 | { | 658 | { |
| 657 | host->ios.bus_width = width; | 659 | host->ios.bus_width = width; |
| 660 | host->ios.ddr = ddr; | ||
| 658 | mmc_set_ios(host); | 661 | mmc_set_ios(host); |
| 659 | } | 662 | } |
| 660 | 663 | ||
| 664 | /* | ||
| 665 | * Change data bus width of a host. | ||
| 666 | */ | ||
| 667 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width) | ||
| 668 | { | ||
| 669 | mmc_set_bus_width_ddr(host, width, MMC_SDR_MODE); | ||
| 670 | } | ||
| 671 | |||
| 661 | /** | 672 | /** |
| 662 | * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number | 673 | * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number |
| 663 | * @vdd: voltage (mV) | 674 | * @vdd: voltage (mV) |
| @@ -771,8 +782,9 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask); | |||
| 771 | 782 | ||
| 772 | /** | 783 | /** |
| 773 | * mmc_regulator_set_ocr - set regulator to match host->ios voltage | 784 | * mmc_regulator_set_ocr - set regulator to match host->ios voltage |
| 774 | * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) | 785 | * @mmc: the host to regulate |
| 775 | * @supply: regulator to use | 786 | * @supply: regulator to use |
| 787 | * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) | ||
| 776 | * | 788 | * |
| 777 | * Returns zero on success, else negative errno. | 789 | * Returns zero on success, else negative errno. |
| 778 | * | 790 | * |
| @@ -780,15 +792,12 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask); | |||
| 780 | * a particular supply voltage. This would normally be called from the | 792 | * a particular supply voltage. This would normally be called from the |
| 781 | * set_ios() method. | 793 | * set_ios() method. |
| 782 | */ | 794 | */ |
| 783 | int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit) | 795 | int mmc_regulator_set_ocr(struct mmc_host *mmc, |
| 796 | struct regulator *supply, | ||
| 797 | unsigned short vdd_bit) | ||
| 784 | { | 798 | { |
| 785 | int result = 0; | 799 | int result = 0; |
| 786 | int min_uV, max_uV; | 800 | int min_uV, max_uV; |
| 787 | int enabled; | ||
| 788 | |||
| 789 | enabled = regulator_is_enabled(supply); | ||
| 790 | if (enabled < 0) | ||
| 791 | return enabled; | ||
| 792 | 801 | ||
| 793 | if (vdd_bit) { | 802 | if (vdd_bit) { |
| 794 | int tmp; | 803 | int tmp; |
| @@ -819,17 +828,25 @@ int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit) | |||
| 819 | else | 828 | else |
| 820 | result = 0; | 829 | result = 0; |
| 821 | 830 | ||
| 822 | if (result == 0 && !enabled) | 831 | if (result == 0 && !mmc->regulator_enabled) { |
| 823 | result = regulator_enable(supply); | 832 | result = regulator_enable(supply); |
| 824 | } else if (enabled) { | 833 | if (!result) |
| 834 | mmc->regulator_enabled = true; | ||
| 835 | } | ||
| 836 | } else if (mmc->regulator_enabled) { | ||
| 825 | result = regulator_disable(supply); | 837 | result = regulator_disable(supply); |
| 838 | if (result == 0) | ||
| 839 | mmc->regulator_enabled = false; | ||
| 826 | } | 840 | } |
| 827 | 841 | ||
| 842 | if (result) | ||
| 843 | dev_err(mmc_dev(mmc), | ||
| 844 | "could not set regulator OCR (%d)\n", result); | ||
| 828 | return result; | 845 | return result; |
| 829 | } | 846 | } |
| 830 | EXPORT_SYMBOL(mmc_regulator_set_ocr); | 847 | EXPORT_SYMBOL(mmc_regulator_set_ocr); |
| 831 | 848 | ||
| 832 | #endif | 849 | #endif /* CONFIG_REGULATOR */ |
| 833 | 850 | ||
| 834 | /* | 851 | /* |
| 835 | * Mask off any voltages we don't support and select | 852 | * Mask off any voltages we don't support and select |
| @@ -907,12 +924,7 @@ static void mmc_power_up(struct mmc_host *host) | |||
| 907 | */ | 924 | */ |
| 908 | mmc_delay(10); | 925 | mmc_delay(10); |
| 909 | 926 | ||
| 910 | if (host->f_min > 400000) { | 927 | host->ios.clock = host->f_init; |
| 911 | pr_warning("%s: Minimum clock frequency too high for " | ||
| 912 | "identification mode\n", mmc_hostname(host)); | ||
| 913 | host->ios.clock = host->f_min; | ||
| 914 | } else | ||
| 915 | host->ios.clock = 400000; | ||
| 916 | 928 | ||
| 917 | host->ios.power_mode = MMC_POWER_ON; | 929 | host->ios.power_mode = MMC_POWER_ON; |
| 918 | mmc_set_ios(host); | 930 | mmc_set_ios(host); |
| @@ -1397,6 +1409,21 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | |||
| 1397 | } | 1409 | } |
| 1398 | EXPORT_SYMBOL(mmc_erase_group_aligned); | 1410 | EXPORT_SYMBOL(mmc_erase_group_aligned); |
| 1399 | 1411 | ||
| 1412 | int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) | ||
| 1413 | { | ||
| 1414 | struct mmc_command cmd; | ||
| 1415 | |||
| 1416 | if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) | ||
| 1417 | return 0; | ||
| 1418 | |||
| 1419 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
| 1420 | cmd.opcode = MMC_SET_BLOCKLEN; | ||
| 1421 | cmd.arg = blocklen; | ||
| 1422 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
| 1423 | return mmc_wait_for_cmd(card->host, &cmd, 5); | ||
| 1424 | } | ||
| 1425 | EXPORT_SYMBOL(mmc_set_blocklen); | ||
| 1426 | |||
| 1400 | void mmc_rescan(struct work_struct *work) | 1427 | void mmc_rescan(struct work_struct *work) |
| 1401 | { | 1428 | { |
| 1402 | struct mmc_host *host = | 1429 | struct mmc_host *host = |
| @@ -1404,6 +1431,8 @@ void mmc_rescan(struct work_struct *work) | |||
| 1404 | u32 ocr; | 1431 | u32 ocr; |
| 1405 | int err; | 1432 | int err; |
| 1406 | unsigned long flags; | 1433 | unsigned long flags; |
| 1434 | int i; | ||
| 1435 | const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; | ||
| 1407 | 1436 | ||
| 1408 | spin_lock_irqsave(&host->lock, flags); | 1437 | spin_lock_irqsave(&host->lock, flags); |
| 1409 | 1438 | ||
| @@ -1443,55 +1472,71 @@ void mmc_rescan(struct work_struct *work) | |||
| 1443 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) | 1472 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) |
| 1444 | goto out; | 1473 | goto out; |
| 1445 | 1474 | ||
| 1446 | mmc_claim_host(host); | 1475 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { |
| 1476 | mmc_claim_host(host); | ||
| 1447 | 1477 | ||
| 1448 | mmc_power_up(host); | 1478 | if (freqs[i] >= host->f_min) |
| 1449 | sdio_reset(host); | 1479 | host->f_init = freqs[i]; |
| 1450 | mmc_go_idle(host); | 1480 | else if (!i || freqs[i-1] > host->f_min) |
| 1481 | host->f_init = host->f_min; | ||
| 1482 | else { | ||
| 1483 | mmc_release_host(host); | ||
| 1484 | goto out; | ||
| 1485 | } | ||
| 1486 | #ifdef CONFIG_MMC_DEBUG | ||
| 1487 | pr_info("%s: %s: trying to init card at %u Hz\n", | ||
| 1488 | mmc_hostname(host), __func__, host->f_init); | ||
| 1489 | #endif | ||
| 1490 | mmc_power_up(host); | ||
| 1491 | sdio_reset(host); | ||
| 1492 | mmc_go_idle(host); | ||
| 1451 | 1493 | ||
| 1452 | mmc_send_if_cond(host, host->ocr_avail); | 1494 | mmc_send_if_cond(host, host->ocr_avail); |
| 1453 | 1495 | ||
| 1454 | /* | 1496 | /* |
| 1455 | * First we search for SDIO... | 1497 | * First we search for SDIO... |
| 1456 | */ | 1498 | */ |
| 1457 | err = mmc_send_io_op_cond(host, 0, &ocr); | 1499 | err = mmc_send_io_op_cond(host, 0, &ocr); |
| 1458 | if (!err) { | 1500 | if (!err) { |
| 1459 | if (mmc_attach_sdio(host, ocr)) { | 1501 | if (mmc_attach_sdio(host, ocr)) { |
| 1460 | mmc_claim_host(host); | 1502 | mmc_claim_host(host); |
| 1461 | /* try SDMEM (but not MMC) even if SDIO is broken */ | 1503 | /* |
| 1462 | if (mmc_send_app_op_cond(host, 0, &ocr)) | 1504 | * Try SDMEM (but not MMC) even if SDIO |
| 1463 | goto out_fail; | 1505 | * is broken. |
| 1506 | */ | ||
| 1507 | if (mmc_send_app_op_cond(host, 0, &ocr)) | ||
| 1508 | goto out_fail; | ||
| 1509 | |||
| 1510 | if (mmc_attach_sd(host, ocr)) | ||
| 1511 | mmc_power_off(host); | ||
| 1512 | } | ||
| 1513 | goto out; | ||
| 1514 | } | ||
| 1464 | 1515 | ||
| 1516 | /* | ||
| 1517 | * ...then normal SD... | ||
| 1518 | */ | ||
| 1519 | err = mmc_send_app_op_cond(host, 0, &ocr); | ||
| 1520 | if (!err) { | ||
| 1465 | if (mmc_attach_sd(host, ocr)) | 1521 | if (mmc_attach_sd(host, ocr)) |
| 1466 | mmc_power_off(host); | 1522 | mmc_power_off(host); |
| 1523 | goto out; | ||
| 1467 | } | 1524 | } |
| 1468 | goto out; | ||
| 1469 | } | ||
| 1470 | 1525 | ||
| 1471 | /* | 1526 | /* |
| 1472 | * ...then normal SD... | 1527 | * ...and finally MMC. |
| 1473 | */ | 1528 | */ |
| 1474 | err = mmc_send_app_op_cond(host, 0, &ocr); | 1529 | err = mmc_send_op_cond(host, 0, &ocr); |
| 1475 | if (!err) { | 1530 | if (!err) { |
| 1476 | if (mmc_attach_sd(host, ocr)) | 1531 | if (mmc_attach_mmc(host, ocr)) |
| 1477 | mmc_power_off(host); | 1532 | mmc_power_off(host); |
| 1478 | goto out; | 1533 | goto out; |
| 1479 | } | 1534 | } |
| 1480 | |||
| 1481 | /* | ||
| 1482 | * ...and finally MMC. | ||
| 1483 | */ | ||
| 1484 | err = mmc_send_op_cond(host, 0, &ocr); | ||
| 1485 | if (!err) { | ||
| 1486 | if (mmc_attach_mmc(host, ocr)) | ||
| 1487 | mmc_power_off(host); | ||
| 1488 | goto out; | ||
| 1489 | } | ||
| 1490 | 1535 | ||
| 1491 | out_fail: | 1536 | out_fail: |
| 1492 | mmc_release_host(host); | 1537 | mmc_release_host(host); |
| 1493 | mmc_power_off(host); | 1538 | mmc_power_off(host); |
| 1494 | 1539 | } | |
| 1495 | out: | 1540 | out: |
| 1496 | if (host->caps & MMC_CAP_NEEDS_POLL) | 1541 | if (host->caps & MMC_CAP_NEEDS_POLL) |
| 1497 | mmc_schedule_delayed_work(&host->detect, HZ); | 1542 | mmc_schedule_delayed_work(&host->detect, HZ); |
| @@ -1538,37 +1583,45 @@ void mmc_stop_host(struct mmc_host *host) | |||
| 1538 | mmc_power_off(host); | 1583 | mmc_power_off(host); |
| 1539 | } | 1584 | } |
| 1540 | 1585 | ||
| 1541 | void mmc_power_save_host(struct mmc_host *host) | 1586 | int mmc_power_save_host(struct mmc_host *host) |
| 1542 | { | 1587 | { |
| 1588 | int ret = 0; | ||
| 1589 | |||
| 1543 | mmc_bus_get(host); | 1590 | mmc_bus_get(host); |
| 1544 | 1591 | ||
| 1545 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { | 1592 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { |
| 1546 | mmc_bus_put(host); | 1593 | mmc_bus_put(host); |
| 1547 | return; | 1594 | return -EINVAL; |
| 1548 | } | 1595 | } |
| 1549 | 1596 | ||
| 1550 | if (host->bus_ops->power_save) | 1597 | if (host->bus_ops->power_save) |
| 1551 | host->bus_ops->power_save(host); | 1598 | ret = host->bus_ops->power_save(host); |
| 1552 | 1599 | ||
| 1553 | mmc_bus_put(host); | 1600 | mmc_bus_put(host); |
| 1554 | 1601 | ||
| 1555 | mmc_power_off(host); | 1602 | mmc_power_off(host); |
| 1603 | |||
| 1604 | return ret; | ||
| 1556 | } | 1605 | } |
| 1557 | EXPORT_SYMBOL(mmc_power_save_host); | 1606 | EXPORT_SYMBOL(mmc_power_save_host); |
| 1558 | 1607 | ||
| 1559 | void mmc_power_restore_host(struct mmc_host *host) | 1608 | int mmc_power_restore_host(struct mmc_host *host) |
| 1560 | { | 1609 | { |
| 1610 | int ret; | ||
| 1611 | |||
| 1561 | mmc_bus_get(host); | 1612 | mmc_bus_get(host); |
| 1562 | 1613 | ||
| 1563 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { | 1614 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { |
| 1564 | mmc_bus_put(host); | 1615 | mmc_bus_put(host); |
| 1565 | return; | 1616 | return -EINVAL; |
| 1566 | } | 1617 | } |
| 1567 | 1618 | ||
| 1568 | mmc_power_up(host); | 1619 | mmc_power_up(host); |
| 1569 | host->bus_ops->power_restore(host); | 1620 | ret = host->bus_ops->power_restore(host); |
| 1570 | 1621 | ||
| 1571 | mmc_bus_put(host); | 1622 | mmc_bus_put(host); |
| 1623 | |||
| 1624 | return ret; | ||
| 1572 | } | 1625 | } |
| 1573 | EXPORT_SYMBOL(mmc_power_restore_host); | 1626 | EXPORT_SYMBOL(mmc_power_restore_host); |
| 1574 | 1627 | ||
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 9d9eef50e5d1..77240cd11bcf 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
| @@ -22,8 +22,8 @@ struct mmc_bus_ops { | |||
| 22 | void (*detect)(struct mmc_host *); | 22 | void (*detect)(struct mmc_host *); |
| 23 | int (*suspend)(struct mmc_host *); | 23 | int (*suspend)(struct mmc_host *); |
| 24 | int (*resume)(struct mmc_host *); | 24 | int (*resume)(struct mmc_host *); |
| 25 | void (*power_save)(struct mmc_host *); | 25 | int (*power_save)(struct mmc_host *); |
| 26 | void (*power_restore)(struct mmc_host *); | 26 | int (*power_restore)(struct mmc_host *); |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); | 29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); |
| @@ -35,6 +35,8 @@ void mmc_set_chip_select(struct mmc_host *host, int mode); | |||
| 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); | 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); |
| 36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); | 36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); |
| 37 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); | 37 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); |
| 38 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, | ||
| 39 | unsigned int ddr); | ||
| 38 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); | 40 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); |
| 39 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); | 41 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); |
| 40 | 42 | ||
| @@ -58,7 +60,6 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr); | |||
| 58 | 60 | ||
| 59 | /* Module parameters */ | 61 | /* Module parameters */ |
| 60 | extern int use_spi_crc; | 62 | extern int use_spi_crc; |
| 61 | extern int mmc_assume_removable; | ||
| 62 | 63 | ||
| 63 | /* Debugfs information for hosts and cards */ | 64 | /* Debugfs information for hosts and cards */ |
| 64 | void mmc_add_host_debugfs(struct mmc_host *host); | 65 | void mmc_add_host_debugfs(struct mmc_host *host); |
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 46bc6d7551a3..eed1405fd742 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
| @@ -134,6 +134,33 @@ static const struct file_operations mmc_ios_fops = { | |||
| 134 | .release = single_release, | 134 | .release = single_release, |
| 135 | }; | 135 | }; |
| 136 | 136 | ||
| 137 | static int mmc_clock_opt_get(void *data, u64 *val) | ||
| 138 | { | ||
| 139 | struct mmc_host *host = data; | ||
| 140 | |||
| 141 | *val = host->ios.clock; | ||
| 142 | |||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | static int mmc_clock_opt_set(void *data, u64 val) | ||
| 147 | { | ||
| 148 | struct mmc_host *host = data; | ||
| 149 | |||
| 150 | /* We need this check due to input value is u64 */ | ||
| 151 | if (val > host->f_max) | ||
| 152 | return -EINVAL; | ||
| 153 | |||
| 154 | mmc_claim_host(host); | ||
| 155 | mmc_set_clock(host, (unsigned int) val); | ||
| 156 | mmc_release_host(host); | ||
| 157 | |||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, | ||
| 162 | "%llu\n"); | ||
| 163 | |||
| 137 | void mmc_add_host_debugfs(struct mmc_host *host) | 164 | void mmc_add_host_debugfs(struct mmc_host *host) |
| 138 | { | 165 | { |
| 139 | struct dentry *root; | 166 | struct dentry *root; |
| @@ -150,11 +177,15 @@ void mmc_add_host_debugfs(struct mmc_host *host) | |||
| 150 | host->debugfs_root = root; | 177 | host->debugfs_root = root; |
| 151 | 178 | ||
| 152 | if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) | 179 | if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) |
| 153 | goto err_ios; | 180 | goto err_node; |
| 181 | |||
| 182 | if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, | ||
| 183 | &mmc_clock_fops)) | ||
| 184 | goto err_node; | ||
| 154 | 185 | ||
| 155 | return; | 186 | return; |
| 156 | 187 | ||
| 157 | err_ios: | 188 | err_node: |
| 158 | debugfs_remove_recursive(root); | 189 | debugfs_remove_recursive(root); |
| 159 | host->debugfs_root = NULL; | 190 | host->debugfs_root = NULL; |
| 160 | err_root: | 191 | err_root: |
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index d80cfdc8edd2..10b8af27e03a 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
| @@ -94,8 +94,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
| 94 | * By default, hosts do not support SGIO or large requests. | 94 | * By default, hosts do not support SGIO or large requests. |
| 95 | * They have to set these according to their abilities. | 95 | * They have to set these according to their abilities. |
| 96 | */ | 96 | */ |
| 97 | host->max_hw_segs = 1; | 97 | host->max_segs = 1; |
| 98 | host->max_phys_segs = 1; | ||
| 99 | host->max_seg_size = PAGE_CACHE_SIZE; | 98 | host->max_seg_size = PAGE_CACHE_SIZE; |
| 100 | 99 | ||
| 101 | host->max_req_size = PAGE_CACHE_SIZE; | 100 | host->max_req_size = PAGE_CACHE_SIZE; |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6909a54c39be..995261f7fd70 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -258,6 +258,21 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { | 260 | switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { |
| 261 | case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | | ||
| 262 | EXT_CSD_CARD_TYPE_26: | ||
| 263 | card->ext_csd.hs_max_dtr = 52000000; | ||
| 264 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; | ||
| 265 | break; | ||
| 266 | case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | | ||
| 267 | EXT_CSD_CARD_TYPE_26: | ||
| 268 | card->ext_csd.hs_max_dtr = 52000000; | ||
| 269 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; | ||
| 270 | break; | ||
| 271 | case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | | ||
| 272 | EXT_CSD_CARD_TYPE_26: | ||
| 273 | card->ext_csd.hs_max_dtr = 52000000; | ||
| 274 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; | ||
| 275 | break; | ||
| 261 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: | 276 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: |
| 262 | card->ext_csd.hs_max_dtr = 52000000; | 277 | card->ext_csd.hs_max_dtr = 52000000; |
| 263 | break; | 278 | break; |
| @@ -360,7 +375,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 360 | struct mmc_card *oldcard) | 375 | struct mmc_card *oldcard) |
| 361 | { | 376 | { |
| 362 | struct mmc_card *card; | 377 | struct mmc_card *card; |
| 363 | int err; | 378 | int err, ddr = MMC_SDR_MODE; |
| 364 | u32 cid[4]; | 379 | u32 cid[4]; |
| 365 | unsigned int max_dtr; | 380 | unsigned int max_dtr; |
| 366 | 381 | ||
| @@ -503,17 +518,35 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 503 | mmc_set_clock(host, max_dtr); | 518 | mmc_set_clock(host, max_dtr); |
| 504 | 519 | ||
| 505 | /* | 520 | /* |
| 506 | * Activate wide bus (if supported). | 521 | * Indicate DDR mode (if supported). |
| 522 | */ | ||
| 523 | if (mmc_card_highspeed(card)) { | ||
| 524 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) | ||
| 525 | && (host->caps & (MMC_CAP_1_8V_DDR))) | ||
| 526 | ddr = MMC_1_8V_DDR_MODE; | ||
| 527 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) | ||
| 528 | && (host->caps & (MMC_CAP_1_2V_DDR))) | ||
| 529 | ddr = MMC_1_2V_DDR_MODE; | ||
| 530 | } | ||
| 531 | |||
| 532 | /* | ||
| 533 | * Activate wide bus and DDR (if supported). | ||
| 507 | */ | 534 | */ |
| 508 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && | 535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && |
| 509 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { | 536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { |
| 510 | unsigned ext_csd_bit, bus_width; | 537 | unsigned ext_csd_bit, bus_width; |
| 511 | 538 | ||
| 512 | if (host->caps & MMC_CAP_8_BIT_DATA) { | 539 | if (host->caps & MMC_CAP_8_BIT_DATA) { |
| 513 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | 540 | if (ddr) |
| 541 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; | ||
| 542 | else | ||
| 543 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | ||
| 514 | bus_width = MMC_BUS_WIDTH_8; | 544 | bus_width = MMC_BUS_WIDTH_8; |
| 515 | } else { | 545 | } else { |
| 516 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | 546 | if (ddr) |
| 547 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; | ||
| 548 | else | ||
| 549 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | ||
| 517 | bus_width = MMC_BUS_WIDTH_4; | 550 | bus_width = MMC_BUS_WIDTH_4; |
| 518 | } | 551 | } |
| 519 | 552 | ||
| @@ -524,12 +557,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 524 | goto free_card; | 557 | goto free_card; |
| 525 | 558 | ||
| 526 | if (err) { | 559 | if (err) { |
| 527 | printk(KERN_WARNING "%s: switch to bus width %d " | 560 | printk(KERN_WARNING "%s: switch to bus width %d ddr %d " |
| 528 | "failed\n", mmc_hostname(card->host), | 561 | "failed\n", mmc_hostname(card->host), |
| 529 | 1 << bus_width); | 562 | 1 << bus_width, ddr); |
| 530 | err = 0; | 563 | err = 0; |
| 531 | } else { | 564 | } else { |
| 532 | mmc_set_bus_width(card->host, bus_width); | 565 | mmc_card_set_ddr_mode(card); |
| 566 | mmc_set_bus_width_ddr(card->host, bus_width, ddr); | ||
| 533 | } | 567 | } |
| 534 | } | 568 | } |
| 535 | 569 | ||
| @@ -623,12 +657,16 @@ static int mmc_resume(struct mmc_host *host) | |||
| 623 | return err; | 657 | return err; |
| 624 | } | 658 | } |
| 625 | 659 | ||
| 626 | static void mmc_power_restore(struct mmc_host *host) | 660 | static int mmc_power_restore(struct mmc_host *host) |
| 627 | { | 661 | { |
| 662 | int ret; | ||
| 663 | |||
| 628 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 664 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
| 629 | mmc_claim_host(host); | 665 | mmc_claim_host(host); |
| 630 | mmc_init_card(host, host->ocr, host->card); | 666 | ret = mmc_init_card(host, host->ocr, host->card); |
| 631 | mmc_release_host(host); | 667 | mmc_release_host(host); |
| 668 | |||
| 669 | return ret; | ||
| 632 | } | 670 | } |
| 633 | 671 | ||
| 634 | static int mmc_sleep(struct mmc_host *host) | 672 | static int mmc_sleep(struct mmc_host *host) |
| @@ -685,7 +723,7 @@ static void mmc_attach_bus_ops(struct mmc_host *host) | |||
| 685 | { | 723 | { |
| 686 | const struct mmc_bus_ops *bus_ops; | 724 | const struct mmc_bus_ops *bus_ops; |
| 687 | 725 | ||
| 688 | if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable) | 726 | if (!mmc_card_is_removable(host)) |
| 689 | bus_ops = &mmc_ops_unsafe; | 727 | bus_ops = &mmc_ops_unsafe; |
| 690 | else | 728 | else |
| 691 | bus_ops = &mmc_ops; | 729 | bus_ops = &mmc_ops; |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 0f5241085557..49da4dffd28e 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -722,12 +722,16 @@ static int mmc_sd_resume(struct mmc_host *host) | |||
| 722 | return err; | 722 | return err; |
| 723 | } | 723 | } |
| 724 | 724 | ||
| 725 | static void mmc_sd_power_restore(struct mmc_host *host) | 725 | static int mmc_sd_power_restore(struct mmc_host *host) |
| 726 | { | 726 | { |
| 727 | int ret; | ||
| 728 | |||
| 727 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 729 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
| 728 | mmc_claim_host(host); | 730 | mmc_claim_host(host); |
| 729 | mmc_sd_init_card(host, host->ocr, host->card); | 731 | ret = mmc_sd_init_card(host, host->ocr, host->card); |
| 730 | mmc_release_host(host); | 732 | mmc_release_host(host); |
| 733 | |||
| 734 | return ret; | ||
| 731 | } | 735 | } |
| 732 | 736 | ||
| 733 | static const struct mmc_bus_ops mmc_sd_ops = { | 737 | static const struct mmc_bus_ops mmc_sd_ops = { |
| @@ -750,7 +754,7 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) | |||
| 750 | { | 754 | { |
| 751 | const struct mmc_bus_ops *bus_ops; | 755 | const struct mmc_bus_ops *bus_ops; |
| 752 | 756 | ||
| 753 | if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable) | 757 | if (!mmc_card_is_removable(host)) |
| 754 | bus_ops = &mmc_sd_ops_unsafe; | 758 | bus_ops = &mmc_sd_ops_unsafe; |
| 755 | else | 759 | else |
| 756 | bus_ops = &mmc_sd_ops; | 760 | bus_ops = &mmc_sd_ops; |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index f332c52968b7..c3ad1058cd31 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
| 13 | #include <linux/pm_runtime.h> | ||
| 13 | 14 | ||
| 14 | #include <linux/mmc/host.h> | 15 | #include <linux/mmc/host.h> |
| 15 | #include <linux/mmc/card.h> | 16 | #include <linux/mmc/card.h> |
| @@ -456,7 +457,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 456 | return -ENOENT; | 457 | return -ENOENT; |
| 457 | 458 | ||
| 458 | card = oldcard; | 459 | card = oldcard; |
| 459 | return 0; | ||
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | if (card->type == MMC_TYPE_SD_COMBO) { | 462 | if (card->type == MMC_TYPE_SD_COMBO) { |
| @@ -546,6 +546,11 @@ static void mmc_sdio_detect(struct mmc_host *host) | |||
| 546 | BUG_ON(!host); | 546 | BUG_ON(!host); |
| 547 | BUG_ON(!host->card); | 547 | BUG_ON(!host->card); |
| 548 | 548 | ||
| 549 | /* Make sure card is powered before detecting it */ | ||
| 550 | err = pm_runtime_get_sync(&host->card->dev); | ||
| 551 | if (err < 0) | ||
| 552 | goto out; | ||
| 553 | |||
| 549 | mmc_claim_host(host); | 554 | mmc_claim_host(host); |
| 550 | 555 | ||
| 551 | /* | 556 | /* |
| @@ -555,6 +560,7 @@ static void mmc_sdio_detect(struct mmc_host *host) | |||
| 555 | 560 | ||
| 556 | mmc_release_host(host); | 561 | mmc_release_host(host); |
| 557 | 562 | ||
| 563 | out: | ||
| 558 | if (err) { | 564 | if (err) { |
| 559 | mmc_sdio_remove(host); | 565 | mmc_sdio_remove(host); |
| 560 | 566 | ||
| @@ -562,6 +568,9 @@ static void mmc_sdio_detect(struct mmc_host *host) | |||
| 562 | mmc_detach_bus(host); | 568 | mmc_detach_bus(host); |
| 563 | mmc_release_host(host); | 569 | mmc_release_host(host); |
| 564 | } | 570 | } |
| 571 | |||
| 572 | /* Tell PM core that we're done */ | ||
| 573 | pm_runtime_put(&host->card->dev); | ||
| 565 | } | 574 | } |
| 566 | 575 | ||
| 567 | /* | 576 | /* |
| @@ -614,14 +623,6 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
| 614 | mmc_claim_host(host); | 623 | mmc_claim_host(host); |
| 615 | err = mmc_sdio_init_card(host, host->ocr, host->card, | 624 | err = mmc_sdio_init_card(host, host->ocr, host->card, |
| 616 | (host->pm_flags & MMC_PM_KEEP_POWER)); | 625 | (host->pm_flags & MMC_PM_KEEP_POWER)); |
| 617 | if (!err) { | ||
| 618 | /* We may have switched to 1-bit mode during suspend. */ | ||
| 619 | err = sdio_enable_4bit_bus(host->card); | ||
| 620 | if (err > 0) { | ||
| 621 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); | ||
| 622 | err = 0; | ||
| 623 | } | ||
| 624 | } | ||
| 625 | if (!err && host->sdio_irqs) | 626 | if (!err && host->sdio_irqs) |
| 626 | mmc_signal_sdio_irq(host); | 627 | mmc_signal_sdio_irq(host); |
| 627 | mmc_release_host(host); | 628 | mmc_release_host(host); |
| @@ -647,11 +648,29 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
| 647 | return err; | 648 | return err; |
| 648 | } | 649 | } |
| 649 | 650 | ||
| 651 | static int mmc_sdio_power_restore(struct mmc_host *host) | ||
| 652 | { | ||
| 653 | int ret; | ||
| 654 | |||
| 655 | BUG_ON(!host); | ||
| 656 | BUG_ON(!host->card); | ||
| 657 | |||
| 658 | mmc_claim_host(host); | ||
| 659 | ret = mmc_sdio_init_card(host, host->ocr, host->card, | ||
| 660 | (host->pm_flags & MMC_PM_KEEP_POWER)); | ||
| 661 | if (!ret && host->sdio_irqs) | ||
| 662 | mmc_signal_sdio_irq(host); | ||
| 663 | mmc_release_host(host); | ||
| 664 | |||
| 665 | return ret; | ||
| 666 | } | ||
| 667 | |||
| 650 | static const struct mmc_bus_ops mmc_sdio_ops = { | 668 | static const struct mmc_bus_ops mmc_sdio_ops = { |
| 651 | .remove = mmc_sdio_remove, | 669 | .remove = mmc_sdio_remove, |
| 652 | .detect = mmc_sdio_detect, | 670 | .detect = mmc_sdio_detect, |
| 653 | .suspend = mmc_sdio_suspend, | 671 | .suspend = mmc_sdio_suspend, |
| 654 | .resume = mmc_sdio_resume, | 672 | .resume = mmc_sdio_resume, |
| 673 | .power_restore = mmc_sdio_power_restore, | ||
| 655 | }; | 674 | }; |
| 656 | 675 | ||
| 657 | 676 | ||
| @@ -699,6 +718,18 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
| 699 | card = host->card; | 718 | card = host->card; |
| 700 | 719 | ||
| 701 | /* | 720 | /* |
| 721 | * Let runtime PM core know our card is active | ||
| 722 | */ | ||
| 723 | err = pm_runtime_set_active(&card->dev); | ||
| 724 | if (err) | ||
| 725 | goto remove; | ||
| 726 | |||
| 727 | /* | ||
| 728 | * Enable runtime PM for this card | ||
| 729 | */ | ||
| 730 | pm_runtime_enable(&card->dev); | ||
| 731 | |||
| 732 | /* | ||
| 702 | * The number of functions on the card is encoded inside | 733 | * The number of functions on the card is encoded inside |
| 703 | * the ocr. | 734 | * the ocr. |
| 704 | */ | 735 | */ |
| @@ -712,6 +743,11 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
| 712 | err = sdio_init_func(host->card, i + 1); | 743 | err = sdio_init_func(host->card, i + 1); |
| 713 | if (err) | 744 | if (err) |
| 714 | goto remove; | 745 | goto remove; |
| 746 | |||
| 747 | /* | ||
| 748 | * Enable Runtime PM for this func | ||
| 749 | */ | ||
| 750 | pm_runtime_enable(&card->sdio_func[i]->dev); | ||
| 715 | } | 751 | } |
| 716 | 752 | ||
| 717 | mmc_release_host(host); | 753 | mmc_release_host(host); |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 4a890dcb95ab..2716c7ab6bbf 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/pm_runtime.h> | ||
| 17 | 18 | ||
| 18 | #include <linux/mmc/card.h> | 19 | #include <linux/mmc/card.h> |
| 19 | #include <linux/mmc/sdio_func.h> | 20 | #include <linux/mmc/sdio_func.h> |
| @@ -125,21 +126,46 @@ static int sdio_bus_probe(struct device *dev) | |||
| 125 | if (!id) | 126 | if (!id) |
| 126 | return -ENODEV; | 127 | return -ENODEV; |
| 127 | 128 | ||
| 129 | /* Unbound SDIO functions are always suspended. | ||
| 130 | * During probe, the function is set active and the usage count | ||
| 131 | * is incremented. If the driver supports runtime PM, | ||
| 132 | * it should call pm_runtime_put_noidle() in its probe routine and | ||
| 133 | * pm_runtime_get_noresume() in its remove routine. | ||
| 134 | */ | ||
| 135 | ret = pm_runtime_get_sync(dev); | ||
| 136 | if (ret < 0) | ||
| 137 | goto out; | ||
| 138 | |||
| 128 | /* Set the default block size so the driver is sure it's something | 139 | /* Set the default block size so the driver is sure it's something |
| 129 | * sensible. */ | 140 | * sensible. */ |
| 130 | sdio_claim_host(func); | 141 | sdio_claim_host(func); |
| 131 | ret = sdio_set_block_size(func, 0); | 142 | ret = sdio_set_block_size(func, 0); |
| 132 | sdio_release_host(func); | 143 | sdio_release_host(func); |
| 133 | if (ret) | 144 | if (ret) |
| 134 | return ret; | 145 | goto disable_runtimepm; |
| 146 | |||
| 147 | ret = drv->probe(func, id); | ||
| 148 | if (ret) | ||
| 149 | goto disable_runtimepm; | ||
| 135 | 150 | ||
| 136 | return drv->probe(func, id); | 151 | return 0; |
| 152 | |||
| 153 | disable_runtimepm: | ||
| 154 | pm_runtime_put_noidle(dev); | ||
| 155 | out: | ||
| 156 | return ret; | ||
| 137 | } | 157 | } |
| 138 | 158 | ||
| 139 | static int sdio_bus_remove(struct device *dev) | 159 | static int sdio_bus_remove(struct device *dev) |
| 140 | { | 160 | { |
| 141 | struct sdio_driver *drv = to_sdio_driver(dev->driver); | 161 | struct sdio_driver *drv = to_sdio_driver(dev->driver); |
| 142 | struct sdio_func *func = dev_to_sdio_func(dev); | 162 | struct sdio_func *func = dev_to_sdio_func(dev); |
| 163 | int ret; | ||
| 164 | |||
| 165 | /* Make sure card is powered before invoking ->remove() */ | ||
| 166 | ret = pm_runtime_get_sync(dev); | ||
| 167 | if (ret < 0) | ||
| 168 | goto out; | ||
| 143 | 169 | ||
| 144 | drv->remove(func); | 170 | drv->remove(func); |
| 145 | 171 | ||
| @@ -151,9 +177,63 @@ static int sdio_bus_remove(struct device *dev) | |||
| 151 | sdio_release_host(func); | 177 | sdio_release_host(func); |
| 152 | } | 178 | } |
| 153 | 179 | ||
| 180 | /* First, undo the increment made directly above */ | ||
| 181 | pm_runtime_put_noidle(dev); | ||
| 182 | |||
| 183 | /* Then undo the runtime PM settings in sdio_bus_probe() */ | ||
| 184 | pm_runtime_put_noidle(dev); | ||
| 185 | |||
| 186 | out: | ||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | |||
| 190 | #ifdef CONFIG_PM_RUNTIME | ||
| 191 | |||
| 192 | static int sdio_bus_pm_prepare(struct device *dev) | ||
| 193 | { | ||
| 194 | /* | ||
| 195 | * Resume an SDIO device which was suspended at run time at this | ||
| 196 | * point, in order to allow standard SDIO suspend/resume paths | ||
| 197 | * to keep working as usual. | ||
| 198 | * | ||
| 199 | * Ultimately, the SDIO driver itself will decide (in its | ||
| 200 | * suspend handler, or lack thereof) whether the card should be | ||
| 201 | * removed or kept, and if kept, at what power state. | ||
| 202 | * | ||
| 203 | * At this point, PM core have increased our use count, so it's | ||
| 204 | * safe to directly resume the device. After system is resumed | ||
| 205 | * again, PM core will drop back its runtime PM use count, and if | ||
| 206 | * needed device will be suspended again. | ||
| 207 | * | ||
| 208 | * The end result is guaranteed to be a power state that is | ||
| 209 | * coherent with the device's runtime PM use count. | ||
| 210 | * | ||
| 211 | * The return value of pm_runtime_resume is deliberately unchecked | ||
| 212 | * since there is little point in failing system suspend if a | ||
| 213 | * device can't be resumed. | ||
| 214 | */ | ||
| 215 | pm_runtime_resume(dev); | ||
| 216 | |||
| 154 | return 0; | 217 | return 0; |
| 155 | } | 218 | } |
| 156 | 219 | ||
| 220 | static const struct dev_pm_ops sdio_bus_pm_ops = { | ||
| 221 | SET_RUNTIME_PM_OPS( | ||
| 222 | pm_generic_runtime_suspend, | ||
| 223 | pm_generic_runtime_resume, | ||
| 224 | pm_generic_runtime_idle | ||
| 225 | ) | ||
| 226 | .prepare = sdio_bus_pm_prepare, | ||
| 227 | }; | ||
| 228 | |||
| 229 | #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) | ||
| 230 | |||
| 231 | #else /* !CONFIG_PM_RUNTIME */ | ||
| 232 | |||
| 233 | #define SDIO_PM_OPS_PTR NULL | ||
| 234 | |||
| 235 | #endif /* !CONFIG_PM_RUNTIME */ | ||
| 236 | |||
| 157 | static struct bus_type sdio_bus_type = { | 237 | static struct bus_type sdio_bus_type = { |
| 158 | .name = "sdio", | 238 | .name = "sdio", |
| 159 | .dev_attrs = sdio_dev_attrs, | 239 | .dev_attrs = sdio_dev_attrs, |
| @@ -161,6 +241,7 @@ static struct bus_type sdio_bus_type = { | |||
| 161 | .uevent = sdio_bus_uevent, | 241 | .uevent = sdio_bus_uevent, |
| 162 | .probe = sdio_bus_probe, | 242 | .probe = sdio_bus_probe, |
| 163 | .remove = sdio_bus_remove, | 243 | .remove = sdio_bus_remove, |
| 244 | .pm = SDIO_PM_OPS_PTR, | ||
| 164 | }; | 245 | }; |
| 165 | 246 | ||
| 166 | int sdio_register_bus(void) | 247 | int sdio_register_bus(void) |
