sdio: link unknown CIS tuples to the sdio_func structure
[linux-2.6.git] / drivers / mmc / core / sdio_bus.c
1 /*
2  *  linux/drivers/mmc/core/sdio_bus.c
3  *
4  *  Copyright 2007 Pierre Ossman
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or (at
9  * your option) any later version.
10  *
11  * SDIO function driver model
12  */
13
14 #include <linux/device.h>
15 #include <linux/err.h>
16
17 #include <linux/mmc/card.h>
18 #include <linux/mmc/sdio_func.h>
19
20 #include "sdio_cis.h"
21 #include "sdio_bus.h"
22
23 #define dev_to_sdio_func(d)     container_of(d, struct sdio_func, dev)
24
25 /*
26  * This currently matches any SDIO function to any driver in order
27  * to help initial development and testing.
28  */
29 static int sdio_bus_match(struct device *dev, struct device_driver *drv)
30 {
31         return 1;
32 }
33
34 static int
35 sdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
36                 int buf_size)
37 {
38         envp[0] = NULL;
39
40         return 0;
41 }
42
43 static int sdio_bus_probe(struct device *dev)
44 {
45         return -ENODEV;
46 }
47
48 static int sdio_bus_remove(struct device *dev)
49 {
50         return 0;
51 }
52
53 static struct bus_type sdio_bus_type = {
54         .name           = "sdio",
55         .match          = sdio_bus_match,
56         .uevent         = sdio_bus_uevent,
57         .probe          = sdio_bus_probe,
58         .remove         = sdio_bus_remove,
59 };
60
61 int sdio_register_bus(void)
62 {
63         return bus_register(&sdio_bus_type);
64 }
65
66 void sdio_unregister_bus(void)
67 {
68         bus_unregister(&sdio_bus_type);
69 }
70
71 /**
72  *      sdio_register_driver - register a function driver
73  *      @drv: SDIO function driver
74  */
75 int sdio_register_driver(struct sdio_driver *drv)
76 {
77         drv->drv.name = drv->name;
78         drv->drv.bus = &sdio_bus_type;
79         return driver_register(&drv->drv);
80 }
81 EXPORT_SYMBOL_GPL(sdio_register_driver);
82
83 /**
84  *      sdio_unregister_driver - unregister a function driver
85  *      @drv: SDIO function driver
86  */
87 void sdio_unregister_driver(struct sdio_driver *drv)
88 {
89         drv->drv.bus = &sdio_bus_type;
90         driver_unregister(&drv->drv);
91 }
92 EXPORT_SYMBOL_GPL(sdio_unregister_driver);
93
94 static void sdio_release_func(struct device *dev)
95 {
96         struct sdio_func *func = dev_to_sdio_func(dev);
97
98         sdio_free_cis(func);
99
100         kfree(func);
101 }
102
103 /*
104  * Allocate and initialise a new SDIO function structure.
105  */
106 struct sdio_func *sdio_alloc_func(struct mmc_card *card)
107 {
108         struct sdio_func *func;
109
110         func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL);
111         if (!func)
112                 return ERR_PTR(-ENOMEM);
113
114         memset(func, 0, sizeof(struct sdio_func));
115
116         func->card = card;
117
118         device_initialize(&func->dev);
119
120         func->dev.parent = &card->dev;
121         func->dev.bus = &sdio_bus_type;
122         func->dev.release = sdio_release_func;
123
124         return func;
125 }
126
127 /*
128  * Register a new SDIO function with the driver model.
129  */
130 int sdio_add_func(struct sdio_func *func)
131 {
132         int ret;
133
134         snprintf(func->dev.bus_id, sizeof(func->dev.bus_id),
135                  "%s:%d", mmc_card_id(func->card), func->num);
136
137         ret = device_add(&func->dev);
138         if (ret == 0)
139                 sdio_func_set_present(func);
140
141         return ret;
142 }
143
144 /*
145  * Unregister a SDIO function with the driver model, and
146  * (eventually) free it.
147  */
148 void sdio_remove_func(struct sdio_func *func)
149 {
150         if (sdio_func_present(func))
151                 device_del(&func->dev);
152
153         put_device(&func->dev);
154 }
155