4. [mmc subsystem] mmc core(第四章)——host模塊說明

来源:https://www.cnblogs.com/linhaostudy/archive/2019/04/29/10790541.html
-Advertisement-
Play Games

零、說明 對應代碼drivers/mmc/core/host.c,drivers/mmc/core/host.h。 為底層host controller driver實現mmc host的申請以及註冊的API等等,以及host相關屬性的實現。 一、API總覽 1、mmc host分配、註冊相關 mm ...


零、說明

對應代碼drivers/mmc/core/host.c,drivers/mmc/core/host.h。

為底層host controller driver實現mmc host的申請以及註冊的API等等,以及host相關屬性的實現。

一、API總覽

1、mmc host分配、註冊相關

  • mmc_alloc_host & mmc_free_host

底層host controller驅動調用,用來分配或者釋放一個struct mmc_host結構體,將其於mmc_host_class關聯,並且做部分初始化操作。

    原型:struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
    參數說明:extra——》mmc_host的私有數據的長度,會和mmc_host結構體一起分配,
                     dev——》底層host controller的device結構體,用於作為mmc_host的device的父設備

    原型:void mmc_free_host(struct mmc_host *host)
  • mmc_add_host & mmc_remove_host

底層host controller驅動調用,註冊或者卸載mmc_host到設備驅動中,添加到sys類下麵,並設置相應的debug目錄。然後啟動mmc_host。

    原型:int mmc_add_host(struct mmc_host *host)
    原型:void mmc_remove_host(struct mmc_host *host)

2、mmc host class相關

  • mmc_register_host_class & mmc_unregister_host_class

註冊或者卸載mmc_host類。

    原型:int mmc_register_host_class(void)
    原型:void mmc_unregister_host_class(void)

3、mmc host屬性解析相關

  • mmc_of_parse

底層host controller驅動調用,解析mmc_host的dtsi節點的部分屬性。

    原型:void mmc_of_parse(struct mmc_host *host)

4、mmc host時鐘相關

mmc_host_clk_hold & mmc_host_clk_release

mmc core主模塊調用,用於獲取host時鐘和釋放host時鐘

二、數據結構

1、mmc_host_class

mmc_host_class代表了mmc_host這個類。其內容如下:

static struct class mmc_host_class = {
    .name       = "mmc_host",        // 添加到sys文件系統之後,會生成/sys/class/mmc_host這個目錄
    .dev_release    = mmc_host_classdev_release,    // 從mmc_host這個class下release掉某個設備之後要做的對應操作
    .pm     = &mmc_host_pm_ops,        // 該class下的host的pm電源管理操作
};

static const struct dev_pm_ops mmc_host_pm_ops = {
    SET_SYSTEM_SLEEP_PM_OPS(mmc_host_suspend, mmc_host_resume)
    SET_RUNTIME_PM_OPS(mmc_host_runtime_suspend, mmc_host_runtime_resume,
               pm_generic_runtime_idle)
};
// 具體函數實現遇到了再補充

2、clk_scaling_attr_grp

一些和時鐘縮放(clk_scaling)相關的屬性組

static struct attribute *clk_scaling_attrs[] = {
    &dev_attr_enable.attr,
    &dev_attr_up_threshold.attr,
    &dev_attr_down_threshold.attr,
    &dev_attr_polling_interval.attr,
    NULL,
};

static struct attribute_group clk_scaling_attr_grp = {
    .name = "clk_scaling",
    .attrs = clk_scaling_attrs,
};

對應/sys/class/mmc_host/mmc0/clk_scaling目錄下的屬性

3、dev_attr_grp

和設備相關的屬性組,只定義了perf屬性

static struct attribute *dev_attrs[] = {
#ifdef CONFIG_MMC_PERF_PROFILING
    &dev_attr_perf.attr,
#endif
    NULL,
};
static struct attribute_group dev_attr_grp = {
    .attrs = dev_attrs,
};

對應/sys/class/mmc_host/mmc0/perf屬性

三、介面代碼說明

1、mmc_register_host_class實現

註冊mmc_host class。

int mmc_register_host_class(void)
{
    return class_register(&mmc_host_class);   // 以mmc_host_class為class創建一個class,關於mmc_host_class在上述數據結構已經說明過了
}

相關節點:/sys/class/mmc_host

2、mmc_alloc_host實現

底層host controller驅動調用,用來分配一個struct mmc_host結構體,將其於mmc_host_class關聯,並且做部分初始化操作。

  • 主要工作:
    • 分配記憶體空間
    • 初始化其class device(對應/sys/class/mmc0節點)
    • clock gate、鎖、工作隊列、wakelock、detect工作的初始化
    • 初始化detect成員(也就是檢測工作)為mmc_rescan
  • 代碼如下:
/**
 *  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)
{
//    參數說明:extra——》mmc_host的私有數據的長度,會和mmc_host結構體一起分配,
//                     dev——》底層host controller的device結構體,用於作為mmc_host的device的父設備
    int err;
    struct mmc_host *host;

/* 分配記憶體空間,其中多分配了extra位元組作為私有數據 */
    host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
    if (!host)
        return NULL;
        
     /* scanning will be enabled when we're ready */
/* 因為只是分配了一個mmc_host,host還沒有準備好,所以這裡禁用rescan,也就是設置mmc_host->rescan_disable 
    host->rescan_disable = 1;   // 在在mmc_start_host中會去使能
/* 為該mmc_host分配一個唯一的id號,設置到host->index */
    idr_preload(GFP_KERNEL);
    spin_lock(&mmc_host_lock);
    err = idr_alloc(&mmc_host_idr, host, 0, 0, GFP_NOWAIT);
    if (err >= 0)
        host->index = err;
    spin_unlock(&mmc_host_lock);
    idr_preload_end();
    if (err < 0)
        goto free;

/* 設置mmc_host name */
    dev_set_name(&host->class_dev, "mmc%d", host->index);   // 以mmc_host的id號構成mmc_host的name,例如mmc0、mmc1

/* 關聯mmc_host class_dev併進行初始化 */
/* class_dev就代表了mmc_host 的device結構體,是其在設備驅動模型中的體現 */
    host->parent = dev;                              // 將mmc_host的parent設置成對應host controller節點轉化出來的device
    host->class_dev.parent = dev;             
        // 將mmc_host的device(class_dev)的parent設置成對應host controller節點轉化出來的device
        // 註冊到sysfs之後,會相應生成/sys/bus/platform/devices/7824900.sdhci/mmc_host/mmc0
        // 其中7824900.sdhci表示qcom的host controller節點轉化出來的device
    host->class_dev.class = &mmc_host_class;
         // 將mmc_device(class_dev)的類設置為mmc_host_class
        // 註冊到sysfs之後,會相應生成/sys/class/mmc_host/mmc0

    device_initialize(&host->class_dev);   // 初始化mmc_host->class_dev

/* clock gate、鎖、工作隊列、wakelock、detect工作的初始化 */
    mmc_host_clk_init(host);

    mutex_init(&host->slot.lock);
    host->slot.cd_irq = -EINVAL;

    spin_lock_init(&host->lock);
    init_waitqueue_head(&host->wq);
    host->wlock_name = kasprintf(GFP_KERNEL, "%s_detect", mmc_hostname(host)); // 設置detect_wake_lock的名稱為mmc0_detect,在card檢測的時候會使用
    wake_lock_init(&host->detect_wake_lock, WAKE_LOCK_SUSPEND, host->wlock_name);   // // 初始化detect_wake_lock
        // 可以通過/sys/kernel/debug/wakeup_sources,相應生成了mmc0_detect和mmc1_detect兩個wakelock

    INIT_DELAYED_WORK(&host->detect, mmc_rescan);
        // !!!!這個很重要!!!!初始化detect工作為mmc_rescan,後續調度host->detect來檢測是否有card插入時,就會調用到mmc_rescan。
#ifdef CONFIG_PM
    host->pm_notify.notifier_call = mmc_pm_notify;
#endif

/* 一些size的初始化 */
    host->max_segs = 1;   // 初始化最大支持段(由host自己根據硬體進行修改),可以通過/sys/block/mmcblk0/queue/max_segments進行修改
    host->max_seg_size = PAGE_CACHE_SIZE;   // 初始化段大小,(由host自己根據硬體進行修改)

    host->max_req_size = PAGE_CACHE_SIZE;   // 一次MMC請求的最大位元組數
    host->max_blk_size = 512;   // 一個塊的最大位元組數
    host->max_blk_count = PAGE_CACHE_SIZE / 512; // 一次MMC請求的最大塊數量

    return host;

free:
    kfree(host);
    return NULL;
}

3、mmc_add_host實現

底層host controller驅動調用,註冊mmc_host到設備驅動中,添加到sys類下麵,並設置相應的debug目錄。然後啟動mmc_host。

  • 主要工作:
    • 使能pm runtime功能
    • 將mmc_host的class_dev添加到設備驅動模型中,在sysfs中生成相應的節點
    • 初始化mmc_host相關的debug目錄
    • 設置mmc_host的class_dev的屬性
    • 調用mmc_start_host啟動host(進入mmc core主模塊的部分)
/**
 *  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;
/* 使能mmc host的class_dev的pm runtime功能 */
    err = pm_runtime_set_active(&host->class_dev);
    if (err)
        pr_err("%s: %s: failed setting runtime active: err: %d\n",
               mmc_hostname(host), __func__, err);
    else if (mmc_use_core_runtime_pm(host))
        pm_runtime_enable(&host->class_dev);

/* 通過device_add將mmc_host->class_dev添加到設備驅動模型中,在sys下生成相應節點 */
    err = device_add(&host->class_dev);
        // 通過mmc_alloc_host中關於mmc_host的class_dev的關聯,可以生成如下兩個節點
        // /sys/bus/platform/devices/7824900.sdhci/mmc_host/mmc0
        // /sys/class/mmc_host/mmc0

/* 使能mmc host的class_dev的非同步suspend的功能 */
    device_enable_async_suspend(&host->class_dev);
    led_trigger_register_simple(dev_name(&host->class_dev), &host->led);

/* 設置mmc_host的debug節點 */
#ifdef CONFIG_DEBUG_FS
    mmc_add_host_debugfs(host);
#endif
        // 對應sys節點為/sys/kernel/debug/mmc0

/* 以下設置mmc host的class_dev的屬性 */
    mmc_host_clk_sysfs_init(host);
        // 對應/sys/class/mmc_host/mmc0/clkgate_delay屬性

    host->clk_scaling.up_threshold = 35;
    host->clk_scaling.down_threshold = 5;
    host->clk_scaling.polling_delay_ms = 100;
    err = sysfs_create_group(&host->class_dev.kobj, &clk_scaling_attr_grp);
        // 對應/sys/class/mmc_host/mmc0/clk_scaling目錄下的四個屬性,clk_scaling_attr_grp前面已經說明過了

    err = sysfs_create_group(&host->class_dev.kobj, &dev_attr_grp);
        // 對應/sys/class/mmc_host/mmc0/perf屬性,dev_attr_grp前面已經說明過了

/* 調用mmc_start_host,也就調用到了mmc core主模塊的啟動host部分,在mmc core主模塊的時候說明 */
    mmc_start_host(host);
    if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
        register_pm_notifier(&host->pm_notify);

    return 0;
}

註意,最後調用了mmc_start_host來啟動host。關於mmc_start_host會在mmc core主模塊的部分裡面說明。

也就是說,關於host的初始化工作,需要在調用mmc_add_host之前就要完成了。

相關節點:

/sys/bus/platform/devices/7824900.sdhci/mmc_host/mmc0 
/sys/class/mmc_host/mmc0 
/sys/kernel/debug/mmc0

4、mmc_of_parse實現

解析mmc_host的dtsi節點的部分屬性。

mmc_of_parse提供了通用的、解析host controller dtsi節點的屬性的方法,這就要依賴於dtsi的屬性是否符合規範。

但是host controller driver並一定要使用這個,也可以使用自己一套解析的方法。

簡單說明如下:

void mmc_of_parse(struct mmc_host *host)
{
    struct device_node *np;
    u32 bus_width;
    bool explicit_inv_wp, gpio_inv_wp = false;
    enum of_gpio_flags flags;
    int len, ret, gpio;

    if (!host->parent || !host->parent->of_node)
        return;

/* 獲取到mmc_host對應的host controller的dts節點 */
    np = host->parent->of_node;
        // host->parent指向了mmc_host的對應host controller的device,獲取其of_node就獲取到了對應的dtsi節點

/* 以下就是解析屬性,並設置到mmc_host的屬性標識caps和caps2 中 */
    /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */
    if (of_property_read_u32(np, "bus-width", &bus_width) < 0) {
        dev_dbg(host->parent,
            "\"bus-width\" property is missing, assuming 1 bit.\n");
        bus_width = 1;
    }

    switch (bus_width) {
    case 8:
        host->caps |= MMC_CAP_8_BIT_DATA;   // "bus-width"——》MMC_CAP_8_BIT_DATA
        /* Hosts capable of 8-bit transfers can also do 4 bits */
    case 4:
        host->caps |= MMC_CAP_4_BIT_DATA;  // "bus-width"——》MMC_CAP_4_BIT_DATA
        break;
    case 1:
        break;
    default:
        dev_err(host->parent,
            "Invalid \"bus-width\" value %ud!\n", bus_width);
    }

    /* f_max is obtained from the optional "max-frequency" property */
    of_property_read_u32(np, "max-frequency", &host->f_max);
       //................後面的代碼都類似,直接略過了
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 您可以在令牌端點處將自定義代碼作為令牌頒發管道的一部分運行。這允許例如 添加額外的驗證邏輯 動態地改變某些參數(例如令牌生存期) 為此,實現(並註冊) 介面: 上下文對象使您可以訪問: 添加自定義響應參數 返回錯誤和錯誤說明 修改請求參數,例如訪問令牌生存期和類型,客戶端聲明和確認方法 您可以使用配 ...
  • 1. 新建一個文件夾 one 2. 新建三個文件夾three,four,five 3. 新建一個多層級文件夾 201904/a/01 ...
  • 1. 複製當前目錄的test文件夾 到/201904 目錄 出現如下截圖問題是因為test目錄下還有文件,所以得加-r,使用遞歸拷貝。我現在用這個命令拷貝文件都加-r了,不管有文件還是沒文件 2.複製當前目錄的lym壓縮包,到/201904/a 3.將a文件複製且命名為b文件 ...
  • 今天介紹的是如何在Linux CentOS7系統中配置 phpMyAdmin 。 目錄 + 環境準備 + 安裝包 + 基本設置 + 網站預覽 環境準備 + linux centos7系統 + ssh軟體 + php語言環境 + mysql資料庫 安裝包 "phpMyAdmin官網下載" 安裝前,請使 ...
  • 恩智浦半導體2017年10月正式發佈了業內首款跨界處理器—i.MX RT系列,超強的性能、超高的性價比使得i.MX RT系列火遍大江南北,一度成為基於MCU的產品主控首選,尤其是那些對於性能有較高要求的產品,客戶工程師更是苦盼i.MX RT久矣。經過一年多的評估與研發期,目前基於i.MX RT的產品... ...
  • 1、傳遞參數 可以在執行 Shell 腳本時,向腳本傳遞參數,腳本內獲取參數的格式為:$n。n 代表一個數字,1 為執行腳本的第一個參數,2 為執行腳本的第二個參數,以此類推…… 向腳本傳遞三個參數,並分別輸出,其中 $0 為執行的文件名: 為腳本設置可執行許可權,並執行腳本,輸出結果如下所示: 另外 ...
  • 1、本機網卡配置信息如下: 編輯網卡後使用systemctl restart network重啟服務。 2、使用ntpdate -u ntp.aliyun.com 同步時間,確保時間的正確性。 3、安裝Python。 3.1 下載Python包 wget -P /usr/src/ https://w ...
  • 1、後臺運行jar包程式,輸入:nohup java -jar /路徑/程式.jar & 2、後臺終止jar包程式,輸入:ps -ef | grep java,查看使用java命令的進程,再輸入:kill pid 即可終止運行 ps -ef|grep指令介紹:ps命令:將某個進程顯示出來,是Linu ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...