sdio_bus.c revision 22bfc979d38f57d5b10d141990175d8fc47f6775
1e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 2e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * linux/drivers/mmc/core/sdio_bus.c 3e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * 4e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Copyright 2007 Pierre Ossman 5e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * 6e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * This program is free software; you can redistribute it and/or modify 7e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * it under the terms of the GNU General Public License as published by 8e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at 9e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * your option) any later version. 10e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * 11e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * SDIO function driver model 12e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 13e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 14e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/device.h> 15e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/err.h> 16e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 17e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/card.h> 18e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/sdio_func.h> 19e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 20b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre#include "sdio_cis.h" 21e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include "sdio_bus.h" 22e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 23e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) 243b38bea0d976513970f947806b08b9faca418e7aPierre Ossman#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) 253b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 26bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman/* show configuration fields */ 27bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman#define sdio_config_attr(field, format_string) \ 28bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstatic ssize_t \ 29bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanfield##_show(struct device *dev, struct device_attribute *attr, char *buf) \ 30bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman{ \ 31bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman struct sdio_func *func; \ 32bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman \ 33bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman func = dev_to_sdio_func (dev); \ 34bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman return sprintf (buf, format_string, func->field); \ 35bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman} 36bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 37bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(class, "0x%02x\n"); 38bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(vendor, "0x%04x\n"); 39bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(device, "0x%04x\n"); 40bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 41bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstatic ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) 42bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman{ 43bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman struct sdio_func *func = dev_to_sdio_func (dev); 44bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 45bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n", 46bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman func->class, func->vendor, func->device); 47bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman} 48bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 4922bfc979d38f57d5b10d141990175d8fc47f6775Adrian Bunkstatic struct device_attribute sdio_dev_attrs[] = { 50bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(class), 51bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(vendor), 52bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(device), 53bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(modalias), 54bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_NULL, 55bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman}; 56bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 573b38bea0d976513970f947806b08b9faca418e7aPierre Ossmanstatic const struct sdio_device_id *sdio_match_one(struct sdio_func *func, 583b38bea0d976513970f947806b08b9faca418e7aPierre Ossman const struct sdio_device_id *id) 593b38bea0d976513970f947806b08b9faca418e7aPierre Ossman{ 603b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class) 613b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 623b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor) 633b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 643b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device) 653b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 663b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return id; 673b38bea0d976513970f947806b08b9faca418e7aPierre Ossman} 683b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 693b38bea0d976513970f947806b08b9faca418e7aPierre Ossmanstatic const struct sdio_device_id *sdio_match_device(struct sdio_func *func, 703b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *sdrv) 713b38bea0d976513970f947806b08b9faca418e7aPierre Ossman{ 723b38bea0d976513970f947806b08b9faca418e7aPierre Ossman const struct sdio_device_id *ids; 733b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 743b38bea0d976513970f947806b08b9faca418e7aPierre Ossman ids = sdrv->id_table; 753b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 763b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (ids) { 773b38bea0d976513970f947806b08b9faca418e7aPierre Ossman while (ids->class || ids->vendor || ids->device) { 783b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (sdio_match_one(func, ids)) 793b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return ids; 803b38bea0d976513970f947806b08b9faca418e7aPierre Ossman ids++; 813b38bea0d976513970f947806b08b9faca418e7aPierre Ossman } 823b38bea0d976513970f947806b08b9faca418e7aPierre Ossman } 833b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 843b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 853b38bea0d976513970f947806b08b9faca418e7aPierre Ossman} 86e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 87e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_match(struct device *dev, struct device_driver *drv) 88e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 893b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 903b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *sdrv = to_sdio_driver(drv); 913b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 923b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (sdio_match_device(func, sdrv)) 933b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return 1; 943b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 953b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return 0; 96e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 97e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 98e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int 99e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmansdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, 100e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int buf_size) 101e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 102d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 103d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman int i = 0, length = 0; 104d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 105d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman if (add_uevent_var(envp, num_envp, &i, 106d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman buf, buf_size, &length, 107d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "SDIO_CLASS=%02X", func->class)) 108d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 109d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 110d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman if (add_uevent_var(envp, num_envp, &i, 111d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman buf, buf_size, &length, 112d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "SDIO_ID=%04X:%04X", func->vendor, func->device)) 113d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 114d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 115d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman if (add_uevent_var(envp, num_envp, &i, 116d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman buf, buf_size, &length, 117d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "MODALIAS=sdio:c%02Xv%04Xd%04X", 118d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman func->class, func->vendor, func->device)) 119d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 120d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 121d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman envp[i] = NULL; 122e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 123e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 124e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 125e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 126e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_probe(struct device *dev) 127e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 1283b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *drv = to_sdio_driver(dev->driver); 1293b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 1303b38bea0d976513970f947806b08b9faca418e7aPierre Ossman const struct sdio_device_id *id; 1313b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1323b38bea0d976513970f947806b08b9faca418e7aPierre Ossman id = sdio_match_device(func, drv); 1333b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (!id) 1343b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return -ENODEV; 1353b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1363b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return drv->probe(func, id); 137e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 138e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 139e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_remove(struct device *dev) 140e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 1413b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *drv = to_sdio_driver(dev->driver); 1423b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 1433b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1443b38bea0d976513970f947806b08b9faca418e7aPierre Ossman drv->remove(func); 1453b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 146d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre if (func->irq_handler) { 147d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre printk(KERN_WARNING "WARNING: driver %s did not remove " 148d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre "its interrupt handler!\n", drv->name); 149d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_claim_host(func); 150d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_release_irq(func); 151d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_release_host(func); 152d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre } 153d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre 154e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 155e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 156e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 157e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = { 158e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .name = "sdio", 159bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman .dev_attrs = sdio_dev_attrs, 160e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .match = sdio_bus_match, 161e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .uevent = sdio_bus_uevent, 162e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .probe = sdio_bus_probe, 163e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .remove = sdio_bus_remove, 164e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}; 165e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 166e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void) 167e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 168e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return bus_register(&sdio_bus_type); 169e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 170e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 171e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void) 172e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 173e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman bus_unregister(&sdio_bus_type); 174e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 175e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 176f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 177f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_register_driver - register a function driver 178f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 179f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 180f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanint sdio_register_driver(struct sdio_driver *drv) 181f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 182f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.name = drv->name; 183f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 184f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman return driver_register(&drv->drv); 185f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 186f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_register_driver); 187f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 188f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 189f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_unregister_driver - unregister a function driver 190f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 191f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 192f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanvoid sdio_unregister_driver(struct sdio_driver *drv) 193f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 194f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 195f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman driver_unregister(&drv->drv); 196f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 197f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_unregister_driver); 198f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 199e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev) 200e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 201e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 202b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre 2031a632f8cdc33e7f8edca352164f0c96a75d08f08Pierre Ossman sdio_free_func_cis(func); 204e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 205e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman kfree(func); 206e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 207e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 208e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 209e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure. 210e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 211e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card) 212e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 213e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func; 214e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 215e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL); 216e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (!func) 217e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ERR_PTR(-ENOMEM); 218e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 219e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman memset(func, 0, sizeof(struct sdio_func)); 220e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 221e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->card = card; 222e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 223e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_initialize(&func->dev); 224e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 225e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.parent = &card->dev; 226e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.bus = &sdio_bus_type; 227e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.release = sdio_release_func; 228e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 229e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return func; 230e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 231e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 232e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 233e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model. 234e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 235e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func) 236e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 237e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int ret; 238e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 239e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman snprintf(func->dev.bus_id, sizeof(func->dev.bus_id), 240e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman "%s:%d", mmc_card_id(func->card), func->num); 241e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 242e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman ret = device_add(&func->dev); 243e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (ret == 0) 244e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman sdio_func_set_present(func); 245e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 246e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ret; 247e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 248e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 249e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 250e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and 251e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it. 252e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 253e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func) 254e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 255e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (sdio_func_present(func)) 256e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_del(&func->dev); 257e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 258e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman put_device(&func->dev); 259e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 260e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 261