sdio_bus.c revision 9a08f82b3cc522f727ace580a2aaee5402435bc8
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/mmc/core/sdio_bus.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2007 Pierre Ossman 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SDIO function driver model 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/sdio_func.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sdio_cis.h" 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sdio_bus.h" 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* show configuration fields */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sdio_config_attr(field, format_string) \ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t \ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfield##_show(struct device *dev, struct device_attribute *attr, char *buf) \ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func; \ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds \ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func = dev_to_sdio_func (dev); \ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf (buf, format_string, func->field); \ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssdio_config_attr(class, "0x%02x\n"); 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssdio_config_attr(vendor, "0x%04x\n"); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssdio_config_attr(device, "0x%04x\n"); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func = dev_to_sdio_func (dev); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n", 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func->class, func->vendor, func->device); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct device_attribute sdio_dev_attrs[] = { 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __ATTR_RO(class), 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __ATTR_RO(vendor), 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __ATTR_RO(device), 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __ATTR_RO(modalias), 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __ATTR_NULL, 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct sdio_device_id *sdio_match_one(struct sdio_func *func, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct sdio_device_id *id) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return id; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct sdio_device_id *sdio_match_device(struct sdio_func *func, 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_driver *sdrv) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct sdio_device_id *ids; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ids = sdrv->id_table; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ids) { 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (ids->class || ids->vendor || ids->device) { 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sdio_match_one(func, ids)) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ids; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ids++; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sdio_bus_match(struct device *dev, struct device_driver *drv) 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func = dev_to_sdio_func(dev); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_driver *sdrv = to_sdio_driver(drv); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sdio_match_device(func, sdrv)) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int buf_size) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func = dev_to_sdio_func(dev); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 0, length = 0; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (add_uevent_var(envp, num_envp, &i, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf, buf_size, &length, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SDIO_CLASS=%02X", func->class)) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (add_uevent_var(envp, num_envp, &i, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf, buf_size, &length, 11228120be5d6830cd7c7777d8bf570bdb20abef58aPaul Walmsley "SDIO_ID=%04X:%04X", func->vendor, func->device)) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (add_uevent_var(envp, num_envp, &i, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf, buf_size, &length, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "MODALIAS=sdio:c%02Xv%04Xd%04X", 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func->class, func->vendor, func->device)) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds envp[i] = NULL; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sdio_bus_probe(struct device *dev) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_driver *drv = to_sdio_driver(dev->driver); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func = dev_to_sdio_func(dev); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct sdio_device_id *id; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id = sdio_match_device(func, drv); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!id) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set the default block size so the driver is sure it's something 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sensible. */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdio_claim_host(func); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = sdio_set_block_size(func, 0); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdio_release_host(func); 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return drv->probe(func, id); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sdio_bus_remove(struct device *dev) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_driver *drv = to_sdio_driver(dev->driver); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func = dev_to_sdio_func(dev); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->remove(func); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func->irq_handler) { 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "WARNING: driver %s did not remove " 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "its interrupt handler!\n", drv->name); 15886dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm sdio_claim_host(func); 159a4e628328ec60873fec9d506d682155391f589ceMatthew Dharm sdio_release_irq(func); 160a4e628328ec60873fec9d506d682155391f589ceMatthew Dharm sdio_release_host(func); 161a4e628328ec60873fec9d506d682155391f589ceMatthew Dharm } 162a4e628328ec60873fec9d506d682155391f589ceMatthew Dharm 163a4e628328ec60873fec9d506d682155391f589ceMatthew Dharm return 0; 164a4e628328ec60873fec9d506d682155391f589ceMatthew Dharm} 16528120be5d6830cd7c7777d8bf570bdb20abef58aPaul Walmsley 166a4e628328ec60873fec9d506d682155391f589ceMatthew Dharmstatic struct bus_type sdio_bus_type = { 16786dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm .name = "sdio", 16886dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm .dev_attrs = sdio_dev_attrs, 16986dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm .match = sdio_bus_match, 17086dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm .uevent = sdio_bus_uevent, 17186dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm .probe = sdio_bus_probe, 17286dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm .remove = sdio_bus_remove, 17386dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm}; 17486dbde9cbdfe8bc2c2dfe5d33027d3acc55e0470Matthew Dharm 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint sdio_register_bus(void) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return bus_register(&sdio_bus_type); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid sdio_unregister_bus(void) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_unregister(&sdio_bus_type); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sdio_register_driver - register a function driver 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: SDIO function driver 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint sdio_register_driver(struct sdio_driver *drv) 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->drv.name = drv->name; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->drv.bus = &sdio_bus_type; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return driver_register(&drv->drv); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(sdio_register_driver); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sdio_unregister_driver - unregister a function driver 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: SDIO function driver 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid sdio_unregister_driver(struct sdio_driver *drv) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->drv.bus = &sdio_bus_type; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_unregister(&drv->drv); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(sdio_unregister_driver); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sdio_release_func(struct device *dev) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func = dev_to_sdio_func(dev); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdio_free_func_cis(func); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(func); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate and initialise a new SDIO function structure. 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sdio_func *sdio_alloc_func(struct mmc_card *card) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sdio_func *func; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!func) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(func, 0, sizeof(struct sdio_func)); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func->card = card; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_initialize(&func->dev); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func->dev.parent = &card->dev; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func->dev.bus = &sdio_bus_type; 236226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm func->dev.release = sdio_release_func; 237226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm 238226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm return func; 239226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm} 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 242226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm * Register a new SDIO function with the driver model. 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint sdio_add_func(struct sdio_func *func) 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(func->dev.bus_id, sizeof(func->dev.bus_id), 249226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm "%s:%d", mmc_card_id(func->card), func->num); 250226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm 251226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm ret = device_add(&func->dev); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdio_func_set_present(func); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 257226173edae1c49c68ebb723771a02302c85e3475Matthew Dharm 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Unregister a SDIO function with the driver model, and 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (eventually) free it. 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid sdio_remove_func(struct sdio_func *func) 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sdio_func_present(func)) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_del(&func->dev); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(&func->dev); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds