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" 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"); 374101c16aSPierre Ossman default: 384101c16aSPierre Ossman return -EFAULT; 394101c16aSPierre Ossman } 404101c16aSPierre Ossman } 414101c16aSPierre Ossman 424101c16aSPierre Ossman static struct device_attribute mmc_dev_attrs[] = { 434101c16aSPierre Ossman MMC_ATTR_RO(type), 444101c16aSPierre Ossman __ATTR_NULL, 454101c16aSPierre Ossman }; 464101c16aSPierre Ossman 474101c16aSPierre Ossman /* 484101c16aSPierre Ossman * This currently matches any MMC driver to any MMC card - drivers 494101c16aSPierre Ossman * themselves make the decision whether to drive this card in their 504101c16aSPierre Ossman * probe method. 514101c16aSPierre Ossman */ 524101c16aSPierre Ossman static int mmc_bus_match(struct device *dev, struct device_driver *drv) 534101c16aSPierre Ossman { 544101c16aSPierre Ossman return 1; 554101c16aSPierre Ossman } 564101c16aSPierre Ossman 574101c16aSPierre Ossman static int 584101c16aSPierre Ossman mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, 594101c16aSPierre Ossman int buf_size) 604101c16aSPierre Ossman { 614101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 624101c16aSPierre Ossman int retval = 0, i = 0, length = 0; 634101c16aSPierre Ossman 644101c16aSPierre Ossman #define add_env(fmt,val) do { \ 654101c16aSPierre Ossman retval = add_uevent_var(envp, num_envp, &i, \ 664101c16aSPierre Ossman buf, buf_size, &length, \ 674101c16aSPierre Ossman fmt, val); \ 684101c16aSPierre Ossman if (retval) \ 694101c16aSPierre Ossman return retval; \ 704101c16aSPierre Ossman } while (0); 714101c16aSPierre Ossman 724101c16aSPierre Ossman switch (card->type) { 734101c16aSPierre Ossman case MMC_TYPE_MMC: 744101c16aSPierre Ossman add_env("MMC_TYPE=%s", "MMC"); 754101c16aSPierre Ossman break; 764101c16aSPierre Ossman case MMC_TYPE_SD: 774101c16aSPierre Ossman add_env("MMC_TYPE=%s", "SD"); 784101c16aSPierre Ossman break; 794101c16aSPierre Ossman } 804101c16aSPierre Ossman 814101c16aSPierre Ossman add_env("MMC_NAME=%s", mmc_card_name(card)); 824101c16aSPierre Ossman 834101c16aSPierre Ossman #undef add_env 844101c16aSPierre Ossman 854101c16aSPierre Ossman envp[i] = NULL; 864101c16aSPierre Ossman 874101c16aSPierre Ossman return 0; 884101c16aSPierre Ossman } 894101c16aSPierre Ossman 904101c16aSPierre Ossman static int mmc_bus_probe(struct device *dev) 914101c16aSPierre Ossman { 924101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 934101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 944101c16aSPierre Ossman 954101c16aSPierre Ossman return drv->probe(card); 964101c16aSPierre Ossman } 974101c16aSPierre Ossman 984101c16aSPierre Ossman static int mmc_bus_remove(struct device *dev) 994101c16aSPierre Ossman { 1004101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1014101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1024101c16aSPierre Ossman 1034101c16aSPierre Ossman drv->remove(card); 1044101c16aSPierre Ossman 1054101c16aSPierre Ossman return 0; 1064101c16aSPierre Ossman } 1074101c16aSPierre Ossman 1084101c16aSPierre Ossman static int mmc_bus_suspend(struct device *dev, pm_message_t state) 1094101c16aSPierre Ossman { 1104101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1114101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1124101c16aSPierre Ossman int ret = 0; 1134101c16aSPierre Ossman 1144101c16aSPierre Ossman if (dev->driver && drv->suspend) 1154101c16aSPierre Ossman ret = drv->suspend(card, state); 1164101c16aSPierre Ossman return ret; 1174101c16aSPierre Ossman } 1184101c16aSPierre Ossman 1194101c16aSPierre Ossman static int mmc_bus_resume(struct device *dev) 1204101c16aSPierre Ossman { 1214101c16aSPierre Ossman struct mmc_driver *drv = to_mmc_driver(dev->driver); 1224101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1234101c16aSPierre Ossman int ret = 0; 1244101c16aSPierre Ossman 1254101c16aSPierre Ossman if (dev->driver && drv->resume) 1264101c16aSPierre Ossman ret = drv->resume(card); 1274101c16aSPierre Ossman return ret; 1284101c16aSPierre Ossman } 1294101c16aSPierre Ossman 1304101c16aSPierre Ossman static struct bus_type mmc_bus_type = { 1314101c16aSPierre Ossman .name = "mmc", 1324101c16aSPierre Ossman .dev_attrs = mmc_dev_attrs, 1334101c16aSPierre Ossman .match = mmc_bus_match, 1344101c16aSPierre Ossman .uevent = mmc_bus_uevent, 1354101c16aSPierre Ossman .probe = mmc_bus_probe, 1364101c16aSPierre Ossman .remove = mmc_bus_remove, 1374101c16aSPierre Ossman .suspend = mmc_bus_suspend, 1384101c16aSPierre Ossman .resume = mmc_bus_resume, 1394101c16aSPierre Ossman }; 1404101c16aSPierre Ossman 1414101c16aSPierre Ossman int mmc_register_bus(void) 1424101c16aSPierre Ossman { 1434101c16aSPierre Ossman return bus_register(&mmc_bus_type); 1444101c16aSPierre Ossman } 1454101c16aSPierre Ossman 1464101c16aSPierre Ossman void mmc_unregister_bus(void) 1474101c16aSPierre Ossman { 1484101c16aSPierre Ossman bus_unregister(&mmc_bus_type); 1494101c16aSPierre Ossman } 1504101c16aSPierre Ossman 1514101c16aSPierre Ossman /** 1524101c16aSPierre Ossman * mmc_register_driver - register a media driver 1534101c16aSPierre Ossman * @drv: MMC media driver 1544101c16aSPierre Ossman */ 1554101c16aSPierre Ossman int mmc_register_driver(struct mmc_driver *drv) 1564101c16aSPierre Ossman { 1574101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1584101c16aSPierre Ossman return driver_register(&drv->drv); 1594101c16aSPierre Ossman } 1604101c16aSPierre Ossman 1614101c16aSPierre Ossman EXPORT_SYMBOL(mmc_register_driver); 1624101c16aSPierre Ossman 1634101c16aSPierre Ossman /** 1644101c16aSPierre Ossman * mmc_unregister_driver - unregister a media driver 1654101c16aSPierre Ossman * @drv: MMC media driver 1664101c16aSPierre Ossman */ 1674101c16aSPierre Ossman void mmc_unregister_driver(struct mmc_driver *drv) 1684101c16aSPierre Ossman { 1694101c16aSPierre Ossman drv->drv.bus = &mmc_bus_type; 1704101c16aSPierre Ossman driver_unregister(&drv->drv); 1714101c16aSPierre Ossman } 1724101c16aSPierre Ossman 1734101c16aSPierre Ossman EXPORT_SYMBOL(mmc_unregister_driver); 1744101c16aSPierre Ossman 1754101c16aSPierre Ossman static void mmc_release_card(struct device *dev) 1764101c16aSPierre Ossman { 1774101c16aSPierre Ossman struct mmc_card *card = dev_to_mmc_card(dev); 1784101c16aSPierre Ossman 1794101c16aSPierre Ossman kfree(card); 1804101c16aSPierre Ossman } 1814101c16aSPierre Ossman 1824101c16aSPierre Ossman /* 1834101c16aSPierre Ossman * Allocate and initialise a new MMC card structure. 1844101c16aSPierre Ossman */ 1854101c16aSPierre Ossman struct mmc_card *mmc_alloc_card(struct mmc_host *host) 1864101c16aSPierre Ossman { 1874101c16aSPierre Ossman struct mmc_card *card; 1884101c16aSPierre Ossman 1894101c16aSPierre Ossman card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); 1904101c16aSPierre Ossman if (!card) 1914101c16aSPierre Ossman return ERR_PTR(-ENOMEM); 1924101c16aSPierre Ossman 1934101c16aSPierre Ossman memset(card, 0, sizeof(struct mmc_card)); 1944101c16aSPierre Ossman 1954101c16aSPierre Ossman card->host = host; 1964101c16aSPierre Ossman 1974101c16aSPierre Ossman device_initialize(&card->dev); 1984101c16aSPierre Ossman 1994101c16aSPierre Ossman card->dev.parent = mmc_classdev(host); 2004101c16aSPierre Ossman card->dev.bus = &mmc_bus_type; 2014101c16aSPierre Ossman card->dev.release = mmc_release_card; 2024101c16aSPierre Ossman 2034101c16aSPierre Ossman return card; 2044101c16aSPierre Ossman } 2054101c16aSPierre Ossman 2064101c16aSPierre Ossman /* 2074101c16aSPierre Ossman * Register a new MMC card with the driver model. 2084101c16aSPierre Ossman */ 2094101c16aSPierre Ossman int mmc_add_card(struct mmc_card *card) 2104101c16aSPierre Ossman { 2114101c16aSPierre Ossman int ret; 2124101c16aSPierre Ossman 2134101c16aSPierre Ossman snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), 2144101c16aSPierre Ossman "%s:%04x", mmc_hostname(card->host), card->rca); 2154101c16aSPierre Ossman 2164101c16aSPierre Ossman card->dev.uevent_suppress = 1; 2174101c16aSPierre Ossman 2184101c16aSPierre Ossman ret = device_add(&card->dev); 2194101c16aSPierre Ossman if (ret) 2204101c16aSPierre Ossman return ret; 2214101c16aSPierre Ossman 2224101c16aSPierre Ossman if (card->host->bus_ops->sysfs_add) { 2234101c16aSPierre Ossman ret = card->host->bus_ops->sysfs_add(card->host, card); 2244101c16aSPierre Ossman if (ret) { 2254101c16aSPierre Ossman device_del(&card->dev); 2264101c16aSPierre Ossman return ret; 2274101c16aSPierre Ossman } 2284101c16aSPierre Ossman } 2294101c16aSPierre Ossman 2304101c16aSPierre Ossman card->dev.uevent_suppress = 0; 2314101c16aSPierre Ossman 2324101c16aSPierre Ossman kobject_uevent(&card->dev.kobj, KOBJ_ADD); 2334101c16aSPierre Ossman 2344101c16aSPierre Ossman mmc_card_set_present(card); 2354101c16aSPierre Ossman 2364101c16aSPierre Ossman return 0; 2374101c16aSPierre Ossman } 2384101c16aSPierre Ossman 2394101c16aSPierre Ossman /* 2404101c16aSPierre Ossman * Unregister a new MMC card with the driver model, and 2414101c16aSPierre Ossman * (eventually) free it. 2424101c16aSPierre Ossman */ 2434101c16aSPierre Ossman void mmc_remove_card(struct mmc_card *card) 2444101c16aSPierre Ossman { 2454101c16aSPierre Ossman if (mmc_card_present(card)) { 2464101c16aSPierre Ossman if (card->host->bus_ops->sysfs_remove) 2474101c16aSPierre Ossman card->host->bus_ops->sysfs_remove(card->host, card); 2484101c16aSPierre Ossman device_del(&card->dev); 2494101c16aSPierre Ossman } 2504101c16aSPierre Ossman 2514101c16aSPierre Ossman put_device(&card->dev); 2524101c16aSPierre Ossman } 2534101c16aSPierre Ossman 254