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> 174101c16aSPierre Ossman 184101c16aSPierre Ossman #include <linux/mmc/card.h> 194101c16aSPierre Ossman #include <linux/mmc/host.h> 204101c16aSPierre Ossman 214101c16aSPierre Ossman #include "core.h" 221a632f8cSPierre Ossman #include "sdio_cis.h" 234101c16aSPierre Ossman #include "bus.h" 244101c16aSPierre Ossman 254101c16aSPierre Ossman #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) 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 { 314101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_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 { 654101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_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); 1084101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_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); 1164101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_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); 1264101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_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); 1374101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_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 1454101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 1464101c16aSPierre Ossman .name = "mmc", 1474101c16aSPierre Ossman .dev_attrs = mmc_dev_attrs, 1484101c16aSPierre Ossman .match = mmc_bus_match, 1494101c16aSPierre Ossman .uevent = mmc_bus_uevent, 1504101c16aSPierre Ossman .probe = mmc_bus_probe, 1514101c16aSPierre Ossman .remove = mmc_bus_remove, 1524101c16aSPierre Ossman .suspend = mmc_bus_suspend, 1534101c16aSPierre Ossman .resume = mmc_bus_resume, 1544101c16aSPierre Ossman }; 1554101c16aSPierre Ossman 1564101c16aSPierre Ossman int mmc_register_bus(void) 1574101c16aSPierre Ossman { 1584101c16aSPierre Ossman return bus_register(&mmc_bus_type); 1594101c16aSPierre Ossman } 1604101c16aSPierre Ossman 1614101c16aSPierre Ossman void mmc_unregister_bus(void) 1624101c16aSPierre Ossman { 1634101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 1644101c16aSPierre Ossman } 1654101c16aSPierre Ossman 1664101c16aSPierre Ossman /** 1674101c16aSPierre Ossman * mmc_register_driver - register a media driver 1684101c16aSPierre Ossman * @drv: MMC media driver 1694101c16aSPierre Ossman */ 1704101c16aSPierre Ossman int mmc_register_driver(struct mmc_driver *drv) 1714101c16aSPierre Ossman { 1724101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1734101c16aSPierre Ossman return driver_register(&drv->drv); 1744101c16aSPierre Ossman } 1754101c16aSPierre Ossman 1764101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 1774101c16aSPierre Ossman 1784101c16aSPierre Ossman /** 1794101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 1804101c16aSPierre Ossman * @drv: MMC media driver 1814101c16aSPierre Ossman */ 1824101c16aSPierre Ossman void mmc_unregister_driver(struct mmc_driver *drv) 1834101c16aSPierre Ossman { 1844101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1854101c16aSPierre Ossman driver_unregister(&drv->drv); 1864101c16aSPierre Ossman } 1874101c16aSPierre Ossman 1884101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 1894101c16aSPierre Ossman 1904101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 1914101c16aSPierre Ossman { 1924101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1934101c16aSPierre Ossman 1941a632f8cSPierre Ossman sdio_free_common_cis(card); 1951a632f8cSPierre Ossman 196759bdc7aSPierre Ossman if (card->info) 197759bdc7aSPierre Ossman kfree(card->info); 198759bdc7aSPierre Ossman 1994101c16aSPierre Ossman kfree(card); 2004101c16aSPierre Ossman } 2014101c16aSPierre Ossman 2024101c16aSPierre Ossman /* 2034101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 2044101c16aSPierre Ossman */ 20551ec92e2SPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 2064101c16aSPierre Ossman { 2074101c16aSPierre Ossman struct mmc_card *card; 2084101c16aSPierre Ossman 209733cb1e4SMariusz Kozlowski card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 2104101c16aSPierre Ossman if (!card) 2114101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 2124101c16aSPierre Ossman 2134101c16aSPierre Ossman card->host = host; 2144101c16aSPierre Ossman 2154101c16aSPierre Ossman device_initialize(&card->dev); 2164101c16aSPierre Ossman 2174101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2184101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2194101c16aSPierre Ossman card->dev.release = mmc_release_card; 22051ec92e2SPierre Ossman card->dev.type = type; 2214101c16aSPierre Ossman 2224101c16aSPierre Ossman return card; 2234101c16aSPierre Ossman } 2244101c16aSPierre Ossman 2254101c16aSPierre Ossman /* 2264101c16aSPierre Ossman * Register a new MMC card with the driver model. 2274101c16aSPierre Ossman */ 2284101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 2294101c16aSPierre Ossman { 2304101c16aSPierre Ossman int ret; 231109b5bedSPierre Ossman const char *type; 2324101c16aSPierre Ossman 233d1b26863SKay Sievers dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 2344101c16aSPierre Ossman 235109b5bedSPierre Ossman switch (card->type) { 236109b5bedSPierre Ossman case MMC_TYPE_MMC: 237109b5bedSPierre Ossman type = "MMC"; 238109b5bedSPierre Ossman break; 239109b5bedSPierre Ossman case MMC_TYPE_SD: 240109b5bedSPierre Ossman type = "SD"; 241109b5bedSPierre Ossman if (mmc_card_blockaddr(card)) 242109b5bedSPierre Ossman type = "SDHC"; 243109b5bedSPierre Ossman break; 2445c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 2455c4e6f13SPierre Ossman type = "SDIO"; 2465c4e6f13SPierre Ossman break; 2477310ece8SMichal Miroslaw case MMC_TYPE_SD_COMBO: 2487310ece8SMichal Miroslaw type = "SD-combo"; 2497310ece8SMichal Miroslaw if (mmc_card_blockaddr(card)) 2507310ece8SMichal Miroslaw type = "SDHC-combo"; 251109b5bedSPierre Ossman default: 252109b5bedSPierre Ossman type = "?"; 253109b5bedSPierre Ossman break; 254109b5bedSPierre Ossman } 255109b5bedSPierre Ossman 256af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 257af517150SDavid Brownell printk(KERN_INFO "%s: new %s%s card on SPI\n", 258af517150SDavid Brownell mmc_hostname(card->host), 259af517150SDavid Brownell mmc_card_highspeed(card) ? "high speed " : "", 260af517150SDavid Brownell type); 261af517150SDavid Brownell } else { 262109b5bedSPierre Ossman printk(KERN_INFO "%s: new %s%s card at address %04x\n", 263109b5bedSPierre Ossman mmc_hostname(card->host), 264109b5bedSPierre Ossman mmc_card_highspeed(card) ? "high speed " : "", 265109b5bedSPierre Ossman type, card->rca); 266af517150SDavid Brownell } 267109b5bedSPierre Ossman 2684101c16aSPierre Ossman ret = device_add(&card->dev); 2694101c16aSPierre Ossman if (ret) 2704101c16aSPierre Ossman return ret; 2714101c16aSPierre Ossman 272f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 273f4b7f927SHaavard Skinnemoen mmc_add_card_debugfs(card); 274f4b7f927SHaavard Skinnemoen #endif 275f4b7f927SHaavard Skinnemoen 2764101c16aSPierre Ossman mmc_card_set_present(card); 2774101c16aSPierre Ossman 2784101c16aSPierre Ossman return 0; 2794101c16aSPierre Ossman } 2804101c16aSPierre Ossman 2814101c16aSPierre Ossman /* 2824101c16aSPierre Ossman * Unregister a new MMC card with the driver model, and 2834101c16aSPierre Ossman * (eventually) free it. 2844101c16aSPierre Ossman */ 2854101c16aSPierre Ossman void mmc_remove_card(struct mmc_card *card) 2864101c16aSPierre Ossman { 287f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 288f4b7f927SHaavard Skinnemoen mmc_remove_card_debugfs(card); 289f4b7f927SHaavard Skinnemoen #endif 290f4b7f927SHaavard Skinnemoen 2914101c16aSPierre Ossman if (mmc_card_present(card)) { 292af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 293af517150SDavid Brownell printk(KERN_INFO "%s: SPI card removed\n", 294af517150SDavid Brownell mmc_hostname(card->host)); 295af517150SDavid Brownell } else { 296109b5bedSPierre Ossman printk(KERN_INFO "%s: card %04x removed\n", 297109b5bedSPierre Ossman mmc_hostname(card->host), card->rca); 298af517150SDavid Brownell } 2994101c16aSPierre Ossman device_del(&card->dev); 3004101c16aSPierre Ossman } 3014101c16aSPierre Ossman 3024101c16aSPierre Ossman put_device(&card->dev); 3034101c16aSPierre Ossman } 3044101c16aSPierre Ossman 305