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