sd/mmc驱动框架-(三)mmc子系统的数据结构

2023-12-28 10:08

本文主要是介绍sd/mmc驱动框架-(三)mmc子系统的数据结构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

知识脉络框图:

 

一、host相关

1、struct mmc_host

struct mmc_host是mmc core由host controller抽象出来的结构体,用于代表一个mmc host控制器。 
* 数据结构如下:

struct mmc_host {struct device       *parent;   // 对应的host controller的devicestruct device       class_dev;   // mmc_host的device结构体,会挂在class/mmc_host下int         index;   // 该host的索引号const struct mmc_host_ops *ops; // 该host的操作集,由host controller设置,后面说明unsigned int        f_min;   // 该host支持的最低频率unsigned int        f_max;   // 该host支持的最大频率unsigned int        f_init;   // 该host使用的初始化频率/// 以下是和clock相关的成员int         clk_requests;   /* internal reference counter */unsigned int        clk_delay;  /* number of MCI clk hold cycles */bool            clk_gated;  /* clock gated */struct delayed_work clk_gate_work; /* delayed clock gate */unsigned int        clk_old;    /* old clock value cache */spinlock_t      clk_lock;   /* lock for clk fields */struct mutex        clk_gate_mutex; /* mutex for clock gating */struct device_attribute clkgate_delay_attr;unsigned long           clkgate_delay;/* host specific block data */   // 被主控制器驱动的mmc块设备数据和块相关的成员unsigned int        max_seg_size;   /* see blk_queue_max_segment_size */unsigned short      max_segs;   /* see blk_queue_max_segments */unsigned short      unused;unsigned int        max_req_size;   /* maximum number of bytes in one req */unsigned int        max_blk_size;   /* maximum size of one mmc block */unsigned int        max_blk_count;  /* maximum number of blocks in one req */unsigned int        max_discard_to; /* max. discard timeout in ms *//* private data 私有数据*/spinlock_t      lock;       /* lock for claim and bus ops */   // host的bus使用的锁struct mmc_ios      ios;        /* current io bus settings */   // io setting,后续说明u32         ocr;        /* the current OCR setting */   // 当前使用的ocr的值/* group bitfields together to minimize padding */unsigned int        use_spi_crc:1;unsigned int        claimed:1;  /* host exclusively claimed */   // host是否已经被占用unsigned int        bus_dead:1; /* bus has been released */   // host的bus是否处于激活状态int         rescan_disable; /* disable card detection */   // 禁止rescan的标识,禁止搜索cardint         rescan_entered; /* used with nonremovable devices */   // 是否已经rescan过的标识,对应不可移除的设备只能rescan一次struct mmc_card     *card;      /* device attached to this host */   // 和该host绑定在一起的cardwait_queue_head_t   wq;struct task_struct  *claimer;   /* task that has host claimed */   // 该host的占有者进程struct task_struct  *suspend_task;int         claim_cnt;  /* "claim" nesting count */   // 占有者进程对该host的占用计数struct delayed_work detect;   // 检测卡槽变化的工作struct wake_lock    detect_wake_lock;   // 检测卡槽变化的工作使用的锁const char      *wlock_name;   // 锁名称int         detect_change;  /* card detect flag */ // 需要检测卡槽变化的标识struct mmc_slot     slot;   // 卡槽的结构体const struct mmc_bus_ops *bus_ops;  /* current bus driver */   // host的mmc总线的操作集,后面说明unsigned int        bus_refs;   /* reference counter */   // host的mmc总线的使用计数unsigned int        bus_resume_flags;   // host的mmc总线的resume标识mmc_pm_flag_t       pm_flags;   /* requested pm features */#ifdef CONFIG_REGULATORbool            regulator_enabled; /* regulator state */   // 代表regulator(LDO)的状态
#endifstruct mmc_supply   supply;struct dentry       *debugfs_root;   // 对应的debug目录结构体struct mmc_async_req    *areq;      /* active async req */   // 当前正在处理的异步请求struct mmc_context_info context_info;   /* async synchronization info */ // 异步请求的信息unsigned int        actual_clock;   /* Actual HC clock rate */ // 实际的时钟频率
};
  • ocr值各个位代表的电压意义如下:
#define MMC_VDD_165_195     0x00000080  /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21       0x00000100  /* VDD voltage 2.0 ~ 2.1 */
#define MMC_VDD_21_22       0x00000200  /* VDD voltage 2.1 ~ 2.2 */
#define MMC_VDD_22_23       0x00000400  /* VDD voltage 2.2 ~ 2.3 */
#define MMC_VDD_23_24       0x00000800  /* VDD voltage 2.3 ~ 2.4 */
#define MMC_VDD_24_25       0x00001000  /* VDD voltage 2.4 ~ 2.5 */
#define MMC_VDD_25_26       0x00002000  /* VDD voltage 2.5 ~ 2.6 */
#define MMC_VDD_26_27       0x00004000  /* VDD voltage 2.6 ~ 2.7 */
#define MMC_VDD_27_28       0x00008000  /* VDD voltage 2.7 ~ 2.8 */
#define MMC_VDD_28_29       0x00010000  /* VDD voltage 2.8 ~ 2.9 */
#define MMC_VDD_29_30       0x00020000  /* VDD voltage 2.9 ~ 3.0 */
#define MMC_VDD_30_31       0x00040000  /* VDD voltage 3.0 ~ 3.1 */
#define MMC_VDD_31_32       0x00080000  /* VDD voltage 3.1 ~ 3.2 */
#define MMC_VDD_32_33       0x00100000  /* VDD voltage 3.2 ~ 3.3 */
#define MMC_VDD_33_34       0x00200000  /* VDD voltage 3.3 ~ 3.4 */
#define MMC_VDD_34_35       0x00400000  /* VDD voltage 3.4 ~ 3.5 */
#define MMC_VDD_35_36       0x00800000  /* VDD voltage 3.5 ~ 3.6 */
  • host属性(mmc_host->caps)caps1支持的属性如下
#define MMC_CAP_4_BIT_DATA  (1 << 0)    /* Can the host do 4 bit transfers */
#define MMC_CAP_MMC_HIGHSPEED   (1 << 1)    /* Can do MMC high-speed timing */
#define MMC_CAP_SD_HIGHSPEED    (1 << 2)    /* Can do SD high-speed timing */
#define MMC_CAP_SDIO_IRQ    (1 << 3)    /* Can signal pending SDIO IRQs */
#define MMC_CAP_SPI     (1 << 4)    /* Talks only SPI protocols */
#define MMC_CAP_NEEDS_POLL  (1 << 5)    /* Needs polling for card-detection */
#define MMC_CAP_8_BIT_DATA  (1 << 6)    /* Can the host do 8 bit transfers */#define MMC_CAP_NONREMOVABLE    (1 << 8)    /* Nonremovable e.g. eMMC */
#define MMC_CAP_WAIT_WHILE_BUSY (1 << 9)    /* Waits while card is busy */
#define MMC_CAP_ERASE       (1 << 10)   /* Allow erase/trim commands */
#define MMC_CAP_1_8V_DDR    (1 << 11)   /* can support *//* DDR mode at 1.8V */
#define MMC_CAP_1_2V_DDR    (1 << 12)   /* can support *//* DDR mode at 1.2V */
#define MMC_CAP_POWER_OFF_CARD  (1 << 13)   /* Can power off after boot */
#define MMC_CAP_BUS_WIDTH_TEST  (1 << 14)   /* CMD14/CMD19 bus width ok */
#define MMC_CAP_UHS_SDR12   (1 << 15)   /* Host supports UHS SDR12 mode */
#define MMC_CAP_UHS_SDR25   (1 << 16)   /* Host supports UHS SDR25 mode */
#define MMC_CAP_UHS_SDR50   (1 << 17)   /* Host supports UHS SDR50 mode */
#define MMC_CAP_UHS_SDR104  (1 << 18)   /* Host supports UHS SDR104 mode */
#define MMC_CAP_UHS_DDR50   (1 << 19)   /* Host supports UHS DDR50 mode */
#define MMC_CAP_DRIVER_TYPE_A   (1 << 23)   /* Host supports Driver Type A */
#define MMC_CAP_DRIVER_TYPE_C   (1 << 24)   /* Host supports Driver Type C */
#define MMC_CAP_DRIVER_TYPE_D   (1 << 25)   /* Host supports Driver Type D */
#define MMC_CAP_CMD23       (1 << 30)   /* CMD23 supported. */
#define MMC_CAP_HW_RESET    (1 << 31)   /* Hardware reset */

2、struct mmc_host_ops
mmc core将host需要提供的一些操作方法封装成struct mmc_host_ops。 
mmc core主模块的很多接口都是基于这里面的操作方法来实现的,通过这些方法来操作host硬件达到对应的目的。 
所以struct mmc_host_ops也是host controller driver需要实现的核心部分。

struct mmc_host_ops {/** 'enable' is called when the host is claimed and 'disable' is called* when the host is released. 'enable' and 'disable' are deprecated.*/int (*enable)(struct mmc_host *host);   // 使能host,当host被占用时(第一次调用mmc_claim_host)调用int (*disable)(struct mmc_host *host);   // 禁用host,当host被释放时(第一次调用mmc_release_host)调用/** It is optional for the host to implement pre_req and post_req in* order to support double buffering of requests (prepare one* request while another request is active).* pre_req() must always be followed by a post_req().* To undo a call made to pre_req(), call post_req() with* a nonzero err condition.*/// post_req和pre_req是为了实现异步请求处理而设置的// 异步请求处理就是指,当另外一个异步请求还没有处理完成的时候,可以先准备另外一个异步请求而不必等待// 具体参考《mmc core主模块》void    (*post_req)(struct mmc_host *host, struct mmc_request *req,int err);void    (*pre_req)(struct mmc_host *host, struct mmc_request *req,bool is_first_req);void    (*request)(struct mmc_host *host, struct mmc_request *req); // host处理mmc请求的方法,在mmc_start_request中会调用void    (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);   // 设置host的总线的io settingint (*get_ro)(struct mmc_host *host);   // 获取host上的card的读写属性int (*get_cd)(struct mmc_host *host);   // 检测host的卡槽中card的插入状态/* optional callback for HC quirks */void    (*init_card)(struct mmc_host *host, struct mmc_card *card);   // 初始化card的方法int (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios);   // 切换信号电压的方法/* Check if the card is pulling dat[0:3] low */int (*card_busy)(struct mmc_host *host);   // 用于检测card是否处于busy状态/* The tuning command opcode value is different for SD and eMMC cards */int (*execute_tuning)(struct mmc_host *host, u32 opcode);   // 执行tuning操作,为card选择一个合适的采样点int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);   // 选择信号的驱动强度void    (*hw_reset)(struct mmc_host *host);   // 硬件复位void    (*card_event)(struct mmc_host *host);   // unsigned long (*get_max_frequency)(struct mmc_host *host); // 获取host支持的最大频率的方法unsigned long (*get_min_frequency)(struct mmc_host *host);   // 获取host支持的最小频率的方法int (*notify_load)(struct mmc_host *, enum mmc_load);int (*stop_request)(struct mmc_host *host);   // 停止请求处理的方法unsigned int    (*get_xfer_remain)(struct mmc_host *host);
};

 

3.s3c2440 host驱动中初始化hmmc_host结构体成员的实战代码分析:

/** Platform driver and initialization.*/
static void __init s3c2440mmc_host_init(struct s3c2440mmc_host *host, struct mmc_host *mmc)
{struct s3c2440mmc_platform_data *pdata = host->pdata;mmc->ops = &s3c2440mmc_ops;//主控制器操作函数集合mmc->f_min = 200000;//控制器的最小时钟频率mmc->f_max = pdata->max_freq;//控制器的最大时钟频率mmc->ocr_avail = pdata->ocr_avail;//控制器的供电范围mmc->caps |= pdata->capacity;//控制器的支持的特殊功能mmc->pm_flags |= pdata->pm_flags;
#ifdef CONFIG_MMC_BLOCK_BOUNCEmmc->max_blk_count = 65535;//mmc块设备的最大块数mmc->max_req_size = PAGE_SIZE * 16;//单个请求的最大数据长度,以字节为单位
#elsemmc->max_segs = MAX_SEGS;//mmc->max_blk_count = 4096;//单个请求的最大块数mmc->max_req_size = 4096 * 512; //单个请求的最大数据长度,以字节为单位
#endifmmc->max_blk_size = 512; //mmc块设备的最大块大小mmc->max_seg_size = mmc->max_req_size;//物理段的最大长度,以字节为单位host->mmc = mmc; setup_timer(&host->request_timer, s3c2440mmc_request_timeout,(unsigned long)host);mmc_add_host(mmc);//添加mmc host
}

 

 

 

 

参考文献:

1.《深入实践嵌入Linux系统移植 范展源 刘韬》

2. https://blog.csdn.net/ooonebook/article/details/55105481

这篇关于sd/mmc驱动框架-(三)mmc子系统的数据结构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/545595

相关文章

C++的模板(八):子系统

平常所见的大部分模板代码,模板所传的参数类型,到了模板里面,或实例化为对象,或嵌入模板内部结构中,或在模板内又派生了子类。不管怎样,最终他们在模板内,直接或间接,都实例化成对象了。 但这不是唯一的用法。试想一下。如果在模板内限制调用参数类型的构造函数会发生什么?参数类的对象在模板内无法构造。他们只能从模板的成员函数传入。模板不保存这些对象或者只保存他们的指针。因为构造函数被分离,这些指针在模板外

【数据结构】线性表:顺序表

文章目录 1. 线性表2. 顺序表2.1 概念及结构2.2 接口实现2.3 顺序表的问题及思考 1. 线性表 线性表是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式

数据结构9——排序

一、冒泡排序 冒泡排序(Bubble Sort),顾名思义,就是指越小的元素会经由交换慢慢“浮”到数列的顶端。 算法原理 从左到右,依次比较相邻的元素大小,更大的元素交换到右边;从第一组相邻元素比较到最后一组相邻元素,这一步结束最后一个元素必然是参与比较的元素中最大的元素;按照大的居右原则,重新从左到后比较,前一轮中得到的最后一个元素不参4与比较,得出新一轮的最大元素;按照上述规则,每一轮结

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚

[分布式网络通讯框架]----Zookeeper客户端基本操作----ls、get、create、set、delete

Zookeeper数据结构 zk客户端常用命令 进入客户端 在bin目录下输入./zkCli.sh 查看根目录下数据ls / 注意:要查看哪一个节点,必须把路径写全 查看节点数据信息 get /第一行代码数据,没有的话表示没有数据 创建节点create /sl 20 /sl为节点的路径,20为节点的数据 注意,不能跨越创建,也就是说,创建sl2的时候,必须确保sl

【服务器08】之【游戏框架】之【加载主角】

首先简单了解一下帧率 FixedUpdate( )   >   Update( )   >   LateUpdate( ) 首先FixedUpdate的设置值 默认一秒运行50次 虽然默认是0.02秒,但FiexedUpdate并不是真的0.02秒调用一次,因为在脚本的生命周期内,FixedUpdate有一个小循环,这个循环也是通过物理时间累计看是不是大于0.02了,然后调用一次。有

Java中的集合框架使用技巧

Java中的集合框架使用技巧 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Java中集合框架的使用技巧,这些技巧能够帮助我们更高效地处理数据和优化程序性能。 Java集合框架概述 Java集合框架提供了一组实现了各种集合接口的类和接口,用于存储和操作数据。它包括列表、集合、队列和映射等数据结构,能够满足不

算法与数据结构面试宝典——回溯算法详解(C#,C++)

文章目录 1. 回溯算法的定义及应用场景2. 回溯算法的基本思想3. 递推关系式与回溯算法的建立4. 状态转移方法5. 边界条件与结束条件6. 算法的具体实现过程7. 回溯算法在C#,C++中的实际应用案例C#示例C++示例 8. 总结回溯算法的主要特点与应用价值 回溯算法是一种通过尝试各种可能的组合来找到所有解的算法。这种算法通常用于解决组合问题,如排列、组合、棋盘游

[分布式网络通讯框架]----ZooKeeper下载以及Linux环境下安装与单机模式部署(附带每一步截图)

首先进入apache官网 点击中间的see all Projects->Project List菜单项进入页面 找到zookeeper,进入 在Zookeeper主页的顶部点击菜单Project->Releases,进入Zookeeper发布版本信息页面,如下图: 找到需要下载的版本 进行下载既可,这里我已经下载过3.4.10,所以以下使用3.4.10进行演示其他的步骤。

嵌入式学习——数据结构(哈希、排序)——day50

1. 查找二叉树、搜索二叉树、平衡二叉树 2. 哈希表——人的身份证——哈希函数 3. 哈希冲突、哈希矛盾 4. 哈希代码 4.1 创建哈希表 4.2  5. 算法设计 5.1 正确性 5.2 可读性(高内聚、低耦合) 5.3 健壮性 5.4 高效率(时间复杂度)时间复杂度越低,效率越高, 5.5 低储存(空间复杂度)空间复杂度越低,存储空间越少 6.排序算法 6.1 冒