文章目录
-
-
- 1)资料快车
- 2)概述
- [3)ARM 功耗架构规范-PSCA](#3)ARM 功耗架构规范-PSCA)
- 4)ARM内部的电源划分(电源域和电压域)
- 5)电源管理软件协议栈
- 6)ATF安全固件基础
- 7)ARM-SCP
- 8)SCP与AP的通信
- 9)PMIC/PMU
-
1)资料快车
ARM SCP入门-简介和代码下载: https://mp.weixin.qq.com/s/jHtVscToPEIc7qVnNrIo-A
ARM SCP入门-framework框架:https://mp.weixin.qq.com/s/pPepd-JNqmNUf76jpmPAcA
ARM SCP入门-AP与SCP通信:https://mp.weixin.qq.com/s/QSxurWKTXiYmxesCE59T_w?scene=1
2)概述
1、由于电源架构设计到SOC上的每一个模块,复杂度高,不加以管控则会导致混乱失控,因为务必有巨头来设计对应规范,让软件硬件设计更加规范;比如ARM推出PSCA规范来让硬件和软件设计更加规范!大家都可以参照PSCA来设计自己的ARM体系电源架构;
2、规范只是参考(大而全),实际上厂商都会根据自家产品来定制电源架构,总体上会符合规范思想;
3、电源管理架构 依赖于硬件设计;
3)ARM 功耗架构规范-PSCA
1、PSCA (power control system architecture) 功耗控制系统架构
随着SOC的复杂性增加,为了更好的功耗管理,需要从系统中其他的控制器和应用处理器中抽象出来各种电源或其他系统管理任务,进行集中管理,利用一个独立的控制器核心实现。因此ARM提出了功耗控制系统架构(power control system architecture,简称PCSA),用来规范芯片功耗控制的逻辑实现。
2、为什么SoC需要集中功耗控制?
1)首先SoC的复杂性,现代SOC集成了不同的处理器(CPU/GPU/NPU)、大量的硬件模块,实现电源管理,这些模块间需要进行集成和协调,实现难度大;
2)其次功耗管理的复杂性,涉及时钟、电源域、传感器、事件等方面。
3、PCSA描述了一种使用标准基础设施组件、低功耗接口和相关方法进行功率控制集成的方法。PCSA基于ARM的组件实现,规范包括:
- 电压、电源和时钟的划分;
- 电源的状态和模式;
- ARM电源控制框架和集成规范;
- ARM特定组件的电源和时钟集成;
- 带有低功耗Q-channel和P-channel接口的IP。
4、基于PSCA规范的标准SOC设计如下
1)Always On 顾名思义,在设备接通电源的情况下,Always on模块应该一直在线,不能断电,相当于一个总开关,控制其它模块的断电上电,这个称为SCP,一般是一个内置在SOC里MCU模块;
4)ARM内部的电源划分(电源域和电压域)
1、为了实现更精细的电源控制,ARM将SOC内部划分了两个电相关的概念:电源域(power domain)和电压域(voltage domain)。
2、将ARM内部模块拆分到不同电源域,规范中的例子

如上图,不同颜色表示不同的电压域,VBIG是大核处理器的电源供电,VLITTLE是小核处理器的电源供电,VGPU是图形处理器的电源供电,VSYS是系统电源。虚线框包围的模块表示可以做电源开关处理,比如处理器核。实线框包围的模块表示不能做电源开关,比如SCP。
1)划分不同的电压域有利于精细化控制;
2)比如运行时,某些域不再使用-则可以关闭(电源管理芯片)
3)待机时,只留必要的域,其它也可以关闭(外接standby)
3、RK3399有PD和VD

5)电源管理软件协议栈
结合电源硬件架构,看下软件的协议栈宏观实现

用户层:
首先用户发起的一些操作,通过用户空间的各service处理,会经过内核提供的sysfs,操作cpu hotplug、device pm、EAS、IPA等。
内核层:
在linux内核中,EAS(energy aware scheduling)通过感知到当前的负载及相应的功耗,经过cpu idle、cpu dvfs及调度选择idle等级、cpu频率及大核或者小核上运行。IPA(intrlligent power allocation)经过与EAS的交互,做热相关的管理。
ATF层:
Linux kernel中发起的操作,会经过电源状态协调接口(Power State Coordination Interface,简称PSCI),由操作系统无关的framework(ARM Trusted Firmware,简称ATF)做相关的处理后,通过系统控制与管理接口(System Control and Management Interface,简称SCMI),向系统控制处理器(system control processor,简称SCP)发起低功耗操作。
SCP层:
SCP最终会控制芯片上的sensor、clock、power domain、及板级的pmic做低功耗相关的处理。
总结:用户进程 --sysfs--> 内核(EAS、IPA)-- PSCI --> ATF --SCMI-->SCP --LPI--> 功耗输出器件
SCP和AP共同完成电源和时钟管理架构

6)ATF安全固件基础
1)ARM推出的安全启动项目,ARMv8架构中ARM提供的ARM可信固件称为ATF,注意ATF不是bootloader!
2)Bootloader、Linux内核、TEE OS的启动都由ATF来加载和引导以及验签
3)ATF启动过程中的各个阶段流程

两个概念:restart--冷启动、reset--热启动
ATF冷启动实现分为5个步骤:
• BL1 - AP Trusted ROM,一般为BootRom。
• BL2 - Trusted Boot Firmware,一般为Trusted Bootloader。
• BL31 - EL3 Runtime Firmware,一般为SML,管理SMC执行处理和中断,运行在secure monitor中。
• BL32 - Secure-EL1 Payload,一般为TEE OS Image。
• BL33 - Non-Trusted Firmware,一般为uboot、linux kernel。
ATF输出BL1、BL2、BL31,提供BL32和BL33接口。
4)Linux 内核如何与 ATF 通信?
---->通过 SMC指令实现
5)ATF常驻内存?
---->BL31部分会常驻内存,作为一个后台的可信复位,等待Linux内核的请求;
6)ATF与电源管理的关系?
---->由于重启、关机、待机属于比较重要的特性,现代架构都在ATF进行电源处理,以保证系统安全;
---->如果硬件带有SCP,则ATF最终移交给SCP处理;否则直接在ATF中设置寄存器处理;
7)厂商的ATF情况 - RK3399
现在芯片级的休眠唤醒操作主要放在ATF中,但厂商一般闭源,比如RK

7)ARM-SCP
1、SCP官方定义的概念

1)PCSA 定义了系统控制处理器 (SCP) 的概念,一般是一个硬件模块,例如cortex-M4微处理器再加上一些外围逻辑电路做成的功耗控制单元(简单说就一个内置的MCU)。SCP用于从应用程序处理器中抽象出电源和系统管理任务,配合操作系统的功耗管理软件或驱动,来完成顶层的功耗控制。
2)基础概念
1、SCP - System control processor,就是一个集成在SOC上的专用于电源管理的MCU;
2)Agent : Agent就是SOC上的其它模块(CPU/NPU/GPU 和外设等等),他们可以单独向SCP请求功耗控制需求;
3)AP : 其中最大Agent当然是CPU(Linux/Windows/MAC),称为AP,AP与SCP的交互最多(包括上电初始化、运行时控制等)
4)OSPM : 指的是OS系统中PM功能
2、SCP相关的软件交互
- AP软件是SCP服务的请求者。
- 系统中的其他Agent也可以请求SCP的服务。代理例如一个modem子系统,或者其他的硬件模块。
- SCP基于处理器,有自己的固件 ,控制自己的一组硬件资源,例如本地私有内存、计时器、中断控制以及系统配置、控制和状态的寄存器。
- 最底层是SCP控制的硬件资源,例如时钟源、电源域门控、电压电压和传感器等
3、SCP提供的服务
1、系统初始化:SCP负责通电复位系统初始化任务,从主系统和AP核心电源域的通电顺序到AP启动。
2、OSPM定向操作:SCP在OSPM指导下执行电压供应变化、电源控制操作和时钟源管理。这些服务也可以被其他请求的Agent使用。
3、对系统事件的响应:中断唤醒事件、计时器事件、调试访问电源控制;
4、看门狗事件和系统恢复操作:在本地看门狗超时时,SCP可以执行一个重置和重新初始化序列。
5、系统感知能力:SCP可以协调来自OSPM和其他代理对共享资源的请求。例如,它可以控制到主存的路径,或进入SoC睡眠模式和退出,而不需要AP核心活动。
SCP提供的服务是根据硬件和软件的能力而定,上面是规范中罗列的功能(大而全),实际SOC芯片方案根据厂商的设计而定
4、SCP的地位
由于其是一个独立 的硬件模块和固件,其内部资源例如内存、外设不能够被外界控制,另外其还能控制外界的一些公共资源,SCP具有较高的权限。配合安全引导过程,SCP可以成为一个可信软件模块。
SOC中除了SCP处理器外,还有一些其他的可管理性控制处理器 (MCP),其他MCP的实现固件框架跟SCP类似,目的是为需要可管理性的片上系统 (SoC) 提供管理入口点。
5、运行在SCP的软件
1、SCP的官方固件实现: https://github.com/ARM-software/SCP-firmware
2、官方实现功能很强大,厂商可以参考其设计,但实际上,厂商会裁剪,大大简化SCP功能
3、主要流程:
1)上电时:系统负责将SCP固件加载到SCP内部ram,并跳转执行,之后循环等待AP发送指令;
2)运行时:主要runtime应用代码(一个main循环),提供scp各种服务,例如scmi。
3)复位时:当硬件发生复位时;
6、小结
SCP在SOC中就是一个内置的MCU,可以运行裸机程序或者上RTOS;
值得关注的使用Mailbox与其他模块通信,管控着ARM内部模块的电源开关(也就是写寄存器);
8)SCP与AP的通信
1、总体框架

1、用户层:首先用户发起的一些操作,通过用户空间的各service处理,会经过内核提供的sysfs,操作cpu hotplug、device pm、EAS、IPA等。
2、内核层:在linux内核中,EAS(energy aware scheduling)通过感知到当前的负载及相应的功耗,经过cpu idle、cpu dvfs及调度选择idle等级、cpu频率及大核或者小核上运行。IPA(intelligent power allocation)经过与EAS的交互,做热相关的管理。
3、ATF层:Linux kernel中发起的操作,会经过电源状态协调接口(Power State Coordination Interface,简称PSCI),由操作系统无关的framework(ARM Trusted Firmware,简称ATF)做相关的处理后,通过系统控制与管理接口(System Control and Management Interface,简称SCMI),向系统控制处理器(system control processor,简称SCP)发起低功耗操作。
4、SCP层:SCP(系统控制处理器system control processor)最终会控制芯片上的sensor、clock、power domain、及板级的pmic做低功耗相关的处理。
整体流程:用户进程 --sysfs--> 内核(EAS、IPA)--PSCI--> ATF --SCMI-->SCP --> PMIC
2、PSCI协议介绍
1、PSCI协议官方地址:
https://developer.arm.com/documentation/den0022/d/
《Power_State_Coordination_Interface_PDD_v1_1_DEN0022D》
2、PSCI与ATF:https://kernel.meizu.com/2025/04/10/Linux SMP启动罗曼史(下):PSCI的安全唤醒与TrustZone的密室协约/
3、PSCI架构:https://www.cnblogs.com/LoyenWang/p/11370557.html
4、PSCI定义了一个电源管理的标准接口,操作系统供应商可用于在ARM设备上使用不同特权级别的监控软件。该接口旨在在以下电源管理场景中代码通用化,说白了就是设计一个中间层,保证上层稳定,PSCI接口比较固定不复杂,规范命令集如下
1)在规范的表6-2:分配给不同服务的功能标识符的子范围中,

2)表中的各种功能就是走安全通道的,不是SMC(切换安全世界)或者HVC(切换虚拟化) 命令的功能就是非安全通道的,当然也可以根据自己的需求选择,一般PSCI协议中的功能都是走安全通道。
5、psci的实现
1.psci_1_0_init
/android/vendor/amlogic/common/kernel/common_5.4/drivers/firmware/psci/psci.c
int __init psci_1_0_init(struct device_node *np)
--psci_0_2_init()
----psci_probe()
------psci_0_2_set_functions(); //设置各种回调函数
------psci_init_smccc();
------psci_init_cpu_suspend();
------psci_init_system_suspend(); //注册suspend接口给PM core
------psci_init_system_reset2();
2.注册suspend接口给PM core使用
__init psci_init_system_suspend(void)
/android/vendor/amlogic/common/kernel/common_5.4/kernel/power/suspend.c
--suspend_set_ops(&psci_suspend_ops);
/android/vendor/amlogic/common/kernel/common_5.4/include/linux/suspend.h
struct platform_suspend_ops {
int (*valid)(suspend_state_t state);
int (*begin)(suspend_state_t state);
int (*prepare)(suspend_state_t state);
int (*enter)(suspend_state_t state);
}
3.PSCI power off
/android/vendor/amlogic/common/kernel/common_5.4/drivers/firmware/psci/psci.c
#define PSCI_0_2_FN_BASE 0x84000000
#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8)
static void psci_sys_poweroff(void)
{
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
}
3.psci_operations
/android/vendor/amlogic/common/kernel/common_5.4/include/linux/psci.h
struct psci_operations {
u32 (*get_version)(void);
int (*cpu_suspend)();
int (*cpu_off)();
int (*cpu_on)();
int (*migrate)();
int (*affinity_info)();
}
6、数据结构

3、SCMI协议介绍
1、SCMI协议规范同样还是去ARM官网找:
《DEN0056B_System_Control_and_Management_Interface_v2_0》
2、这个协议在哪里用到,我们来看一个图:

1)Linux端是非安全世界,直接调用SCMI驱动提供过的接口;
2)BL31是安全世界,经由PSCI协议调用SCMI;
3)SCMI驱动模块源码实现
/android/vendor/amlogic/common/kernel/common_5.4/drivers/firmware/arm_scmi
3、SCMI规范中的命令消息格式

- 通道(channel)必须是分开独立的,各个agent不能使用同一个。避免platform无法识别message对应方
- agent必须是独立的操作系统
- 通道支持双向通讯,另外也能够支持中断、polling两种方式,让agent选择
从agent到platform的消息分为两种,同步和异步,为A2P通道:
- 同步(synchronous),agent返回的时候对应的platform操作就已经完成了。platform返回操作结果命令也是通过agent到platform的通道,同一个通道完成这些操作
- 异步(asynchronoous),当platform完成后,会发送 delayed response给到agent告知对方工作完成,这是P2A通道。agent发送完消息后,立马得到platform的返回,然后释放通道继续做下一次传输
4、SCMI规范中有协议包的说明
1)比如Protocol identifiers

5、SCMI协议的整体应用框图

scmi transport,channel,agent的对应关系:
1)一个scp可以有多个agent, agent是运行在操作系统,安全固件的软件或者一个使用scmi协议的设备。
2)transport定义了scmi协议如何传输。比如shared memory。一个agent可以有多个A2P或P2A channel,channel是双向的,但是协议发起者(主)-接收者(从)关系是固定的。故若要使能通知功能,除了一个A2P channel外,还需要一个P2A channel分配给这个agent。
6、传输层
传输层文档也就定义了一种方式,mailbox 方式(核间通讯的一种ip)。这种通讯的前提是系统能够在agents和platform之间存在共享内存 (ddr和片上flash都行,最好是片上flash)。mailebox能够完美支持前面提到的通道的需求,中断、内存和完成中断等都能够,而且是软件可操控。比如下面流程指出的中断和polling方式:

4、Mailbox框架
1)Mailbox原理及内核驱动架构:https://blog.csdn.net/qq_41483419/article/details/129520679
2)Mailbox是核间通信软硬件的统称,是一种框架,具体用哪一类软件协议或硬件模块 视乎厂商设计,不要混淆概念
1、Mailbox常见的硬件模块PL320或者MHU - 通常直接叫mailbox
2、软件协议使用SCMI协议(方便不同系统通信而协定的标准格式)+共享内存报文头 - 通常也叫mailbox消息
3)核间Mailbox通信模型

ARM核和DSP核进行mailbox通信,ARM要发送数据给DSP流程如下:
1、ARM核先往某个指定的共享内存空间buffer写入数据,然后MAILBOX触发中断和写入关于共享内存空间的地址信息给DSP。
2、DSP通过得到mailbox中断的信息读取共享内存空间ARM核发送的buffer数据。
3、DSP核读取完数据后将触发mailbox中断给ARM作为回应,告诉ARM核你发送的数据我已经接受完成了。
buffer需要是共享内存,ARM核和DSP核都能访问到的空间
如何点对点通信?Mailbox使用通道通信,一般来说AP和SCP要提前约定好通信的通道,
在大多数嵌入式系统中都使用静态配置,在芯片设计阶段,mailbox的每个通道已固定分配给特定通信方向或数据类型,共享内存布局也是预先定义的:
Agent scmi消息处理流程
下面是一个protocol_id为0x11 的power domain 控制消息为例子(SCP运行的是官方固件)

5、arm-scmi和mailbox核间通信
1、以reset操作为例

1)重点关注Linux framework调用reset driver到SCP的过程;
2、reset-scmi如何和arm-scmi挂接?
涉及的源码
1)reset driver
/android/vendor/amlogic/common/kernel/common_5.4/drivers/reset/core.c
/android/vendor/amlogic/common/kernel/common_5.4/drivers/reset/reset-scmi.c
/android/vendor/amlogic/common/kernel/common_5.4/drivers/reset/reset-meson.c
2)scmi driver
/android/vendor/amlogic/common/kernel/common_5.4/drivers/firmware/arm_scmi/reset.c
1) scmi_handle -- pointer to the SCMI device
/android/common-5.15/common/include/linux/scmi_protocol.h
struct scmi_handle {
void (*devm_protocol_get)(struct scmi_device *sdev, u8 proto, struct scmi_protocol_handle **ph);
void (*devm_protocol_put)(struct scmi_device *sdev, u8 proto);
const struct scmi_notify_ops *notify_ops;
};
2)scmi_reset_init 将reset接口注册到bus总线上
/android/vendor/amlogic/common/kernel/common_5.4/drivers/firmware/arm_scmi/reset.c
scmi_reset_init
--scmi_protocol_register(SCMI_PROTOCOL_RESET, &scmi_reset_protocol_init); //SCMI_PROTOCOL_RESET = 0x16,
----handle->reset_ops = &reset_ops;
static struct scmi_reset_ops reset_ops = {
.reset = scmi_reset_domain_reset,
};
3)当reset driver发现设备时,bus调用probe 连接reset driver和scmi driver
/android/vendor/amlogic/common/kernel/common_5.4/drivers/firmware/arm_scmi/bus.c
scmi_dev_probe()
--scmi_protocol_init(scmi_dev->protocol_id, scmi_dev->handle);
--scmi_drv->probe(scmi_dev);
/android/vendor/amlogic/common/kernel/common_5.4/drivers/reset/reset-scmi.c
----scmi_reset_probe(scmi_dev)
----data->handle = sdev->handle; //将scmi的接口挂接给reset子系统
protocol标识reset操作类
/android/vendor/amlogic/common/kernel/common_5.4/drivers/reset/reset-scmi.c
static const struct scmi_device_id scmi_id_table[] = {
{ SCMI_PROTOCOL_RESET },
{ },
};
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
3、reset driver到SCP过程
1.上层会调用reset driver的reset成员
static const struct reset_control_ops scmi_reset_ops = {
.assert = scmi_reset_assert,
.deassert = scmi_reset_deassert,
.reset = scmi_reset_reset,
};
2.
scmi_reset_reset()
--scmi_handle *handle = to_scmi_handle(rcdev);
--handle->reset_ops->reset(handle, id);
/android/vendor/amlogic/common/kernel/common_5.4/drivers/firmware/arm_scmi/reset.c
----scmi_reset_domain_reset(hanle, domaiin)
------scmi_domain_reset(handle, domain)
--------scmi_do_xfer(handle, t); //通过mailbox发送给SCP处理
/android/vendor/amlogic/common/kernel/common_5.4/drivers/mailbox/mailbox.c
----------mbox_send_message(cinfo->chan, xfer);
9)PMIC/PMU
1、概述
1)PMIC (Power management integrated circuit) ,即电源管理芯片,一般情况下是一颗独立于主控的芯片,集成了电源控制、电源键控制(唤醒)、充电控制等模块;注意不同的电源芯片功能差异大,根据当前产品场景选取合适的型号,常见的有 RK818 / fan53555芯片;
2)PMU一般指X86/MAC架构的电源管理芯片;
4)CPU能集成PMIC?PMIC一般是大功率专用器件,因此不太能集成到CPU内部,电源供电是专一的芯片领域!
5)不同产品的电源控制策略差异大,注意方案的区别!
1、电池场景-比如手机平板,有复杂的电源管控;
2、220V供电场景-比如TV,外部可以只用一个MOS管控制电源关闭/打开;
2、PMIC驱动框架regulator
1)常见芯片 RK818 / fan53555 复杂电源管理芯片(用于带电池的产品场景,手机,平板,TV没有用到)
2)系统中各路电源总体分为两种:DCDC 和 LDO;
3)RK818电源芯片
从使用者的角度看,RK818 的功能概况起来可以分为 4 个部分:
RK818 是一款高性能 PMIC,可以同时输出DCDC/LDO
1、regulator 功能:控制各路 DCDC、LDO 电源状态;
2、rtc 功能:提供时钟计时、定时等功能;
3、clk 功能:有两个32.768KHZ时钟输出,一个不可以控常开,一个是软件可控。
4、充电功能和电量计功能,
4)regulator框架
1.regulator框架
/android/vendor/amlogic/common/kernel/common_5.4/drivers/regulator/core.c
/android/vendor/amlogic/common/kernel/common_5.4/drivers/regulator/of_regulator.c
/android/vendor/amlogic/common/kernel/common_5.4/drivers/regulator/devres.c
2.设备驱动 - 电源芯片驱动
/android/vendor/amlogic/common/kernel/common_5.4/drivers/regulator/pwm-regulator.c
3.设备树节点
vdd_center: vdd-center {
compatible = "pwm-regulator";
rockchip,pwm_id = <2>;
rockchip,pwm_voltage = <900000>;
pwms = <&pwm2 0 25000 1>;
regulator-name = "vdd_center";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1400000>;
regulator-always-on;
regulator-boot-on;
}
4.
static int __init regulator_init(void){
class_register(®ulator_class);
debugfs_create_dir("regulator", NULL);
}