• SD/MMC子系统之一——插卡、检测


    一、SDHCI与控制器驱动

      SDHC:Secure Digital(SD) Host Controller,是指一套sd host控制器的设计标准,其寄存器偏移以及意义都有一定的规范,并且提供了对应的驱动程序,方便vendor进行host controller的开发。
      厂商按照这套标准设计host controller之后,可以直接使用sdhci driver来实现host controller的使用,(qcom和samsung都使用了这套标准)。而vendor只需要实现平台相关的部分、如clock、pinctrl、power等等的部分即可。
      关于这个标准,可以参考《SDHC_Ver3.00_Final_110225》。
      注意,强调一下,这是一种mmc host controller的设计标准,其本质上还是属于mmc host。并且,其兼容mmc type card,而不是说只能使用于sd type card。

      SDHCI:Secure Digital(SD) Host Controller Interface,是针对SDHC标准的驱动接口。

      其常见接口如:

        sdhci_pltfm_init:平台设备SDHCI初始化,主要是分配、设置sdhci_host,最终关联到platform_device的device

        sdhci_alloc_host:分配sdhci_host

          mmc_alloc_host:分配、设置mmc_host(卡检测的扫描工作队列)

        sdhci_add_host:设置sdhci_host,关联到mmc_host,并注册mmc_host

          sdhci_setup_host:设置sdhci_host  

    二、卡检测的初始化:

      自定义SDHC驱动初始化调用platform_driver_register平台注册用户platform_driver。

      其中自定义SDHC驱动的probe会分配sdhci_host、sdhci_pltfm_host内存,并对sdhci_host进行设置

      然后进行关联mmc_host、sdhci_host、sdhci_pltfm_host。

      然后调用SDHCI接口sdhci_add_host,将得到的sdhci_host注册到sdhci core中。

      SDHCI接口sdhci_add_host会设置sdhci_host,并调用下级__sdhci_add_host。

      SDHCI接口__sdhci_add_host

        设置请求处理完成时调用的任务队列处理函数sdhci_tasklet_finish

        设置当前请求命令的响应定时处理函数sdhci_timeout_timer

        设置当前数据交互的响应定时sdhci_timeout_data_timer

        设置等待队列的缓冲区读准备中断

        设置sdhci_host

        设置外部中断

        注册LE灯

        调用mmc_add_host

        使能卡检测sdhci_enable_card_detection

      其中mmc_add_host添加设备类,调用mmc_start_host开启主机,并注册电源管理通知。

      其中mmc_claim_host声明独占主机,设置电源,使用host->slot.handler_priv->cd_gpio注册线程化中断,执行一次卡检测_mmc_detect_change

      注意:其中SD插拔经常出现一个打印问题“mmcblk1: error -110 sending status command, aborting ”

      其实问题原因:

      

    二、卡检测的执行:

      因为在启动主机时会执行卡检测,但是这里也不一定会检测成功,因为有可能没插卡。

      除了SDHC驱动以外,还会编写一份控制器驱动,比如海思的himci。

      自定义控制器驱动初始化调用platform_driver_register平台注册用户platform_driver。

      其中自定义SDHC驱动的probe会分配、设置自定义主机属性,其中卡检测函数有三种使用情况:

      1)自定义主机属性的mmc_host_ops的get_cd函数

      2)自定义主机属性的card_status函数

      3)自定义主机属性的定时器

      其中通常插卡检测是由定时器的处理函数检测到的,定时器处理函数的流程为:

      1)通过卡检测寄存器或者IO,连续检查5次SD卡状态,相同则继续,否则重复100次。(次数均为自定义)

      2)如果5次相同则判断其值是否为插入,如果是插入则软复位,初始化自定义主机属性,调用MMC子系统API的mmc_detect_change

      mmc_detect_change调用_mmc_detect_change,两者的区别为电源管理是否唤醒事件,默认为有

      _mmc_detect_change会判断如果设备被配置为唤醒,我们将防止新的休眠5秒,以便为用户提供使用事件的空间。

      然后设置mmc_host->detect_change为1,检测更改

      然后调用mmc_schedule_delayed_work调度工作队列

      mmc_schedule_delayed_work会调用queue_delayed_work执行system_freezable_wq的工作队列,其中使用system_freezable_wq的原因有2个:

      1)它允许同时执行多个工作(不是相同的工作项)。

      2)当用户空间在系统PM期间冻结时,队列将冻结。

      而此处的工作任务为mmc_alloc_host中设置的INIT_DELAYED_WORK(&host->detect, mmc_rescan);

      所以,这里跳转到mmc_rescan

      mmc_rescan:

        根据mmc_host->rescan_disable判断是否允许扫描,如果为真则不允许直接退出。

        根据mmc_host->cap判断是否为不可移动的已注册卡只扫描一次还是可以继续扫描。

        设置mmc_host->rescan_entered=1,表示进入扫描

        调用mmc_bus_get递增总线操作计数

        调用mmc_rescan_try_freq,以四种频率进行初始化SDIO SD EMMC

      mmc_rescan_try_freq

        设置mmc_host->f_init,根据mmc_recan函数传进来的频率参数,一般mmc/sd/sdio的初始化时钟采用的是400kHZ.

        调用mmc_power_up,进行上电。在mmc_add_host时,会调用mmc_start_host,而那里首先是将host掉电的,所以这里上电。

        调用mmc_hw_reset_for_init,有些emmc (VCCQ总是开着的)可能在通电后无法复位,所以如果可能的话,可以进行硬件复位。

        根据不同卡做不同的操作:

        1)纯SD卡,则目标卡不会应答,一般主机host的寄存器会报错,但是这个无关紧要,可以不理它。

        2)纯SDIO卡,那么这里就是复位SDIO卡,通过发送命令CMD52来实现的。

        3)SD卡和SDIO卡的组合卡,则需要先发送CMD52来复位SDIO卡,再复位SD卡,因为CMD52要先于CMD0发送。

        调用mmc_go_idle,发送CMD0,复位SD卡,进入IDLE模式

        调用mmc_send_if_cond,如果是SD卡,则发送CMD8 获取支持的电压值

        根据不同卡做不同的卡检测操作:

        1)SDIO卡,调用mmc_attach_sdio

        2)SD卡,调用mmc_attach_sd

        3)MMC卡,调用mmc_attach_mmc

        4)都不是,则调用mmc_power_off进行下电

      此处以SD卡为例,所以只看mmc_attach_sd

        

  • 相关阅读:
    git 删除远程分支
    测试模板--接口测试
    测试模板--PC浏览器兼容性测试
    Mock作用
    Docker实践--搭建JIRA平台
    Docker实践--搭建分布式UI测试环境
    Docker实践--搭建HttpRunnerManager测试平台
    Docker实践--搭建Yapi测试平台
    微博爬虫实践---搜索关键词
    接口实践--演练地址集合
  • 原文地址:https://www.cnblogs.com/pokerface/p/11059611.html
Copyright © 2020-2023  润新知