Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12-rc5 238 lines 5.6 kB view raw
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...) \ 25static 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 31MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], 32 card->raw_cid[2], card->raw_cid[3]); 33MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], 34 card->raw_csd[2], card->raw_csd[3]); 35MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); 36MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); 37MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); 38MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid); 39MMC_ATTR(name, "%s\n", card->cid.prod_name); 40MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid); 41MMC_ATTR(serial, "0x%08x\n", card->cid.serial); 42 43#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL) 44 45static 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 59static 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 */ 71static 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 77static int 78mmc_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 112static 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 123static 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 134static 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 144static 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 152static 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 */ 167int 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 175EXPORT_SYMBOL(mmc_register_driver); 176 177/** 178 * mmc_unregister_driver - unregister a media driver 179 * @drv: MMC media driver 180 */ 181void mmc_unregister_driver(struct mmc_driver *drv) 182{ 183 drv->drv.bus = &mmc_bus_type; 184 driver_unregister(&drv->drv); 185} 186 187EXPORT_SYMBOL(mmc_unregister_driver); 188 189 190/* 191 * Internal function. Initialise a MMC card structure. 192 */ 193void 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 */ 206int 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 */ 218void 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 227static int __init mmc_init(void) 228{ 229 return bus_register(&mmc_bus_type); 230} 231 232static void __exit mmc_exit(void) 233{ 234 bus_unregister(&mmc_bus_type); 235} 236 237module_init(mmc_init); 238module_exit(mmc_exit);