工作中需要对MMC驱动中的DMA进行调试,因此借此机会对kernel/drivers/mmc/host/sdhci.c
中关于DMA的部分代码进行了简单的梳理,结合在网络中查到的资料在这里记录一下。
本文基于5.15内核版本
ADMA2
简介
ADMA2(Advanced Direct Memory Access)是主控制器与系统内存之间的数据传输机制。在ADMA2中,由主机驱动程序在系统内存中创建并维护一个描述符表,每个描述符项包含数据的地址、长度和用于指定描述符操作的属性。
描述符表
上图中左半部分为MMC控制器,右边部分为系统内存,储存在系统内存中的描述符表由Host驱动来进行管理。MMC控制器通过配置在System Address Register中描述符表在内存里的首地址就可以获取整张描述符表,数据传输是通过向Command register写入来触发的,ADMA2会逐行处理描述符表中的信息,直到遇到标有结束(End=1)属性的描述符。在数据传输过程中,ADMA2会管理各种状态和标志,包括中断请求、错误处理以及传输完成的标志。
描述符项
每个描述符项遵循特定的格式,例如在64位寻址模式下,描述符行由以下部分组成:
- 保留位(32-Bit Reserved);
- 64位地址(64-Bit Address):数据存储的起始地址;
- 16位长度(16-Bit Length):从存储地址开始的数据长度;
- 10位长度(10-Bit Length):从4.10版本开始的扩展数据长度;
- 属性位(6-Bit Attribute):用来控制和指示描述符的行为和状态。
属性位的组合定义了ADMA2控制器如何解释和执行描述符表中的每一行,描述符的属性位通常包括以下几个部分:
- Valid(有效位):
- 此位指示描述符行是否有效。当此位被设置时,ADMA2控制器会处理该描述符行;当未设置时,表示描述符行不应被处理。
- End(结束位):
- 当此位被设置时,它表示当前描述符行是表中的最后一条有效描述符。ADMA2控制器在处理到标有结束位的描述符行后会停止处理后续描述符,这标志着数据传输操作的结束。
- Int(中断位):
- 如果此位被设置,ADMA2控制器在处理完该描述符行后会产生一个中断。这允许系统响应传输完成或处理其他事件。
- Act(操作码):
- 这是由Act2、Act1、Act0三个位组成的字段,用来定义描述符行的操作类型。通常的操作类型包括:
- Nop(无操作): 控制器将忽略该行,并继续处理下一行描述符。
- Rsv(保留): 与Nop相同,这通常是为了未来的扩展保留的。
- Tran(传输数据): 控制器将执行数据传输操作。
- Link(链接描述符): 控制器将链接到另一个描述符表,通常用于实现更复杂的传输序列。
- 这是由Act2、Act1、Act0三个位组成的字段,用来定义描述符行的操作类型。通常的操作类型包括:
Secure Digital Host Controller Interface driver
在了解了ADMA2 的结构后,对sdhci.c中关于DMA相关操作的代码逻辑进行梳理如下:
在驱动probe后会调用sdhci_add_host()
进而在sdhci_setup_host()
申请用于存放描述符表的内存空间,最终将申请到的物理地址在sdhci_set_adma_addr()
中被配置到控制器的寄存器中。
在描述符表的内存空间分配完成后, 调用sdhci_send_command()
时会首先在sdhci_pre_dma_transfer()
中申请用于储存数据内存空间,并将地址以及长度在sdhci_adma_table_pre()
中通过__sdhci_adma_write_desc()
写入到描述符表中。
至此,MMC控制器便可以通过描述符表完成数据的交互。
参考
- DMA数据传输
- SD controller note-2
- 本文部分内容由ChatGPT辅助生成