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> 164101c16aSPierre Ossman 174101c16aSPierre Ossman #include <linux/mmc/card.h> 184101c16aSPierre Ossman #include <linux/mmc/host.h> 194101c16aSPierre Ossman 204101c16aSPierre Ossman #include "core.h" 211a632f8cSPierre Ossman #include "sdio_cis.h" 224101c16aSPierre Ossman #include "bus.h" 234101c16aSPierre Ossman 244101c16aSPierre Ossman #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) 254101c16aSPierre Ossman #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) 264101c16aSPierre Ossman 274101c16aSPierre Ossman static ssize_t mmc_type_show(struct device *dev, 284101c16aSPierre Ossman struct device_attribute *attr, char *buf) 294101c16aSPierre Ossman { 304101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 314101c16aSPierre Ossman 324101c16aSPierre Ossman switch (card->type) { 334101c16aSPierre Ossman case MMC_TYPE_MMC: 344101c16aSPierre Ossman return sprintf(buf, "MMC\n"); 354101c16aSPierre Ossman case MMC_TYPE_SD: 364101c16aSPierre Ossman return sprintf(buf, "SD\n"); 375c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 385c4e6f13SPierre Ossman return sprintf(buf, "SDIO\n"); 394101c16aSPierre Ossman default: 404101c16aSPierre Ossman return -EFAULT; 414101c16aSPierre Ossman } 424101c16aSPierre Ossman } 434101c16aSPierre Ossman 444101c16aSPierre Ossman static struct device_attribute mmc_dev_attrs[] = { 4551ec92e2SPierre Ossman __ATTR(type, S_IRUGO, mmc_type_show, NULL), 464101c16aSPierre Ossman __ATTR_NULL, 474101c16aSPierre Ossman }; 484101c16aSPierre Ossman 494101c16aSPierre Ossman /* 504101c16aSPierre Ossman * This currently matches any MMC driver to any MMC card - drivers 514101c16aSPierre Ossman * themselves make the decision whether to drive this card in their 524101c16aSPierre Ossman * probe method. 534101c16aSPierre Ossman */ 544101c16aSPierre Ossman static int mmc_bus_match(struct device *dev, struct device_driver *drv) 554101c16aSPierre Ossman { 564101c16aSPierre Ossman return 1; 574101c16aSPierre Ossman } 584101c16aSPierre Ossman 594101c16aSPierre Ossman static int 607eff2e7aSKay Sievers mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 614101c16aSPierre Ossman { 624101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 639eb3a94dSPierre Ossman const char *type; 647eff2e7aSKay Sievers int retval = 0; 654101c16aSPierre Ossman 664101c16aSPierre Ossman switch (card->type) { 674101c16aSPierre Ossman case MMC_TYPE_MMC: 689eb3a94dSPierre Ossman type = "MMC"; 694101c16aSPierre Ossman break; 704101c16aSPierre Ossman case MMC_TYPE_SD: 719eb3a94dSPierre Ossman type = "SD"; 724101c16aSPierre Ossman break; 735c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 749eb3a94dSPierre Ossman type = "SDIO"; 755c4e6f13SPierre Ossman break; 769eb3a94dSPierre Ossman default: 779eb3a94dSPierre Ossman type = NULL; 784101c16aSPierre Ossman } 794101c16aSPierre Ossman 809eb3a94dSPierre Ossman if (type) { 817eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_TYPE=%s", type); 827eff2e7aSKay Sievers if (retval) 837eff2e7aSKay Sievers return retval; 849eb3a94dSPierre Ossman } 854101c16aSPierre Ossman 867eff2e7aSKay Sievers retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); 874101c16aSPierre Ossman 887eff2e7aSKay Sievers return retval; 894101c16aSPierre Ossman } 904101c16aSPierre Ossman 914101c16aSPierre Ossman static int mmc_bus_probe(struct device *dev) 924101c16aSPierre Ossman { 934101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 944101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 954101c16aSPierre Ossman 964101c16aSPierre Ossman return drv->probe(card); 974101c16aSPierre Ossman } 984101c16aSPierre Ossman 994101c16aSPierre Ossman static int mmc_bus_remove(struct device *dev) 1004101c16aSPierre Ossman { 1014101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1024101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1034101c16aSPierre Ossman 1044101c16aSPierre Ossman drv->remove(card); 1054101c16aSPierre Ossman 1064101c16aSPierre Ossman return 0; 1074101c16aSPierre Ossman } 1084101c16aSPierre Ossman 1094101c16aSPierre Ossman static int mmc_bus_suspend(struct device *dev, pm_message_t state) 1104101c16aSPierre Ossman { 1114101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1124101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1134101c16aSPierre Ossman int ret = 0; 1144101c16aSPierre Ossman 1154101c16aSPierre Ossman if (dev->driver && drv->suspend) 1164101c16aSPierre Ossman ret = drv->suspend(card, state); 1174101c16aSPierre Ossman return ret; 1184101c16aSPierre Ossman } 1194101c16aSPierre Ossman 1204101c16aSPierre Ossman static int mmc_bus_resume(struct device *dev) 1214101c16aSPierre Ossman { 1224101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1234101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1244101c16aSPierre Ossman int ret = 0; 1254101c16aSPierre Ossman 1264101c16aSPierre Ossman if (dev->driver && drv->resume) 1274101c16aSPierre Ossman ret = drv->resume(card); 1284101c16aSPierre Ossman return ret; 1294101c16aSPierre Ossman } 1304101c16aSPierre Ossman 1314101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 1324101c16aSPierre Ossman .name = "mmc", 1334101c16aSPierre Ossman .dev_attrs = mmc_dev_attrs, 1344101c16aSPierre Ossman .match = mmc_bus_match, 1354101c16aSPierre Ossman .uevent = mmc_bus_uevent, 1364101c16aSPierre Ossman .probe = mmc_bus_probe, 1374101c16aSPierre Ossman .remove = mmc_bus_remove, 1384101c16aSPierre Ossman .suspend = mmc_bus_suspend, 1394101c16aSPierre Ossman .resume = mmc_bus_resume, 1404101c16aSPierre Ossman }; 1414101c16aSPierre Ossman 1424101c16aSPierre Ossman int mmc_register_bus(void) 1434101c16aSPierre Ossman { 1444101c16aSPierre Ossman return bus_register(&mmc_bus_type); 1454101c16aSPierre Ossman } 1464101c16aSPierre Ossman 1474101c16aSPierre Ossman void mmc_unregister_bus(void) 1484101c16aSPierre Ossman { 1494101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 1504101c16aSPierre Ossman } 1514101c16aSPierre Ossman 1524101c16aSPierre Ossman /** 1534101c16aSPierre Ossman * mmc_register_driver - register a media driver 1544101c16aSPierre Ossman * @drv: MMC media driver 1554101c16aSPierre Ossman */ 1564101c16aSPierre Ossman int mmc_register_driver(struct mmc_driver *drv) 1574101c16aSPierre Ossman { 1584101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1594101c16aSPierre Ossman return driver_register(&drv->drv); 1604101c16aSPierre Ossman } 1614101c16aSPierre Ossman 1624101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 1634101c16aSPierre Ossman 1644101c16aSPierre Ossman /** 1654101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 1664101c16aSPierre Ossman * @drv: MMC media driver 1674101c16aSPierre Ossman */ 1684101c16aSPierre Ossman void mmc_unregister_driver(struct mmc_driver *drv) 1694101c16aSPierre Ossman { 1704101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1714101c16aSPierre Ossman driver_unregister(&drv->drv); 1724101c16aSPierre Ossman } 1734101c16aSPierre Ossman 1744101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 1754101c16aSPierre Ossman 1764101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 1774101c16aSPierre Ossman { 1784101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1794101c16aSPierre Ossman 1801a632f8cSPierre Ossman sdio_free_common_cis(card); 1811a632f8cSPierre Ossman 182759bdc7aSPierre Ossman if (card->info) 183759bdc7aSPierre Ossman kfree(card->info); 184759bdc7aSPierre Ossman 1854101c16aSPierre Ossman kfree(card); 1864101c16aSPierre Ossman } 1874101c16aSPierre Ossman 1884101c16aSPierre Ossman /* 1894101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 1904101c16aSPierre Ossman */ 19151ec92e2SPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 1924101c16aSPierre Ossman { 1934101c16aSPierre Ossman struct mmc_card *card; 1944101c16aSPierre Ossman 195733cb1e4SMariusz Kozlowski card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 1964101c16aSPierre Ossman if (!card) 1974101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 1984101c16aSPierre Ossman 1994101c16aSPierre Ossman card->host = host; 2004101c16aSPierre Ossman 2014101c16aSPierre Ossman device_initialize(&card->dev); 2024101c16aSPierre Ossman 2034101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2044101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2054101c16aSPierre Ossman card->dev.release = mmc_release_card; 20651ec92e2SPierre Ossman card->dev.type = type; 2074101c16aSPierre Ossman 2084101c16aSPierre Ossman return card; 2094101c16aSPierre Ossman } 2104101c16aSPierre Ossman 2114101c16aSPierre Ossman /* 2124101c16aSPierre Ossman * Register a new MMC card with the driver model. 2134101c16aSPierre Ossman */ 2144101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 2154101c16aSPierre Ossman { 2164101c16aSPierre Ossman int ret; 217109b5bedSPierre Ossman const char *type; 2184101c16aSPierre Ossman 219d1b26863SKay Sievers dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 2204101c16aSPierre Ossman 221109b5bedSPierre Ossman switch (card->type) { 222109b5bedSPierre Ossman case MMC_TYPE_MMC: 223109b5bedSPierre Ossman type = "MMC"; 224109b5bedSPierre Ossman break; 225109b5bedSPierre Ossman case MMC_TYPE_SD: 226109b5bedSPierre Ossman type = "SD"; 227109b5bedSPierre Ossman if (mmc_card_blockaddr(card)) 228109b5bedSPierre Ossman type = "SDHC"; 229109b5bedSPierre Ossman break; 2305c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 2315c4e6f13SPierre Ossman type = "SDIO"; 2325c4e6f13SPierre Ossman break; 233109b5bedSPierre Ossman default: 234109b5bedSPierre Ossman type = "?"; 235109b5bedSPierre Ossman break; 236109b5bedSPierre Ossman } 237109b5bedSPierre Ossman 238af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 239af517150SDavid Brownell printk(KERN_INFO "%s: new %s%s card on SPI\n", 240af517150SDavid Brownell mmc_hostname(card->host), 241af517150SDavid Brownell mmc_card_highspeed(card) ? "high speed " : "", 242af517150SDavid Brownell type); 243af517150SDavid Brownell } else { 244109b5bedSPierre Ossman printk(KERN_INFO "%s: new %s%s card at address %04x\n", 245109b5bedSPierre Ossman mmc_hostname(card->host), 246109b5bedSPierre Ossman mmc_card_highspeed(card) ? "high speed " : "", 247109b5bedSPierre Ossman type, card->rca); 248af517150SDavid Brownell } 249109b5bedSPierre Ossman 2504101c16aSPierre Ossman ret = device_add(&card->dev); 2514101c16aSPierre Ossman if (ret) 2524101c16aSPierre Ossman return ret; 2534101c16aSPierre Ossman 254f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 255f4b7f927SHaavard Skinnemoen mmc_add_card_debugfs(card); 256f4b7f927SHaavard Skinnemoen #endif 257f4b7f927SHaavard Skinnemoen 2584101c16aSPierre Ossman mmc_card_set_present(card); 2594101c16aSPierre Ossman 2604101c16aSPierre Ossman return 0; 2614101c16aSPierre Ossman } 2624101c16aSPierre Ossman 2634101c16aSPierre Ossman /* 2644101c16aSPierre Ossman * Unregister a new MMC card with the driver model, and 2654101c16aSPierre Ossman * (eventually) free it. 2664101c16aSPierre Ossman */ 2674101c16aSPierre Ossman void mmc_remove_card(struct mmc_card *card) 2684101c16aSPierre Ossman { 269f4b7f927SHaavard Skinnemoen #ifdef CONFIG_DEBUG_FS 270f4b7f927SHaavard Skinnemoen mmc_remove_card_debugfs(card); 271f4b7f927SHaavard Skinnemoen #endif 272f4b7f927SHaavard Skinnemoen 2734101c16aSPierre Ossman if (mmc_card_present(card)) { 274af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 275af517150SDavid Brownell printk(KERN_INFO "%s: SPI card removed\n", 276af517150SDavid Brownell mmc_hostname(card->host)); 277af517150SDavid Brownell } else { 278109b5bedSPierre Ossman printk(KERN_INFO "%s: card %04x removed\n", 279109b5bedSPierre Ossman mmc_hostname(card->host), card->rca); 280af517150SDavid Brownell } 2814101c16aSPierre Ossman device_del(&card->dev); 2824101c16aSPierre Ossman } 2834101c16aSPierre Ossman 2844101c16aSPierre Ossman put_device(&card->dev); 2854101c16aSPierre Ossman } 2864101c16aSPierre Ossman 287