sdio_bus.c revision 297c7f2f158f7dfa9ab5813260ff954f9c2f83d2
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> 165a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 1780fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#include <linux/pm_runtime.h> 18e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 19e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/card.h> 20ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen#include <linux/mmc/host.h> 21e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/sdio_func.h> 22e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 23b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre#include "sdio_cis.h" 24e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include "sdio_bus.h" 25e29a7d73f4277eb92aa64e17017dea33460828efPierre 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 997ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Virosdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 100e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 101d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 102d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 1037ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Viro if (add_uevent_var(env, 104d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "SDIO_CLASS=%02X", func->class)) 105d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 106d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 1077ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Viro if (add_uevent_var(env, 108d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "SDIO_ID=%04X:%04X", func->vendor, func->device)) 109d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 110d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 1117ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Viro if (add_uevent_var(env, 112d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "MODALIAS=sdio:c%02Xv%04Xd%04X", 113d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman func->class, func->vendor, func->device)) 114d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 115d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 116e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 117e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 118e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 119e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_probe(struct device *dev) 120e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 1213b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *drv = to_sdio_driver(dev->driver); 1223b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 1233b38bea0d976513970f947806b08b9faca418e7aPierre Ossman const struct sdio_device_id *id; 1249a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel int ret; 1253b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1263b38bea0d976513970f947806b08b9faca418e7aPierre Ossman id = sdio_match_device(func, drv); 1273b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (!id) 1283b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return -ENODEV; 1293b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 13040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen /* Unbound SDIO functions are always suspended. 13140bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen * During probe, the function is set active and the usage count 13240bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen * is incremented. If the driver supports runtime PM, 13340bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen * it should call pm_runtime_put_noidle() in its probe routine and 13440bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen * pm_runtime_get_noresume() in its remove routine. 13540bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen */ 136ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) { 137ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen ret = pm_runtime_get_sync(dev); 138ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen if (ret < 0) 139ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen goto out; 140ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen } 14140bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen 1429a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel /* Set the default block size so the driver is sure it's something 1439a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel * sensible. */ 1449a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel sdio_claim_host(func); 1459a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel ret = sdio_set_block_size(func, 0); 1469a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel sdio_release_host(func); 1479a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel if (ret) 14840bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen goto disable_runtimepm; 14940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen 15040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen ret = drv->probe(func, id); 15140bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen if (ret) 15240bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen goto disable_runtimepm; 15340bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen 15440bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen return 0; 1559a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel 15640bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohendisable_runtimepm: 157ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) 158ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen pm_runtime_put_noidle(dev); 15940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohenout: 16040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen return ret; 161e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 162e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 163e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_remove(struct device *dev) 164e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 1653b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *drv = to_sdio_driver(dev->driver); 1663b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 167ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen int ret = 0; 16840bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen 16940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen /* Make sure card is powered before invoking ->remove() */ 170ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) { 171ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen ret = pm_runtime_get_sync(dev); 172ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen if (ret < 0) 173ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen goto out; 174ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen } 1753b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1763b38bea0d976513970f947806b08b9faca418e7aPierre Ossman drv->remove(func); 1773b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 178d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre if (func->irq_handler) { 179d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre printk(KERN_WARNING "WARNING: driver %s did not remove " 180d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre "its interrupt handler!\n", drv->name); 181d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_claim_host(func); 182d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_release_irq(func); 183d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre sdio_release_host(func); 184d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre } 185d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre 18640bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen /* First, undo the increment made directly above */ 187ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) 188ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen pm_runtime_put_noidle(dev); 18940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen 19040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen /* Then undo the runtime PM settings in sdio_bus_probe() */ 191ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) 192297c7f2f158f7dfa9ab5813260ff954f9c2f83d2Ohad Ben-Cohen pm_runtime_put_sync(dev); 19340bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen 19440bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohenout: 19540bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen return ret; 196e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 197e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 19880fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#ifdef CONFIG_PM_RUNTIME 19980fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen 20080fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohenstatic const struct dev_pm_ops sdio_bus_pm_ops = { 20180fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen SET_RUNTIME_PM_OPS( 20280fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen pm_generic_runtime_suspend, 20380fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen pm_generic_runtime_resume, 20480fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen pm_generic_runtime_idle 20580fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen ) 20680fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen}; 20780fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen 20880fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) 20980fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen 21080fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#else /* !CONFIG_PM_RUNTIME */ 21180fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen 21280fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#define SDIO_PM_OPS_PTR NULL 21380fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen 21480fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#endif /* !CONFIG_PM_RUNTIME */ 21580fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen 216e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = { 217e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .name = "sdio", 218bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman .dev_attrs = sdio_dev_attrs, 219e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .match = sdio_bus_match, 220e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .uevent = sdio_bus_uevent, 221e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .probe = sdio_bus_probe, 222e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .remove = sdio_bus_remove, 22380fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen .pm = SDIO_PM_OPS_PTR, 224e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}; 225e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 226e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void) 227e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 228e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return bus_register(&sdio_bus_type); 229e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 230e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 231e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void) 232e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 233e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman bus_unregister(&sdio_bus_type); 234e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 235e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 236f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 237f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_register_driver - register a function driver 238f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 239f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 240f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanint sdio_register_driver(struct sdio_driver *drv) 241f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 242f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.name = drv->name; 243f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 244f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman return driver_register(&drv->drv); 245f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 246f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_register_driver); 247f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 248f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 249f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_unregister_driver - unregister a function driver 250f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 251f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 252f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanvoid sdio_unregister_driver(struct sdio_driver *drv) 253f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 254f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 255f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman driver_unregister(&drv->drv); 256f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 257f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_unregister_driver); 258f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 259e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev) 260e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 261e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 262b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre 2631a632f8cdc33e7f8edca352164f0c96a75d08f08Pierre Ossman sdio_free_func_cis(func); 264e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 265759bdc7af450404382e937c76722ae8736daef92Pierre Ossman if (func->info) 266759bdc7af450404382e937c76722ae8736daef92Pierre Ossman kfree(func->info); 267759bdc7af450404382e937c76722ae8736daef92Pierre Ossman 268e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman kfree(func); 269e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 270e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 271e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 272e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure. 273e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 274e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card) 275e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 276e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func; 277e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 2789f2fcf99394b34769e3243a7f42a0ba8d21fc774Mariusz Kozlowski func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL); 279e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (!func) 280e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ERR_PTR(-ENOMEM); 281e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 282e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->card = card; 283e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 284e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_initialize(&func->dev); 285e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 286e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.parent = &card->dev; 287e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.bus = &sdio_bus_type; 288e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.release = sdio_release_func; 289e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 290e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return func; 291e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 292e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 293e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 294e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model. 295e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 296e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func) 297e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 298e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int ret; 299e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 300d1b268630875a7713b5d468a0c03403c5b721c8eKay Sievers dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); 301e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 302e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman ret = device_add(&func->dev); 303e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (ret == 0) 304e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman sdio_func_set_present(func); 305e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 306e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ret; 307e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 308e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 309e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 310e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and 311e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it. 3123d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake * This function can be called through error paths where sdio_add_func() was 3133d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake * never executed (because a failure occurred at an earlier point). 314e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 315e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func) 316e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 3173d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake if (!sdio_func_present(func)) 3183d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake return; 319e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 3203d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake device_del(&func->dev); 321e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman put_device(&func->dev); 322e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 323e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 324