[mmc subsystem] mmc core(第六章)——mmc core主模块

本文深入解析mmc core主模块,包括初始化、mmc host管理、mmc card操作、总线设置、请求处理等关键接口。内容涵盖mmc_core初始化、host的电源管理、card检测、总线io设置等,帮助理解mmc subsystem工作原理。
摘要由CSDN通过智能技术生成

mmc subsystem系列(持续更新中):
[mmc subsystem] 概念与框架
[mmc subsystem] mmc core(第一章)——概述
[mmc subsystem] mmc core(第二章)——数据结构和宏定义说明
[mmc subsystem] mmc core(第三章)——bus模块说明
[mmc subsystem] mmc core(第四章)——host模块说明
[mmc subsystem] mmc core(第五章)——card相关模块(mmc type card)
[mmc subsystem] mmc core(第六章)——mmc core主模块

建议先参考《[mmc subsystem] 概念与框架》和《[mmc subsystem] mmc core(第一章)——概述》对整体有一个了解。

=========================================================================================================

一、说明

1、mmc core概述

mmc core主模块是mmc core的实现核心。也是本章的重点内容。
对应代码位置drivers/mmc/core/core.c。
其主要负责如下功能:

  • mmc core初始化,包括注册mmc bus、mm host class等等
  • mmc host的管理和维护,包括为其他模块提供mmc_host的操作接口,如下
    • host的启动和停止
    • host的占用和释放
    • host电源状态的保存和恢复
    • host总线操作集的绑定和解绑
    • host上卡状态检测
  • 为其他模块提供mmc_card的操作接口,如下
    • card的唤醒和休眠
    • card擦除
    • card属性的获取
  • 为其他模块提供总线io setting的接口
  • 为其他模块提供mmc请求接口
  • card检测接口
  • bkops操作接口
  • regulator操作接口
  • clock操作接口
  • mmc core电源管理操作接口

2、操作集说明

在mmc_host中有两个操作集成员,需要理解一下,以免在代码中产生误会:

  • mmc_host->struct mmc_host_ops *ops,这个是host的操作集,由host controller驱动决定。对于sdhci类host来说,就是sdhci_ops(sdhci.c中设置)。
  • mmc_host->struct mmc_bus_ops *bus_ops,这个是mmc总线的操作集(也可以理解为host的mmc bus handler,host的总线处理方法),由总线上的card type决定。对于mmc card type来说,就是mmc_ops_unsafe或者mmc_ops(mmc_attach_bus_ops中设置)。

二、API总览

1、mmc core初始化相关

  • mmc_init & mmc_exit (模块内使用)

2、mmc host的管理和维护相关

  • mmc_claim_host & mmc_try_claim_host & mmc_release_host (模块内使用)
  • mmc_power_up & mmc_power_off
  • mmc_start_host & mmc_stop_host
  • mmc_power_save_host & mmc_power_restore_host
  • mmc_resume_host & mmc_suspend_host
  • mmc_pm_notify

3、mmc card的操作相关(包括card状态的获取)

  • mmc_hw_reset & mmc_hw_reset_check &
  • mmc_card_awake & mmc_card_sleep
  • mmc_card_is_prog_state
  • mmc_can_erase
  • mmc_can_trim
  • mmc_can_discard
  • mmc_can_sanitize
  • mmc_can_secure_erase_trim
  • mmc_erase_group_aligned

4、总线io setting相关

  • mmc_set_ios
  • mmc_set_chip_select
  • mmc_set_clock
  • mmc_set_bus_mode
  • mmc_set_bus_width
  • mmc_select_voltage
  • mmc_set_signal_voltage(特殊)
  • mmc_set_timing
  • mmc_set_driver_type

  • mmc_get_max_frequency & mmc_get_min_frequency

5、host的mmc总线相关

  • mmc_resume_bus
  • mmc_attach_bus & mmc_detach_bus

6、mmc请求相关

  • mmc_request_done
  • mmc_wait_for_req
  • mmc_wait_for_cmd
  • mmc_set_data_timeout
  • mmc_align_data_size

7、card检测相关

  • mmc_detect_change
  • mmc_rescan
  • mmc_detect_card_removed

8、bkops操作相关

  • mmc_blk_init_bkops_statistics
  • mmc_start_delayed_bkops
  • mmc_start_bkops & mmc_stop_bkops
  • mmc_start_idle_time_bkops
  • mmc_read_bkops_status

9、regulator操作相关

  • mmc_regulator_get_ocrmask
  • mmc_regulator_set_ocr
  • mmc_regulator_get_supply

10、card擦除操作相关

  • mmc_init_erase
  • mmc_erase

11、clock操作接口

  • mmc_init_clk_scaling & mmc_exit_clk_scaling
  • mmc_can_scale_clk
  • mmc_disable_clk_scaling

12、mmc core电源管理操作

  • mmc_rpm_hold & mmc_rpm_release

二、接口代码说明——mmc core初始化相关

1、mmc_init实现

负责初始化整个mmc core。

  • 主要工作:

    • 分配一个workqueue,用于专门处理mmc core的执行的工作
    • 注册mmc bus
    • 注册mmc host class
  • 代码如下:

static int __init mmc_init(void)
{
    int ret;

/* 分配一个workqueue,用于专门处理mmc core的执行的工作 */
    workqueue = alloc_ordered_workqueue("kmmcd", 0);

/* 注册mmc bus */
    ret = mmc_register_bus();    // 调用mmc_register_bus注册mmc bus,具体参考《mmc core——bus模块说明》
        // 会生成/sys/bus/mmc目录

/* 注册mmc host class */
    ret = mmc_register_host_class();    // 调用mmc_register_host_class注册mmc host class,具体参考《mmc core——host模块说明》
        // 会生成/sys/class/mmc_host目录

/* 注册sdio bus */
    ret = sdio_register_bus();

    return 0;

}

subsys_initcall(mmc_init);

三、接口代码说明——mmc host的管理和维护相关

1、mmc_claim_host & mmc_try_claim_host & mmc_release_host

host被使能之后就不能再次被使能,并且只能被某个进程独自占用。
可以简单地将host理解为一种资源,同时只能被一个进程获取,但是在占用进程里面可以重复占用。
在对host进行操作之前(包括发起mmc请求),必须使用mmc_claim_host和mmc_release_host来进行获取和释放。

  • 变量说明

    • mmc_host->claimed用来表示host是否被占用
    • mmc_host->claimer用来表示host的占用者(进程)
    • mmc_host->claim_cnt用来表示host的占用者的占用计数,为0时则会释放这个host
  • 代码如下

static inline void mmc_claim_host(struct mmc_host *host)
{
    __mmc_claim_host(host, NULL);·// 调用__mmc_claim_host来获取host
}

int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
{
/只考虑abort为NULL的情况,在mmc core中的mmc_claim_host也是将其设置为NULL
    DECLARE_WAITQUEUE(wait, current);    
    unsigned long flags;
    int stop;

    might_sleep();        // 说明这个函数可能导致进程休眠

    add_wait_queue(&host->wq, &wait);    // 把当前进程加入到等待队列中

    spin_lock_irqsave(&host->lock, flags);
    while (1) {    // 以下尝试获取host,如果host正在被占用,会进入休眠
        set_current_state(TASK_UNINTERRUPTIBLE);    // 设置进程状态为TASK_UNINTERRUPTIBLE状态
        stop = abort ? atomic_read(abort) : 0;
        if (stop || !host->claimed || host->claimer == current)    // 当host的占用标志claimed为0,或者占用者是当前进程的时候,说明可以占用了,退出
            break;
        spin_unlock_irqrestore(&host->lock, flags);
        schedule();    // 否则,进行调度进入休眠
        spin_lock_irqsave(&host->lock, flags);
    }
    set_current_state(TASK_RUNNING);    // 设置进程为运行状态
    if (!stop) {
        host->claimed = 1;    // 设置占用标志claimed 
        host->claimer = current;    // 设置占用者为当前进程
        host->claim_cnt += 1;    // 占用计数加1
    } else
        wake_up(&host->wq);
    spin_unlock_irqrestore(&host->lock, flags);
    remove_wait_queue(&host->wq, &wait);    // 将当前进程从等待队列中退出
    if (host->ops->enable && !stop && host->claim_cnt == 1)
        host->ops->enable(host);  // 调用host操作集中的enable方法来占用该host,对应sdhci类host即为sdhci_enable
    return stop;
}

void mmc_release_host(struct mmc_host *host)
{
    unsigned long flags;

    WARN_ON(!host->claimed);

    if (host->ops->disable && host->claim_cnt == 1)    // 当前claim_cnt为1(马上要变为0),调用释放host了
        host->ops->disable(host);    // 调用host操作集中的disable方法来释放该host,对应sdhci类host即为sdhci_disable

    spin_lock_irqsave(&host->lock, flags);
    if (--host->claim_cnt) {
        /* Release for nested claim */
        spin_unlock_irqrestore(&host->lock, flags);    // 如果减一之后计数还不为0,说明当前进程需要继续占用该host,不做其他操作
    } else {    // 以下需要释放该host
        host->claimed = 0;    // 设置占用标志claimed为0
        host->claimer = NULL;    // 清空占用者(进程)
        spin_unlock_irqrestore(&host->lock, flags);
        wake_up(&host->wq);    // 唤醒host的等待队列,让那些调用mmc_claim_host睡眠等待host资源的进程被唤醒
    }
}

int mmc_try_claim_host(struct mmc_host *host) 
{
// 和mmc_claim_host的主要区别在于进程不会休眠,获取失败直接返回
    int claimed_host = 0;
    unsigned long flags;

    spin_lock_irqsave(&host->lock, flags);
    if (!host->claimed || host->claimer == current) {
        host->claimed = 1;
        host->claimer = current;
        host->claim_cnt += 1;
        claimed_host = 1;
    }
    spin_unlock_irqrestore(&host->lock, flags);
    if (host->ops->enable && claimed_host && host->
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值