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 1250dd1bfebSChuanxiao Dong #ifdef CONFIG_PM_SLEEP 12632d317c6SChuanxiao Dong static int mmc_bus_suspend(struct device *dev) 1274101c16aSPierre Ossman { 1284101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 129265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1304101c16aSPierre Ossman int ret = 0; 1314101c16aSPierre Ossman 1324101c16aSPierre Ossman if (dev->driver && drv->suspend) 13332d317c6SChuanxiao Dong ret = drv->suspend(card); 1344101c16aSPierre Ossman return ret; 1354101c16aSPierre Ossman } 1364101c16aSPierre Ossman 1374101c16aSPierre Ossman static int mmc_bus_resume(struct device *dev) 1384101c16aSPierre Ossman { 1394101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 140265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1414101c16aSPierre Ossman int ret = 0; 1424101c16aSPierre Ossman 1434101c16aSPierre Ossman if (dev->driver && drv->resume) 1444101c16aSPierre Ossman ret = drv->resume(card); 1454101c16aSPierre Ossman return ret; 1464101c16aSPierre Ossman } 1470dd1bfebSChuanxiao Dong #endif 1484101c16aSPierre Ossman 149516d5ccdSOhad Ben-Cohen #ifdef CONFIG_PM_RUNTIME 150516d5ccdSOhad Ben-Cohen 151516d5ccdSOhad Ben-Cohen static int mmc_runtime_suspend(struct device *dev) 152516d5ccdSOhad Ben-Cohen { 153516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 154516d5ccdSOhad Ben-Cohen 155516d5ccdSOhad Ben-Cohen return mmc_power_save_host(card->host); 156516d5ccdSOhad Ben-Cohen } 157516d5ccdSOhad Ben-Cohen 158516d5ccdSOhad Ben-Cohen static int mmc_runtime_resume(struct device *dev) 159516d5ccdSOhad Ben-Cohen { 160516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 161516d5ccdSOhad Ben-Cohen 162516d5ccdSOhad Ben-Cohen return mmc_power_restore_host(card->host); 163516d5ccdSOhad Ben-Cohen } 164516d5ccdSOhad Ben-Cohen 165516d5ccdSOhad Ben-Cohen static int mmc_runtime_idle(struct device *dev) 166516d5ccdSOhad Ben-Cohen { 167516d5ccdSOhad Ben-Cohen return pm_runtime_suspend(dev); 168516d5ccdSOhad Ben-Cohen } 169516d5ccdSOhad Ben-Cohen 170516d5ccdSOhad Ben-Cohen #endif /* !CONFIG_PM_RUNTIME */ 171516d5ccdSOhad Ben-Cohen 17232d317c6SChuanxiao Dong static const struct dev_pm_ops mmc_bus_pm_ops = { 17332d317c6SChuanxiao Dong SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, 17432d317c6SChuanxiao Dong mmc_runtime_idle) 17532d317c6SChuanxiao Dong SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) 17632d317c6SChuanxiao Dong }; 17732d317c6SChuanxiao Dong 1784101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 1794101c16aSPierre Ossman .name = "mmc", 1804101c16aSPierre Ossman .dev_attrs = mmc_dev_attrs, 1814101c16aSPierre Ossman .match = mmc_bus_match, 1824101c16aSPierre Ossman .uevent = mmc_bus_uevent, 1834101c16aSPierre Ossman .probe = mmc_bus_probe, 1844101c16aSPierre Ossman .remove = mmc_bus_remove, 18532d317c6SChuanxiao Dong .pm = &mmc_bus_pm_ops, 1864101c16aSPierre Ossman }; 1874101c16aSPierre Ossman 1884101c16aSPierre Ossman int mmc_register_bus(void) 1894101c16aSPierre Ossman { 1904101c16aSPierre Ossman return bus_register(&mmc_bus_type); 1914101c16aSPierre Ossman } 1924101c16aSPierre Ossman 1934101c16aSPierre Ossman void mmc_unregister_bus(void) 1944101c16aSPierre Ossman { 1954101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 1964101c16aSPierre Ossman } 1974101c16aSPierre Ossman 1984101c16aSPierre Ossman /** 1994101c16aSPierre Ossman * mmc_register_driver - register a media driver 2004101c16aSPierre Ossman * @drv: MMC media driver 2014101c16aSPierre Ossman */ 2024101c16aSPierre Ossman int mmc_register_driver(struct mmc_driver *drv) 2034101c16aSPierre Ossman { 2044101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 2054101c16aSPierre Ossman return driver_register(&drv->drv); 2064101c16aSPierre Ossman } 2074101c16aSPierre Ossman 2084101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 2094101c16aSPierre Ossman 2104101c16aSPierre Ossman /** 2114101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 2124101c16aSPierre Ossman * @drv: MMC media driver 2134101c16aSPierre Ossman */ 2144101c16aSPierre Ossman void mmc_unregister_driver(struct mmc_driver *drv) 2154101c16aSPierre Ossman { 2164101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 2174101c16aSPierre Ossman driver_unregister(&drv->drv); 2184101c16aSPierre Ossman } 2194101c16aSPierre Ossman 2204101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 2214101c16aSPierre Ossman 2224101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 2234101c16aSPierre Ossman { 224265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 2254101c16aSPierre Ossman 2261a632f8cSPierre Ossman sdio_free_common_cis(card); 2271a632f8cSPierre Ossman 228759bdc7aSPierre Ossman if (card->info) 229759bdc7aSPierre Ossman kfree(card->info); 230759bdc7aSPierre Ossman 2314101c16aSPierre Ossman kfree(card); 2324101c16aSPierre Ossman } 2334101c16aSPierre Ossman 2344101c16aSPierre Ossman /* 2354101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 2364101c16aSPierre Ossman */ 23751ec92e2SPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 2384101c16aSPierre Ossman { 2394101c16aSPierre Ossman struct mmc_card *card; 2404101c16aSPierre Ossman 241733cb1e4SMariusz Kozlowski card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 2424101c16aSPierre Ossman if (!card) 2434101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 2444101c16aSPierre Ossman 2454101c16aSPierre Ossman card->host = host; 2464101c16aSPierre Ossman 2474101c16aSPierre Ossman device_initialize(&card->dev); 2484101c16aSPierre Ossman 2494101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2504101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2514101c16aSPierre Ossman card->dev.release = mmc_release_card; 25251ec92e2SPierre Ossman card->dev.type = type; 2534101c16aSPierre Ossman 2544101c16aSPierre Ossman return card; 2554101c16aSPierre Ossman } 2564101c16aSPierre Ossman 2574101c16aSPierre Ossman /* 2584101c16aSPierre Ossman * Register a new MMC card with the driver model. 2594101c16aSPierre Ossman */ 2604101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 2614101c16aSPierre Ossman { 2624101c16aSPierre Ossman int ret; 263109b5bedSPierre Ossman const char *type; 2646500c8edSSubhash Jadavani const char *uhs_bus_speed_mode = ""; 2656500c8edSSubhash Jadavani static const char *const uhs_speeds[] = { 2666500c8edSSubhash Jadavani [UHS_SDR12_BUS_SPEED] = "SDR12 ", 2676500c8edSSubhash Jadavani [UHS_SDR25_BUS_SPEED] = "SDR25 ", 2686500c8edSSubhash Jadavani [UHS_SDR50_BUS_SPEED] = "SDR50 ", 2696500c8edSSubhash Jadavani [UHS_SDR104_BUS_SPEED] = "SDR104 ", 2706500c8edSSubhash Jadavani [UHS_DDR50_BUS_SPEED] = "DDR50 ", 2716500c8edSSubhash Jadavani }; 2726500c8edSSubhash Jadavani 2734101c16aSPierre Ossman 274d1b26863SKay Sievers dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 2754101c16aSPierre Ossman 276109b5bedSPierre Ossman switch (card->type) { 277109b5bedSPierre Ossman case MMC_TYPE_MMC: 278109b5bedSPierre Ossman type = "MMC"; 279109b5bedSPierre Ossman break; 280109b5bedSPierre Ossman case MMC_TYPE_SD: 281109b5bedSPierre Ossman type = "SD"; 2823a303511SArindam Nath if (mmc_card_blockaddr(card)) { 2833a303511SArindam Nath if (mmc_card_ext_capacity(card)) 2843a303511SArindam Nath type = "SDXC"; 2853a303511SArindam Nath else 286109b5bedSPierre Ossman type = "SDHC"; 2873a303511SArindam Nath } 288109b5bedSPierre Ossman break; 2895c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 2905c4e6f13SPierre Ossman type = "SDIO"; 2915c4e6f13SPierre Ossman break; 2927310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 2937310ece8SMichal Miroslaw type = "SD-combo"; 2947310ece8SMichal Miroslaw if (mmc_card_blockaddr(card)) 2957310ece8SMichal Miroslaw type = "SDHC-combo"; 2969bc21848SMichał Mirosław break; 297109b5bedSPierre Ossman default: 298109b5bedSPierre Ossman type = "?"; 299109b5bedSPierre Ossman break; 300109b5bedSPierre Ossman } 301109b5bedSPierre Ossman 3026500c8edSSubhash Jadavani if (mmc_sd_card_uhs(card) && 3036500c8edSSubhash Jadavani (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) 3046500c8edSSubhash Jadavani uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; 3056500c8edSSubhash Jadavani 306af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 307a3c76eb9SGirish K S pr_info("%s: new %s%s%s card on SPI\n", 308af517150SDavid Brownell mmc_hostname(card->host), 309af517150SDavid Brownell mmc_card_highspeed(card) ? "high speed " : "", 3100f8d8ea6SAdrian Hunter mmc_card_ddr_mode(card) ? "DDR " : "", 311af517150SDavid Brownell type); 312af517150SDavid Brownell } else { 3136500c8edSSubhash Jadavani pr_info("%s: new %s%s%s%s%s card at address %04x\n", 314109b5bedSPierre Ossman mmc_hostname(card->host), 315a303c531SPhilip Rakity mmc_card_uhs(card) ? "ultra high speed " : 3163a303511SArindam Nath (mmc_card_highspeed(card) ? "high speed " : ""), 317a4924c71SGirish K S (mmc_card_hs200(card) ? "HS200 " : ""), 3180f8d8ea6SAdrian Hunter mmc_card_ddr_mode(card) ? "DDR " : "", 3196500c8edSSubhash Jadavani uhs_bus_speed_mode, type, card->rca); 320af517150SDavid Brownell } 321109b5bedSPierre Ossman 322f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 323f4b7f927SHaavard Skinnemoen mmc_add_card_debugfs(card); 324f4b7f927SHaavard Skinnemoen #endif 325f4b7f927SHaavard Skinnemoen 3261a2727e9SViresh Kumar ret = device_add(&card->dev); 3271a2727e9SViresh Kumar if (ret) 3281a2727e9SViresh Kumar return ret; 3291a2727e9SViresh Kumar 3304101c16aSPierre Ossman mmc_card_set_present(card); 3314101c16aSPierre Ossman 3324101c16aSPierre Ossman return 0; 3334101c16aSPierre Ossman } 3344101c16aSPierre Ossman 3354101c16aSPierre Ossman /* 3364101c16aSPierre Ossman * Unregister a new MMC card with the driver model, and 3374101c16aSPierre Ossman * (eventually) free it. 3384101c16aSPierre Ossman */ 3394101c16aSPierre Ossman void mmc_remove_card(struct mmc_card *card) 3404101c16aSPierre Ossman { 341f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 342f4b7f927SHaavard Skinnemoen mmc_remove_card_debugfs(card); 343f4b7f927SHaavard Skinnemoen #endif 344f4b7f927SHaavard Skinnemoen 3454101c16aSPierre Ossman if (mmc_card_present(card)) { 346af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 347a3c76eb9SGirish K S pr_info("%s: SPI card removed\n", 348af517150SDavid Brownell mmc_hostname(card->host)); 349af517150SDavid Brownell } else { 350a3c76eb9SGirish K S pr_info("%s: card %04x removed\n", 351109b5bedSPierre Ossman mmc_hostname(card->host), card->rca); 352af517150SDavid Brownell } 3534101c16aSPierre Ossman device_del(&card->dev); 3544101c16aSPierre Ossman } 3554101c16aSPierre Ossman 3564101c16aSPierre Ossman put_device(&card->dev); 3574101c16aSPierre Ossman } 3584101c16aSPierre Ossman 359