Qcom ARM平台Windows驱动(一):SD Host控制器配置与DLL调谐

Qcom ARM平台Windows驱动(一):SD Host控制器配置与 DLL 调谐

日期: 2026-03-21
系列: Qcom ARM平台Windows驱动开发
适用: Windows ARM 驱动开发者、Qualcomm 平台工程师


1. 概述

1.1 平台差异

与 x86 平台的 Storport SD Host 驱动不同,Qcom ARM 平台的 SD Host 控制器面临独特的挑战:

平台 架构特点 关键挑战
x86 (Intel/AMD) 标准 PCIe + ACPI DMA Remapping 兼容性
Qcom ARM (Snapdragon) SOC 集成 + 厂商特定寄存器 DLL 解锁、EMI/SSC 配置

1.2 BH202 驱动架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
┌─────────────────────────────────────────────────────────────────────┐
│ BH202-Windows 驱动架构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Windows Storage Stack │ │
│ │ (Storport Miniport) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ BH202 Driver (sdstor/) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Host Layer (host/) │ │ │
│ │ │ ├── host.c ←─── 通用 Host 初始化 │ │ │
│ │ │ ├── sdhci_msm.c ←─── ★ Qualcomm DLL 调谐 │ │ │
│ │ │ ├── ven_ggc.c ←─── ★ GGC 输出调谐 │ │ │
│ │ │ └── irqhandler.c ←─── 中断处理 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Core Layer (main/) │ │ │
│ │ │ ├── pmfunc.c ←─── PoFx 电源管理 │ │ │
│ │ │ ├── reqmng.c ←─── 请求管理 │ │ │
│ │ │ └── cfgmng.c ←─── 配置管理 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Card Layer (card/) │ │ │
│ │ │ └── sd.c / mmc.c │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Qualcomm Snapdragon SoC │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ SD Host Controller │ │ │
│ │ │ ├── SDHC (Secure Digital Host Controller) │ │ │
│ │ │ └── DLL (Delay-Locked Loop) ←─── 高速时钟必需 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ PMIC (Power Management IC) │ │ │
│ │ │ └── SD Card VCC/VCCQ 电源控制 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ GCC (Global Clock Controller) │ │ │
│ │ │ └── SD Card 时钟频率控制 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

2. Qualcomm DLL 原理

2.1 什么是 DLL?

DLL (Delay-Locked Loop) 是 Qualcomm SoC 中 SD Host 控制器的关键组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
┌─────────────────────────────────────────────────────────────────────┐
│ SD Host DLL 功能说明 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ DLL 原理 │ │
│ │ │ │
│ │ 输入时钟 ──► Phase Detector ──► Loop Filter ──► VCO │ │
│ │ │ ▲ │ │
│ │ │ │ │ │
│ │ │ Delay Line │ │
│ │ │ │ │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ │ 输出: 相位对齐的延迟时钟,用于: │ │
│ │ • SDR104 (208 MHz) 数据采样 │ │
│ │ • HS200/HS400 (200 MHz) 数据采样 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 为什么需要 DLL? │
│ ───────────────── │
│ • DDR 模式下数据在时钟的上升/下降沿采样 │
│ • PCB 走线延迟导致数据与时钟相位偏移 │
│ • DLL 自动补偿相位差,确保正确采样 │
│ │
│ 为什么 DLL Unlock 是问题? │
│ ─────────────────────────── │
│ • DLL 未正确锁定时,采样点可能落在眼图中心外 │
│ • 导致数据错误、CRC 错误、甚至卡片识别失败 │
│ │
└─────────────────────────────────────────────────────────────────────┘

2.2 DLL 关键寄存器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// sdhci_msm.c - Qualcomm DLL 寄存器定义

// DLL 配置寄存器
#define CORE_DLL_CONFIG 0x200 // DLL 主配置
#define CORE_DLL_STATUS 0x208 // DLL 锁定状态
#define CORE_VENDOR_SPEC 0x20C // 厂商特定控制
#define CORE_DLL_CONFIG_2 0x254 // DLL 增强配置
#define CORE_DLL_CONFIG_3 0x258 // DLL 精细配置
#define CORE_DDR_CONFIG 0x25C // DDR 模式配置
#define CORE_DLL_USR_CTL 0x388 // DLL 用户控制

// DLL 关键控制位
#define CORE_DLL_EN (1 << 16) // DLL 使能
#define CORE_DLL_LOCK (1 << 7) // DLL 锁定状态
#define CORE_DLL_PDN (1 << 29) // DLL 掉电控制
#define CORE_DLL_RST (1 << 30) // DLL 复位
#define CORE_DLL_CLOCK_DISABLE (1 << 21) // DLL 时钟禁用
#define CORE_CK_OUT_EN (1 << 18) // 时钟输出使能
#define CORE_CLK_PWRSAVE (1 << 1) // 时钟功耗节省

2.3 DLL 解锁失败的后果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
┌─────────────────────────────────────────────────────────────────────┐
│ DLL Unlock 问题症状 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 现象 原因 │
│ ──────────────────────────────────────────────────────────────── │
│ │
│ ┌────────────────────┐ ┌──────────────────────────────┐ │
│ │ │ │ DLL 未锁定时: │ │
│ │ SD 卡识别失败 │ │ • 采样点随机偏移 │ │
│ │ 或识别缓慢 │ │ • 眼图闭合 │ │
│ │ │ │ • CMD 响应错误 │ │
│ └────────────────────┘ └──────────────────────────────┘ │
│ │
│ ┌────────────────────┐ ┌──────────────────────────────┐ │
│ │ │ │ DDR 模式 (HS400) 失败: │ │
│ │ DDR 模式不稳定 │ │ • 上升/下降沿采样需要 │ │
│ │ 频繁 CRC 错误 │ │ 精确相位对齐 │ │
│ │ │ │ • DLL 决定采样点位置 │ │
│ └────────────────────┘ └──────────────────────────────┘ │
│ │
│ ┌────────────────────┐ ┌──────────────────────────────┐ │
│ │ │ │ SDR104 超高频失败: │ │
│ │ SDR104 (208MHz) │ │ • 208MHz 数据速率 │ │
│ │ 降级到 SDR50 │ │ • 必须使用 DLL │ │
│ │ │ │ • 无 DLL = 最高 SDR50 │ │
│ └────────────────────┘ └──────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

3. Linux DTS 到 Windows 配置的转换

3.1 Linux DTS 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 来自 Qcom SC8340 Linux Kernel DTS (device tree source)

&sdc2_hs200_1v8 {
status = "okay";

// DLL 配置
qcom,dll-config = <0x7442c>; // DLL 基础配置
qcom,dll-usr-ctl = <0x90106c0>; // 用户控制

// 特定模式配置
qcom,sdr50-dll-config = <0x5400>;
qcom,sdr104-dll-config = <0xa800>;

// DDR 配置
qcom,ddr-config = <0x8008431f>;

// 时钟配置
clock-frequency = <202000000>; // 202 MHz (SDR104)
};

3.2 Windows 驱动配置映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// sdhci_msm.c - Windows 驱动配置

/*
* For QCOM SC8340, must config DLL as below,
* this is Windows BIOS ASL value translated from Linux DTS:
*
* HsrSettings{
* DLLConfig = <0x7442C>;
* DLLConfig2 = <0x5400>;
* DLLConfig3 = <0x08>;
* DLLUserCtrl = <0x90106C0>;
* SDR104 {
* DLLConfig2 = <0xA800>;
* DLLConfig3 = <0x10>;
* };
* SDR50 {
* DLLConfig2 = <0x5400>;
* DLLConfig3 = <0x08>;
* };
* };
*/

int msm_init_cm_dll(sd_host_t *host)
{
u32 config = 0;

// 1. 基础 DLL 配置
host->msm_host.dll_config = 0x0007442c;

// 2. SDR104 模式 (208 MHz) - 最高性能
if (sd_mode == SD_FNC_AM_SDR104) {
config |= 0xA800; // DLL_CONFIG_2
config |= 0x10; // DLL_CONFIG_3
host->msm_host.clock = 202000000; // 202 MHz
}
// 3. SDR50 模式 (100 MHz)
else if (sd_mode == SD_FNC_AM_SDR50) {
config |= 0x5400; // DLL_CONFIG_2
config |= 0x08; // DLL_CONFIG_3
}

// 4. DDR 配置 (HS400 DDR)
host->msm_host.ddr_config = 0x8008431f;

// 5. 用户控制
host->msm_host.dll_usr_ctl = 0x90106c0;
}

3.3 配置来源追溯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
┌─────────────────────────────────────────────────────────────────────┐
│ 配置值溯源流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Linux Kernel Source (DTS) │ │
│ │ │ │
│ │ arch/arm64/boot/dts/qcom/sc8340.dtsi │ │
│ │ └── &sdc2_hs200_1v8 { │ │
│ │ qcom,dll-config = <0x7442C>; │ │
│ │ } │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ Qcom 工程师提供 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Qcom Platform Team │ │
│ │ • 芯片验证测试 │ │
│ │ • 信号完整性分析 │ │
│ │ • 推荐寄存器值 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ 文档化 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ SC8340 Hardware Design Guide / ASL Spec │ │
│ │ │ │
│ │ HsrSettings: │ │
│ │ DLLConfig = <0x7442C>; │ │
│ │ DLLConfig2 = <0x5400>; // SDR50 │ │
│ │ DLLConfig3 = <0x08>; │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ BIOS 团队实现 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ BIOS ACPI ASL Code │ │
│ │ │ │
│ │ Method (_SRS) { │ │
│ │ Store(0x7442C, \_SB.SDC2.HSRR) // DLL Config │ │
│ │ } │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ Windows 驱动读取 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ BH202-Windows Driver (sdhci_msm.c) │ │
│ │ │ │
│ │ host->msm_host.dll_config = 0x0007442c; │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

4. DLL 初始化流程

4.1 完整 DLL 配置序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// sdhci_msm.c - DLL 初始化

int msm_init_cm_dll(sd_host_t *host)
{
u32 dll_config;
u32 dll_config2;
u32 dll_config3;
u32 ddr_config;
u32 dll_usr_ctl;

DbgInfo("Enter %s\n", __FUNCTION__);

// 1. 读取 BIOS/ACPI 配置 (如果有)
if (host->cfg->msm_config_from_acpi) {
dll_config = host->cfg->dll_config;
dll_config2 = host->cfg->dll_config2;
dll_config3 = host->cfg->dll_config3;
ddr_config = host->cfg->ddr_config;
dll_usr_ctl = host->cfg->dll_usr_ctl;
} else {
// 2. 使用默认值 (SC8340)
dll_config = 0x0007442c;
dll_config2 = 0x5400;
dll_config3 = 0x08;
ddr_config = 0x8008431f;
dll_usr_ctl = 0x90106c0;
}

// 3. 保存配置
host->msm_host.dll_config = dll_config;
host->msm_host.dll_config2 = dll_config2;
host->msm_host.dll_config3 = dll_config3;
host->msm_host.ddr_config = ddr_config;

// 4. DLL 复位序列
dll_config |= CORE_DLL_RST; // 设置复位位
sdhci_writel(host, CORE_DLL_CONFIG, dll_config);

// 5. 等待复位完成
os_udelay(5);

// 6. 清除复位位
dll_config &= ~CORE_DLL_RST;
sdhci_writel(host, CORE_DLL_CONFIG, dll_config);

// 7. DLL 使能
dll_config |= CORE_DLL_EN;
sdhci_writel(host, CORE_DLL_CONFIG, dll_config);

// 8. DDR 配置
sdhci_writel(host, CORE_DDR_CONFIG, ddr_config);

// 9. DLL 配置2/3
sdhci_writel(host, CORE_DLL_CONFIG_2, dll_config2);
sdhci_writel(host, CORE_DLL_CONFIG_3, dll_config3);

// 10. 用户控制
sdhci_writel(host, CORE_DLL_USR_CTL, dll_usr_ctl);

DbgInfo("Exit %s\n", __FUNCTION__);
return 0;
}

4.2 DLL 锁定检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 检查 DLL 是否成功锁定

bool msm_check_dll_lock(sd_host_t *host)
{
int retry = 100;
u32 dll_status;

while (retry--) {
dll_status = sdhci_readl(host, CORE_DLL_STATUS);

if (dll_status & CORE_DLL_LOCK) {
DbgInfo("DLL locked successfully!\n");
host->msm_host.qualcomm_dll_unlock_flag = TRUE;
return TRUE;
}

os_udelay(100); // 等待 100us
}

DbgErr("DLL lock failed! Status=0x%08X\n", dll_status);
host->msm_host.qualcomm_dll_unlock_flag = FALSE;
return FALSE;
}

4.3 DLL 初始化时序图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
┌─────────────────────────────────────────────────────────────────────┐
│ DLL 初始化时序图 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 驱动代码 寄存器 硬件状态 │
│ ───────── ─────── ───────── │
│ │
│ msm_init_cm_dll() Idle │
│ │ │ │
│ ▼ ▼ │
│ DLL_CONFIG = 0x7442C|RST DLL Reset │
│ │ │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ os_udelay(5) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ ▼ ▼ │
│ DLL_CONFIG = 0x7442C|EN DLL Enable │
│ │ │ │
│ ▼ ▼ │
│ DDR_CONFIG = 0x8008431f DDR Enabled │
│ │ │ │
│ ▼ ▼ │
│ DLL_CONFIG_2 = 0x5400 Phase Config │
│ │ │ │
│ ▼ ▼ │
│ DLL_CONFIG_3 = 0x08 Fine Tuning │
│ │ │ │
│ ▼ ▼ │
│ DLL_USR_CTL = 0x90106C0 User Control │
│ │ │ │
│ ▼ ▼ │
│ msm_check_dll_lock() │ │
│ │ │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ 轮询 DLL_STATUS[DLL_LOCK] │ │
│ │ │ │
│ ▼ ▼ │
│ DLL_STATUS[DLL_LOCK] = 1 DLL Locked ★ │
│ │ │ │
│ ▼ ▼ │
│ return TRUE Ready for IO │
│ │
└─────────────────────────────────────────────────────────────────────┘

5. GGC (General GPIO Controller) 输出调谐

5.1 GGC 简介

GGC 是 Qualcomm 平台特有的输出调谐机制,用于优化 SD 卡数据信号的电气特性:

1
2
3
4
5
6
7
8
9
10
11
12
// ven_ggc.c - GGC 调谐核心

typedef struct {
// 调谐参数
u8 output_tuning_val; // 输出调谐值
u8 pre_emphasis_val; // 预加重值
u8 drive_strength; // 驱动强度

// 调谐状态
bool tuning_done; // 调谐完成标志
u8 best_tuning_phase; // 最佳相位
} ggc_platform_t;

5.2 GGC 调谐流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
┌─────────────────────────────────────────────────────────────────────┐
│ GGC 输出调谐流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. 初始化调谐环境 │ │
│ │ │ │
│ │ ven_ggc_init() │ │
│ │ └── 读取默认值/DTS配置 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 2. 预调谐阶段 (Pre-Tuning) │ │
│ │ │ │
│ │ ven_ggc_pretuning() │ │
│ │ ├── 设置默认驱动强度 │ │
│ │ └── 配置 SSC (Spread Spectrum Clock) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 3. 精确调谐阶段 (Fine-Tuning) ★ │ │
│ │ │ │
│ │ ven_ggc_tuning() │ │
│ │ │ │ │
│ │ ├── for phase in [0..63]: │ │
│ │ │ ├── 设置相位 = phase │ │
│ │ │ ├── 执行 CMD19 (发送测试数据) │ │
│ │ │ ├── 检查 CRC 错误 │ │
│ │ │ └── 记录错误率 │ │
│ │ │ │ │
│ │ └── 选择最低错误率的相位作为最佳相位 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 4. 验证阶段 (Verification) │ │
│ │ │ │
│ │ ven_ggc_verify() │ │
│ │ ├── 使用最佳相位 │ │
│ │ ├── 执行多次读写测试 │ │
│ │ └── 确认错误率可接受 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 调谐完成 │
│ │
└─────────────────────────────────────────────────────────────────────┘

5.3 SSC (Spread Spectrum Clock) 配置

SSC 用于减少 EMI (电磁干扰):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// ven_ggc_ssc.c - SSC 配置

typedef struct {
bool enable; // SSC 使能
u32 freq_deviation; // 频率偏差 (ppm)
u32 modulation_rate; // 调制速率 (kHz)
} ssc_config_t;

// SSC 典型配置
ssc_config_t sc8340_ssc_config = {
.enable = TRUE,
.freq_deviation = 3000, // ±3000 ppm (0.3%)
.modulation_rate = 31, // 31 kHz
};

int ven_ggc_config_ssc(sd_host_t *host)
{
u32 ssc_config = 0;

if (!host->ggc.ssc.enable)
return 0;

// 配置 SSC 寄存器
ssc_config |= (host->ggc.ssc.freq_deviation & 0xFFFF) << 16;
ssc_config |= (host->ggc.ssc.modulation_rate & 0xFF);

sdhci_writel(host, GGC_SSC_CONFIG, ssc_config);
sdhci_writel(host, GGC_SSC_ENABLE, 1);

DbgInfo("SSC configured: %d ppm @ %d kHz\n",
host->ggc.ssc.freq_deviation,
host->ggc.ssc.modulation_rate);

return 0;
}

6. Qualcomm 特定主机能力检测

6.1 核心版本检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// host.c - Qualcomm MSM 初始化

void host_msm_init(sd_host_t *host)
{
u32 core_version_318;

// 读取核心版本寄存器
core_version_318 = sdhci_readl(host, 0x318);

// 解析版本号
u8 core_major = (core_version_318 >> 28) & 0xF;
u8 core_minor = (core_version_318 >> 16) & 0xFFF;

DbgInfo("MSM Core Version: v%d.%d (0x%08X)\n",
core_major, core_minor, core_version_318);

// 根据版本配置不同特性
if (core_major == 1 && core_minor >= 0x42) {
// 14LPP 工艺使用不同的 DLL 复位序列
host->msm_host.use_14lpp_dll_reset = TRUE;
DbgInfo("Using 14LPP DLL reset sequence\n");
}

if (core_major >= 1 && core_minor >= 0x71) {
// Tassadar DLL 支持
host->msm_host.uses_tassadar_dll = TRUE;
DbgInfo("Tassadar DLL supported\n");
}
}

6.2 MSM Host 特定结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// host.h - MSM Host 特定数据

typedef struct
{
// DLL 相关
bool use_14lpp_dll_reset; // 使用 14LPP DLL 复位序列
bool uses_tassadar_dll; // Tassadar DLL 支持
bool tuning_done; // 调谐完成
u8 saved_tuning_phase; // 保存的调谐相位

// 配置值
u32 dll_config; // DLL 配置
u32 dll_config2; // DLL 配置2
u32 dll_config3; // DLL 配置3
u32 ddr_config; // DDR 配置
u32 dll_usr_ctl; // 用户控制
u32 clock; // 当前时钟频率

// EMI/SSC
bool use_cdclp533; // CDC LP533 支持

// 电源状态
u32 curr_pwr_state; // 当前电源状态
u32 curr_io_level; // 当前 IO 电平
} sdhci_msm_host_t;

7. 常见问题与调试

7.1 DLL 相关问题排查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 调试 DLL 状态
void dump_dll_status(sd_host_t *host)
{
u32 dll_status = sdhci_readl(host, CORE_DLL_STATUS);
u32 dll_config = sdhci_readl(host, CORE_DLL_CONFIG);

DbgInfo("=== DLL Status ===\n");
DbgInfo("DLL_STATUS: 0x%08X\n", dll_status);
DbgInfo(" DLL_LOCK: %s\n",
(dll_status & CORE_DLL_LOCK) ? "LOCKED" : "UNLOCKED");
DbgInfo(" DLL_EN: %s\n",
(dll_config & CORE_DLL_EN) ? "ENABLED" : "DISABLED");
DbgInfo(" DLL_RST: %s\n",
(dll_config & CORE_DLL_RST) ? "RESET" : "NORMAL");
DbgInfo("DLL_CONFIG: 0x%08X\n", dll_config);
DbgInfo("DLL_CONFIG2: 0x%08X\n",
sdhci_readl(host, CORE_DLL_CONFIG_2));
DbgInfo("DLL_CONFIG3: 0x%08X\n",
sdhci_readl(host, CORE_DLL_CONFIG_3));
}

7.2 问题诊断流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
┌─────────────────────────────────────────────────────────────────────┐
│ DLL Unlock 问题诊断流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 问题: SD 卡识别失败或不稳定 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Step 1: 检查 DLL 是否使能 │ │
│ │ │ │
│ │ 读取 CORE_DLL_CONFIG │ │
│ │ 检查 DLL_EN 位 (bit 16) │ │
│ │ │ │
│ │ 如果未使能 → 检查时钟源配置 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Step 2: 检查 DLL 是否锁定 │ │
│ │ │ │
│ │ 读取 CORE_DLL_STATUS │ │
│ │ 检查 DLL_LOCK 位 (bit 7) │ │
│ │ │ │
│ │ 如果未锁定 → 检查 DLL 配置值 / 时钟频率 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Step 3: 检查时钟频率 │ │
│ │ │ │
│ │ 确认目标频率在 DLL 支持范围内 │ │
│ │ SDR104 需要 ≥100MHz │ │
│ │ DDR 模式需要 DLL 支持 │ │
│ │ │ │
│ │ 如果频率不对 → 检查 GCC 配置 / 时钟分频 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Step 4: 检查 BIOS/ACPI 配置 │ │
│ │ │ │
│ │ 对比 BIOS 提供的值与驱动默认值 │ │
│ │ 检查 _DSM 方法是否正确返回配置 │ │
│ │ │ │
│ │ 如果配置不一致 → 更新 BIOS / 修改驱动默认值 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

8. 总结

8.1 Qualcomm 平台关键差异

项目 x86 (Storport) Qcom ARM (BH202)
Host 配置 标准 PCI 配置空间 厂商特定寄存器
DLL 不需要 (PCIe 时钟) 必须正确配置
EMI/SSC 主板设计决定 软件可配置
配置来源 INF 注册表 BIOS ACPI/DTS
时序调谐 固定 GGC 动态调谐

8.2 配置检查清单

  • DLL 配置值与 Qcom 推荐值一致
  • DDR 配置正确 (HS400 模式)
  • SSC 参数符合 EMI 要求
  • 时钟频率在 DLL 支持范围内
  • BIOS/ACPI 提供正确配置值
  • DLL 锁定状态正常
  • GGC 调谐完成 (如果启用)

参考资料

  1. Qualcomm SC8340 Hardware Design Guide
  2. SD Host Controller Simplified Specification
  3. JEDEC eMMC Specification JESD84-B51

文档生成日期: 2026-03-21
驱动版本: BH202-Windows v1.0+