sdio_bus.c revision bcfe66e21ef78a078bb0de0bab532701996695d3
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
49bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstruct 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
146e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return 0;
147e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
148e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
149e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = {
150e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.name		= "sdio",
151bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	.dev_attrs	= sdio_dev_attrs,
152e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.match		= sdio_bus_match,
153e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.uevent		= sdio_bus_uevent,
154e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.probe		= sdio_bus_probe,
155e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.remove		= sdio_bus_remove,
156e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman};
157e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
158e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void)
159e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
160e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return bus_register(&sdio_bus_type);
161e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
162e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
163e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void)
164e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
165e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	bus_unregister(&sdio_bus_type);
166e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
167e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
168f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/**
169f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	sdio_register_driver - register a function driver
170f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	@drv: SDIO function driver
171f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */
172f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanint sdio_register_driver(struct sdio_driver *drv)
173f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{
174f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	drv->drv.name = drv->name;
175f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	drv->drv.bus = &sdio_bus_type;
176f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	return driver_register(&drv->drv);
177f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman}
178f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_register_driver);
179f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman
180f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/**
181f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	sdio_unregister_driver - unregister a function driver
182f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	@drv: SDIO function driver
183f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */
184f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanvoid sdio_unregister_driver(struct sdio_driver *drv)
185f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{
186f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	drv->drv.bus = &sdio_bus_type;
187f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	driver_unregister(&drv->drv);
188f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman}
189f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_unregister_driver);
190f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman
191e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev)
192e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
193e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	struct sdio_func *func = dev_to_sdio_func(dev);
194b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre
1951a632f8cdc33e7f8edca352164f0c96a75d08f08Pierre Ossman	sdio_free_func_cis(func);
196e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
197e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	kfree(func);
198e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
199e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
200e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
201e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure.
202e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
203e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card)
204e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
205e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	struct sdio_func *func;
206e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
207e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL);
208e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (!func)
209e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		return ERR_PTR(-ENOMEM);
210e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
211e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	memset(func, 0, sizeof(struct sdio_func));
212e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
213e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->card = card;
214e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
215e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	device_initialize(&func->dev);
216e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
217e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.parent = &card->dev;
218e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.bus = &sdio_bus_type;
219e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.release = sdio_release_func;
220e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
221e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return func;
222e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
223e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
224e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
225e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model.
226e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
227e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func)
228e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
229e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	int ret;
230e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
231e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	snprintf(func->dev.bus_id, sizeof(func->dev.bus_id),
232e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		 "%s:%d", mmc_card_id(func->card), func->num);
233e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
234e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	ret = device_add(&func->dev);
235e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (ret == 0)
236e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		sdio_func_set_present(func);
237e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
238e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return ret;
239e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
240e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
241e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
242e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and
243e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it.
244e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
245e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func)
246e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
247e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (sdio_func_present(func))
248e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		device_del(&func->dev);
249e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
250e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	put_device(&func->dev);
251e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
252e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
253