PMIC驱动开发指导手册
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
1.0 | 02/18/2023 | |
1.1 | 04/21/2025 |
1. 概述¶
PCUPID 开发板默认采用IDAC控制电源,而PCUPID SSZ001A/SSZ001C单板则是采用PMIC控制电源。PCUPID SSZ001A/SSZ001C单板使用的PMIC为laiyuan ICP1301。客户若是需要用其他的PMIC代替,软件上就需要适配新的PMIC。本文就替换新的PMIC后,软硬件层面上需要做哪些工作做进行一些说明。这些工作大致可以分为以下这些:
- 确保PMIC满足硬件方面的需求,整理好PMIC供电管脚和SOC 管脚之间的连接关系
- 基于Linux regulator框架开发PMIC的电源管理控制驱动
- 基于Linux rtc框架开发PMIC的RTC驱动
- 适配系统poweroff和STR过程中涉及的电源控制
2. 关键字说明¶
-
PMIC
电源管理IC(Power Management IC),是一种特定用途的集成电路,其功能是为主系统管理电源等工作。
-
IDAC
DAC一般是指输出电压型DAC,IDAC顾名思义输出是电流型DAC。
-
Linux regulator framework
Linux Regulator Framework 设计出主要是提供一个标准的内核接口来控制电压和电流调节器。目的是允许系统动态控制 regulator power 输出以节省能源延长电池寿命。
-
Linux RTC framework
Linux RTC(Real-Time Clock)框架是内核用于管理实时时钟硬件的统一接口。
3. PMIC硬件方面的要求¶
硬件方面由诸多要求,这里无法一一陈述,我们以下图来讲解几个要点,这是后续软件开发的关键。
上图是PCUPID SSZ001C单板PMIC和SOC的线路连接图。需要注意的地方就是上面红色圈圈对应的线路,我们按照序号顺序来说明一下:
- SOC和PMIC是通过I2C通信
- 需要搞清楚SOC的硬件核心硬件IP是由PMIC的那个管脚供电的,特别是CPU_Power和CORE_power
- 系统进入STR状态的时候,DDR是需要供电的,所以要确保DDR供电的管脚在STR时候依然有电
- 有些PMIC的单板,通过SOC上的某根管脚的电平是高是低来判断系统现在处于冷启动还是resume流程,如果是这样的单板,需要特别注意PMIC上这根管脚的选择,同时接到SOC指定的GPIO上。
4. 基于Linux regulator框架开发PMIC的电源管理控制驱动¶
4.1 PCUPID 电压调控框架¶
在基于Linux regulator框架开发PMIC regulator驱动前,让我们先了解一下目前PCUPID 内核系统的电压调节框架,了解上层是进行CPU调压的时候是如何一步步调到PMIC regulator的驱动代码函数的。整体框架下图所示:
4.1.1 使用层¶
Cpufrequency驱动,该驱动接收上层的指令,根据CPU要运行的频率,动态调节CPU电压。
用户可以通过以下命令,调整CPU频率,从而测量CPU电压是否发生改变:
echo powersave > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq
4.1.2 PMIC控制层¶
本层主要实现以下几个功能:
(1) 实现以下两个接口,使得上层可以通过这两个接口那个获得和调整CPU电压
int set_core_voltage(const char *name, VOLTAGE_DEMANDER_E demander, u32 mV) int get_core_vlotage(const char *name , u32 *mV)
(2) 提供设备节点/dev/sstar_pmic,使得用户层可以通过IOCTL命令调控CPU电压
(3) 提供debugfs节点/sys/kernel/debug/sstar_pmic用于用户层设置和查看电压
4.1.3 PMIC驱动¶
本层主要实现以下几个功能:
(1) 根据DTS中的IDAC或者PMIC节点信息注册regulator
(2) 实现regulator中调用的regulator_ops。例如:
struct regulator_ops ICP1301_regulator_ops{ .set_voltage = icp1301_set_voltage, .get_voltage = icp1301_get_voltage, .enable = icp1301_enable, .disable = icp1301_disable }
regulator_ops实现后,上层根据需求选择要调节电路对应的regultor,利用以下接口就可以对电路进行控制
int regulator_get(dev, name); //根据电路名称获取到regulator int regulator_set_volatage(regulator, min_uV, max_uV); //调整电压 int regulator_get_voltage(regulator); //获取电压 int regulator_put(regulator); //释放regulator
4.1.4 传输/控制层¶
SOC一般通过GPIO控制IDAC,通过IIC控制PMIC硬件,对应PMIC而言,本层要实现以下功能:
(1) 实现和向上提供系统和PMIC通信的IIC接口
4.2 PMIC的regulator驱动开发和适配¶
从上个章节的内容,我们知道这部分驱动对应的是下图中红色框框框起来的部分:
4.2.1 开发PMIC 电压控制驱动¶
这部分的实现不同的PMIC在细节方面是不同的,一般PMIC厂商会提供相应的模板代码,如果没有相应的模板代码,就需要用户根据PMIC数据手册自己来实现对应的功能了。不管是采用PMIC厂商提供的模板代码还是用户自己编写的代码,在适配的时候有几点要求需要实现:
- SOC和PMIC之间最好通过I2C来通信,相应的控制代码建议注册成为一个I2C驱动,同时export出相应的读写接口,方便PMIC的regulator驱动和RTC驱动调用
- 需要基于Linux regulator框架来实现,控制cpu电压的regulator的注册名称需要是“cpu_power”
- 驱动需要有对应的.suspend()和.resume函数,用来系统在进入和退出STR状态前后配置PMIC
- PMIC硬件相关的信息最好都记录在DTS中。
代码的层面的实现和PMIC本身密切相关,无法从细节上给予更多的说明,建议用户参考SDK中icp1301目录下的代码和dts中icp1301相关的节点描述。
4.2.2 代码植入位置和新增kernel config¶
(1) 代码存放路径
目前PCUPID单板使用的PMIC驱动代码放在kernel/drivers/sstar/pmic/icp1301目录下,所以建 议用户在kernel/driver/sstar/pmic下创建一个新的目录,用来存储相应的代码
目录:kernel/drivers/sstar/pmic/
|---->pmic\ | ----> Makefile\ | ----> Kconfig\ | ----> pmic.c | ---->icp1301\ | -----> icp1301_regulator.c | ----->icp1301_core.c | ----->icp1301_rtc.c | ----->icp1301.h | ----->NewPMIC\ | -----> NewPMIC_regulator.c | -----> NewPMIC_core.c | -----> NewPMIC.h
(2) 新增kernel config
在kernel/drivers/sstar/pmic/目录下有一个Kconfig文件,用户在增加了PMIC相关的驱动代码后,需要新增一个kernel config,内容可以借鉴SSTAR_PMIC_ICP1301。
在增加完kernel config后,还要修改一下kernel/drivers/sstar/pmic/Makefile的内容,增添一条obj-$(CONFIG_SSTAR_PMIC_XXXX0 += xxxx/
4.2.3 自测¶
用户开发完PMIC的regulator驱动后,可以通过下面的命令进行一下自测
a. 调节电压命令
命令格式:echo name value N > /sys/kernel/devugs/sstar_pmic 参数说明:input: [name] [voltage] [demander] name : cpu_power/core_power/ voltage: unit mv demander: 0 - VOLTAGE_DEMANDER_INIT 1 - VOLTAGE_DEMANDER_CPUFREQ 2 - VOLTAGE_DEMANDER_TEMPERATURE 3 - VOLTAGE_DEMANDER_USER
b .查看电压命令
命令格式:cat /sys/kernel/debug/sstar_pmic
5. PMIC RTC驱动开发和适配¶
5.1 PMC RTC驱动开发¶
PMIC RTC驱动的框架建议符合kernel RTC子系统的要求,这样可以很容易接入到现有的kernel系统中。在适配的时候有几点要求需要实现:
- 需要能够获取和设置PMIC RTC的硬件时间和闹钟时间,并分别对接到kernel RTC子系统的定义的rtc_class_ops中的“.read_time”、“.set_time”、“.read_alarm”、“.set_alarm”。
- 将第一步对接后的rtc_class_ops,通过接口的devm_rtc_device_register进行注册。
- 当有STR需求的时候,还需要对接“suspend”、“resume”的回调。
- 当用PMIC厂商的RTC驱动替代SSTAR的RTC,需要将SSTAR RTC相关的config关闭。
细节部分不同PMIC不同,整体方案可以参考kernel/drivers/sstar/pmic/icp1301/icp1301_core.c文件。
5.2 PMIC RTC驱动自测¶
(1) 读取时间
date
(2) 设置系统时间
date -s “2024-08-21 22:18:00” date
(3) 更新硬件时间到系统时间
hwclock -s # Set system time from hardware clock date
(4) 更新系统时间到硬件时间
hwclock –w # Set hardware clock from system time hwclock -r # Show hardware clock time
(5) 设置闹钟
设置RTC alarm唤醒 echo +n > /sys/class/rtc/rtc0/wakealarm //n单位为秒,表示n秒后触发rtc alarm 注意:上述命令执行后,需要等n秒后闹钟响了才能在执行,否则会有sh: write error报错 eg:STR 5秒唤醒 echo +5 > /sys/class/rtc/rtc0/wakealarm echo mem > /sys/power/state //系统需要支持STR功能
6. STR和poweroff流程适配¶
这里先介绍一些系统poweroff和STR操作时候的宏观流程:
(1)poweroff宏观流程
默认情况下,系统会将函数指针pm_power_off指向PSCI的标准下电函数psci_sys_poweroff函数,从而跳到TF-a去执行掉电的操作。
(2)STR宏观流程
如上图所示,系统执行STR操作的时候,将从kernel跳到TF-a,在TF-a中去执行设置DDR进行自刷新,以及让CPU和多数硬件掉电的操作。
6.1 TF-a中涉及PMIC的代码¶
系统执行poweroff或者进入STR的指令后,对应具体的下电和进行休眠的操作命令都是在TF-a固件中去下发给PMIC的,如下图中的两个函数,客户需要去实现的就是这两个函数,这两个函数要保证满足硬件在下电和STR状态时候的要求,这就需要具体情况具体分析了。
TF-a部分,目前TF-a的代码本公司还未开放,用户可以将PMIC执行掉电和进行休眠操作的寄存器配置表单提供给FAE,再由FAE转交给本公司软件开发人员进行开发。
6.2 PMIC regulator 驱动suspend/resume函数¶
由于客户对于PMIC不同管脚的使用很多样化,这些设置可能导致系统无法进入休眠状态,客户可以在PMIC regulator驱动的probe/suspend和resume函数中去实现这些个性化的设置。
6.3 IPL 部分¶
(1)芯片带有RTC
由于单板SOC上带有RTC,所以系统可以通过读取RTCPOC寄存器上存储的magic num来判断是冷启动还是resume。这类单板,用户无需关系IPL部分的内容。
(2)芯片不带RTC
由于单板SOC上不带RTC,所以在STR唤醒过程中是通过SOC的某根GPIO电平的高低来区分是冷启动还是resume流程。需要选择SOC上的GPIOE19这根管脚来作为这个GPIO,所以在休眠到退出STR的这段时间,PMIC要确保SOC的GPIOE19一直高电平。注意GPIOE19这根管脚在其他情况下都是低电平的。
6.4 测试用例¶
(1) Poweroff Test Case
执行poweroff 后,系统掉电 通过按PMIC的powerkey按键可以让系统重新启动
(2)STR Test Case
执行echo mem >/sys/power/state 系统进入休眠,按下PMIC的powerkey系统可以唤醒。 设置RTC alarm唤醒 echo +15 > /sys/class/rtc/rtc0/wakealarm // 15秒后触发rtc alarm echo mem > /sys/power/state //执行该命令后,15秒后系统自动唤醒
7. FAQ¶
NA