Qcom ARM平台Windows驱动(二):PMIC上下电与PoFx电源框架

Qcom ARM平台Windows驱动(二):PMIC上下电与 PoFx 电源框架

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


1. 概述

1.1 硬件架构背景

在 Qualcomm ARM 平台上,SD 存储系统与 x86 平台有根本性的架构差异:

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
┌─────────────────────────────────────────────────────────────────────┐
│ x86 平台电源架构 (对比) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ BIOS/ACPI │ │ PCIe │ │
│ │ 统一管理 │ │ Slot Power │ │
│ └──────────────┘ └──────────────┘ │
│ │ │ │
│ │ ┌────┴────┐ │
│ │ │ SD Card │ │
│ │ │ VCC │ │
│ │ └──────────┘ │
│ │ │
│ ┌──────┴───────┐ │
│ │ 独立控制 │ ← PCIE_SLTPLN# 等信号控制 │
│ │ Slot 电源 │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│ Qcom ARM 平台电源架构 (本文主题) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ PMIC │ ←── 统一管理所有电源轨 │
│ │ (SPMI/I2C) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌────┴────┬─────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ VDD │ │VDD_Q│ │ VDD │ │
│ │(SD) │ │(IO) │ │Core │ │
│ └─────┘ └─────┘ └─────┘ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ SD Host Controller │ │
│ │ (BH202 SD Card) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ SD Bus │ │
│ ▼ │
│ ┌───────────┐ │
│ │ SD Card │ │
│ └───────────┘ │
│ │
│ 关键差异: SD Card 和 Host Controller 由同一 PMIC 控制上下电 │
│ │
└─────────────────────────────────────────────────────────────────────┘

1.2 BH202 电源控制特点

特点 说明
PMIC 统一控制 SD Card 和 Host Controller 共享 PMIC 电源轨
PoFx 引用计数 Windows Power Framework 管理设备电源状态
协同上下电 SD Card 和 Host 必须同时上下电
Qualcomm 特定 通过 SPMI/I2C 与 PMIC 通信

2. 硬件电源架构

2.1 PMIC 电源管理芯片

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
┌─────────────────────────────────────────────────────────────────────┐
│ PMIC 电源管理架构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ PMIC (Power Management IC) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ 电源轨 (Power Rails) │ │ │
│ │ │ │ │ │
│ │ │ • LDO1: SD VCC (3.3V / 1.8V) │ │ │
│ │ │ • LDO2: SD VCCQ (1.8V / 1.2V) │ │ │
│ │ │ • BUCK: Core Voltage (0.7V - 1.2V) │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ 控制接口 │ │ │
│ │ │ │ │ │
│ │ │ • SPMI (Serial Peripheral Management Interface) │ │ │
│ │ │ • I2C (备用) │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────┴─────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ SD Host Controller │ │ SD Card │ │
│ │ (BH202 Chip) │ │ │ │
│ │ │ │ VCC = 3.3V/1.8V │ │
│ │ • 需要 Core Voltage │ │ VCCQ = 1.8V/1.2V │ │
│ │ • 需要 IO Voltage │ │ │ │
│ │ • 需要 Card Voltage │ │ 必须和 Host 同时上下电 │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
│ 重要: Host 和 Card 必须协同上下电,否则可能损坏硬件! │
│ │
└─────────────────────────────────────────────────────────────────────┘

2.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
49
50
51
52
53
54
55
56
57
┌─────────────────────────────────────────────────────────────────────┐
│ SD Card 电源时序 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 上电顺序 (Power-Up Sequence): │
│ ──────────────────────────── │
│ │
│ T0: ─────────────────────────────────────────────────────────► │
│ │ │
│ ▼ │
│ T1: Core Voltage ON (BUCK) │
│ │ │
│ │ [等待 1-10ms] │
│ ▼ │
│ T2: IO Voltage ON (VDD_Q) │
│ │ │
│ │ [等待电压稳定] │
│ ▼ │
│ T3: Host Controller Enable │
│ │ │
│ │ [Host 初始化完成] │
│ ▼ │
│ T4: Card Voltage ON (VCC) │
│ │ │
│ │ [等待 100ms+ for card power up] │
│ ▼ │
│ T5: Card Initialization │
│ │ │
│ ▼ │
│ T6: Ready for I/O │
│ │
│ ────────────────────────────────────────────────────────────────── │
│ │
│ 下电顺序 (Power-Down Sequence): │
│ ───────────────────────────── │
│ │
│ T0: ─────────────────────────────────────────────────────────► │
│ │ │
│ ▼ │
│ T1: 停止所有 I/O │
│ │ │
│ ▼ │
│ T2: Card Voltage OFF (VCC) │
│ │ │
│ ▼ │
│ T3: Host Controller Disable │
│ │ │
│ ▼ │
│ T4: IO Voltage OFF (VDD_Q) │
│ │ │
│ ▼ │
│ T5: Core Voltage OFF (BUCK) │
│ │ │
│ ▼ │
│ T6: 完全断电 │
│ │
└─────────────────────────────────────────────────────────────────────┘

3. PoFx (Power Framework) 架构

3.1 PoFx 简介

PoFx (Power Framework) 是 Windows 8+ 引入的电源管理框架,用于精细控制设备的电源状态:

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
┌─────────────────────────────────────────────────────────────────────┐
│ PoFx 电源框架 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Windows Power Manager │ │
│ │ (系统电源决策) │ │
│ └─────────────────────────────┬───────────────────────────────┘ │
│ │ │
│ │ PoFx │
│ │ Notifications │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ PoFx.sys (Power Framework) │ │
│ │ │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
│ │ │ PoFx │ │ PoFx │ │ PoFx │ │ │
│ │ │ Device 1 │ │ Device 2 │ │ Device N │ │ │
│ │ │ (BH202) │ │ │ │ │ │ │
│ │ └───────────┘ └───────────┘ └───────────┘ │ │
│ └─────────────────────────────┬───────────────────────────────┘ │
│ │ │
│ │ Driver Callbacks │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ BH202 Driver │ │
│ │ │ │
│ │ PoFxIdleCallback() ←── 收到空闲通知,准备进入低功耗 │ │
│ │ PoFxWakeCallback() ←── 收到唤醒通知,恢复到工作状态 │ │
│ │ │ │
│ │ PoFxIdleCallback() │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ req_enter_d3() → PMIC 关闭 Card/Host 电源 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

3.2 PoFx 核心概念

概念 说明
Component PoFx 管理的最小电源单元
F-State Component 的电源状态 (F0=工作, F1=空闲…)
Active Condition 保持 Component 活跃的条件
Idle Timeout 进入空闲前的等待时间
Reference Count 引用计数,决定是否保持活跃

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
// pmfunc.c - BH202 PoFx 组件定义

void pm_init(bht_dev_ext_t *pdx)
{
// 1. 初始化 PoFx 设备结构
pdx->pofx_device = &pdx->pofx_dev;

// 2. 设置版本
pdx->pofx_device->Version = STOR_POFX_DEVICE_VERSION_V2;
pdx->pofx_device->Size = sizeof(STOR_POFX_DEVICE_V2);

// 3. 设置组件数量 (BH202 使用 1 个组件管理 Card + Host)
pdx->pofx_device->ComponentCount = 1;

// 4. 配置组件 0 (SD Card + Host)
pdx->pofx_device->Components[0].Version = STOR_POFX_COMPONENT_VERSION_V1;
pdx->pofx_device->Components[0].Size = STOR_POFX_COMPONENT_SIZE;
pdx->pofx_device->Components[0].FStateCount = 2; // F0 + F1

// F0 = 工作状态 (Full Power)
pdx->pofx_device->Components[0].FStates[0].Version =
STOR_POFX_COMPONENT_IDLE_STATE_VERSION_V1;
pdx->pofx_device->Components[0].FStates[0].NominalPower = 100; // mW

// F1 = 空闲状态 (Low Power)
pdx->pofx_device->Components[0].FStates[1].Version =
STOR_POFX_COMPONENT_IDLE_STATE_VERSION_V1;
pdx->pofx_device->Components[0].FStates[1].NominalPower = 1; // mW

// 5. 设置设备标志
pdx->pofx_device->Flags |=
STOR_POFX_DEVICE_FLAG_IDLE_TIMEOUT |
STOR_POFX_DEVICE_FLAG_ADAPTER_D3_WAKE;

// 6. 设置空闲超时 (默认 10 秒)
pdx->pofx_device->AdapterIdleTimeoutInMS =
pdx->cfg->feature_item.psd_mode.adapter_idle_time_s * 1000;
}

4. 引用计数机制

4.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
30
31
32
33
34
35
36
37
38
39
40
41
┌─────────────────────────────────────────────────────────────────────┐
│ PoFx 引用计数机制 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Reference Count │ │
│ │ │ │
│ │ Component 状态 = Reference Count > 0 ? F0 : F1 │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ 引用计数增加 (+1) │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ ┌────────────────────┐ │ │ │
│ │ │ │ Ref Count: 0 → 1 │ │ │ │
│ │ │ │ 状态: F1 → F0 │ │ │ │
│ │ │ │ (唤醒设备) │ │ │ │
│ │ │ └────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ 引用计数减少 (-1) │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ ┌────────────────────┐ │ │ │
│ │ │ │ Ref Count: 1 → 0 │ │ │ │
│ │ │ │ 状态: F0 → F1 │ │ │ │
│ │ │ │ (设备可进入空闲) │ │ │ │
│ │ │ └────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ BH202 中的引用来源: │
│ ─────────────────── │
│ • I/O 请求处理 (SRB 执行中) │
│ • 卡插拔检测 (GPIO 中断) │
│ • 电源状态转换中 │
│ • 热管理需要 │
│ │
└─────────────────────────────────────────────────────────────────────┘

4.2 PoFx 引用计数 API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Storport 提供的 PoFx 引用计数 API

// 增加引用计数 (防止设备进入低功耗)
STOR_API_RETURN_VALUE
StorPortPoFxActivateComponent(
_In_ PVOID DeviceExtension,
_In_ ULONG Component,
_In_ ULONG Flags,
_In_ ULONG ActiveCondition,
_In_ PVOID ActiveConditionData
);
// 效果: Ref Count++, 组件保持在 F0

// 减少引用计数 (允许设备进入低功耗)
STOR_API_RETURN_VALUE
StorPortPoFxIdleComponent(
_In_ PVOID DeviceExtension,
_In_ ULONG Component,
_In_ ULONG Flags
);
// 效果: Ref Count--, 当 Ref Count = 0 时,组件可进入 F1

4.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// cardinterface.c - BH202 引用计数实现

static atomic_t card_request_d0 = 0; // D0 引用计数
static atomic_t card_request_d3 = 0; // D3 引用计数

// 请求进入 D0 (增加引用计数)
int pofx_request_d0(bht_dev_ext_t *pdx, int timeout_ms)
{
int ret = STOR_STATUS_SUCCESS;
int old_val;

// 增加引用计数
old_val = os_atomic_inc(&card_request_d0);

// 如果是第一次请求,激活组件
if (old_val == 0) {
// 调用 PoFx API
ret = StorPortPoFxActivateComponent(
pdx, // DeviceExtension
0, // Component 0
0, // Flags
POFX_ACTIVECONDITION_IO_REQUEST, // Active Condition
NULL // ActiveConditionData
);

if (ret != STOR_STATUS_SUCCESS) {
DbgErr("PoFxActivateComponent failed: 0x%X\n", ret);
os_atomic_dec(&card_request_d0);
return -1;
}

DbgInfo("PoFxActivateComponent: RefCount -> 1, Device Woken\n");
} else {
DbgInfo("PoFxRequestD0: RefCount %d -> %d\n", old_val, old_val + 1);
}

return 0;
}

// 请求进入 D3 (减少引用计数)
int pofx_request_d3(bht_dev_ext_t *pdx, int timeout_ms)
{
int ret = STOR_STATUS_SUCCESS;
int old_val;

// 检查引用计数
if (os_atomic_read(&card_request_d0) == 0) {
// 引用计数已经是 0,不需要再次 idle
DbgInfo("PoFxRequestD3: Already idle, skip\n");
return 0;
}

// 减少引用计数
old_val = os_atomic_dec(&card_request_d0);

// 如果减少到 0,调用 PoFx Idle
if (old_val == 1) {
// 调用 PoFx API
ret = StorPortPoFxIdleComponent(
pdx, // DeviceExtension
0, // Component 0
0 // Flags
);

if (ret != STOR_STATUS_SUCCESS) {
DbgErr("PoFxIdleComponent failed: 0x%X\n", ret);
// 恢复引用计数
os_atomic_inc(&card_request_d0);
return -1;
}

DbgInfo("PoFxIdleComponent: RefCount -> 0, Device Can Idle\n");
} else {
DbgInfo("PoFxRequestD3: RefCount %d -> %d\n", old_val, old_val - 1);
}

return 0;
}

5. PMIC 电源控制实现

5.1 电源控制结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// pmfunc.c - 电源管理功能

typedef struct {
bool rtd3_en; // Runtime D3 使能
bool s3s4_entered; // S3/S4 进入标志
bool rtd3_entered; // RTD3 进入标志
atomic_t pofx_active; // PoFx 激活状态
} pm_state_t;

// BH202 Qcom 特定设置 (更短的 idle 时间)
void cfg_default_psd_mode(cfg_psd_mode_t *psd_mode)
{
// adapter_idle_time_s: 系统空闲多久后请求 D3
// disk_idle_time_s: 驱动空闲多久后请求 D3
// 0202 = adapter 2s, disk 2s (比 x86 版本更激进)
fill_registry_struct(psd_mode, 0x80040202, 4);
}

5.2 进入 D0 流程

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
// pmfunc.c - 进入 D0 (工作状态)

void req_enter_d0(bht_dev_ext_t *pdx)
{
DbgInfo("Enter %s\n", __FUNCTION__);

// 1. 请求 PoFx 激活 (增加引用计数)
if (pofx_request_d0(pdx, 1000) != 0) {
DbgErr("PoFxRequestD0 failed\n");
// 继续执行,即使 PoFx 调用失败
}

// 2. PMIC 上电序列
pmic_enable_vdd_core(pdx); // 1. 打开 Core 电源
os_mdelay(5); // 等待稳定
pmic_enable_vdd_io(pdx); // 2. 打开 IO 电源
os_mdelay(5); // 等待稳定
pmic_enable_vdd_card(pdx); // 3. 打开 Card 电源

// 3. Host 控制器初始化
host_init(&pdx->host);

// 4. 重新初始化 DLL (如果需要)
if (pdx->host.msm_host.dll_config)
msm_init_cm_dll(&pdx->host);

// 5. 重新初始化卡
if (pdx->card.card_present) {
if (!card_init(&pdx->card, 3, FALSE)) {
DbgErr("Card init failed after D0\n");
}
}

// 6. 启用中断
host_int_sig_en(&pdx->host, 0xFFFFFFFF);

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

5.3 进入 D3 流程

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
// pmfunc.c - 进入 D3 (低功耗状态)

void req_enter_d3(bht_dev_ext_t *pdx)
{
DbgInfo("Enter %s\n", __FUNCTION__);

// 1. 停止自动定时器
func_autotimer_stop(pdx);

// 2. 停止卡操作
card_stop_infinite(&pdx->card, FALSE, NULL);

// 3. 请求 PoFx 空闲 (减少引用计数)
if (pofx_request_d3(pdx, 1000) != 0) {
DbgErr("PoFxRequestD3 failed\n");
// 继续执行,强制关闭电源
}

// 4. 关闭 Host 中断
host_int_sig_dis(&pdx->host, 0xFFFFFFFF);

// 5. PMIC 下电序列
pmic_disable_vdd_card(pdx); // 1. 先关闭 Card 电源
os_mdelay(5); // 等待稳定
pmic_disable_vdd_io(pdx); // 2. 关闭 IO 电源
os_mdelay(5); // 等待稳定
pmic_disable_vdd_core(pdx); // 3. 最后关闭 Core 电源

// 6. 更新状态
pdx->pm_state.rtd3_entered = TRUE;

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

5.4 PMIC 控制函数

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
// Qualcomm PMIC 控制实现

static void pmic_write_reg(u8 reg, u8 value)
{
// 通过 SPMI/I2C 写入 PMIC 寄存器
spmi_write(PMIC_SLAVE_ADDR, reg, value);
}

static u8 pmic_read_reg(u8 reg)
{
return spmi_read(PMIC_SLAVE_ADDR, reg);
}

void pmic_enable_vdd_core(bht_dev_ext_t *pdx)
{
// 使能 BUCK (Core Voltage)
u8 val = pmic_read_reg(PMIC_REG_BUCK_ENABLE);
val |= BUCK_ENABLE_BIT;
pmic_write_reg(PMIC_REG_BUCK_ENABLE, val);
DbgInfo("PMIC: Core Voltage enabled\n");
}

void pmic_enable_vdd_io(bht_dev_ext_t *pdx)
{
// 使能 LDO2 (IO Voltage)
u8 val = pmic_read_reg(PMIC_REG_LDO2_ENABLE);
val |= LDO_ENABLE_BIT;
pmic_write_reg(PMIC_REG_LDO2_ENABLE, val);

// 设置电压为 1.8V
val = pmic_read_reg(PMIC_REG_LDO2_VOLTAGE);
val &= ~LDO_VOLTAGE_MASK;
val |= LDO_VOLTAGE_1V8;
pmic_write_reg(PMIC_REG_LDO2_VOLTAGE, val);

DbgInfo("PMIC: IO Voltage enabled (1.8V)\n");
}

void pmic_enable_vdd_card(bht_dev_ext_t *pdx)
{
// 使能 LDO1 (Card Voltage)
u8 val = pmic_read_reg(PMIC_REG_LDO1_ENABLE);
val |= LDO_ENABLE_BIT;
pmic_write_reg(PMIC_REG_LDO1_ENABLE, val);

// 设置电压 (根据卡类型)
val = pmic_read_reg(PMIC_REG_LDO1_VOLTAGE);
val &= ~LDO_VOLTAGE_MASK;
if (pdx->card.card_type == CARD_SD)
val |= LDO_VOLTAGE_3V3; // SD 卡 3.3V
else
val |= LDO_VOLTAGE_1V8; // eMMC 1.8V
pmic_write_reg(PMIC_REG_LDO1_VOLTAGE, val);

// 等待卡电源稳定 (SD 需要较长稳定时间)
os_mdelay(100);

DbgInfo("PMIC: Card Voltage enabled\n");
}

6. 卡插拔与电源管理协同

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// irqhandler.c / thread.c - 卡插入时的电源协同

void insert_card_handle(bht_dev_ext_t *pdx)
{
DbgInfo("Card insert detected\n");

// 1. 更新卡状态
pdx->card.card_present = TRUE;
pdx->card.card_removed = FALSE;

// 2. 保持 Host 电源开启 (如果之前关闭了)
ven_quirk_main_power_ctrl(&pdx->host, TRUE);

// 3. 增加 PoFx 引用计数 (防止电源被关闭)
pofx_request_d0(pdx, 1000);

// 4. 通知工作线程处理
if (pdx->os.task_mgr.tasks[TASK_CARD_CHG].shared_task_cnt == 0)
os_set_event(pdx, &pdx->os, EVENT_TASK_OCCUR, TASK_CARD_CHG);
}

void thread_card_init(void *param)
{
bht_dev_ext_t *pdx = (bht_dev_ext_t *)param;

while (!os_thread_should_terminate(pdx)) {
// 等待卡初始化请求
os_wait_for_event(&pdx->os.evt_card_init);

// 执行卡初始化
if (card_init(&pdx->card, 3, FALSE) == FALSE) {
DbgErr("Card init failed\n");
// 释放 PoFx 引用计数
pofx_request_d3(pdx, 1000);
continue;
}

// 初始化成功,保持 PoFx 激活
DbgInfo("Card init success: %s\n", card_type_str(pdx->card.card_type));

// 卡就绪后,可以释放引用计数
// 但保持 Host 电源开启,因为卡可能随时被访问
// pofx_request_d3(pdx, 1000); // 注释掉,保持电源
}
}

6.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
// irqhandler.c - 卡移除时的电源协同

void remove_card_handle(bht_dev_ext_t *pdx)
{
DbgInfo("Card remove detected\n");

// 1. 更新卡状态
pdx->card.card_present = FALSE;
pdx->card.card_removed = TRUE;

// 2. 标记卡需要重新初始化
pdx->card.initialized_once = FALSE;

// 3. 停止卡操作
card_stop_infinite(&pdx->card, FALSE, NULL);

// 4. 通知工作线程处理
if (pdx->os.task_mgr.tasks[TASK_CARD_CHG].shared_task_cnt == 0)
os_set_event(pdx, &pdx->os, EVENT_TASK_OCCUR, TASK_CARD_CHG);
}

void thread_card_remove(void *param)
{
bht_dev_ext_t *pdx = (bht_dev_ext_t *)param;

while (!os_thread_should_terminate(pdx)) {
// 等待卡移除处理请求
os_wait_for_event(&pdx->os.evt_card_remove);

DbgInfo("Processing card removal\n");

// 1. 停止所有 I/O
req_cancel_all_io(pdx);

// 2. 关闭卡电源
card_power_off(&pdx->card, FALSE);

// 3. 释放 PoFx 引用计数 (允许进入 D3)
if (pofx_request_d3(pdx, 1000) == 0) {
DbgInfo("PoFx idle requested, device can enter low power\n");
}

// 4. 关闭 Host 电源 (可选,取决于系统设计)
// ven_quirk_main_power_ctrl(&pdx->host, FALSE);
}
}

7. 电源状态转换图

7.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
┌─────────────────────────────────────────────────────────────────────┐
│ BH202 电源状态转换图 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ PoFx Framework │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Reference Count > 0 ? F0 : F1 │ │
│ │ │ │ │
│ │ ┌─────────────────┴─────────────────┐ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │ F0 │ ◄──────────────────► │ F1 │ │ │
│ │ │ (D0) │ PoFxActivate/Idle │ (D3) │ │ │
│ │ │ 工作中 │ │ 空闲中 │ │ │
│ │ └─────────┘ └─────────┘ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ PMIC 电源状态 │ │ │
│ │ │ │ │ │
│ │ │ • VDD_Core = ON │ │ │
│ │ │ • VDD_IO = ON │ │ │
│ │ │ • VDD_Card = ON/OFF (取决于卡是否在位) │ │ │
│ │ │ • Host Controller = Enabled │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ 状态触发条件: │
│ │
│ F0 → F1: │
│ • 无活跃的 I/O 请求 │
│ • 无卡插拔事件 │
│ • Idle Timeout 到期 │
│ │
│ F1 → F0: │
│ • 收到新的 I/O 请求 │
│ • 收到卡插拔 GPIO 中断 │
│ • 系统从 S3/S4 唤醒 │
│ │
└─────────────────────────────────────────────────────────────────────┘

7.2 I/O 请求与电源协同

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
┌─────────────────────────────────────────────────────────────────────┐
│ I/O 请求与电源协同时序 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [文件系统] [Storport] [BH202 Driver] [PMIC] │
│ │ │ │ │ │
│ │ I/O Request │ │ │ │
│ │────────────►│ │ │ │
│ │ │ │ │ │
│ │ │ HwStartIo() │ │ │
│ │ │──────────────►│ │ │
│ │ │ │ │ │
│ │ │ │ pofx_request_d0()│ │
│ │ │ │──────────►│ │ │
│ │ │ │ Ref Count++ │ │ │
│ │ │ │ PMIC: D3→D0 │ │ │
│ │ │ │◄──────────│ │ │
│ │ │ │ │ │
│ │ │ │ 执行 DMA 传输 │ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ │ │ │◄────┘ │ │
│ │ │ │ │ │
│ │ │ SRB 完成 │ │ │
│ │ │◄──────────────│ │ │
│ │ │ │ │ │
│ │ │ │ pofx_request_d3() │ │
│ │ │ │──────────►│ │ │
│ │ │ │ Ref Count-- │ │ │
│ │ │ │ Idle Timer Start│ │
│ │ │ │ │ │
│ │ I/O Complete│ │ │ │
│ │◄────────────│ │ │ │
│ │ │ │ │ │
│ │ │ │ [等待 Idle Timeout] │
│ │ │ │ │ │ │
│ │ │ │ │ Timer │ │
│ │ │ │ │ Expired│ │
│ │ │ │ ▼ ▼ │
│ │ │ │ Ref Count = 0 │
│ │ │ │ PMIC: D0 → D3 │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ │
└─────────────────────────────────────────────────────────────────────┘

8. 调试与诊断

8.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
// 调试函数:打印当前电源状态
void dump_power_state(bht_dev_ext_t *pdx)
{
DbgInfo("=== BH202 Power State ===\n");

// PoFx 状态
DbgInfo("PoFx:\n");
DbgInfo(" pofx_active: %d\n", os_atomic_read(&pdx->pofx_active));
DbgInfo(" card_request_d0: %d\n", os_atomic_read(&card_request_d0));

// PM 状态
DbgInfo("PM State:\n");
DbgInfo(" rtd3_en: %s\n", pdx->pm_state.rtd3_en ? "ON" : "OFF");
DbgInfo(" s3s4_entered: %s\n", pdx->pm_state.s3s4_entered ? "YES" : "NO");
DbgInfo(" rtd3_entered: %s\n", pdx->pm_state.rtd3_entered ? "YES" : "NO");

// 卡状态
DbgInfo("Card:\n");
DbgInfo(" card_present: %s\n", pdx->card.card_present ? "YES" : "NO");
DbgInfo(" card_type: %s\n", card_type_str(pdx->card.card_type));
DbgInfo(" card_state: %d\n", pdx->card.state);

// PMIC 寄存器
DbgInfo("PMIC Registers:\n");
DbgInfo(" BUCK_CTRL: 0x%02X\n", pmic_read_reg(PMIC_REG_BUCK_ENABLE));
DbgInfo(" LDO1_CTRL: 0x%02X\n", pmic_read_reg(PMIC_REG_LDO1_ENABLE));
DbgInfo(" LDO2_CTRL: 0x%02X\n", pmic_read_reg(PMIC_REG_LDO2_ENABLE));
}

8.2 常见问题排查

问题 可能原因 排查方法
卡无法识别 PMIC 电源未开启 检查 PMIC 寄存器
D3 无法进入 引用计数 > 0 检查 pofx_active
唤醒失败 DLL 未重新初始化 检查 DLL 锁定状态
S4 abnormal shutdown PoFx timeout 太短 增加 timeout 值

9. 总结

9.1 关键设计点

设计点 实现
统一电源控制 SD Card 和 Host 由同一 PMIC 控制
PoFx 引用计数 Ref Count > 0 保持 D0,= 0 可进入 D3
协同上下电 Host → IO → Card 上电顺序,逆序下电
Qualcomm 特定 SPMI/I2C 与 PMIC 通信

9.2 与 x86 平台对比

项目 x86 (PCIe) Qcom ARM (BH202)
电源控制 PCIe Slot Power PMIC (SPMI/I2C)
电源框架 ACPI PoFx
引用计数 设备就绪协议 PoFx Activate/Idle
电源域 Slot 级别 芯片级别
上电时序 Slot 顺序 PMIC 寄存器序列

参考资料

  1. StorPort Power Management
  2. Power Framework (PoFx)
  3. Component-level Power Management
  4. Qualcomm SPMI Specification

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