diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/mmc/mmc_sysfs.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/mmc/mmc_sysfs.c')
-rw-r--r-- | drivers/mmc/mmc_sysfs.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c new file mode 100644 index 000000000000..29a56e9cd5b3 --- /dev/null +++ b/drivers/mmc/mmc_sysfs.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/mmc_sysfs.c | ||
3 | * | ||
4 | * Copyright (C) 2003 Russell King, All Rights Reserved. | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * MMC sysfs/driver model support. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/device.h> | ||
15 | |||
16 | #include <linux/mmc/card.h> | ||
17 | #include <linux/mmc/host.h> | ||
18 | |||
19 | #include "mmc.h" | ||
20 | |||
21 | #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) | ||
22 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) | ||
23 | |||
24 | #define MMC_ATTR(name, fmt, args...) \ | ||
25 | static ssize_t mmc_##name##_show (struct device *dev, char *buf) \ | ||
26 | { \ | ||
27 | struct mmc_card *card = dev_to_mmc_card(dev); \ | ||
28 | return sprintf(buf, fmt, args); \ | ||
29 | } | ||
30 | |||
31 | MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], | ||
32 | card->raw_cid[2], card->raw_cid[3]); | ||
33 | MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | ||
34 | card->raw_csd[2], card->raw_csd[3]); | ||
35 | MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | ||
36 | MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | ||
37 | MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | ||
38 | MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid); | ||
39 | MMC_ATTR(name, "%s\n", card->cid.prod_name); | ||
40 | MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid); | ||
41 | MMC_ATTR(serial, "0x%08x\n", card->cid.serial); | ||
42 | |||
43 | #define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL) | ||
44 | |||
45 | static struct device_attribute mmc_dev_attrs[] = { | ||
46 | MMC_ATTR_RO(cid), | ||
47 | MMC_ATTR_RO(csd), | ||
48 | MMC_ATTR_RO(date), | ||
49 | MMC_ATTR_RO(fwrev), | ||
50 | MMC_ATTR_RO(hwrev), | ||
51 | MMC_ATTR_RO(manfid), | ||
52 | MMC_ATTR_RO(name), | ||
53 | MMC_ATTR_RO(oemid), | ||
54 | MMC_ATTR_RO(serial), | ||
55 | __ATTR_NULL | ||
56 | }; | ||
57 | |||
58 | |||
59 | static void mmc_release_card(struct device *dev) | ||
60 | { | ||
61 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
62 | |||
63 | kfree(card); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * This currently matches any MMC driver to any MMC card - drivers | ||
68 | * themselves make the decision whether to drive this card in their | ||
69 | * probe method. However, we force "bad" cards to fail. | ||
70 | */ | ||
71 | static int mmc_bus_match(struct device *dev, struct device_driver *drv) | ||
72 | { | ||
73 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
74 | return !mmc_card_bad(card); | ||
75 | } | ||
76 | |||
77 | static int | ||
78 | mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf, | ||
79 | int buf_size) | ||
80 | { | ||
81 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
82 | char ccc[13]; | ||
83 | int i = 0; | ||
84 | |||
85 | #define add_env(fmt,val) \ | ||
86 | ({ \ | ||
87 | int len, ret = -ENOMEM; \ | ||
88 | if (i < num_envp) { \ | ||
89 | envp[i++] = buf; \ | ||
90 | len = snprintf(buf, buf_size, fmt, val) + 1; \ | ||
91 | buf_size -= len; \ | ||
92 | buf += len; \ | ||
93 | if (buf_size >= 0) \ | ||
94 | ret = 0; \ | ||
95 | } \ | ||
96 | ret; \ | ||
97 | }) | ||
98 | |||
99 | for (i = 0; i < 12; i++) | ||
100 | ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0'; | ||
101 | ccc[12] = '\0'; | ||
102 | |||
103 | i = 0; | ||
104 | add_env("MMC_CCC=%s", ccc); | ||
105 | add_env("MMC_MANFID=%06x", card->cid.manfid); | ||
106 | add_env("MMC_NAME=%s", mmc_card_name(card)); | ||
107 | add_env("MMC_OEMID=%04x", card->cid.oemid); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int mmc_bus_suspend(struct device *dev, pm_message_t state) | ||
113 | { | ||
114 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
115 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
116 | int ret = 0; | ||
117 | |||
118 | if (dev->driver && drv->suspend) | ||
119 | ret = drv->suspend(card, state); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | static int mmc_bus_resume(struct device *dev) | ||
124 | { | ||
125 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
126 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
127 | int ret = 0; | ||
128 | |||
129 | if (dev->driver && drv->resume) | ||
130 | ret = drv->resume(card); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static struct bus_type mmc_bus_type = { | ||
135 | .name = "mmc", | ||
136 | .dev_attrs = mmc_dev_attrs, | ||
137 | .match = mmc_bus_match, | ||
138 | .hotplug = mmc_bus_hotplug, | ||
139 | .suspend = mmc_bus_suspend, | ||
140 | .resume = mmc_bus_resume, | ||
141 | }; | ||
142 | |||
143 | |||
144 | static int mmc_drv_probe(struct device *dev) | ||
145 | { | ||
146 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
147 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
148 | |||
149 | return drv->probe(card); | ||
150 | } | ||
151 | |||
152 | static int mmc_drv_remove(struct device *dev) | ||
153 | { | ||
154 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
155 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
156 | |||
157 | drv->remove(card); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * mmc_register_driver - register a media driver | ||
165 | * @drv: MMC media driver | ||
166 | */ | ||
167 | int mmc_register_driver(struct mmc_driver *drv) | ||
168 | { | ||
169 | drv->drv.bus = &mmc_bus_type; | ||
170 | drv->drv.probe = mmc_drv_probe; | ||
171 | drv->drv.remove = mmc_drv_remove; | ||
172 | return driver_register(&drv->drv); | ||
173 | } | ||
174 | |||
175 | EXPORT_SYMBOL(mmc_register_driver); | ||
176 | |||
177 | /** | ||
178 | * mmc_unregister_driver - unregister a media driver | ||
179 | * @drv: MMC media driver | ||
180 | */ | ||
181 | void mmc_unregister_driver(struct mmc_driver *drv) | ||
182 | { | ||
183 | drv->drv.bus = &mmc_bus_type; | ||
184 | driver_unregister(&drv->drv); | ||
185 | } | ||
186 | |||
187 | EXPORT_SYMBOL(mmc_unregister_driver); | ||
188 | |||
189 | |||
190 | /* | ||
191 | * Internal function. Initialise a MMC card structure. | ||
192 | */ | ||
193 | void mmc_init_card(struct mmc_card *card, struct mmc_host *host) | ||
194 | { | ||
195 | memset(card, 0, sizeof(struct mmc_card)); | ||
196 | card->host = host; | ||
197 | device_initialize(&card->dev); | ||
198 | card->dev.parent = card->host->dev; | ||
199 | card->dev.bus = &mmc_bus_type; | ||
200 | card->dev.release = mmc_release_card; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Internal function. Register a new MMC card with the driver model. | ||
205 | */ | ||
206 | int mmc_register_card(struct mmc_card *card) | ||
207 | { | ||
208 | snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), | ||
209 | "%s:%04x", card->host->host_name, card->rca); | ||
210 | |||
211 | return device_add(&card->dev); | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Internal function. Unregister a new MMC card with the | ||
216 | * driver model, and (eventually) free it. | ||
217 | */ | ||
218 | void mmc_remove_card(struct mmc_card *card) | ||
219 | { | ||
220 | if (mmc_card_present(card)) | ||
221 | device_del(&card->dev); | ||
222 | |||
223 | put_device(&card->dev); | ||
224 | } | ||
225 | |||
226 | |||
227 | static int __init mmc_init(void) | ||
228 | { | ||
229 | return bus_register(&mmc_bus_type); | ||
230 | } | ||
231 | |||
232 | static void __exit mmc_exit(void) | ||
233 | { | ||
234 | bus_unregister(&mmc_bus_type); | ||
235 | } | ||
236 | |||
237 | module_init(mmc_init); | ||
238 | module_exit(mmc_exit); | ||