Chinaunix首页 | 论坛 | 博客
  • 博客访问: 82691
  • 博文数量: 62
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-23 21:49
文章分类

全部博文(62)

文章存档

2014年(55)

2013年(7)

我的朋友

分类: 嵌入式

2014-05-03 20:44:47

    本节中主要讲述探测函数中的初始化和移除slot,首先看下初始化:
static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
{
    struct mmc_host *mmc;
    struct dw_mci_slot *slot;
    mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->pdev->dev);    //core中申请host,后面讲述
    if (!mmc)
        return -ENOMEM;
    slot = mmc_priv(mmc);    //mmc操作函数集,后面讲述
    slot->id = id;
    slot->mmc = mmc;
    slot->host = host;
    mmc->ops = &dw_mci_ops;
    mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
    mmc->f_max = host->bus_hz;
    if (host->pdata->get_ocr)
        mmc->ocr_avail = host->pdata->get_ocr(id);
    else
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
    /*
     * Start with slot power disabled, it will be enabled when a card
     * is detected.
     */
    if (host->pdata->setpower)
        host->pdata->setpower(id, 0);
    if (host->pdata->caps)
        mmc->caps = host->pdata->caps;
    else
        mmc->caps = 0;
    if (host->pdata->get_bus_wd)
        if (host->pdata->get_bus_wd(slot->id) >= 4)
            mmc->caps |= MMC_CAP_4_BIT_DATA;
    if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
        mmc->caps |= MMC_CAP_SD_HIGHSPEED;
#ifdef CONFIG_MMC_DW_IDMAC
    mmc->max_segs = host->ring_size;
    mmc->max_blk_size = 65536;
    mmc->max_blk_count = host->ring_size;
    mmc->max_seg_size = 0x1000;
    mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
#else
    if (host->pdata->blk_settings) {
        mmc->max_segs = host->pdata->blk_settings->max_segs;
        mmc->max_blk_size = host->pdata->blk_settings->max_blk_size;
        mmc->max_blk_count = host->pdata->blk_settings->max_blk_count;
        mmc->max_req_size = host->pdata->blk_settings->max_req_size;
        mmc->max_seg_size = host->pdata->blk_settings->max_seg_size;
    } else {
        /* Useful defaults if platform data is unset. */
        mmc->max_segs = 64;
        mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
        mmc->max_blk_count = 512;
        mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
        mmc->max_seg_size = mmc->max_req_size;
    }
#endif /* CONFIG_MMC_DW_IDMAC */
    host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
    if (IS_ERR(host->vmmc)) {
        printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc));
        host->vmmc = NULL;
    } else
        regulator_enable(host->vmmc);
    if (dw_mci_get_cd(mmc))
        set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
    else
        clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
    host->slot[id] = slot;
    mmc_add_host(mmc);    //初始化host,后面讲述
#if defined(CONFIG_DEBUG_FS)
    dw_mci_init_debugfs(slot);
#endif
    /* Card initially undetected */
    slot->last_detect_state = 0;
    /*
     * Card may have been plugged in prior to boot so we
     * need to run the detect tasklet
     */
    tasklet_schedule(&host->card_tasklet);
    return 0;
}
     core中申请host
/**
 *    mmc_alloc_host - initialise the per-host structure.
 *    @extra: sizeof private data structure
 *    @dev: pointer to host device model structure
 *
 *    Initialise the per-host structure.
 */
struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
    int err;
    struct mmc_host *host;
    if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
        return NULL;
    host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
    if (!host)
        return NULL;
    spin_lock(&mmc_host_lock);
    err = idr_get_new(&mmc_host_idr, host, &host->index);
    spin_unlock(&mmc_host_lock);
    if (err)
        goto free;
    dev_set_name(&host->class_dev, "mmc%d", host->index);
    host->parent = dev;
    host->class_dev.parent = dev;
    host->class_dev.class = &mmc_host_class;
    device_initialize(&host->class_dev);
    mmc_host_clk_init(host);
    spin_lock_init(&host->lock);
    init_waitqueue_head(&host->wq);
    INIT_DELAYED_WORK(&host->detect, mmc_rescan);
    INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable);
#ifdef CONFIG_PM
    host->pm_notify.notifier_call = mmc_pm_notify;
#endif
    /*
     * By default, hosts do not support SGIO or large requests.
     * They have to set these according to their abilities.
     */
    host->max_segs = 1;
    host->max_seg_size = PAGE_CACHE_SIZE;
    host->max_req_size = PAGE_CACHE_SIZE;
    host->max_blk_size = 512;
    host->max_blk_count = PAGE_CACHE_SIZE / 512;
    return host;
free:
    kfree(host);
    return NULL;
}
EXPORT_SYMBOL(mmc_alloc_host);
    初始化host
/**
 *    mmc_add_host - initialise host hardware
 *    @host: mmc host
 *
 *    Register the host with the driver model. The host must be
 *    prepared to start servicing requests before this function
 *    completes.
 */
int mmc_add_host(struct mmc_host *host)
{
    int err;
    WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
        !host->ops->enable_sdio_irq);
    err = device_add(&host->class_dev);
    if (err)
        return err;
    led_trigger_register_simple(dev_name(&host->class_dev), &host->led);
#ifdef CONFIG_DEBUG_FS
    mmc_add_host_debugfs(host);
#endif
    mmc_start_host(host);
    register_pm_notifier(&host->pm_notify);
    return 0;
}
EXPORT_SYMBOL(mmc_add_host);

    清除slot:
static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
{
    /* Shutdown detect IRQ */
    if (slot->host->pdata->exit)
        slot->host->pdata->exit(id);
    /* Debugfs stuff is cleaned up by mmc core */
    mmc_remove_host(slot->mmc);    //移除host
    slot->host->slot[id] = NULL;
    mmc_free_host(slot->mmc);    //释放host
}
    移除host:
/**
 *    mmc_remove_host - remove host hardware
 *    @host: mmc host
 *
 *    Unregister and remove all cards associated with this host,
 *    and power down the MMC bus. No new requests will be issued
 *    after this function has returned.
 */
void mmc_remove_host(struct mmc_host *host)
{
    unregister_pm_notifier(&host->pm_notify);
    mmc_stop_host(host);
#ifdef CONFIG_DEBUG_FS
    mmc_remove_host_debugfs(host);
#endif
    device_del(&host->class_dev);
    led_trigger_unregister_simple(host->led);
    mmc_host_clk_exit(host);
}
EXPORT_SYMBOL(mmc_remove_host);
    释放host
/**
 *    mmc_free_host - free the host structure
 *    @host: mmc host
 *
 *    Free the host once all references to it have been dropped.
 */
void mmc_free_host(struct mmc_host *host)
{
    spin_lock(&mmc_host_lock);
    idr_remove(&mmc_host_idr, host->index);
    spin_unlock(&mmc_host_lock);
    put_device(&host->class_dev);
}
EXPORT_SYMBOL(mmc_free_host);
阅读(622) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~