博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
10. [mmc subsystem] host(第四章)——host实例(sdhci-msm说明)
阅读量:5365 次
发布时间:2019-06-15

本文共 5584 字,大约阅读时间需要 18 分钟。

一、说明

sdhci-msm是指高通的mmc host,其使用了标准SDHC标准。故可以使用前面说的《host(第二章)——sdhci》和《host(第三章)——sdhci-pltfm说明》的接口。

后续代码以msm8916平台的host实现以及linux 4.6.0版本中的sdhci-msm的实现为例,这部分代码都是开源的。

由于有一些寄存器内容需要文档的支撑但我们并没有,所以这里只是简单地介绍一下设计思想和代码结构。

二、dtsi节点

msm8916有两个sdhci host,我们以第一个host为例,默认接的是emmc

arch/arm64/boot/dts/qcom/msm8916.dtsi

aliases {        sdhc1 = &sdhc_1; /* SDC1 eMMC slot */    };        sdhc_1: sdhci@07824000 {            compatible = "qcom,sdhci-msm-v4";                        // 会和sdhci-msm.c的driver匹配            reg = <0x07824900 0x11c>, <0x07824000 0x800>;            reg-names = "hc_mem", "core_mem";                            // 两部分寄存器,hc_mem表示sdhci使用的寄存器,core_mem表示msm host独立于sdhci标准之外的、自己需要使用的寄存器                        // 因为驱动里面会使用sdhci-pltfm来进行解析,所以这里必须把hc_mem放在寄存器的第一个属性,具体参考《host(第三章)——sdhci-pltfm说明》            interrupts = <0 123 0>, <0 138 0>;            interrupt-names = "hc_irq", "pwr_irq";                        // 两部分中断,hc_irq表示sdhci使用的中断,core_mem表示msm host检测host电源状态的中断、独立于sdhci标准                        // 因为驱动里面会使用sdhci-pltfm来进行解析,所以这里必须把hc_irq放在中断的第一个属性,具体参考《host(第三章)——sdhci-pltfm说明》            clocks = <&gcc GCC_SDCC1_APPS_CLK>,                 <&gcc GCC_SDCC1_AHB_CLK>;            clock-names = "core", "iface";                        // 两个时钟                        // core->GCC_SDCC1_APPS_CLK,工作时钟,也就是输出时钟                        // iface->GCC_SDCC1_AHB_CLK,总线时钟            bus-width = <8>;                        // 总线宽度设置为8            non-removable;                        // 设置为不可移除            status = "disabled";        };

三、数据结构

1、struct sdhci_msm_host

sdhci-msm host driver根据自身资源定制的host结构体。

struct sdhci_msm_host {    struct platform_device *pdev;    // 对应dtsi节点解析出来的平台设备    void __iomem *core_mem; /* MSM SDCC mapped address */    // host自身的寄存器基地址    struct clk *clk;    /* main SD/MMC bus clock */    // 工作时钟,对应    struct clk *pclk;   /* SDHC peripheral bus clock */    struct clk *bus_clk;    /* SDHC bus voter clock */    struct mmc_host *mmc;    // 对应的mmc_host结构体,具体参考《mmc core》};

2、sdhci_msm_pdata

struct sdhci_pltfm_data类型。

提供给sdhci-pltfm接口使用的平台数据结构体,定义了sdhci_host的ops、quirks和quirks2。会在调用sdhci_pltfm_init生成sdhci_host的时候使用。

具体参考《host(第三章)——sdhci-pltfm说明》

static const struct sdhci_pltfm_data sdhci_msm_pdata = {    .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |          SDHCI_QUIRK_SINGLE_POWER_WRITE,    .ops = &sdhci_msm_ops,};

3、sdhci_msm_ops

struct sdhci_ops类型。

为sdhci_host提供出sdhci标准之外的一些实际的硬件操作方法的操作集给sdhci core。

具体参考《host(第二章)——sdhci》

static const struct sdhci_ops sdhci_msm_ops = {    .platform_execute_tuning = sdhci_msm_execute_tuning,    .reset = sdhci_reset,    .set_clock = sdhci_set_clock,    .set_bus_width = sdhci_set_bus_width,    .set_uhs_signaling = sdhci_set_uhs_signaling,};

具体后面说明。这个操作集的内容也是sdhci host要实现的核心内容。

四、代码说明

1、设备驱动模型相关代码

static struct platform_driver sdhci_msm_driver = {    .probe = sdhci_msm_probe,        // probe方法,也就是后面代码的介绍核心    .remove = sdhci_msm_remove,    // remove方法    .driver = {           .name = "sdhci_msm",           .of_match_table = sdhci_msm_dt_match,    },};static const struct of_device_id sdhci_msm_dt_match[] = {    { .compatible = "qcom,sdhci-msm-v4" },        // 以此来和dtsi节点匹配    {},};module_platform_driver(sdhci_msm_driver);

2、sdhci_msm_probe

  • 主要工作

    • 调用调用sdhci_pltfm_init为sdhci_host、sdhci_pltfm_host、sdhci_msm_host分配内存、设置
    • 关联mmc_host、sdhci_host、sdhci_pltfm_host、sdhci_msm_host
    • 解析dtsi属性设置到mmc_host和sdhci_host中
    • 获取各种时钟
    • 获取host独立于sdhci的寄存器基地址
    • 调用sdhci_add_host将sdhci_host注册到sdhci core中,相应的mmc_host也会被调用到mmc core中了。host的注册就完成了。
  • 代码如下

static int sdhci_msm_probe(struct platform_device *pdev){    struct sdhci_host *host;    struct sdhci_pltfm_host *pltfm_host;    struct sdhci_msm_host *msm_host;    struct resource *core_memres;    int ret;    u16 host_version, core_minor;    u32 core_version, caps;    u8 core_major;    host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));        // 调用sdhci_pltfm_init为sdhci_host、sdhci_pltfm_host、sdhci_msm_host分配内存        // 并对sdhci_host进行设置,具体可以参考《host(第三章)——sdhci-pltfm说明》        // 这里传入了sdhci_msm_pdata会用来设置sdhci_host的相关成员。        // 注意由于和前面文章的kernel版本的差异,这边的接口可能有点出入    pltfm_host = sdhci_priv(host);    msm_host = sdhci_pltfm_priv(pltfm_host);    msm_host->mmc = host->mmc;    msm_host->pdev = pdev;        // 关联mmc_host、sdhci_host、sdhci_pltfm_host、sdhci_msm_host        // 几个结构体之间的关系可以参考《host(第一章)——概述》    ret = mmc_of_parse(host->mmc);        // 调用mmc_of_parse解析host的dtsi节点属性,设置到mmc_host的caps属性中        // mmc_of_parse属于mmc core提供的标准接口,具体参考《mmc core——host模块说明》    sdhci_get_of_property(pdev);        // 调用sdhci_get_of_property解析host的dtsi节点属性,设置到sdhci_host的quirks和quirks2中    /* Setup SDCC bus voter clock. */    msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");        // 获取bus时钟    /* Setup main peripheral bus clock */    msm_host->pclk = devm_clk_get(&pdev->dev, "iface");        // 获取iface时钟到msm_host->pclk中(GCC_SDCC1_AHB_CLK)    ret = clk_prepare_enable(msm_host->pclk);    /* Setup SDC MMC clock */    msm_host->clk = devm_clk_get(&pdev->dev, "core");        // 获取core时钟到msm_host->clk中(GCC_SDCC1_AHB_CLK)    core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1);    msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres);        // 获取msm host的寄存器基地址    /* Reset the core and Enable SDHC mode */    writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |               CORE_SW_RST, msm_host->core_mem + CORE_POWER);        //.......以下过滤一下msm host的复位操作和初始化操作    ret = sdhci_add_host(host);        // 调用sdhci_add_host将得到的sdhci_host注册到sdhci core中。    return 0;}

转载于:https://www.cnblogs.com/linhaostudy/p/10818152.html

你可能感兴趣的文章
[elk]Mutate filter plugin增删改查字段
查看>>
mysql的查询、子查询及连接查询
查看>>
Java内功心法,行为型设计模式
查看>>
向github项目push代码后,Jenkins实现其自动构建
查看>>
C语言时间头文件
查看>>
Java8中的 lambda 和Stream API
查看>>
兼容性测试相关
查看>>
对称排序
查看>>
走进MySQL
查看>>
Remove Duplicates from Sorted Array
查看>>
Java 反射机制
查看>>
科技园区
查看>>
λ和列表解析
查看>>
LeetCode 3. Longest Substring Without Repeating
查看>>
通过Measure & Arrange实现UWP瀑布流布局
查看>>
如何在linux下安装jdk并运行java程序
查看>>
gkENGINE跨平台的问题总结
查看>>
什么是webpack
查看>>
Golang基础
查看>>
数据清洗——python定位csv中的特定字符位置
查看>>