sdio_bus.c revision b1538bcf75e2e11459947ec4d4329ed04fbe2b2c
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) 24e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 25e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 26e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * This currently matches any SDIO function to any driver in order 27e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * to help initial development and testing. 28e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 29e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_match(struct device *dev, struct device_driver *drv) 30e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 31e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 1; 32e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 33e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 34e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int 35e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmansdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, 36e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int buf_size) 37e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 38e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman envp[0] = NULL; 39e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 40e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 41e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 42e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 43e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_probe(struct device *dev) 44e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 45e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return -ENODEV; 46e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 47e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 48e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_remove(struct device *dev) 49e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 50e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 51e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 52e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 53e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = { 54e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .name = "sdio", 55e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .match = sdio_bus_match, 56e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .uevent = sdio_bus_uevent, 57e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .probe = sdio_bus_probe, 58e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .remove = sdio_bus_remove, 59e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}; 60e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 61e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void) 62e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 63e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return bus_register(&sdio_bus_type); 64e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 65e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 66e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void) 67e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 68e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman bus_unregister(&sdio_bus_type); 69e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 70e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 71f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 72f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_register_driver - register a function driver 73f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 74f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 75f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanint sdio_register_driver(struct sdio_driver *drv) 76f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 77f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.name = drv->name; 78f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 79f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman return driver_register(&drv->drv); 80f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 81f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_register_driver); 82f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 83f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 84f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_unregister_driver - unregister a function driver 85f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 86f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 87f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanvoid sdio_unregister_driver(struct sdio_driver *drv) 88f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 89f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 90f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman driver_unregister(&drv->drv); 91f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 92f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_unregister_driver); 93f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 94e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev) 95e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 96e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 97b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre 98b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre sdio_free_cis(func); 99e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 100e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman kfree(func); 101e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 102e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 103e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 104e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure. 105e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 106e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card) 107e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 108e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func; 109e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 110e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL); 111e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (!func) 112e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ERR_PTR(-ENOMEM); 113e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 114e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman memset(func, 0, sizeof(struct sdio_func)); 115e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 116e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->card = card; 117e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 118e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_initialize(&func->dev); 119e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 120e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.parent = &card->dev; 121e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.bus = &sdio_bus_type; 122e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.release = sdio_release_func; 123e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 124e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return func; 125e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 126e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 127e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 128e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model. 129e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 130e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func) 131e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 132e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int ret; 133e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 134e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman snprintf(func->dev.bus_id, sizeof(func->dev.bus_id), 135e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman "%s:%d", mmc_card_id(func->card), func->num); 136e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 137e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman ret = device_add(&func->dev); 138e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (ret == 0) 139e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman sdio_func_set_present(func); 140e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 141e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ret; 142e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 143e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 144e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 145e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and 146e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it. 147e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 148e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func) 149e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 150e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (sdio_func_present(func)) 151e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_del(&func->dev); 152e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 153e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman put_device(&func->dev); 154e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 155e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 156