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 "sysfs.h" 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"); 404101c16aSPierre Ossman default: 414101c16aSPierre Ossman return -EFAULT; 424101c16aSPierre Ossman } 434101c16aSPierre Ossman } 444101c16aSPierre Ossman 454101c16aSPierre Ossman static struct device_attribute mmc_dev_attrs[] = { 464101c16aSPierre Ossman MMC_ATTR_RO(type), 474101c16aSPierre Ossman __ATTR_NULL, 484101c16aSPierre Ossman }; 494101c16aSPierre Ossman 504101c16aSPierre Ossman /* 514101c16aSPierre Ossman * This currently matches any MMC driver to any MMC card - drivers 524101c16aSPierre Ossman * themselves make the decision whether to drive this card in their 534101c16aSPierre Ossman * probe method. 544101c16aSPierre Ossman */ 554101c16aSPierre Ossman static int mmc_bus_match(struct device *dev, struct device_driver *drv) 564101c16aSPierre Ossman { 574101c16aSPierre Ossman return 1; 584101c16aSPierre Ossman } 594101c16aSPierre Ossman 604101c16aSPierre Ossman static int 614101c16aSPierre Ossman mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, 624101c16aSPierre Ossman int buf_size) 634101c16aSPierre Ossman { 644101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 659eb3a94dSPierre Ossman const char *type; 669eb3a94dSPierre Ossman int i = 0, length = 0; 674101c16aSPierre Ossman 684101c16aSPierre Ossman switch (card->type) { 694101c16aSPierre Ossman case MMC_TYPE_MMC: 709eb3a94dSPierre Ossman type = "MMC"; 714101c16aSPierre Ossman break; 724101c16aSPierre Ossman case MMC_TYPE_SD: 739eb3a94dSPierre Ossman type = "SD"; 744101c16aSPierre Ossman break; 755c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 769eb3a94dSPierre Ossman type = "SDIO"; 775c4e6f13SPierre Ossman break; 789eb3a94dSPierre Ossman default: 799eb3a94dSPierre Ossman type = NULL; 804101c16aSPierre Ossman } 814101c16aSPierre Ossman 829eb3a94dSPierre Ossman if (type) { 839eb3a94dSPierre Ossman if (add_uevent_var(envp, num_envp, &i, 849eb3a94dSPierre Ossman buf, buf_size, &length, 859eb3a94dSPierre Ossman "MMC_TYPE=%s", type)) 869eb3a94dSPierre Ossman return -ENOMEM; 879eb3a94dSPierre Ossman } 884101c16aSPierre Ossman 899eb3a94dSPierre Ossman if (add_uevent_var(envp, num_envp, &i, 909eb3a94dSPierre Ossman buf, buf_size, &length, 919eb3a94dSPierre Ossman "MMC_NAME=%s", mmc_card_name(card))) 929eb3a94dSPierre Ossman return -ENOMEM; 934101c16aSPierre Ossman 944101c16aSPierre Ossman envp[i] = NULL; 954101c16aSPierre Ossman 964101c16aSPierre Ossman return 0; 974101c16aSPierre Ossman } 984101c16aSPierre Ossman 994101c16aSPierre Ossman static int mmc_bus_probe(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 return drv->probe(card); 1054101c16aSPierre Ossman } 1064101c16aSPierre Ossman 1074101c16aSPierre Ossman static int mmc_bus_remove(struct device *dev) 1084101c16aSPierre Ossman { 1094101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1104101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1114101c16aSPierre Ossman 1124101c16aSPierre Ossman drv->remove(card); 1134101c16aSPierre Ossman 1144101c16aSPierre Ossman return 0; 1154101c16aSPierre Ossman } 1164101c16aSPierre Ossman 1174101c16aSPierre Ossman static int mmc_bus_suspend(struct device *dev, pm_message_t state) 1184101c16aSPierre Ossman { 1194101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1204101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1214101c16aSPierre Ossman int ret = 0; 1224101c16aSPierre Ossman 1234101c16aSPierre Ossman if (dev->driver && drv->suspend) 1244101c16aSPierre Ossman ret = drv->suspend(card, state); 1254101c16aSPierre Ossman return ret; 1264101c16aSPierre Ossman } 1274101c16aSPierre Ossman 1284101c16aSPierre Ossman static int mmc_bus_resume(struct device *dev) 1294101c16aSPierre Ossman { 1304101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1314101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1324101c16aSPierre Ossman int ret = 0; 1334101c16aSPierre Ossman 1344101c16aSPierre Ossman if (dev->driver && drv->resume) 1354101c16aSPierre Ossman ret = drv->resume(card); 1364101c16aSPierre Ossman return ret; 1374101c16aSPierre Ossman } 1384101c16aSPierre Ossman 1394101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 1404101c16aSPierre Ossman .name = "mmc", 1414101c16aSPierre Ossman .dev_attrs = mmc_dev_attrs, 1424101c16aSPierre Ossman .match = mmc_bus_match, 1434101c16aSPierre Ossman .uevent = mmc_bus_uevent, 1444101c16aSPierre Ossman .probe = mmc_bus_probe, 1454101c16aSPierre Ossman .remove = mmc_bus_remove, 1464101c16aSPierre Ossman .suspend = mmc_bus_suspend, 1474101c16aSPierre Ossman .resume = mmc_bus_resume, 1484101c16aSPierre Ossman }; 1494101c16aSPierre Ossman 1504101c16aSPierre Ossman int mmc_register_bus(void) 1514101c16aSPierre Ossman { 1524101c16aSPierre Ossman return bus_register(&mmc_bus_type); 1534101c16aSPierre Ossman } 1544101c16aSPierre Ossman 1554101c16aSPierre Ossman void mmc_unregister_bus(void) 1564101c16aSPierre Ossman { 1574101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 1584101c16aSPierre Ossman } 1594101c16aSPierre Ossman 1604101c16aSPierre Ossman /** 1614101c16aSPierre Ossman * mmc_register_driver - register a media driver 1624101c16aSPierre Ossman * @drv: MMC media driver 1634101c16aSPierre Ossman */ 1644101c16aSPierre Ossman int mmc_register_driver(struct mmc_driver *drv) 1654101c16aSPierre Ossman { 1664101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1674101c16aSPierre Ossman return driver_register(&drv->drv); 1684101c16aSPierre Ossman } 1694101c16aSPierre Ossman 1704101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 1714101c16aSPierre Ossman 1724101c16aSPierre Ossman /** 1734101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 1744101c16aSPierre Ossman * @drv: MMC media driver 1754101c16aSPierre Ossman */ 1764101c16aSPierre Ossman void mmc_unregister_driver(struct mmc_driver *drv) 1774101c16aSPierre Ossman { 1784101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1794101c16aSPierre Ossman driver_unregister(&drv->drv); 1804101c16aSPierre Ossman } 1814101c16aSPierre Ossman 1824101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 1834101c16aSPierre Ossman 1844101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 1854101c16aSPierre Ossman { 1864101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1874101c16aSPierre Ossman 1881a632f8cSPierre Ossman sdio_free_common_cis(card); 1891a632f8cSPierre Ossman 190759bdc7aSPierre Ossman if (card->info) 191759bdc7aSPierre Ossman kfree(card->info); 192759bdc7aSPierre Ossman 1934101c16aSPierre Ossman kfree(card); 1944101c16aSPierre Ossman } 1954101c16aSPierre Ossman 1964101c16aSPierre Ossman /* 1974101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 1984101c16aSPierre Ossman */ 1994101c16aSPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host) 2004101c16aSPierre Ossman { 2014101c16aSPierre Ossman struct mmc_card *card; 2024101c16aSPierre Ossman 203733cb1e4SMariusz Kozlowski card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 2044101c16aSPierre Ossman if (!card) 2054101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 2064101c16aSPierre Ossman 2074101c16aSPierre Ossman card->host = host; 2084101c16aSPierre Ossman 2094101c16aSPierre Ossman device_initialize(&card->dev); 2104101c16aSPierre Ossman 2114101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2124101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2134101c16aSPierre Ossman card->dev.release = mmc_release_card; 2144101c16aSPierre Ossman 2154101c16aSPierre Ossman return card; 2164101c16aSPierre Ossman } 2174101c16aSPierre Ossman 2184101c16aSPierre Ossman /* 2194101c16aSPierre Ossman * Register a new MMC card with the driver model. 2204101c16aSPierre Ossman */ 2214101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 2224101c16aSPierre Ossman { 2234101c16aSPierre Ossman int ret; 224109b5bedSPierre Ossman const char *type; 2254101c16aSPierre Ossman 2264101c16aSPierre Ossman snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), 2274101c16aSPierre Ossman "%s:%04x", mmc_hostname(card->host), card->rca); 2284101c16aSPierre Ossman 229109b5bedSPierre Ossman switch (card->type) { 230109b5bedSPierre Ossman case MMC_TYPE_MMC: 231109b5bedSPierre Ossman type = "MMC"; 232109b5bedSPierre Ossman break; 233109b5bedSPierre Ossman case MMC_TYPE_SD: 234109b5bedSPierre Ossman type = "SD"; 235109b5bedSPierre Ossman if (mmc_card_blockaddr(card)) 236109b5bedSPierre Ossman type = "SDHC"; 237109b5bedSPierre Ossman break; 2385c4e6f13SPierre Ossman case MMC_TYPE_SDIO: 2395c4e6f13SPierre Ossman type = "SDIO"; 2405c4e6f13SPierre Ossman break; 241109b5bedSPierre Ossman default: 242109b5bedSPierre Ossman type = "?"; 243109b5bedSPierre Ossman break; 244109b5bedSPierre Ossman } 245109b5bedSPierre Ossman 246af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 247af517150SDavid Brownell printk(KERN_INFO "%s: new %s%s card on SPI\n", 248af517150SDavid Brownell mmc_hostname(card->host), 249af517150SDavid Brownell mmc_card_highspeed(card) ? "high speed " : "", 250af517150SDavid Brownell type); 251af517150SDavid Brownell } else { 252109b5bedSPierre Ossman printk(KERN_INFO "%s: new %s%s card at address %04x\n", 253109b5bedSPierre Ossman mmc_hostname(card->host), 254109b5bedSPierre Ossman mmc_card_highspeed(card) ? "high speed " : "", 255109b5bedSPierre Ossman type, card->rca); 256af517150SDavid Brownell } 257109b5bedSPierre Ossman 2584101c16aSPierre Ossman card->dev.uevent_suppress = 1; 2594101c16aSPierre Ossman 2604101c16aSPierre Ossman ret = device_add(&card->dev); 2614101c16aSPierre Ossman if (ret) 2624101c16aSPierre Ossman return ret; 2634101c16aSPierre Ossman 2644101c16aSPierre Ossman if (card->host->bus_ops->sysfs_add) { 2654101c16aSPierre Ossman ret = card->host->bus_ops->sysfs_add(card->host, card); 2664101c16aSPierre Ossman if (ret) { 2674101c16aSPierre Ossman device_del(&card->dev); 2684101c16aSPierre Ossman return ret; 2694101c16aSPierre Ossman } 2704101c16aSPierre Ossman } 2714101c16aSPierre Ossman 2724101c16aSPierre Ossman card->dev.uevent_suppress = 0; 2734101c16aSPierre Ossman 2744101c16aSPierre Ossman kobject_uevent(&card->dev.kobj, KOBJ_ADD); 2754101c16aSPierre Ossman 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 { 2874101c16aSPierre Ossman if (mmc_card_present(card)) { 288af517150SDavid Brownell if (mmc_host_is_spi(card->host)) { 289af517150SDavid Brownell printk(KERN_INFO "%s: SPI card removed\n", 290af517150SDavid Brownell mmc_hostname(card->host)); 291af517150SDavid Brownell } else { 292109b5bedSPierre Ossman printk(KERN_INFO "%s: card %04x removed\n", 293109b5bedSPierre Ossman mmc_hostname(card->host), card->rca); 294af517150SDavid Brownell } 295109b5bedSPierre Ossman 2964101c16aSPierre Ossman if (card->host->bus_ops->sysfs_remove) 2974101c16aSPierre Ossman card->host->bus_ops->sysfs_remove(card->host, card); 2984101c16aSPierre Ossman device_del(&card->dev); 2994101c16aSPierre Ossman } 3004101c16aSPierre Ossman 3014101c16aSPierre Ossman put_device(&card->dev); 3024101c16aSPierre Ossman } 3034101c16aSPierre Ossman 304