14101c16aSPierre Ossman /* 24101c16aSPierre Ossman * linux/drivers/mmc/core/bus.c 34101c16aSPierre Ossman * 44101c16aSPierre Ossman * Copyright (C) 2003 Russell King, All Rights Reserved. 54101c16aSPierre Ossman * Copyright (C) 2007 Pierre Ossman 64101c16aSPierre Ossman * 74101c16aSPierre Ossman * This program is free software; you can redistribute it and/or modify 84101c16aSPierre Ossman * it under the terms of the GNU General Public License version 2 as 94101c16aSPierre Ossman * published by the Free Software Foundation. 104101c16aSPierre Ossman * 114101c16aSPierre Ossman * MMC card bus driver model 124101c16aSPierre Ossman */ 134101c16aSPierre Ossman 143ef77af1SPaul Gortmaker #include <linux/export.h> 154101c16aSPierre Ossman #include <linux/device.h> 164101c16aSPierre Ossman #include <linux/err.h> 175a0e3ad6STejun Heo #include <linux/slab.h> 180205a904SPaul Gortmaker #include <linux/stat.h> 19516d5ccdSOhad Ben-Cohen #include <linux/pm_runtime.h> 204101c16aSPierre Ossman 214101c16aSPierre Ossman #include <linux/mmc/card.h> 224101c16aSPierre Ossman #include <linux/mmc/host.h> 234101c16aSPierre Ossman 244101c16aSPierre Ossman #include "core.h" 251a632f8cSPierre Ossman #include "sdio_cis.h" 264101c16aSPierre Ossman #include "bus.h" 274101c16aSPierre Ossman 284101c16aSPierre Ossman #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) 294101c16aSPierre Ossman 304101c16aSPierre Ossman static ssize_t mmc_type_show(struct device *dev, 314101c16aSPierre Ossman struct device_attribute *attr, char *buf) 324101c16aSPierre Ossman { 33265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 344101c16aSPierre Ossman 354101c16aSPierre Ossman switch (card->type) { 364101c16aSPierre Ossman case MMC_TYPE_MMC: 374101c16aSPierre Ossman return sprintf(buf, "MMC\n"); 384101c16aSPierre Ossman case MMC_TYPE_SD: 394101c16aSPierre Ossman return sprintf(buf, "SD\n"); 405c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 415c4e6f13SPierre Ossman return sprintf(buf, "SDIO\n"); 427310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 437310ece8SMichal Miroslaw return sprintf(buf, "SDcombo\n"); 444101c16aSPierre Ossman default: 454101c16aSPierre Ossman return -EFAULT; 464101c16aSPierre Ossman } 474101c16aSPierre Ossman } 484101c16aSPierre Ossman 494101c16aSPierre Ossman static struct device_attribute mmc_dev_attrs[] = { 5051ec92e2SPierre Ossman __ATTR(type, S_IRUGO, mmc_type_show, NULL), 514101c16aSPierre Ossman __ATTR_NULL, 524101c16aSPierre Ossman }; 534101c16aSPierre Ossman 544101c16aSPierre Ossman /* 554101c16aSPierre Ossman * This currently matches any MMC driver to any MMC card - drivers 564101c16aSPierre Ossman * themselves make the decision whether to drive this card in their 574101c16aSPierre Ossman * probe method. 584101c16aSPierre Ossman */ 594101c16aSPierre Ossman static int mmc_bus_match(struct device *dev, struct device_driver *drv) 604101c16aSPierre Ossman { 614101c16aSPierre Ossman return 1; 624101c16aSPierre Ossman } 634101c16aSPierre Ossman 644101c16aSPierre Ossman static int 657eff2e7aSKay Sievers mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 664101c16aSPierre Ossman { 67265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 689eb3a94dSPierre Ossman const char *type; 697eff2e7aSKay Sievers int retval = 0; 704101c16aSPierre Ossman 714101c16aSPierre Ossman switch (card->type) { 724101c16aSPierre Ossman case MMC_TYPE_MMC: 739eb3a94dSPierre Ossman type = "MMC"; 744101c16aSPierre Ossman break; 754101c16aSPierre Ossman case MMC_TYPE_SD: 769eb3a94dSPierre Ossman type = "SD"; 774101c16aSPierre Ossman break; 785c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 799eb3a94dSPierre Ossman type = "SDIO"; 805c4e6f13SPierre Ossman break; 817310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 827310ece8SMichal Miroslaw type = "SDcombo"; 837310ece8SMichal Miroslaw break; 849eb3a94dSPierre Ossman default: 859eb3a94dSPierre Ossman type = NULL; 864101c16aSPierre Ossman } 874101c16aSPierre Ossman 889eb3a94dSPierre Ossman if (type) { 897eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_TYPE=%s", type); 907eff2e7aSKay Sievers if (retval) 917eff2e7aSKay Sievers return retval; 929eb3a94dSPierre Ossman } 934101c16aSPierre Ossman 947eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); 956b0b6285SAndy Whitcroft if (retval) 966b0b6285SAndy Whitcroft return retval; 976b0b6285SAndy Whitcroft 986b0b6285SAndy Whitcroft /* 996b0b6285SAndy Whitcroft * Request the mmc_block device. Note: that this is a direct request 1006b0b6285SAndy Whitcroft * for the module it carries no information as to what is inserted. 1016b0b6285SAndy Whitcroft */ 1026b0b6285SAndy Whitcroft retval = add_uevent_var(env, "MODALIAS=mmc:block"); 1034101c16aSPierre Ossman 1047eff2e7aSKay Sievers return retval; 1054101c16aSPierre Ossman } 1064101c16aSPierre Ossman 1074101c16aSPierre Ossman static int mmc_bus_probe(struct device *dev) 1084101c16aSPierre Ossman { 1094101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 110265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1114101c16aSPierre Ossman 1124101c16aSPierre Ossman return drv->probe(card); 1134101c16aSPierre Ossman } 1144101c16aSPierre Ossman 1154101c16aSPierre Ossman static int mmc_bus_remove(struct device *dev) 1164101c16aSPierre Ossman { 1174101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 118265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1194101c16aSPierre Ossman 1204101c16aSPierre Ossman drv->remove(card); 1214101c16aSPierre Ossman 1224101c16aSPierre Ossman return 0; 1234101c16aSPierre Ossman } 1244101c16aSPierre Ossman 12576287748SUlf Hansson static void mmc_bus_shutdown(struct device *dev) 12676287748SUlf Hansson { 12776287748SUlf Hansson struct mmc_driver *drv = to_mmc_driver(dev->driver); 12876287748SUlf Hansson struct mmc_card *card = mmc_dev_to_card(dev); 1296b086bdeSUlf Hansson struct mmc_host *host = card->host; 1306b086bdeSUlf Hansson int ret; 13176287748SUlf Hansson 13276287748SUlf Hansson drv->shutdown(card); 1336b086bdeSUlf Hansson 1346b086bdeSUlf Hansson if (host->bus_ops->shutdown) { 1356b086bdeSUlf Hansson ret = host->bus_ops->shutdown(host); 1366b086bdeSUlf Hansson if (ret) 1376b086bdeSUlf Hansson pr_warn("%s: error %d during shutdown\n", 1386b086bdeSUlf Hansson mmc_hostname(host), ret); 1396b086bdeSUlf Hansson } 14076287748SUlf Hansson } 14176287748SUlf Hansson 1420dd1bfebSChuanxiao Dong #ifdef CONFIG_PM_SLEEP 14332d317c6SChuanxiao Dong static int mmc_bus_suspend(struct device *dev) 1444101c16aSPierre Ossman { 1454101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 146265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 147986892caSUlf Hansson struct mmc_host *host = card->host; 148986892caSUlf Hansson int ret; 1494101c16aSPierre Ossman 150986892caSUlf Hansson if (dev->driver && drv->suspend) { 15132d317c6SChuanxiao Dong ret = drv->suspend(card); 152986892caSUlf Hansson if (ret) 153986892caSUlf Hansson return ret; 154986892caSUlf Hansson } 155986892caSUlf Hansson 156986892caSUlf Hansson ret = host->bus_ops->suspend(host); 1574101c16aSPierre Ossman return ret; 1584101c16aSPierre Ossman } 1594101c16aSPierre Ossman 1604101c16aSPierre Ossman static int mmc_bus_resume(struct device *dev) 1614101c16aSPierre Ossman { 1624101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 163265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 164986892caSUlf Hansson struct mmc_host *host = card->host; 165986892caSUlf Hansson int ret; 166986892caSUlf Hansson 167986892caSUlf Hansson ret = host->bus_ops->resume(host); 168986892caSUlf Hansson if (ret) 169986892caSUlf Hansson pr_warn("%s: error %d during resume (card was removed?)\n", 170986892caSUlf Hansson mmc_hostname(host), ret); 1714101c16aSPierre Ossman 1724101c16aSPierre Ossman if (dev->driver && drv->resume) 1734101c16aSPierre Ossman ret = drv->resume(card); 174986892caSUlf Hansson 1754101c16aSPierre Ossman return ret; 1764101c16aSPierre Ossman } 1770dd1bfebSChuanxiao Dong #endif 1784101c16aSPierre Ossman 179516d5ccdSOhad Ben-Cohen #ifdef CONFIG_PM_RUNTIME 180516d5ccdSOhad Ben-Cohen 181516d5ccdSOhad Ben-Cohen static int mmc_runtime_suspend(struct device *dev) 182516d5ccdSOhad Ben-Cohen { 183516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 18412d01d0bSUlf Hansson struct mmc_host *host = card->host; 18512d01d0bSUlf Hansson int ret = 0; 186516d5ccdSOhad Ben-Cohen 18712d01d0bSUlf Hansson if (host->bus_ops->runtime_suspend) 18812d01d0bSUlf Hansson ret = host->bus_ops->runtime_suspend(host); 18912d01d0bSUlf Hansson 19012d01d0bSUlf Hansson return ret; 191516d5ccdSOhad Ben-Cohen } 192516d5ccdSOhad Ben-Cohen 193516d5ccdSOhad Ben-Cohen static int mmc_runtime_resume(struct device *dev) 194516d5ccdSOhad Ben-Cohen { 195516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 19612d01d0bSUlf Hansson struct mmc_host *host = card->host; 19712d01d0bSUlf Hansson int ret = 0; 198516d5ccdSOhad Ben-Cohen 19912d01d0bSUlf Hansson if (host->bus_ops->runtime_resume) 20012d01d0bSUlf Hansson ret = host->bus_ops->runtime_resume(host); 20112d01d0bSUlf Hansson 20212d01d0bSUlf Hansson return ret; 203516d5ccdSOhad Ben-Cohen } 204516d5ccdSOhad Ben-Cohen 205516d5ccdSOhad Ben-Cohen static int mmc_runtime_idle(struct device *dev) 206516d5ccdSOhad Ben-Cohen { 207516d5ccdSOhad Ben-Cohen return pm_runtime_suspend(dev); 208516d5ccdSOhad Ben-Cohen } 209516d5ccdSOhad Ben-Cohen 210516d5ccdSOhad Ben-Cohen #endif /* !CONFIG_PM_RUNTIME */ 211516d5ccdSOhad Ben-Cohen 21232d317c6SChuanxiao Dong static const struct dev_pm_ops mmc_bus_pm_ops = { 21332d317c6SChuanxiao Dong SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, 21432d317c6SChuanxiao Dong mmc_runtime_idle) 21532d317c6SChuanxiao Dong SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) 21632d317c6SChuanxiao Dong }; 21732d317c6SChuanxiao Dong 2184101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 2194101c16aSPierre Ossman .name = "mmc", 2204101c16aSPierre Ossman .dev_attrs = mmc_dev_attrs, 2214101c16aSPierre Ossman .match = mmc_bus_match, 2224101c16aSPierre Ossman .uevent = mmc_bus_uevent, 2234101c16aSPierre Ossman .probe = mmc_bus_probe, 2244101c16aSPierre Ossman .remove = mmc_bus_remove, 22576287748SUlf Hansson .shutdown = mmc_bus_shutdown, 22632d317c6SChuanxiao Dong .pm = &mmc_bus_pm_ops, 2274101c16aSPierre Ossman }; 2284101c16aSPierre Ossman 2294101c16aSPierre Ossman int mmc_register_bus(void) 2304101c16aSPierre Ossman { 2314101c16aSPierre Ossman return bus_register(&mmc_bus_type); 2324101c16aSPierre Ossman } 2334101c16aSPierre Ossman 2344101c16aSPierre Ossman void mmc_unregister_bus(void) 2354101c16aSPierre Ossman { 2364101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 2374101c16aSPierre Ossman } 2384101c16aSPierre Ossman 2394101c16aSPierre Ossman /** 2404101c16aSPierre Ossman * mmc_register_driver - register a media driver 2414101c16aSPierre Ossman * @drv: MMC media driver 2424101c16aSPierre Ossman */ 2434101c16aSPierre Ossman int mmc_register_driver(struct mmc_driver *drv) 2444101c16aSPierre Ossman { 2454101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 2464101c16aSPierre Ossman return driver_register(&drv->drv); 2474101c16aSPierre Ossman } 2484101c16aSPierre Ossman 2494101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 2504101c16aSPierre Ossman 2514101c16aSPierre Ossman /** 2524101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 2534101c16aSPierre Ossman * @drv: MMC media driver 2544101c16aSPierre Ossman */ 2554101c16aSPierre Ossman void mmc_unregister_driver(struct mmc_driver *drv) 2564101c16aSPierre Ossman { 2574101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 2584101c16aSPierre Ossman driver_unregister(&drv->drv); 2594101c16aSPierre Ossman } 2604101c16aSPierre Ossman 2614101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 2624101c16aSPierre Ossman 2634101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 2644101c16aSPierre Ossman { 265265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 2664101c16aSPierre Ossman 2671a632f8cSPierre Ossman sdio_free_common_cis(card); 2681a632f8cSPierre Ossman 269759bdc7aSPierre Ossman kfree(card->info); 270759bdc7aSPierre Ossman 2714101c16aSPierre Ossman kfree(card); 2724101c16aSPierre Ossman } 2734101c16aSPierre Ossman 2744101c16aSPierre Ossman /* 2754101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 2764101c16aSPierre Ossman */ 27751ec92e2SPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 2784101c16aSPierre Ossman { 2794101c16aSPierre Ossman struct mmc_card *card; 2804101c16aSPierre Ossman 281733cb1e4SMariusz Kozlowski card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 2824101c16aSPierre Ossman if (!card) 2834101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 2844101c16aSPierre Ossman 2854101c16aSPierre Ossman card->host = host; 2864101c16aSPierre Ossman 2874101c16aSPierre Ossman device_initialize(&card->dev); 2884101c16aSPierre Ossman 2894101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2904101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2914101c16aSPierre Ossman card->dev.release = mmc_release_card; 29251ec92e2SPierre Ossman card->dev.type = type; 2934101c16aSPierre Ossman 2944101c16aSPierre Ossman return card; 2954101c16aSPierre Ossman } 2964101c16aSPierre Ossman 2974101c16aSPierre Ossman /* 2984101c16aSPierre Ossman * Register a new MMC card with the driver model. 2994101c16aSPierre Ossman */ 3004101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 3014101c16aSPierre Ossman { 3024101c16aSPierre Ossman int ret; 303109b5bedSPierre Ossman const char *type; 3046500c8edSSubhash Jadavani const char *uhs_bus_speed_mode = ""; 3056500c8edSSubhash Jadavani static const char *const uhs_speeds[] = { 3066500c8edSSubhash Jadavani [UHS_SDR12_BUS_SPEED] = "SDR12 ", 3076500c8edSSubhash Jadavani [UHS_SDR25_BUS_SPEED] = "SDR25 ", 3086500c8edSSubhash Jadavani [UHS_SDR50_BUS_SPEED] = "SDR50 ", 3096500c8edSSubhash Jadavani [UHS_SDR104_BUS_SPEED] = "SDR104 ", 3106500c8edSSubhash Jadavani [UHS_DDR50_BUS_SPEED] = "DDR50 ", 3116500c8edSSubhash Jadavani }; 3126500c8edSSubhash Jadavani 3134101c16aSPierre Ossman 314d1b26863SKay Sievers dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 3154101c16aSPierre Ossman 316109b5bedSPierre Ossman switch (card->type) { 317109b5bedSPierre Ossman case MMC_TYPE_MMC: 318109b5bedSPierre Ossman type = "MMC"; 319109b5bedSPierre Ossman break; 320109b5bedSPierre Ossman case MMC_TYPE_SD: 321109b5bedSPierre Ossman type = "SD"; 3223a303511SArindam Nath if (mmc_card_blockaddr(card)) { 3233a303511SArindam Nath if (mmc_card_ext_capacity(card)) 3243a303511SArindam Nath type = "SDXC"; 3253a303511SArindam Nath else 326109b5bedSPierre Ossman type = "SDHC"; 3273a303511SArindam Nath } 328109b5bedSPierre Ossman break; 3295c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 3305c4e6f13SPierre Ossman type = "SDIO"; 3315c4e6f13SPierre Ossman break; 3327310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 3337310ece8SMichal Miroslaw type = "SD-combo"; 3347310ece8SMichal Miroslaw if (mmc_card_blockaddr(card)) 3357310ece8SMichal Miroslaw type = "SDHC-combo"; 3369bc21848SMichał Mirosław break; 337109b5bedSPierre Ossman default: 338109b5bedSPierre Ossman type = "?"; 339109b5bedSPierre Ossman break; 340109b5bedSPierre Ossman } 341109b5bedSPierre Ossman 3426500c8edSSubhash Jadavani if (mmc_sd_card_uhs(card) && 3436500c8edSSubhash Jadavani (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) 3446500c8edSSubhash Jadavani uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; 3456500c8edSSubhash Jadavani 346af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 347a3c76eb9SGirish K S pr_info("%s: new %s%s%s card on SPI\n", 348af517150SDavid Brownell mmc_hostname(card->host), 349af517150SDavid Brownell mmc_card_highspeed(card) ? "high speed " : "", 3500f8d8ea6SAdrian Hunter mmc_card_ddr_mode(card) ? "DDR " : "", 351af517150SDavid Brownell type); 352af517150SDavid Brownell } else { 3536500c8edSSubhash Jadavani pr_info("%s: new %s%s%s%s%s card at address %04x\n", 354109b5bedSPierre Ossman mmc_hostname(card->host), 355a303c531SPhilip Rakity mmc_card_uhs(card) ? "ultra high speed " : 3563a303511SArindam Nath (mmc_card_highspeed(card) ? "high speed " : ""), 357a4924c71SGirish K S (mmc_card_hs200(card) ? "HS200 " : ""), 3580f8d8ea6SAdrian Hunter mmc_card_ddr_mode(card) ? "DDR " : "", 3596500c8edSSubhash Jadavani uhs_bus_speed_mode, type, card->rca); 360af517150SDavid Brownell } 361109b5bedSPierre Ossman 362f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 363f4b7f927SHaavard Skinnemoen mmc_add_card_debugfs(card); 364f4b7f927SHaavard Skinnemoen #endif 3652220eedfSKonstantin Dorfman mmc_init_context_info(card->host); 366f4b7f927SHaavard Skinnemoen 3671a2727e9SViresh Kumar ret = device_add(&card->dev); 3681a2727e9SViresh Kumar if (ret) 3691a2727e9SViresh Kumar return ret; 3701a2727e9SViresh Kumar 3714101c16aSPierre Ossman mmc_card_set_present(card); 3724101c16aSPierre Ossman 3734101c16aSPierre Ossman return 0; 3744101c16aSPierre Ossman } 3754101c16aSPierre Ossman 3764101c16aSPierre Ossman /* 3774101c16aSPierre Ossman * Unregister a new MMC card with the driver model, and 3784101c16aSPierre Ossman * (eventually) free it. 3794101c16aSPierre Ossman */ 3804101c16aSPierre Ossman void mmc_remove_card(struct mmc_card *card) 3814101c16aSPierre Ossman { 382f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 383f4b7f927SHaavard Skinnemoen mmc_remove_card_debugfs(card); 384f4b7f927SHaavard Skinnemoen #endif 385f4b7f927SHaavard Skinnemoen 3864101c16aSPierre Ossman if (mmc_card_present(card)) { 387af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 388a3c76eb9SGirish K S pr_info("%s: SPI card removed\n", 389af517150SDavid Brownell mmc_hostname(card->host)); 390af517150SDavid Brownell } else { 391a3c76eb9SGirish K S pr_info("%s: card %04x removed\n", 392109b5bedSPierre Ossman mmc_hostname(card->host), card->rca); 393af517150SDavid Brownell } 3944101c16aSPierre Ossman device_del(&card->dev); 3954101c16aSPierre Ossman } 3964101c16aSPierre Ossman 3974101c16aSPierre Ossman put_device(&card->dev); 3984101c16aSPierre Ossman } 3994101c16aSPierre Ossman 400