sdio_bus.c revision 9a08f82b3cc522f727ace580a2aaee5402435bc8
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; 1319a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel int ret; 1323b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1333b38bea0d976513970f947806b08b9faca418e7aPierre Ossman id = sdio_match_device(func, drv); 1343b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (!id) 1353b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return -ENODEV; 1363b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1379a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel /* Set the default block size so the driver is sure it's something 1389a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel * sensible. */ 1399a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel sdio_claim_host(func); 1409a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel ret = sdio_set_block_size(func, 0); 1419a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel sdio_release_host(func); 1429a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel if (ret) 1439a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel return ret; 1449a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel 1453b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return drv->probe(func, id); 146e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 147e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 148e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_remove(struct device *dev) 149e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 1503b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *drv = to_sdio_driver(dev->driver); 1513b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 1523b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1533b38bea0d976513970f947806b08b9faca418e7aPierre Ossman drv->remove(func); 1543b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 155d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre if (func->irq_handler) { 156d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre printk(KERN_WARNING "WARNING: driver %s did not remove " 157d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre "its interrupt handler!\n", drv->name); 158d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_claim_host(func); 159d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_release_irq(func); 160d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_release_host(func); 161d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre } 162d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre 163e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 164e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 165e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 166e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = { 167e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .name = "sdio", 168bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman .dev_attrs = sdio_dev_attrs, 169e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .match = sdio_bus_match, 170e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .uevent = sdio_bus_uevent, 171e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .probe = sdio_bus_probe, 172e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .remove = sdio_bus_remove, 173e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}; 174e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 175e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void) 176e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 177e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return bus_register(&sdio_bus_type); 178e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 179e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 180e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void) 181e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 182e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman bus_unregister(&sdio_bus_type); 183e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 184e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 185f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 186f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_register_driver - register a function driver 187f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 188f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 189f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanint sdio_register_driver(struct sdio_driver *drv) 190f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 191f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.name = drv->name; 192f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 193f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman return driver_register(&drv->drv); 194f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 195f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_register_driver); 196f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 197f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 198f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_unregister_driver - unregister a function driver 199f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 200f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 201f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanvoid sdio_unregister_driver(struct sdio_driver *drv) 202f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 203f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 204f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman driver_unregister(&drv->drv); 205f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 206f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_unregister_driver); 207f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 208e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev) 209e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 210e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 211b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre 2121a632f8cdc33e7f8edca352164f0c96a75d08f08Pierre Ossman sdio_free_func_cis(func); 213e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 214e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman kfree(func); 215e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 216e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 217e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 218e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure. 219e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 220e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card) 221e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 222e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func; 223e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 224e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL); 225e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (!func) 226e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ERR_PTR(-ENOMEM); 227e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 228e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman memset(func, 0, sizeof(struct sdio_func)); 229e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 230e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->card = card; 231e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 232e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_initialize(&func->dev); 233e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 234e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.parent = &card->dev; 235e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.bus = &sdio_bus_type; 236e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.release = sdio_release_func; 237e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 238e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return func; 239e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 240e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 241e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 242e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model. 243e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 244e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func) 245e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 246e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int ret; 247e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 248e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman snprintf(func->dev.bus_id, sizeof(func->dev.bus_id), 249e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman "%s:%d", mmc_card_id(func->card), func->num); 250e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 251e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman ret = device_add(&func->dev); 252e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (ret == 0) 253e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman sdio_func_set_present(func); 254e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 255e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ret; 256e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 257e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 258e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 259e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and 260e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it. 261e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 262e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func) 263e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 264e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (sdio_func_present(func)) 265e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_del(&func->dev); 266e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 267e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman put_device(&func->dev); 268e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 269e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 270