diff options
Diffstat (limited to 'drivers/mmc/core/bus.c')
| -rw-r--r-- | drivers/mmc/core/bus.c | 141 |
1 files changed, 97 insertions, 44 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index af8dc6a2a31..d2dbf02022b 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -11,9 +11,11 @@ * MMC card bus driver model */ +#include <linux/export.h> #include <linux/device.h> #include <linux/err.h> #include <linux/slab.h> +#include <linux/stat.h> #include <linux/pm_runtime.h> #include <linux/mmc/card.h> @@ -25,7 +27,7 @@ #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) -static ssize_t mmc_type_show(struct device *dev, +static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mmc_card *card = mmc_dev_to_card(dev); @@ -43,11 +45,13 @@ static ssize_t mmc_type_show(struct device *dev, return -EFAULT; } } +static DEVICE_ATTR_RO(type); -static struct device_attribute mmc_dev_attrs[] = { - __ATTR(type, S_IRUGO, mmc_type_show, NULL), - __ATTR_NULL, +static struct attribute *mmc_dev_attrs[] = { + &dev_attr_type.attr, + NULL, }; +ATTRIBUTE_GROUPS(mmc_dev); /* * This currently matches any MMC driver to any MMC card - drivers @@ -120,14 +124,39 @@ static int mmc_bus_remove(struct device *dev) return 0; } -static int mmc_bus_suspend(struct device *dev, pm_message_t state) +static void mmc_bus_shutdown(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); - int ret = 0; + struct mmc_host *host = card->host; + int ret; + + if (dev->driver && drv->shutdown) + drv->shutdown(card); + + if (host->bus_ops->shutdown) { + ret = host->bus_ops->shutdown(host); + if (ret) + pr_warn("%s: error %d during shutdown\n", + mmc_hostname(host), ret); + } +} + +#ifdef CONFIG_PM_SLEEP +static int mmc_bus_suspend(struct device *dev) +{ + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; + int ret; - if (dev->driver && drv->suspend) - ret = drv->suspend(card, state); + if (dev->driver && drv->suspend) { + ret = drv->suspend(card); + if (ret) + return ret; + } + + ret = host->bus_ops->suspend(host); return ret; } @@ -135,58 +164,61 @@ static int mmc_bus_resume(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); - int ret = 0; + struct mmc_host *host = card->host; + int ret; + + ret = host->bus_ops->resume(host); + if (ret) + pr_warn("%s: error %d during resume (card was removed?)\n", + mmc_hostname(host), ret); if (dev->driver && drv->resume) ret = drv->resume(card); + return ret; } +#endif #ifdef CONFIG_PM_RUNTIME static int mmc_runtime_suspend(struct device *dev) { struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; - return mmc_power_save_host(card->host); + return host->bus_ops->runtime_suspend(host); } static int mmc_runtime_resume(struct device *dev) { struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; - return mmc_power_restore_host(card->host); + return host->bus_ops->runtime_resume(host); } static int mmc_runtime_idle(struct device *dev) { - return pm_runtime_suspend(dev); + return 0; } +#endif /* !CONFIG_PM_RUNTIME */ + static const struct dev_pm_ops mmc_bus_pm_ops = { - .runtime_suspend = mmc_runtime_suspend, - .runtime_resume = mmc_runtime_resume, - .runtime_idle = mmc_runtime_idle, + SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, + mmc_runtime_idle) + SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) }; -#define MMC_PM_OPS_PTR (&mmc_bus_pm_ops) - -#else /* !CONFIG_PM_RUNTIME */ - -#define MMC_PM_OPS_PTR NULL - -#endif /* !CONFIG_PM_RUNTIME */ - static struct bus_type mmc_bus_type = { .name = "mmc", - .dev_attrs = mmc_dev_attrs, + .dev_groups = mmc_dev_groups, .match = mmc_bus_match, .uevent = mmc_bus_uevent, .probe = mmc_bus_probe, .remove = mmc_bus_remove, - .suspend = mmc_bus_suspend, - .resume = mmc_bus_resume, - .pm = MMC_PM_OPS_PTR, + .shutdown = mmc_bus_shutdown, + .pm = &mmc_bus_pm_ops, }; int mmc_register_bus(void) @@ -229,8 +261,7 @@ static void mmc_release_card(struct device *dev) sdio_free_common_cis(card); - if (card->info) - kfree(card->info); + kfree(card->info); kfree(card); } @@ -265,6 +296,15 @@ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; + const char *uhs_bus_speed_mode = ""; + static const char *const uhs_speeds[] = { + [UHS_SDR12_BUS_SPEED] = "SDR12 ", + [UHS_SDR25_BUS_SPEED] = "SDR25 ", + [UHS_SDR50_BUS_SPEED] = "SDR50 ", + [UHS_SDR104_BUS_SPEED] = "SDR104 ", + [UHS_DDR50_BUS_SPEED] = "DDR50 ", + }; + dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); @@ -274,8 +314,12 @@ int mmc_add_card(struct mmc_card *card) break; case MMC_TYPE_SD: type = "SD"; - if (mmc_card_blockaddr(card)) - type = "SDHC"; + if (mmc_card_blockaddr(card)) { + if (mmc_card_ext_capacity(card)) + type = "SDXC"; + else + type = "SDHC"; + } break; case MMC_TYPE_SDIO: type = "SDIO"; @@ -284,32 +328,41 @@ int mmc_add_card(struct mmc_card *card) type = "SD-combo"; if (mmc_card_blockaddr(card)) type = "SDHC-combo"; + break; default: type = "?"; break; } + if (mmc_card_uhs(card) && + (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) + uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; + if (mmc_host_is_spi(card->host)) { - printk(KERN_INFO "%s: new %s%s%s card on SPI\n", + pr_info("%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), - mmc_card_highspeed(card) ? "high speed " : "", - mmc_card_ddr_mode(card) ? "DDR " : "", + mmc_card_hs(card) ? "high speed " : "", + mmc_card_ddr52(card) ? "DDR " : "", type); } else { - printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", + pr_info("%s: new %s%s%s%s%s card at address %04x\n", mmc_hostname(card->host), - mmc_card_highspeed(card) ? "high speed " : "", - mmc_card_ddr_mode(card) ? "DDR " : "", - type, card->rca); + mmc_card_uhs(card) ? "ultra high speed " : + (mmc_card_hs(card) ? "high speed " : ""), + mmc_card_hs400(card) ? "HS400 " : + (mmc_card_hs200(card) ? "HS200 " : ""), + mmc_card_ddr52(card) ? "DDR " : "", + uhs_bus_speed_mode, type, card->rca); } - ret = device_add(&card->dev); - if (ret) - return ret; - #ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); #endif + mmc_init_context_info(card->host); + + ret = device_add(&card->dev); + if (ret) + return ret; mmc_card_set_present(card); @@ -328,10 +381,10 @@ void mmc_remove_card(struct mmc_card *card) if (mmc_card_present(card)) { if (mmc_host_is_spi(card->host)) { - printk(KERN_INFO "%s: SPI card removed\n", + pr_info("%s: SPI card removed\n", mmc_hostname(card->host)); } else { - printk(KERN_INFO "%s: card %04x removed\n", + pr_info("%s: card %04x removed\n", mmc_hostname(card->host), card->rca); } device_del(&card->dev); |
