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