PMIC驱动开发指导手册


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 02/18/2023
    1.1
  • 重新排版
  • 04/21/2025

    1. 概述

    PCUPID 开发板默认采用IDAC控制电源,而PCUPID SSZ001A/SSZ001C单板则是采用PMIC控制电源。PCUPID SSZ001A/SSZ001C单板使用的PMIC为laiyuan ICP1301。客户若是需要用其他的PMIC代替,软件上就需要适配新的PMIC。本文就替换新的PMIC后,软硬件层面上需要做哪些工作做进行一些说明。这些工作大致可以分为以下这些:

    1. 确保PMIC满足硬件方面的需求,整理好PMIC供电管脚和SOC 管脚之间的连接关系
    2. 基于Linux regulator框架开发PMIC的电源管理控制驱动
    3. 基于Linux rtc框架开发PMIC的RTC驱动
    4. 适配系统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的线路连接图。需要注意的地方就是上面红色圈圈对应的线路,我们按照序号顺序来说明一下:

    1. SOC和PMIC是通过I2C通信
    2. 需要搞清楚SOC的硬件核心硬件IP是由PMIC的那个管脚供电的,特别是CPU_Power和CORE_power
    3. 系统进入STR状态的时候,DDR是需要供电的,所以要确保DDR供电的管脚在STR时候依然有电
    4. 有些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厂商提供的模板代码还是用户自己编写的代码,在适配的时候有几点要求需要实现:

    1. SOC和PMIC之间最好通过I2C来通信,相应的控制代码建议注册成为一个I2C驱动,同时export出相应的读写接口,方便PMIC的regulator驱动和RTC驱动调用
    2. 需要基于Linux regulator框架来实现,控制cpu电压的regulator的注册名称需要是“cpu_power”
    3. 驱动需要有对应的.suspend()和.resume函数,用来系统在进入和退出STR状态前后配置PMIC
    4. 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系统中。在适配的时候有几点要求需要实现:

    1. 需要能够获取和设置PMIC RTC的硬件时间和闹钟时间,并分别对接到kernel RTC子系统的定义的rtc_class_ops中的“.read_time”、“.set_time”、“.read_alarm”、“.set_alarm”。
    2. 将第一步对接后的rtc_class_ops,通过接口的devm_rtc_device_register进行注册。
    3. 当有STR需求的时候,还需要对接“suspend”、“resume”的回调。
    4. 当用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