MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / mmc / core / bus.c
blob850efe82a25661a99d8dc4cd318e2baae39f764d
1 /*
2 * linux/drivers/mmc/core/bus.c
4 * Copyright (C) 2003 Russell King, All Rights Reserved.
5 * Copyright (C) 2007 Pierre Ossman
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * MMC card bus driver model
14 #include <linux/device.h>
15 #include <linux/err.h>
17 #include <linux/mmc/card.h>
18 #include <linux/mmc/host.h>
20 #include "sysfs.h"
21 #include "core.h"
22 #include "bus.h"
24 #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
25 #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
27 static ssize_t mmc_type_show(struct device *dev,
28 struct device_attribute *attr, char *buf)
30 struct mmc_card *card = dev_to_mmc_card(dev);
32 switch (card->type) {
33 case MMC_TYPE_MMC:
34 return sprintf(buf, "MMC\n");
35 case MMC_TYPE_SD:
36 return sprintf(buf, "SD\n");
37 default:
38 return -EFAULT;
42 static struct device_attribute mmc_dev_attrs[] = {
43 MMC_ATTR_RO(type),
44 __ATTR_NULL,
48 * This currently matches any MMC driver to any MMC card - drivers
49 * themselves make the decision whether to drive this card in their
50 * probe method.
52 static int mmc_bus_match(struct device *dev, struct device_driver *drv)
54 return 1;
57 static int
58 mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
59 int buf_size)
61 struct mmc_card *card = dev_to_mmc_card(dev);
62 int retval = 0, i = 0, length = 0;
64 #if 0 // mask by Victor Yu. 12-02-2008
65 #define add_env(fmt,val) do { \
66 retval = add_uevent_var(envp, num_envp, &i, \
67 buf, buf_size, &length, \
68 fmt, val); \
69 if (retval) \
70 return retval; \
71 } while (0);
72 #else
73 #define add_env(fmt,val) \
74 ({ \
75 if (i < num_envp) { \
76 envp[i++] = buf; \
77 length = snprintf(buf, buf_size, fmt, val) + 1; \
78 buf_size -= length; \
79 buf += length; \
80 if (buf_size >= 0) \
81 retval = 0; \
82 else \
83 retval = -ENOMEM; \
84 } \
86 #endif
88 switch (card->type) {
89 case MMC_TYPE_MMC:
90 add_env("MMC_TYPE=%s", "MMC");
91 break;
92 case MMC_TYPE_SD:
93 add_env("MMC_TYPE=%s", "SD");
94 break;
97 add_env("MMC_NAME=%s", mmc_card_name(card));
99 #undef add_env
101 envp[i] = NULL;
103 return 0;
106 static int mmc_bus_probe(struct device *dev)
108 struct mmc_driver *drv = to_mmc_driver(dev->driver);
109 struct mmc_card *card = dev_to_mmc_card(dev);
111 return drv->probe(card);
114 static int mmc_bus_remove(struct device *dev)
116 struct mmc_driver *drv = to_mmc_driver(dev->driver);
117 struct mmc_card *card = dev_to_mmc_card(dev);
119 drv->remove(card);
121 return 0;
124 static int mmc_bus_suspend(struct device *dev, pm_message_t state)
126 struct mmc_driver *drv = to_mmc_driver(dev->driver);
127 struct mmc_card *card = dev_to_mmc_card(dev);
128 int ret = 0;
130 if (dev->driver && drv->suspend)
131 ret = drv->suspend(card, state);
132 return ret;
135 static int mmc_bus_resume(struct device *dev)
137 struct mmc_driver *drv = to_mmc_driver(dev->driver);
138 struct mmc_card *card = dev_to_mmc_card(dev);
139 int ret = 0;
141 if (dev->driver && drv->resume)
142 ret = drv->resume(card);
143 return ret;
146 static struct bus_type mmc_bus_type = {
147 .name = "mmc",
148 .dev_attrs = mmc_dev_attrs,
149 .match = mmc_bus_match,
150 #if 0 // mask by Victor Yu. 12-02-2008
151 .uevent = mmc_bus_uevent,
152 .probe = mmc_bus_probe,
153 .remove = mmc_bus_remove,
154 #else
155 .hotplug = mmc_bus_uevent,
156 #endif
157 .suspend = mmc_bus_suspend,
158 .resume = mmc_bus_resume,
161 int mmc_register_bus(void)
163 return bus_register(&mmc_bus_type);
166 void mmc_unregister_bus(void)
168 bus_unregister(&mmc_bus_type);
172 * mmc_register_driver - register a media driver
173 * @drv: MMC media driver
175 int mmc_register_driver(struct mmc_driver *drv)
177 drv->drv.bus = &mmc_bus_type;
178 #if 1 // add by Victor Yu. 12-01-2008
179 drv->drv.probe = mmc_bus_probe;
180 drv->drv.remove = mmc_bus_remove;
181 #endif
182 return driver_register(&drv->drv);
185 EXPORT_SYMBOL(mmc_register_driver);
188 * mmc_unregister_driver - unregister a media driver
189 * @drv: MMC media driver
191 void mmc_unregister_driver(struct mmc_driver *drv)
193 drv->drv.bus = &mmc_bus_type;
194 driver_unregister(&drv->drv);
197 EXPORT_SYMBOL(mmc_unregister_driver);
199 static void mmc_release_card(struct device *dev)
201 #if 0 // mask by Victor Yu. 12-03-2008
202 struct mmc_card *card = dev_to_mmc_card(dev);
203 #else
204 struct mmc_card *card;
206 card = dev_to_mmc_card(dev);
207 #endif
209 kfree(card);
213 * Allocate and initialise a new MMC card structure.
215 struct mmc_card *mmc_alloc_card(struct mmc_host *host)
217 struct mmc_card *card;
219 #if 0 // mask by Victor Yu. 12-02-2008
220 card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
221 #else
222 card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
223 #endif
224 if (!card)
225 return ERR_PTR(-ENOMEM);
226 #if 1 // add by Victor Yu. 12-02-2008
227 memset(card, 0 , sizeof(struct mmc_card));
228 #endif
230 card->host = host;
232 device_initialize(&card->dev);
234 #if 0 // mask by Victor Yu. 12-02-2008
235 card->dev.parent = mmc_classdev(host);
236 #else
237 card->dev.parent = host->dev;
238 #endif
239 card->dev.bus = &mmc_bus_type;
240 card->dev.release = mmc_release_card;
242 return card;
246 * Register a new MMC card with the driver model.
248 int mmc_add_card(struct mmc_card *card)
250 int ret;
251 const char *type;
253 snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
254 "%s:%04x", mmc_hostname(card->host), card->rca);
256 switch (card->type) {
257 case MMC_TYPE_MMC:
258 type = "MMC";
259 break;
260 case MMC_TYPE_SD:
261 type = "SD";
262 if (mmc_card_blockaddr(card))
263 type = "SDHC";
264 break;
265 default:
266 type = "?";
267 break;
270 printk(KERN_INFO "%s: new %s%s card at address %04x\n",
271 mmc_hostname(card->host),
272 mmc_card_highspeed(card) ? "high speed " : "",
273 type, card->rca);
275 #if 0 // mask by Victor Yu. 12-02-2008
276 card->dev.uevent_suppress = 1;
277 #endif
279 ret = device_add(&card->dev);
280 if (ret)
281 return ret;
283 if (card->host->bus_ops->sysfs_add) {
284 ret = card->host->bus_ops->sysfs_add(card->host, card);
285 if (ret) {
286 device_del(&card->dev);
287 return ret;
291 #if 0 // mask by Victor Yu. 12-02-2008
292 card->dev.uevent_suppress = 0;
293 kobject_uevent(&card->dev.kobj, KOBJ_ADD);
294 #endif
296 mmc_card_set_present(card);
298 return 0;
302 * Unregister a new MMC card with the driver model, and
303 * (eventually) free it.
305 void mmc_remove_card(struct mmc_card *card)
307 if (mmc_card_present(card)) {
308 printk(KERN_INFO "%s: card %04x removed\n",
309 mmc_hostname(card->host), card->rca);
311 if (card->host->bus_ops->sysfs_remove) {
312 card->host->bus_ops->sysfs_remove(card->host, card);
314 device_del(&card->dev);
317 put_device(&card->dev);