Phytium E2000Q 平台 CPU 调频架构
平台概述
Phytium 飞腾腾珑 E2000Q 标准版 关键规格:
| 参数 | 值 |
|---|---|
| CPU 架构 | ARM64 (ARMv8-A),big.LITTLE 异构多核 |
| CPU 核心 | 2×飞腾 FTC310 小核(CPU part 0x303)@ 1.5GHz + 2×飞腾 FTC664 大核(CPU part 0x664)@ 2.0GHz |
| L2 Cache | 2MB(大核 cluster)+ 256KB(小核 cluster) |
| 典型功耗 | 6.4W / TDP 11W |
| 内核电压 | 0.85V |
| SCMI 固件 | Phytium:E2000,协议 v2.0 |
调频实现方式:采用 ARM SCMI (System Control and Management Interface) 标准协议。
芯片内置一个系统控制处理器(SCP,位于 SoC 内部但独立于 CPU 核心),
Linux 主核通过 SCMI 协议与 SCP 通信,由 SCP 实际操作时钟/电压硬件完成调频。
一、整体架构分层
┌─────────────────────────────────────────────────────────┐
│ 用户态 (Userspace) │
│ /sys/devices/system/cpu/cpufreq/policy*/ (sysfs) │
│ echo $FREQ > scaling_setspeed │
└──────────────────────┬──────────────────────────────────┘
│ write
┌──────────────────────▼──────────────────────────────────┐
│ ① cpufreq 核心框架 drivers/cpufreq/cpufreq.c │
│ + governor (schedutil/ondemand/userspace...) │
│ 决策目标频率 │
└──────────────────────┬──────────────────────────────────┘
│ cpufreq_driver ops
┌──────────────────────▼──────────────────────────────────┐
│ ② SCMI cpufreq 驱动 drivers/cpufreq/scmi-cpufreq.c │
│ scmi_cpufreq_set_target() / scmi_cpufreq_fast_switch() │
│ → handle->perf_ops->freq_set() │
└──────────────────────┬──────────────────────────────────┘
│ scmi_perf_ops
┌──────────────────────▼──────────────────────────────────┐
│ ③ SCMI Performance 协议 drivers/firmware/arm_scmi/perf.c│
│ scmi_perf_level_set() 两条路径: │
│ a) FastChannel: iowrite32 共享内存 + ring doorbell │
│ b) Mailbox: scmi_do_xfer() 标准 SCMI 消息 │
└──────────────────────┬──────────────────────────────────┘
│ scmi_transport_ops
┌──────────────┴──────────────┐
┌───────▼──────────┐ ┌─────────▼──────────┐
│ ④a Mailbox 传输 │ │ ④b SMC 传输(可选) │
│ scmi/mailbox.c │ │ scmi/smc.c │
│ mbox_send_message │ │ arm_smccc_1_1_invoke│
└───────┬──────────┘ └─────────┬──────────┘
│ mbox_chan_ops │ SMC/HVC 异常
┌───────▼──────────┐ ┌─────────▼──────────┐
│ ⑤ Phytium mailbox│ │ PSCI/ATF 固件 │
│ phytium-mailbox.c│ │ (Trusted Firmware) │
│ 写 INTR_SET 寄存器│ └─────────┬──────────┘
└───────┬──────────┘ │
│ 触发硬件中断 │
════════╪═════════════════════════════╪══════ 硬件边界 ═══
┌───────▼─────────────────────────────▼──────────┐
│ ⑥ SCP 固件 (E2000Q 片内系统控制处理器) │
│ - 接收中断/SCMI 消息 │
│ - 解析 PERF_LEVEL_SET 命令 │
│ - 操作时钟发生器/PLL/电压调节器 │
│ - 实际性能域划分(基于 policy 推测): │
│ 小核 cluster (cpu0-1) → 一个域 │
│ 大核 cpu2 → 一个独立域 │
│ 大核 cpu3 → 一个独立域 │
│ - 写共享内存返回响应 + 触发中断(? 未确认) │
└─────────────────────────────────────────────────┘
二、各组件详解
1. cpufreq 核心框架
drivers/cpufreq/cpufreq.c
职责: 通用调频抽象层,与具体硬件无关。
- 提供 sysfs 接口:
scaling_setspeed,scaling_governor,scaling_cur_freq等 - 管理 governor(调频策略):
userspace— 用户直接指定频率schedutil— 根据 CPU 负载动态调整(默认)performance/powersave— 固定最高/最低ondemand— 按需调节
- 决策后调用驱动的
target_index()或fast_switch()
E2000Q 上的实际 policy 拓扑(依据设备 /sys/devices/system/cpu/cpufreq/ 输出):
| policy | affected_cpus | 核心类型 | 最大频率 | 可用频率(kHz) |
|---|---|---|---|---|
| policy0 | 0-1 | 小核(FTC310) | 1.5GHz | 187500, 375000, 750000, 1500000 |
| policy2 | 2 | 大核(FTC664) | 2.0GHz | 250000, 500000, 1000000, 2000000 |
| policy3 | 3 | 大核(FTC664) | 2.0GHz | 250000, 500000, 1000000, 2000000 |
2. SCMI cpufreq 驱动
drivers/cpufreq/scmi-cpufreq.c
职责: 将 cpufreq 通用操作转换为 SCMI 性能协议调用。
关键函数(scmi-cpufreq.c):
| 函数 | 用途 | 调用 SCMI 接口 |
|---|---|---|
scmi_cpufreq_set_target() |
常规调频(进程上下文) | perf_ops->freq_set(handle, domain_id, freq*1000, false) |
scmi_cpufreq_fast_switch() |
快速切换(中断上下文) | perf_ops->freq_set(..., true) (poll 模式) |
scmi_cpufreq_get_rate() |
读当前频率 | perf_ops->freq_get() |
scmi_get_sharing_cpus() |
获取同 domain 的 CPU | 通过 device_domain_id() 聚类 |
domain 映射(scmi-cpufreq.c):
device_domain_id(cpu_dev)从 DT/ACPI 读取每个 CPU 的 domain- 同 domain 的 CPU 被聚到同一个 policy,共享频率
- E2000Q 实际:cpu0/cpu1 → 同一 domain(推测 domain 0),cpu2 → 独立 domain(推测 domain 1),cpu3 → 独立 domain(推测 domain 2)
3. SCMI Performance 协议
drivers/firmware/arm_scmi/perf.c
职责: 实现 SCMI 规范中的 Performance 协议(协议 ID 0x13),提供 freq_set/freq_get/limits_set 等操作。
两条调频路径(perf.c):
static int scmi_perf_level_set(handle, domain, level, poll) {
if (dom->fc_info && dom->fc_info->level_set_addr) {
// 路径 a: Fast Channel —— 直接写共享内存 + 敲 doorbell
iowrite32(level, dom->fc_info->level_set_addr);
scmi_perf_fc_ring_db(dom->fc_info->level_set_db);
return 0;
}
// 路径 b: 标准 Mailbox 消息
return scmi_perf_mb_level_set(handle, domain, level, poll);
}
| 路径 | 延迟 | 上下文 | 原理 |
|---|---|---|---|
| Fast Channel | ~µs 级 | 可用于中断上下文 | Linux 直接写预共享的 SRAM,写 doorbell 触发 SCP 中断 |
| Mailbox | ~ms 级(实测 ~2.7ms) | 进程上下文 | 完整 SCMI 消息:组帧 → 写 shmem → 发中断 → 等响应 |
关键 SCMI 命令:
| 命令 | ID | 用途 |
|---|---|---|
PERF_LEVEL_SET |
0x7 | 设置目标频率等级 |
PERF_LEVEL_GET |
0x8 | 读当前频率等级 |
PERF_LIMITS_SET |
0x9 | 设置频率上下限 |
PERF_NOTIFY_LIMITS |
0xA | 使能限制变化通知 |
PERF_NOTIFY_LEVEL |
0xB | 使能等级变化通知 |
4. 传输层 (Transport)
a. Mailbox 传输
drivers/firmware/arm_scmi/mailbox.c
- 适配内核 mailbox 框架
chan_lock互斥锁,保证同一时刻只有一条消息在飞- 使用共享内存 (
shmem.c) 传递消息内容 - 关键操作:
send_message/fetch_response/fetch_notification/clear_channel
b. SMC 传输
drivers/firmware/arm_scmi/smc.c,可选
- 通过
arm_smccc_1_1_invoke()触发 SMC/HVC 陷入 EL3 - 由 ATF (ARM Trusted Firmware) 转发给 SCP
- E2000Q 上根据 DT 中
arm,scmi还是arm,scmi-smc选择
5. Phytium Mailbox 控制器驱动
drivers/mailbox/phytium-mailbox.c
职责: 操作 E2000Q 片内 mailbox 硬件(SoC 专用 IP)。
// 发送: 写寄存器触发 SCP 中断
phytium_mbox_send_data():
writel_relaxed(*arg, mlink->tx_reg + INTR_SET);
// 接收: SCP 回中断
phytium_mbox_rx_irq():
val = readl_relaxed(mlink->rx_reg + INTR_STAT);
mbox_chan_received_data(chan, &val); // 唤醒 SCMI 层
writel_relaxed(val, mlink->rx_reg + INTR_CLR);
硬件寄存器:
| 寄存器 | 偏移 | 用途 |
|---|---|---|
INTR_STAT |
0x0 | 中断状态(读) |
INTR_SET |
0x8 | 触发中断(写) |
INTR_CLR |
0x10 | 清除中断 |
TX_REG |
0x100 | 发送通道基址 |
设备匹配:
- ACPI:
PHYT0009 - DeviceTree:
phytium,mbox
6. SCP 固件(E2000Q 片内)
职责: 实际执行频率切换。
- 接收 mailbox 中断或 doorbell
- 解析 SCMI
PERF_LEVEL_SET命令(domain_id, level) - 查 OPP 表,操作:
- 时钟发生器 / PLL 重配置
- 电压调节(DVFS 配套,0.85V 内核电压)
-
实际性能域划分(根据 policy 推测): | CPU | 类型 | domain ID | |—–|——|———–| | cpu0-1 | 小核(FTC310) | 2 | | cpu2 | 大核(FTC664) | 0 | | cpu3 | 大核(FTC664) | 1 |
- 写响应到共享内存,触发回执中断
- 可主动发送异步通知(如温控降频触发
PERF_NOTIFY_LIMITS)
SCP firmware:运行在 SoC 内部 System Control Processor 上的独立固件,
通过 SCMI mailbox/FastChannel 接收 Linux AP 请求,并负责执行 clock、PLL、voltage、power domain 等底层控制。
三、完整调用链(以 userspace 调频为例)
以 echo 2000000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed(小核调频)为例:
1. sysfs write
store_scaling_setspeed() [cpufreq.c]
└── policy->governor->store_setspeed() (userspace governor)
└── cpufreq_driver->target_index()
│
2. SCMI cpufreq 驱动
└── scmi_cpufreq_set_target() [scmi-cpufreq.c]
└── perf_ops->freq_set(handle, domain_id=0, freq*1000, false)
│
3. SCMI perf 协议
└── scmi_dvfs_freq_set() → scmi_perf_level_set()
[perf.c]
├─ 若 Fast Channel 可用: iowrite32 → ring doorbell → 完成
└─ 否则 Mailbox 路径:
└── scmi_perf_mb_level_set() [perf.c]
├── scmi_xfer_get_init() 组 SCMI 消息帧
│ (PERF_LEVEL_SET=0x7, proto=0x13)
└── scmi_do_xfer() [driver.c]
│
4. SCMI 核心
└── info->desc->ops->send_message()
│
5. Mailbox 传输
└── mailbox_send_message()
[mailbox.c]
├── mutex_lock(&chan_lock)
└── mbox_send_message(chan, xfer)
│
6. Mailbox 框架
└── msg_submit → chan->ops->send_data()
│
7. Phytium 硬件驱动
└── phytium_mbox_send_data()
[phytium-mailbox.c]
└── writel(val, tx_reg + INTR_SET)
↓ 触发 SCP 硬件中断
8. SCP 固件 (E2000Q 片内)
├── ISR 读取共享内存消息
├── 解析 PERF_LEVEL_SET(domain, level)
├── 操作对应 PLL/时钟分频器切换频率
四、组件交互关系图
┌────────────┐ freq_table ┌─────────────┐
│ Governor │──────────────▶│ cpufreq core│
│(schedutil) │ 决策频率 │ (policy0/2/3)
└────────────┘ └──────┬──────┘
│ target_index/fast_switch
▼
┌────────────────────┐
│ scmi-cpufreq │◀──┐
│ (cpufreq_driver) │ │
└──────┬─────────────┘ │
│ perf_ops │ scmi_handle
▼ │ (probe 时获得)
┌────────────────────┐ │
│ SCMI perf protocol │ │
│ perf.c │───┘
│ (domains) │
└──────┬─────────────┘
│ xfer
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ mailbox.c │ │ smc.c │ │ notify.c │
│(TX 通道) │ │(SMC 通道) │ │(RX 异步事件) │
└──────┬───────┘ └──────┬───────┘ └──────▲───────┘
│ mbox_send │ SMC │ rx_callback
▼ ▼ │
┌──────────────────────────────────────────┴───────┐
│ Phytium mailbox 硬件 + 共享内存 (shmem) │
└──────────────────────┬───────────────────────────┘
│ 中断
▼
┌─────────────────────┐
│ SCP 固件 (E2000Q) │
│ 多个性能域 │
│ DVFS/时钟/电压控制 │
└─────────────────────┘
五、关键交互机制
| 交互对 | 机制 | 数据结构 |
|---|---|---|
| userspace ↔ cpufreq core | sysfs 文件读写 | cpufreq_policy |
| governor ↔ cpufreq core | 回调函数 | cpufreq_governor ops |
| cpufreq core ↔ scmi-cpufreq | 驱动 ops | cpufreq_driver |
| scmi-cpufreq ↔ perf 协议 | scmi_handle 句柄 | scmi_perf_ops |
| perf 协议 ↔ 传输层 | xfer 消息 | scmi_xfer |
| mailbox 传输 ↔ Phytium 驱动 | mbox 框架 API | mbox_chan |
| Phytium 驱动 ↔ SCP 硬件 | MMIO 寄存器 + 中断 + 共享内存 | INTR_SET/STAT/CLR + shmem |
| SCP → Linux(异步通知) | RX 中断 → notify.c → kfifo → workqueue → notifier chain | scmi_notify_ops |
六、E2000Q big.LITTLE 架构特性
6.1 性能域和调频策略
设备实际显示:
- 小核集群(cpu0-1):共享一个 policy(policy0),频率范围 187.5kHz ~ 1.5GHz,共 4 档。
- 大核(cpu2):独立 policy(policy2),频率范围 250kHz ~ 2.0GHz,共 4 档。
- 大核(cpu3):独立 policy(policy3),频率范围相同。
这意味着大核之间频率不强制同步,系统可以分别调节每个大核的频率,提供更精细的功耗/性能控制。
┌─────────────────────────────────────────────────────────────┐
│ E2000Q SoC │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ FTC310 小核 │ │ FTC664 大核 │ │ FTC664 大核 │ │
│ │ cpu0,cpu1 │ │ cpu2 │ │ cpu3 │ │
│ │ ≤ 1.5 GHz │ │ ≤ 2.0 GHz │ │ ≤ 2.0 GHz │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ │ │ │ │
│ PLL (小核) PLL (大核2) PLL (大核3) │
│ │ │ │ │
│ ┌──────▼─────┐ ┌──────▼─────┐ ┌──────▼─────┐ │
│ │ domain 2 │ │ domain 0 │ │ domain 1 │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ │
│ ┌────────────────────────────┐ │
│ │ SCP 固件 │ │
│ │ 管理所有性能域 │ │
│ └────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
6.2 查看设置频率
# 查看所有 policy
ls /sys/devices/system/cpu/cpufreq/
# 输出:policy0 policy2 policy3
# 查看每个 policy 影响的 CPU
cat /sys/devices/system/cpu/cpufreq/policy0/affected_cpus # 输出:0 1
cat /sys/devices/system/cpu/cpufreq/policy2/affected_cpus # 输出:2
cat /sys/devices/system/cpu/cpufreq/policy3/affected_cpus # 输出:3
# 查看频率表
cat /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies
# 187500 375000 750000 1500000
cat /sys/devices/system/cpu/cpufreq/policy2/scaling_available_frequencies
# 250000 500000 1000000 2000000
cat /sys/devices/system/cpu/cpufreq/policy3/scaling_available_frequencies
# 250000 500000 1000000 2000000
# 独立调频验证(大核各自设置不同频率)
echo 1000000 > /sys/devices/system/cpu/cpufreq/policy2/scaling_setspeed
echo 2000000 > /sys/devices/system/cpu/cpufreq/policy3/scaling_setspeed
cat /sys/devices/system/cpu/cpufreq/policy2/scaling_cur_freq # 应为 1000000
cat /sys/devices/system/cpu/cpufreq/policy3/scaling_cur_freq # 应为 2000000
6.3 调频验证
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ cat affected_cpus
2
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ taskset -c 2 busybox sh -c 'while :; do :; done' &
bdrt:/sys/devices/system/cpu/cpufreq/policy2$
bdrt:/sys/devices/system/cpu/cpufreq/policy2$
bdrt:/sys/devices/system/cpu/cpufreq/policy2$
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ echo 2000000 > scaling_setspeed
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ cat cpuinfo_cur_freq
2000000
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ perf stat -e cycles -C 2 sleep 10
Performance counter stats for 'CPU(s) 2':
20004449692 cycles
10.002217960 seconds time elapsed
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ echo 250000 > scaling_setspeed
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ cat cpuinfo_cur_freq
250000
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ cat scaling_cur_freq
250000
bdrt:/sys/devices/system/cpu/cpufreq/policy2$ perf stat -e cycles -C 2 sleep 10
Performance counter stats for 'CPU(s) 2':
2500662426 cycles
10.002596800 seconds time elapsed
结果对比
| 设置频率 | scaling_cur_freq |
cpuinfo_cur_freq |
perf cycles (10s) | 频率比 | cycles 比 |
|---|---|---|---|---|---|
| 250 kHz | 250000 | 250000 | 2,500,662,426 | 1x | 1x |
| 2000 MHz | 2000000 | 2000000 | 20,004,449,692 | 8x | ~8.0x |
观察:
- cycles 比值 ≈ 8.0,与频率比值(2000/250 = 8)吻合。
- 证明 CPU2 硬件确实以所设频率运行,调频成功。
6.4 低功耗场景特性
E2000Q 典型功耗 6.4W / TDP 11W,面向嵌入式无风扇场景:
- 温控联动降频:SCP 固件可通过
PERF_NOTIFY_LIMITS通知 Linux 调整scaling_max_freq。 - schedutil governor 节能:小核可降至最低档(187.5kHz),大核可降至最低档(250kHz)。
- 大核独立调频:可以在轻负载时单独降频某一个大核,进一步节能。
- Fast Channel 的价值:若固件支持,可大幅降低调频延迟,提升 schedutil 的响应速度,但当前实测平台使用 Mailbox。
七、参考代码位置
内核版本linux-5.4.74
| 组件 | 文件路径 |
|---|---|
| cpufreq 核心 | drivers/cpufreq/cpufreq.c |
| SCMI cpufreq 驱动 | drivers/cpufreq/scmi-cpufreq.c |
| SCMI perf 协议 | drivers/firmware/arm_scmi/perf.c |
| SCMI 核心 | drivers/firmware/arm_scmi/driver.c |
| SCMI 通知子系统 | drivers/firmware/arm_scmi/notify.c |
| Mailbox 传输 | drivers/firmware/arm_scmi/mailbox.c |
| SMC 传输 | drivers/firmware/arm_scmi/smc.c |
| 共享内存操作 | drivers/firmware/arm_scmi/shmem.c |
| Phytium mailbox 驱动 | drivers/mailbox/phytium-mailbox.c |
| SCMI 公共头文件 | include/linux/scmi_protocol.h |