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> 1925185f3fSSascha Hauer #include <linux/of.h> 20516d5ccdSOhad Ben-Cohen #include <linux/pm_runtime.h> 214101c16aSPierre Ossman 224101c16aSPierre Ossman #include <linux/mmc/card.h> 234101c16aSPierre Ossman #include <linux/mmc/host.h> 244101c16aSPierre Ossman 254101c16aSPierre Ossman #include "core.h" 261a632f8cSPierre Ossman #include "sdio_cis.h" 274101c16aSPierre Ossman #include "bus.h" 284101c16aSPierre Ossman 2996541bacSUlf Hansson #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) 3096541bacSUlf Hansson 31f24fc57bSGreg Kroah-Hartman static ssize_t type_show(struct device *dev, 324101c16aSPierre Ossman struct device_attribute *attr, char *buf) 334101c16aSPierre Ossman { 34265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 354101c16aSPierre Ossman 364101c16aSPierre Ossman switch (card->type) { 374101c16aSPierre Ossman case MMC_TYPE_MMC: 384101c16aSPierre Ossman return sprintf(buf, "MMC\n"); 394101c16aSPierre Ossman case MMC_TYPE_SD: 404101c16aSPierre Ossman return sprintf(buf, "SD\n"); 415c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 425c4e6f13SPierre Ossman return sprintf(buf, "SDIO\n"); 437310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 447310ece8SMichal Miroslaw return sprintf(buf, "SDcombo\n"); 454101c16aSPierre Ossman default: 464101c16aSPierre Ossman return -EFAULT; 474101c16aSPierre Ossman } 484101c16aSPierre Ossman } 49f24fc57bSGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 504101c16aSPierre Ossman 51f24fc57bSGreg Kroah-Hartman static struct attribute *mmc_dev_attrs[] = { 52f24fc57bSGreg Kroah-Hartman &dev_attr_type.attr, 53f24fc57bSGreg Kroah-Hartman NULL, 544101c16aSPierre Ossman }; 55f24fc57bSGreg Kroah-Hartman ATTRIBUTE_GROUPS(mmc_dev); 564101c16aSPierre Ossman 574101c16aSPierre Ossman /* 584101c16aSPierre Ossman * This currently matches any MMC driver to any MMC card - drivers 594101c16aSPierre Ossman * themselves make the decision whether to drive this card in their 604101c16aSPierre Ossman * probe method. 614101c16aSPierre Ossman */ 624101c16aSPierre Ossman static int mmc_bus_match(struct device *dev, struct device_driver *drv) 634101c16aSPierre Ossman { 644101c16aSPierre Ossman return 1; 654101c16aSPierre Ossman } 664101c16aSPierre Ossman 674101c16aSPierre Ossman static int 687eff2e7aSKay Sievers mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 694101c16aSPierre Ossman { 70265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 719eb3a94dSPierre Ossman const char *type; 727eff2e7aSKay Sievers int retval = 0; 734101c16aSPierre Ossman 744101c16aSPierre Ossman switch (card->type) { 754101c16aSPierre Ossman case MMC_TYPE_MMC: 769eb3a94dSPierre Ossman type = "MMC"; 774101c16aSPierre Ossman break; 784101c16aSPierre Ossman case MMC_TYPE_SD: 799eb3a94dSPierre Ossman type = "SD"; 804101c16aSPierre Ossman break; 815c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 829eb3a94dSPierre Ossman type = "SDIO"; 835c4e6f13SPierre Ossman break; 847310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 857310ece8SMichal Miroslaw type = "SDcombo"; 867310ece8SMichal Miroslaw break; 879eb3a94dSPierre Ossman default: 889eb3a94dSPierre Ossman type = NULL; 894101c16aSPierre Ossman } 904101c16aSPierre Ossman 919eb3a94dSPierre Ossman if (type) { 927eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_TYPE=%s", type); 937eff2e7aSKay Sievers if (retval) 947eff2e7aSKay Sievers return retval; 959eb3a94dSPierre Ossman } 964101c16aSPierre Ossman 977eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); 986b0b6285SAndy Whitcroft if (retval) 996b0b6285SAndy Whitcroft return retval; 1006b0b6285SAndy Whitcroft 1016b0b6285SAndy Whitcroft /* 1026b0b6285SAndy Whitcroft * Request the mmc_block device. Note: that this is a direct request 1036b0b6285SAndy Whitcroft * for the module it carries no information as to what is inserted. 1046b0b6285SAndy Whitcroft */ 1056b0b6285SAndy Whitcroft retval = add_uevent_var(env, "MODALIAS=mmc:block"); 1064101c16aSPierre Ossman 1077eff2e7aSKay Sievers return retval; 1084101c16aSPierre Ossman } 1094101c16aSPierre Ossman 11096541bacSUlf Hansson static int mmc_bus_probe(struct device *dev) 11196541bacSUlf Hansson { 11296541bacSUlf Hansson struct mmc_driver *drv = to_mmc_driver(dev->driver); 11396541bacSUlf Hansson struct mmc_card *card = mmc_dev_to_card(dev); 11496541bacSUlf Hansson 11596541bacSUlf Hansson return drv->probe(card); 11696541bacSUlf Hansson } 11796541bacSUlf Hansson 11896541bacSUlf Hansson static int mmc_bus_remove(struct device *dev) 11996541bacSUlf Hansson { 12096541bacSUlf Hansson struct mmc_driver *drv = to_mmc_driver(dev->driver); 12196541bacSUlf Hansson struct mmc_card *card = mmc_dev_to_card(dev); 12296541bacSUlf Hansson 12396541bacSUlf Hansson drv->remove(card); 12496541bacSUlf Hansson 12596541bacSUlf Hansson return 0; 12696541bacSUlf Hansson } 12796541bacSUlf Hansson 12876287748SUlf Hansson static void mmc_bus_shutdown(struct device *dev) 12976287748SUlf Hansson { 13096541bacSUlf Hansson struct mmc_driver *drv = to_mmc_driver(dev->driver); 13176287748SUlf Hansson struct mmc_card *card = mmc_dev_to_card(dev); 1326b086bdeSUlf Hansson struct mmc_host *host = card->host; 1336b086bdeSUlf Hansson int ret; 13476287748SUlf Hansson 13596541bacSUlf Hansson if (dev->driver && drv->shutdown) 13696541bacSUlf Hansson drv->shutdown(card); 1376b086bdeSUlf Hansson 1386b086bdeSUlf Hansson if (host->bus_ops->shutdown) { 1396b086bdeSUlf Hansson ret = host->bus_ops->shutdown(host); 1406b086bdeSUlf Hansson if (ret) 1416b086bdeSUlf Hansson pr_warn("%s: error %d during shutdown\n", 1426b086bdeSUlf Hansson mmc_hostname(host), ret); 1436b086bdeSUlf Hansson } 14476287748SUlf Hansson } 14576287748SUlf Hansson 1460dd1bfebSChuanxiao Dong #ifdef CONFIG_PM_SLEEP 14732d317c6SChuanxiao Dong static int mmc_bus_suspend(struct device *dev) 1484101c16aSPierre Ossman { 149265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 150986892caSUlf Hansson struct mmc_host *host = card->host; 151986892caSUlf Hansson int ret; 1524101c16aSPierre Ossman 1530967edc6SUlf Hansson ret = pm_generic_suspend(dev); 154986892caSUlf Hansson if (ret) 155986892caSUlf Hansson return ret; 156986892caSUlf Hansson 157986892caSUlf Hansson ret = host->bus_ops->suspend(host); 1584101c16aSPierre Ossman return ret; 1594101c16aSPierre Ossman } 1604101c16aSPierre Ossman 1614101c16aSPierre Ossman static int mmc_bus_resume(struct device *dev) 1624101c16aSPierre Ossman { 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 1720967edc6SUlf Hansson ret = pm_generic_resume(dev); 1734101c16aSPierre Ossman return ret; 1744101c16aSPierre Ossman } 1750dd1bfebSChuanxiao Dong #endif 1764101c16aSPierre Ossman 177162d6f98SRafael J. Wysocki #ifdef CONFIG_PM 178516d5ccdSOhad Ben-Cohen static int mmc_runtime_suspend(struct device *dev) 179516d5ccdSOhad Ben-Cohen { 180516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 18112d01d0bSUlf Hansson struct mmc_host *host = card->host; 182516d5ccdSOhad Ben-Cohen 1835601aaf7SUlf Hansson return host->bus_ops->runtime_suspend(host); 184516d5ccdSOhad Ben-Cohen } 185516d5ccdSOhad Ben-Cohen 186516d5ccdSOhad Ben-Cohen static int mmc_runtime_resume(struct device *dev) 187516d5ccdSOhad Ben-Cohen { 188516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 18912d01d0bSUlf Hansson struct mmc_host *host = card->host; 190516d5ccdSOhad Ben-Cohen 1915601aaf7SUlf Hansson return host->bus_ops->runtime_resume(host); 192516d5ccdSOhad Ben-Cohen } 193162d6f98SRafael J. Wysocki #endif /* !CONFIG_PM */ 194516d5ccdSOhad Ben-Cohen 19532d317c6SChuanxiao Dong static const struct dev_pm_ops mmc_bus_pm_ops = { 1962e42da59SUlf Hansson SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, NULL) 19732d317c6SChuanxiao Dong SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) 19832d317c6SChuanxiao Dong }; 19932d317c6SChuanxiao Dong 2004101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 2014101c16aSPierre Ossman .name = "mmc", 202f24fc57bSGreg Kroah-Hartman .dev_groups = mmc_dev_groups, 2034101c16aSPierre Ossman .match = mmc_bus_match, 2044101c16aSPierre Ossman .uevent = mmc_bus_uevent, 20596541bacSUlf Hansson .probe = mmc_bus_probe, 20696541bacSUlf Hansson .remove = mmc_bus_remove, 20776287748SUlf Hansson .shutdown = mmc_bus_shutdown, 20832d317c6SChuanxiao Dong .pm = &mmc_bus_pm_ops, 2094101c16aSPierre Ossman }; 2104101c16aSPierre Ossman 2114101c16aSPierre Ossman int mmc_register_bus(void) 2124101c16aSPierre Ossman { 2134101c16aSPierre Ossman return bus_register(&mmc_bus_type); 2144101c16aSPierre Ossman } 2154101c16aSPierre Ossman 2164101c16aSPierre Ossman void mmc_unregister_bus(void) 2174101c16aSPierre Ossman { 2184101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 2194101c16aSPierre Ossman } 2204101c16aSPierre Ossman 2214101c16aSPierre Ossman /** 2224101c16aSPierre Ossman * mmc_register_driver - register a media driver 2234101c16aSPierre Ossman * @drv: MMC media driver 2244101c16aSPierre Ossman */ 22596541bacSUlf Hansson int mmc_register_driver(struct mmc_driver *drv) 2264101c16aSPierre Ossman { 22796541bacSUlf Hansson drv->drv.bus = &mmc_bus_type; 22896541bacSUlf Hansson return driver_register(&drv->drv); 2294101c16aSPierre Ossman } 23096541bacSUlf Hansson 2314101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 2324101c16aSPierre Ossman 2334101c16aSPierre Ossman /** 2344101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 2354101c16aSPierre Ossman * @drv: MMC media driver 2364101c16aSPierre Ossman */ 23796541bacSUlf Hansson void mmc_unregister_driver(struct mmc_driver *drv) 2384101c16aSPierre Ossman { 23996541bacSUlf Hansson drv->drv.bus = &mmc_bus_type; 24096541bacSUlf Hansson driver_unregister(&drv->drv); 2414101c16aSPierre Ossman } 24296541bacSUlf Hansson 2434101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 2444101c16aSPierre Ossman 2454101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 2464101c16aSPierre Ossman { 247265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 2484101c16aSPierre Ossman 2491a632f8cSPierre Ossman sdio_free_common_cis(card); 2501a632f8cSPierre Ossman 251759bdc7aSPierre Ossman kfree(card->info); 252759bdc7aSPierre Ossman 2534101c16aSPierre Ossman kfree(card); 2544101c16aSPierre Ossman } 2554101c16aSPierre Ossman 2564101c16aSPierre Ossman /* 2574101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 2584101c16aSPierre Ossman */ 25951ec92e2SPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 2604101c16aSPierre Ossman { 2614101c16aSPierre Ossman struct mmc_card *card; 2624101c16aSPierre Ossman 263733cb1e4SMariusz Kozlowski card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 2644101c16aSPierre Ossman if (!card) 2654101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 2664101c16aSPierre Ossman 2674101c16aSPierre Ossman card->host = host; 2684101c16aSPierre Ossman 2694101c16aSPierre Ossman device_initialize(&card->dev); 2704101c16aSPierre Ossman 2714101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2724101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2734101c16aSPierre Ossman card->dev.release = mmc_release_card; 27451ec92e2SPierre Ossman card->dev.type = type; 2754101c16aSPierre Ossman 2764101c16aSPierre Ossman return card; 2774101c16aSPierre Ossman } 2784101c16aSPierre Ossman 2794101c16aSPierre Ossman /* 2804101c16aSPierre Ossman * Register a new MMC card with the driver model. 2814101c16aSPierre Ossman */ 2824101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 2834101c16aSPierre Ossman { 2844101c16aSPierre Ossman int ret; 285109b5bedSPierre Ossman const char *type; 2866500c8edSSubhash Jadavani const char *uhs_bus_speed_mode = ""; 2876500c8edSSubhash Jadavani static const char *const uhs_speeds[] = { 2886500c8edSSubhash Jadavani [UHS_SDR12_BUS_SPEED] = "SDR12 ", 2896500c8edSSubhash Jadavani [UHS_SDR25_BUS_SPEED] = "SDR25 ", 2906500c8edSSubhash Jadavani [UHS_SDR50_BUS_SPEED] = "SDR50 ", 2916500c8edSSubhash Jadavani [UHS_SDR104_BUS_SPEED] = "SDR104 ", 2926500c8edSSubhash Jadavani [UHS_DDR50_BUS_SPEED] = "DDR50 ", 2936500c8edSSubhash Jadavani }; 2946500c8edSSubhash Jadavani 2954101c16aSPierre Ossman 296d1b26863SKay Sievers dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 2974101c16aSPierre Ossman 298109b5bedSPierre Ossman switch (card->type) { 299109b5bedSPierre Ossman case MMC_TYPE_MMC: 300109b5bedSPierre Ossman type = "MMC"; 301109b5bedSPierre Ossman break; 302109b5bedSPierre Ossman case MMC_TYPE_SD: 303109b5bedSPierre Ossman type = "SD"; 3043a303511SArindam Nath if (mmc_card_blockaddr(card)) { 3053a303511SArindam Nath if (mmc_card_ext_capacity(card)) 3063a303511SArindam Nath type = "SDXC"; 3073a303511SArindam Nath else 308109b5bedSPierre Ossman type = "SDHC"; 3093a303511SArindam Nath } 310109b5bedSPierre Ossman break; 3115c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 3125c4e6f13SPierre Ossman type = "SDIO"; 3135c4e6f13SPierre Ossman break; 3147310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 3157310ece8SMichal Miroslaw type = "SD-combo"; 3167310ece8SMichal Miroslaw if (mmc_card_blockaddr(card)) 3177310ece8SMichal Miroslaw type = "SDHC-combo"; 3189bc21848SMichał Mirosław break; 319109b5bedSPierre Ossman default: 320109b5bedSPierre Ossman type = "?"; 321109b5bedSPierre Ossman break; 322109b5bedSPierre Ossman } 323109b5bedSPierre Ossman 32471ef1ea4SJackey Shen if (mmc_card_uhs(card) && 3256500c8edSSubhash Jadavani (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) 3266500c8edSSubhash Jadavani uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; 3276500c8edSSubhash Jadavani 328af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 329a3c76eb9SGirish K S pr_info("%s: new %s%s%s card on SPI\n", 330af517150SDavid Brownell mmc_hostname(card->host), 331cdc99179SSeungwon Jeon mmc_card_hs(card) ? "high speed " : "", 332cdc99179SSeungwon Jeon mmc_card_ddr52(card) ? "DDR " : "", 333af517150SDavid Brownell type); 334af517150SDavid Brownell } else { 3356500c8edSSubhash Jadavani pr_info("%s: new %s%s%s%s%s card at address %04x\n", 336109b5bedSPierre Ossman mmc_hostname(card->host), 337a303c531SPhilip Rakity mmc_card_uhs(card) ? "ultra high speed " : 338cdc99179SSeungwon Jeon (mmc_card_hs(card) ? "high speed " : ""), 3390a5b6438SSeungwon Jeon mmc_card_hs400(card) ? "HS400 " : 340a4924c71SGirish K S (mmc_card_hs200(card) ? "HS200 " : ""), 341cdc99179SSeungwon Jeon mmc_card_ddr52(card) ? "DDR " : "", 3426500c8edSSubhash Jadavani uhs_bus_speed_mode, type, card->rca); 343af517150SDavid Brownell } 344109b5bedSPierre Ossman 345f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 346f4b7f927SHaavard Skinnemoen mmc_add_card_debugfs(card); 347f4b7f927SHaavard Skinnemoen #endif 3482220eedfSKonstantin Dorfman mmc_init_context_info(card->host); 349f4b7f927SHaavard Skinnemoen 35025185f3fSSascha Hauer card->dev.of_node = mmc_of_find_child_device(card->host, 0); 35125185f3fSSascha Hauer 3521a2727e9SViresh Kumar ret = device_add(&card->dev); 3531a2727e9SViresh Kumar if (ret) 3541a2727e9SViresh Kumar return ret; 3551a2727e9SViresh Kumar 3564101c16aSPierre Ossman mmc_card_set_present(card); 3574101c16aSPierre Ossman 3584101c16aSPierre Ossman return 0; 3594101c16aSPierre Ossman } 3604101c16aSPierre Ossman 3614101c16aSPierre Ossman /* 3624101c16aSPierre Ossman * Unregister a new MMC card with the driver model, and 3634101c16aSPierre Ossman * (eventually) free it. 3644101c16aSPierre Ossman */ 3654101c16aSPierre Ossman void mmc_remove_card(struct mmc_card *card) 3664101c16aSPierre Ossman { 367f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 368f4b7f927SHaavard Skinnemoen mmc_remove_card_debugfs(card); 369f4b7f927SHaavard Skinnemoen #endif 370f4b7f927SHaavard Skinnemoen 3714101c16aSPierre Ossman if (mmc_card_present(card)) { 372af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 373a3c76eb9SGirish K S pr_info("%s: SPI card removed\n", 374af517150SDavid Brownell mmc_hostname(card->host)); 375af517150SDavid Brownell } else { 376a3c76eb9SGirish K S pr_info("%s: card %04x removed\n", 377109b5bedSPierre Ossman mmc_hostname(card->host), card->rca); 378af517150SDavid Brownell } 3794101c16aSPierre Ossman device_del(&card->dev); 38025185f3fSSascha Hauer of_node_put(card->dev.of_node); 3814101c16aSPierre Ossman } 3824101c16aSPierre Ossman 3834101c16aSPierre Ossman put_device(&card->dev); 3844101c16aSPierre Ossman } 3854101c16aSPierre Ossman 386