linux/drivers/mmc/core/bus.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/mmc/core/bus.c
   3 *
   4 *  Copyright (C) 2003 Russell King, All Rights Reserved.
   5 *  Copyright (C) 2007 Pierre Ossman
   6 *
   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.
  10 *
  11 *  MMC card bus 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/host.h>
  19
  20#include "core.h"
  21#include "sdio_cis.h"
  22#include "bus.h"
  23
  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)
  26
  27static ssize_t mmc_type_show(struct device *dev,
  28        struct device_attribute *attr, char *buf)
  29{
  30        struct mmc_card *card = dev_to_mmc_card(dev);
  31
  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        case MMC_TYPE_SDIO:
  38                return sprintf(buf, "SDIO\n");
  39        default:
  40                return -EFAULT;
  41        }
  42}
  43
  44static struct device_attribute mmc_dev_attrs[] = {
  45        __ATTR(type, S_IRUGO, mmc_type_show, NULL),
  46        __ATTR_NULL,
  47};
  48
  49/*
  50 * This currently matches any MMC driver to any MMC card - drivers
  51 * themselves make the decision whether to drive this card in their
  52 * probe method.
  53 */
  54static int mmc_bus_match(struct device *dev, struct device_driver *drv)
  55{
  56        return 1;
  57}
  58
  59static int
  60mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
  61{
  62        struct mmc_card *card = dev_to_mmc_card(dev);
  63        const char *type;
  64        int retval = 0;
  65
  66        switch (card->type) {
  67        case MMC_TYPE_MMC:
  68                type = "MMC";
  69                break;
  70        case MMC_TYPE_SD:
  71                type = "SD";
  72                break;
  73        case MMC_TYPE_SDIO:
  74                type = "SDIO";
  75                break;
  76        default:
  77                type = NULL;
  78        }
  79
  80        if (type) {
  81                retval = add_uevent_var(env, "MMC_TYPE=%s", type);
  82                if (retval)
  83                        return retval;
  84        }
  85
  86        retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
  87        if (retval)
  88                return retval;
  89
  90        /*
  91         * Request the mmc_block device.  Note: that this is a direct request
  92         * for the module it carries no information as to what is inserted.
  93         */
  94        retval = add_uevent_var(env, "MODALIAS=mmc:block");
  95
  96        return retval;
  97}
  98
  99static int mmc_bus_probe(struct device *dev)
 100{
 101        struct mmc_driver *drv = to_mmc_driver(dev->driver);
 102        struct mmc_card *card = dev_to_mmc_card(dev);
 103
 104        return drv->probe(card);
 105}
 106
 107static int mmc_bus_remove(struct device *dev)
 108{
 109        struct mmc_driver *drv = to_mmc_driver(dev->driver);
 110        struct mmc_card *card = dev_to_mmc_card(dev);
 111
 112        drv->remove(card);
 113
 114        return 0;
 115}
 116
 117static int mmc_bus_suspend(struct device *dev, pm_message_t state)
 118{
 119        struct mmc_driver *drv = to_mmc_driver(dev->driver);
 120        struct mmc_card *card = dev_to_mmc_card(dev);
 121        int ret = 0;
 122
 123        if (dev->driver && drv->suspend)
 124                ret = drv->suspend(card, state);
 125        return ret;
 126}
 127
 128static int mmc_bus_resume(struct device *dev)
 129{
 130        struct mmc_driver *drv = to_mmc_driver(dev->driver);
 131        struct mmc_card *card = dev_to_mmc_card(dev);
 132        int ret = 0;
 133
 134        if (dev->driver && drv->resume)
 135                ret = drv->resume(card);
 136        return ret;
 137}
 138
 139static struct bus_type mmc_bus_type = {
 140        .name           = "mmc",
 141        .dev_attrs      = mmc_dev_attrs,
 142        .match          = mmc_bus_match,
 143        .uevent         = mmc_bus_uevent,
 144        .probe          = mmc_bus_probe,
 145        .remove         = mmc_bus_remove,
 146        .suspend        = mmc_bus_suspend,
 147        .resume         = mmc_bus_resume,
 148};
 149
 150int mmc_register_bus(void)
 151{
 152        return bus_register(&mmc_bus_type);
 153}
 154
 155void mmc_unregister_bus(void)
 156{
 157        bus_unregister(&mmc_bus_type);
 158}
 159
 160/**
 161 *      mmc_register_driver - register a media driver
 162 *      @drv: MMC media driver
 163 */
 164int mmc_register_driver(struct mmc_driver *drv)
 165{
 166        drv->drv.bus = &mmc_bus_type;
 167        return driver_register(&drv->drv);
 168}
 169
 170EXPORT_SYMBOL(mmc_register_driver);
 171
 172/**
 173 *      mmc_unregister_driver - unregister a media driver
 174 *      @drv: MMC media driver
 175 */
 176void mmc_unregister_driver(struct mmc_driver *drv)
 177{
 178        drv->drv.bus = &mmc_bus_type;
 179        driver_unregister(&drv->drv);
 180}
 181
 182EXPORT_SYMBOL(mmc_unregister_driver);
 183
 184static void mmc_release_card(struct device *dev)
 185{
 186        struct mmc_card *card = dev_to_mmc_card(dev);
 187
 188        sdio_free_common_cis(card);
 189
 190        if (card->info)
 191                kfree(card->info);
 192
 193        kfree(card);
 194}
 195
 196/*
 197 * Allocate and initialise a new MMC card structure.
 198 */
 199struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
 200{
 201        struct mmc_card *card;
 202
 203        card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
 204        if (!card)
 205                return ERR_PTR(-ENOMEM);
 206
 207        card->host = host;
 208
 209        device_initialize(&card->dev);
 210
 211        card->dev.parent = mmc_classdev(host);
 212        card->dev.bus = &mmc_bus_type;
 213        card->dev.release = mmc_release_card;
 214        card->dev.type = type;
 215
 216        return card;
 217}
 218
 219/*
 220 * Register a new MMC card with the driver model.
 221 */
 222int mmc_add_card(struct mmc_card *card)
 223{
 224        int ret;
 225        const char *type;
 226
 227        dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
 228
 229        switch (card->type) {
 230        case MMC_TYPE_MMC:
 231                type = "MMC";
 232                break;
 233        case MMC_TYPE_SD:
 234                type = "SD";
 235                if (mmc_card_blockaddr(card))
 236                        type = "SDHC";
 237                break;
 238        case MMC_TYPE_SDIO:
 239                type = "SDIO";
 240                break;
 241        default:
 242                type = "?";
 243                break;
 244        }
 245
 246        if (mmc_host_is_spi(card->host)) {
 247                printk(KERN_INFO "%s: new %s%s card on SPI\n",
 248                        mmc_hostname(card->host),
 249                        mmc_card_highspeed(card) ? "high speed " : "",
 250                        type);
 251        } else {
 252                printk(KERN_INFO "%s: new %s%s card at address %04x\n",
 253                        mmc_hostname(card->host),
 254                        mmc_card_highspeed(card) ? "high speed " : "",
 255                        type, card->rca);
 256        }
 257
 258        ret = device_add(&card->dev);
 259        if (ret)
 260                return ret;
 261
 262#ifdef CONFIG_DEBUG_FS
 263        mmc_add_card_debugfs(card);
 264#endif
 265
 266        mmc_card_set_present(card);
 267
 268        return 0;
 269}
 270
 271/*
 272 * Unregister a new MMC card with the driver model, and
 273 * (eventually) free it.
 274 */
 275void mmc_remove_card(struct mmc_card *card)
 276{
 277#ifdef CONFIG_DEBUG_FS
 278        mmc_remove_card_debugfs(card);
 279#endif
 280
 281        if (mmc_card_present(card)) {
 282                if (mmc_host_is_spi(card->host)) {
 283                        printk(KERN_INFO "%s: SPI card removed\n",
 284                                mmc_hostname(card->host));
 285                } else {
 286                        printk(KERN_INFO "%s: card %04x removed\n",
 287                                mmc_hostname(card->host), card->rca);
 288                }
 289                device_del(&card->dev);
 290        }
 291
 292        put_device(&card->dev);
 293}
 294
 295