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 144101c16aSPierre Ossman #include <linux/device.h> 154101c16aSPierre Ossman #include <linux/err.h> 165a0e3ad6STejun Heo #include <linux/slab.h> 17516d5ccdSOhad Ben-Cohen #include <linux/pm_runtime.h> 184101c16aSPierre Ossman 194101c16aSPierre Ossman #include <linux/mmc/card.h> 204101c16aSPierre Ossman #include <linux/mmc/host.h> 214101c16aSPierre Ossman 224101c16aSPierre Ossman #include "core.h" 231a632f8cSPierre Ossman #include "sdio_cis.h" 244101c16aSPierre Ossman #include "bus.h" 254101c16aSPierre Ossman 264101c16aSPierre Ossman #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) 274101c16aSPierre Ossman 284101c16aSPierre Ossman static ssize_t mmc_type_show(struct device *dev, 294101c16aSPierre Ossman struct device_attribute *attr, char *buf) 304101c16aSPierre Ossman { 31265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 324101c16aSPierre Ossman 334101c16aSPierre Ossman switch (card->type) { 344101c16aSPierre Ossman case MMC_TYPE_MMC: 354101c16aSPierre Ossman return sprintf(buf, "MMC\n"); 364101c16aSPierre Ossman case MMC_TYPE_SD: 374101c16aSPierre Ossman return sprintf(buf, "SD\n"); 385c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 395c4e6f13SPierre Ossman return sprintf(buf, "SDIO\n"); 407310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 417310ece8SMichal Miroslaw return sprintf(buf, "SDcombo\n"); 424101c16aSPierre Ossman default: 434101c16aSPierre Ossman return -EFAULT; 444101c16aSPierre Ossman } 454101c16aSPierre Ossman } 464101c16aSPierre Ossman 474101c16aSPierre Ossman static struct device_attribute mmc_dev_attrs[] = { 4851ec92e2SPierre Ossman __ATTR(type, S_IRUGO, mmc_type_show, NULL), 494101c16aSPierre Ossman __ATTR_NULL, 504101c16aSPierre Ossman }; 514101c16aSPierre Ossman 524101c16aSPierre Ossman /* 534101c16aSPierre Ossman * This currently matches any MMC driver to any MMC card - drivers 544101c16aSPierre Ossman * themselves make the decision whether to drive this card in their 554101c16aSPierre Ossman * probe method. 564101c16aSPierre Ossman */ 574101c16aSPierre Ossman static int mmc_bus_match(struct device *dev, struct device_driver *drv) 584101c16aSPierre Ossman { 594101c16aSPierre Ossman return 1; 604101c16aSPierre Ossman } 614101c16aSPierre Ossman 624101c16aSPierre Ossman static int 637eff2e7aSKay Sievers mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 644101c16aSPierre Ossman { 65265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 669eb3a94dSPierre Ossman const char *type; 677eff2e7aSKay Sievers int retval = 0; 684101c16aSPierre Ossman 694101c16aSPierre Ossman switch (card->type) { 704101c16aSPierre Ossman case MMC_TYPE_MMC: 719eb3a94dSPierre Ossman type = "MMC"; 724101c16aSPierre Ossman break; 734101c16aSPierre Ossman case MMC_TYPE_SD: 749eb3a94dSPierre Ossman type = "SD"; 754101c16aSPierre Ossman break; 765c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 779eb3a94dSPierre Ossman type = "SDIO"; 785c4e6f13SPierre Ossman break; 797310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 807310ece8SMichal Miroslaw type = "SDcombo"; 817310ece8SMichal Miroslaw break; 829eb3a94dSPierre Ossman default: 839eb3a94dSPierre Ossman type = NULL; 844101c16aSPierre Ossman } 854101c16aSPierre Ossman 869eb3a94dSPierre Ossman if (type) { 877eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_TYPE=%s", type); 887eff2e7aSKay Sievers if (retval) 897eff2e7aSKay Sievers return retval; 909eb3a94dSPierre Ossman } 914101c16aSPierre Ossman 927eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); 936b0b6285SAndy Whitcroft if (retval) 946b0b6285SAndy Whitcroft return retval; 956b0b6285SAndy Whitcroft 966b0b6285SAndy Whitcroft /* 976b0b6285SAndy Whitcroft * Request the mmc_block device. Note: that this is a direct request 986b0b6285SAndy Whitcroft * for the module it carries no information as to what is inserted. 996b0b6285SAndy Whitcroft */ 1006b0b6285SAndy Whitcroft retval = add_uevent_var(env, "MODALIAS=mmc:block"); 1014101c16aSPierre Ossman 1027eff2e7aSKay Sievers return retval; 1034101c16aSPierre Ossman } 1044101c16aSPierre Ossman 1054101c16aSPierre Ossman static int mmc_bus_probe(struct device *dev) 1064101c16aSPierre Ossman { 1074101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 108265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1094101c16aSPierre Ossman 1104101c16aSPierre Ossman return drv->probe(card); 1114101c16aSPierre Ossman } 1124101c16aSPierre Ossman 1134101c16aSPierre Ossman static int mmc_bus_remove(struct device *dev) 1144101c16aSPierre Ossman { 1154101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 116265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1174101c16aSPierre Ossman 1184101c16aSPierre Ossman drv->remove(card); 1194101c16aSPierre Ossman 1204101c16aSPierre Ossman return 0; 1214101c16aSPierre Ossman } 1224101c16aSPierre Ossman 1234101c16aSPierre Ossman static int mmc_bus_suspend(struct device *dev, pm_message_t state) 1244101c16aSPierre Ossman { 1254101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 126265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1274101c16aSPierre Ossman int ret = 0; 1284101c16aSPierre Ossman 1294101c16aSPierre Ossman if (dev->driver && drv->suspend) 1304101c16aSPierre Ossman ret = drv->suspend(card, state); 1314101c16aSPierre Ossman return ret; 1324101c16aSPierre Ossman } 1334101c16aSPierre Ossman 1344101c16aSPierre Ossman static int mmc_bus_resume(struct device *dev) 1354101c16aSPierre Ossman { 1364101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 137265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 1384101c16aSPierre Ossman int ret = 0; 1394101c16aSPierre Ossman 1404101c16aSPierre Ossman if (dev->driver && drv->resume) 1414101c16aSPierre Ossman ret = drv->resume(card); 1424101c16aSPierre Ossman return ret; 1434101c16aSPierre Ossman } 1444101c16aSPierre Ossman 145516d5ccdSOhad Ben-Cohen #ifdef CONFIG_PM_RUNTIME 146516d5ccdSOhad Ben-Cohen 147516d5ccdSOhad Ben-Cohen static int mmc_runtime_suspend(struct device *dev) 148516d5ccdSOhad Ben-Cohen { 149516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 150516d5ccdSOhad Ben-Cohen 151516d5ccdSOhad Ben-Cohen return mmc_power_save_host(card->host); 152516d5ccdSOhad Ben-Cohen } 153516d5ccdSOhad Ben-Cohen 154516d5ccdSOhad Ben-Cohen static int mmc_runtime_resume(struct device *dev) 155516d5ccdSOhad Ben-Cohen { 156516d5ccdSOhad Ben-Cohen struct mmc_card *card = mmc_dev_to_card(dev); 157516d5ccdSOhad Ben-Cohen 158516d5ccdSOhad Ben-Cohen return mmc_power_restore_host(card->host); 159516d5ccdSOhad Ben-Cohen } 160516d5ccdSOhad Ben-Cohen 161516d5ccdSOhad Ben-Cohen static int mmc_runtime_idle(struct device *dev) 162516d5ccdSOhad Ben-Cohen { 163516d5ccdSOhad Ben-Cohen return pm_runtime_suspend(dev); 164516d5ccdSOhad Ben-Cohen } 165516d5ccdSOhad Ben-Cohen 166516d5ccdSOhad Ben-Cohen static const struct dev_pm_ops mmc_bus_pm_ops = { 167516d5ccdSOhad Ben-Cohen .runtime_suspend = mmc_runtime_suspend, 168516d5ccdSOhad Ben-Cohen .runtime_resume = mmc_runtime_resume, 169516d5ccdSOhad Ben-Cohen .runtime_idle = mmc_runtime_idle, 170516d5ccdSOhad Ben-Cohen }; 171516d5ccdSOhad Ben-Cohen 172516d5ccdSOhad Ben-Cohen #define MMC_PM_OPS_PTR (&mmc_bus_pm_ops) 173516d5ccdSOhad Ben-Cohen 174516d5ccdSOhad Ben-Cohen #else /* !CONFIG_PM_RUNTIME */ 175516d5ccdSOhad Ben-Cohen 176516d5ccdSOhad Ben-Cohen #define MMC_PM_OPS_PTR NULL 177516d5ccdSOhad Ben-Cohen 178516d5ccdSOhad Ben-Cohen #endif /* !CONFIG_PM_RUNTIME */ 179516d5ccdSOhad Ben-Cohen 1804101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 1814101c16aSPierre Ossman .name = "mmc", 1824101c16aSPierre Ossman .dev_attrs = mmc_dev_attrs, 1834101c16aSPierre Ossman .match = mmc_bus_match, 1844101c16aSPierre Ossman .uevent = mmc_bus_uevent, 1854101c16aSPierre Ossman .probe = mmc_bus_probe, 1864101c16aSPierre Ossman .remove = mmc_bus_remove, 1874101c16aSPierre Ossman .suspend = mmc_bus_suspend, 1884101c16aSPierre Ossman .resume = mmc_bus_resume, 189516d5ccdSOhad Ben-Cohen .pm = MMC_PM_OPS_PTR, 1904101c16aSPierre Ossman }; 1914101c16aSPierre Ossman 1924101c16aSPierre Ossman int mmc_register_bus(void) 1934101c16aSPierre Ossman { 1944101c16aSPierre Ossman return bus_register(&mmc_bus_type); 1954101c16aSPierre Ossman } 1964101c16aSPierre Ossman 1974101c16aSPierre Ossman void mmc_unregister_bus(void) 1984101c16aSPierre Ossman { 1994101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 2004101c16aSPierre Ossman } 2014101c16aSPierre Ossman 2024101c16aSPierre Ossman /** 2034101c16aSPierre Ossman * mmc_register_driver - register a media driver 2044101c16aSPierre Ossman * @drv: MMC media driver 2054101c16aSPierre Ossman */ 2064101c16aSPierre Ossman int mmc_register_driver(struct mmc_driver *drv) 2074101c16aSPierre Ossman { 2084101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 2094101c16aSPierre Ossman return driver_register(&drv->drv); 2104101c16aSPierre Ossman } 2114101c16aSPierre Ossman 2124101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 2134101c16aSPierre Ossman 2144101c16aSPierre Ossman /** 2154101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 2164101c16aSPierre Ossman * @drv: MMC media driver 2174101c16aSPierre Ossman */ 2184101c16aSPierre Ossman void mmc_unregister_driver(struct mmc_driver *drv) 2194101c16aSPierre Ossman { 2204101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 2214101c16aSPierre Ossman driver_unregister(&drv->drv); 2224101c16aSPierre Ossman } 2234101c16aSPierre Ossman 2244101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 2254101c16aSPierre Ossman 2264101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 2274101c16aSPierre Ossman { 228265cdc90SAndy Shevchenko struct mmc_card *card = mmc_dev_to_card(dev); 2294101c16aSPierre Ossman 2301a632f8cSPierre Ossman sdio_free_common_cis(card); 2311a632f8cSPierre Ossman 232759bdc7aSPierre Ossman if (card->info) 233759bdc7aSPierre Ossman kfree(card->info); 234759bdc7aSPierre Ossman 2354101c16aSPierre Ossman kfree(card); 2364101c16aSPierre Ossman } 2374101c16aSPierre Ossman 2384101c16aSPierre Ossman /* 2394101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 2404101c16aSPierre Ossman */ 24151ec92e2SPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 2424101c16aSPierre Ossman { 2434101c16aSPierre Ossman struct mmc_card *card; 2444101c16aSPierre Ossman 245733cb1e4SMariusz Kozlowski card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 2464101c16aSPierre Ossman if (!card) 2474101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 2484101c16aSPierre Ossman 2494101c16aSPierre Ossman card->host = host; 2504101c16aSPierre Ossman 2514101c16aSPierre Ossman device_initialize(&card->dev); 2524101c16aSPierre Ossman 2534101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2544101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2554101c16aSPierre Ossman card->dev.release = mmc_release_card; 25651ec92e2SPierre Ossman card->dev.type = type; 2574101c16aSPierre Ossman 2584101c16aSPierre Ossman return card; 2594101c16aSPierre Ossman } 2604101c16aSPierre Ossman 2614101c16aSPierre Ossman /* 2624101c16aSPierre Ossman * Register a new MMC card with the driver model. 2634101c16aSPierre Ossman */ 2644101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 2654101c16aSPierre Ossman { 2664101c16aSPierre Ossman int ret; 267109b5bedSPierre Ossman const char *type; 2684101c16aSPierre Ossman 269d1b26863SKay Sievers dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 2704101c16aSPierre Ossman 271109b5bedSPierre Ossman switch (card->type) { 272109b5bedSPierre Ossman case MMC_TYPE_MMC: 273109b5bedSPierre Ossman type = "MMC"; 274109b5bedSPierre Ossman break; 275109b5bedSPierre Ossman case MMC_TYPE_SD: 276109b5bedSPierre Ossman type = "SD"; 277109b5bedSPierre Ossman if (mmc_card_blockaddr(card)) 278109b5bedSPierre Ossman type = "SDHC"; 279109b5bedSPierre Ossman break; 2805c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 2815c4e6f13SPierre Ossman type = "SDIO"; 2825c4e6f13SPierre Ossman break; 2837310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 2847310ece8SMichal Miroslaw type = "SD-combo"; 2857310ece8SMichal Miroslaw if (mmc_card_blockaddr(card)) 2867310ece8SMichal Miroslaw type = "SDHC-combo"; 2879bc21848SMichał Mirosław break; 288109b5bedSPierre Ossman default: 289109b5bedSPierre Ossman type = "?"; 290109b5bedSPierre Ossman break; 291109b5bedSPierre Ossman } 292109b5bedSPierre Ossman 293af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 2940f8d8ea6SAdrian Hunter printk(KERN_INFO "%s: new %s%s%s card on SPI\n", 295af517150SDavid Brownell mmc_hostname(card->host), 296af517150SDavid Brownell mmc_card_highspeed(card) ? "high speed " : "", 2970f8d8ea6SAdrian Hunter mmc_card_ddr_mode(card) ? "DDR " : "", 298af517150SDavid Brownell type); 299af517150SDavid Brownell } else { 3000f8d8ea6SAdrian Hunter printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", 301109b5bedSPierre Ossman mmc_hostname(card->host), 302109b5bedSPierre Ossman mmc_card_highspeed(card) ? "high speed " : "", 3030f8d8ea6SAdrian Hunter mmc_card_ddr_mode(card) ? "DDR " : "", 304109b5bedSPierre Ossman type, card->rca); 305af517150SDavid Brownell } 306109b5bedSPierre Ossman 307f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 308f4b7f927SHaavard Skinnemoen mmc_add_card_debugfs(card); 309f4b7f927SHaavard Skinnemoen #endif 310f4b7f927SHaavard Skinnemoen 3111a2727e9SViresh Kumar ret = device_add(&card->dev); 3121a2727e9SViresh Kumar if (ret) 3131a2727e9SViresh Kumar return ret; 3141a2727e9SViresh Kumar 3154101c16aSPierre Ossman mmc_card_set_present(card); 3164101c16aSPierre Ossman 3174101c16aSPierre Ossman return 0; 3184101c16aSPierre Ossman } 3194101c16aSPierre Ossman 3204101c16aSPierre Ossman /* 3214101c16aSPierre Ossman * Unregister a new MMC card with the driver model, and 3224101c16aSPierre Ossman * (eventually) free it. 3234101c16aSPierre Ossman */ 3244101c16aSPierre Ossman void mmc_remove_card(struct mmc_card *card) 3254101c16aSPierre Ossman { 326f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 327f4b7f927SHaavard Skinnemoen mmc_remove_card_debugfs(card); 328f4b7f927SHaavard Skinnemoen #endif 329f4b7f927SHaavard Skinnemoen 3304101c16aSPierre Ossman if (mmc_card_present(card)) { 331af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 332af517150SDavid Brownell printk(KERN_INFO "%s: SPI card removed\n", 333af517150SDavid Brownell mmc_hostname(card->host)); 334af517150SDavid Brownell } else { 335109b5bedSPierre Ossman printk(KERN_INFO "%s: card %04x removed\n", 336109b5bedSPierre Ossman mmc_hostname(card->host), card->rca); 337af517150SDavid Brownell } 3384101c16aSPierre Ossman device_del(&card->dev); 3394101c16aSPierre Ossman } 3404101c16aSPierre Ossman 3414101c16aSPierre Ossman put_device(&card->dev); 3424101c16aSPierre Ossman } 3434101c16aSPierre Ossman 344