• Linux 3.8.1 电源管理之OMAP Voltage Domain分析


    本系列文章将分析Linux对于OMAP的电源管理功能,以AM33XX作为实例(目前的硬件平台先主要关注AM335xStarterKit开发板),在必要时穿插其他相关内容。

    在linux-3.8.1/arch/arm/mach-omap2/board-generic.c中有如下定义(分析某个开发板的内核,自然从board file的machine desc开始):

    其中与比较关键的电源管理相关的代码是am33xx_init_early()函数。该函数在linux-3.8.1/arch/arm/mach-omap2/io.c中。



    下面我们从am33xx_voltagedomains_init(),am33xx_powerdomains_init(),am33xx_clockdomains_init()等几个函数分析。

    下面的文档定义了什么是Voltage Domain【参考TI的PRCM文档SPRUFA5】。

    根据这个定义,我们可以得出Voltage Domain的功能包括下面几项:

    • 一个Voltage Domain由一个Voltage Regulator供电
    • 有一个独立的可控开关
    • 不同Voltage Domain可以有不同电压
    • Voltage Domain的电压可以Scale ,可以基于普通DVFS,或者OPP,当然也可固定
    • 当选定某个电压后,还可用类似SmartReflex的技术微调(软件透明,也可不透明)
    • 可以完全关闭
    • 可以支持唤醒(wake-up)
    • 一个Voltage Domain可以有多个Power Domain

    因此,如果要自己设计一个Voltage Domain的结构,可以考虑在其中支持一个voltage_control()的接口,参数可以是0到最大OPP电压,而全范围的OPP可以作为该结构的附加数据提供。不过我们还是先来看Linux的实现如何。

    首先是am33xx_voltagedomains_init()的Voltage Domain初始化,在内核的linux-3.8.1/arch/arm/mach-omap2/voltagedomains33xx_data.c。

    这里将MPU和CORE分成单独的Voltage Domain。但是实际上,根据《AM335x ARM® Cortex™-A8 Microprocessors (MPUs)》文档在"Power-Up Sequencing"一节中描述,应该可以合并这两个Voltage Domain。

    {

    When using the ZCZ package option, VDD_MPU and VDD_CORE power inputs may be powered from the same source if the application only uses operating performance points (OPPs) that define a common power supply voltage for VDD_MPU and VDD_CORE. The ZCE package option has the VDD_MPU domain merged with the VDD_CORE domain.

    }

    每个Voltage Domain由一个struct voltagedomain来表示。

    注意,尽管TPS65910的文档上说明了该PMIC支持8个可编程的LDO,且在AM335xStarterKit开发板上的确通过AM335X_I2C0链接了这个PMIC的I2C,但是由于这些LDO连接的都是些常规I/O,限定了要求的电压范围(不可使用DVFS这样的方式来类似调整Voltage Domain的电压一样来调整输出电压),因此这里不把这些LDO看做独立的Voltage Domain。但是,实际上如果这些对应的模块不需要的话,应该还是可以在初始化时将其LDO电源关掉。

    再注意到,TPS65910的文档上说明了该PMIC支持通过SmartReflex接口(实际上是独立的I2C接口)来控制Processor Core的Power。但是实际的AM335xStarterKit开发板上却没有连接这个SmartReflex接口。有一点需要注意,TPS65910实现的是SmartReflex Class-3,而AM335x实现的是SmartReflex Class-2B。下面的文字来自TPS65910文档。

    关于SmartReflex的支持,可以参考这个GitHub的patch,但是这是针对AM335X EVM或者BeagleBone开发板的。在AM3359 - TMDXIDK3359开发板中,SmartReflex的I2C接口是接上的。

    https://github.com/Angstrom-distribution/meta-ti/blob/master/recipes-kernel/linux/linux-am335x-3.2.0-psp04.06.00.08/0001-am33xx-Add-SmartReflex-support.patch

    实际上,在TPS65910的文档中还说明了这个PMIC的SmartReflex寄存器是可以通过Control I2C和SmartReflex I2C访问的,但是需要通过Control I2C先配置其DEVCTRL_REG寄存器的SR_CTL_I2C_SEL位来选择。

    下面简单分析对struct voltagedomain的管理。

    首先是平台初始化代码通过voltdm_init()来把自己支持的Voltage Domain注册到系统中,实际上这是通过调用_voltdm_register()来实现的,并且是将这个struct voltagedomain加入到一个全局的voltdm_list中。从而,也就可以对这个voltdm_list进行查找,所以又有voltdm_lookup()函数。

    另外,为了方便起见,还提供一个voltdm_for_each()函数,通过扫描这个voltdm_list,每当发现一个Voltage Domain,就调用指定的函数指针,从而可以实现对所有的Voltage Domain都执行某种操作的功能。由于每个Voltage Domain可以有多个Power Domain,因此voltdm_add_pwrdm()就被用来向一个Voltage Domain添加一个Power Domain(将这些Power Domain连接到这个Voltage Domain的pwrdm_list中)。类似的,还提供了一个voltdm_for_each_pwrdm()来对一个Voltage Domain的所有Power Domain执行指定的操作函数。

    对于每个Voltage Domain,由于可以有不同的Scale的方法(比如可以使用Voltage Controller,也可以用Voltage Processor来实现),因此提供omap_change_voltscale_method()来改变相应的Scale方法。其实这一点,如果为了通用起见,应该让平台代码直接实现Scale方法就行了,也就是可以直接用xxx_set_scale_method()就可以。

    omap_voltage_register_pmic()被用来设置struct voltagedomain的pmic字段。omap_voltage_get_voltdata()用来返回对应电压的相关数据(这里使用voltage table实现),即OPP数据。omap_voltage_get_volttable()就是用来返回这个voltage table的。voltdm_reset()将这个Voltage Domain的电压设置为当前OPP,实际调用的是voltdm_scale()实现的。voltdm_scale()就是用来实现Voltage Scale功能的,根据参数指定电压,在该Voltage Domain自己的voltage table中找到一项恰好大于该指定电压的"标称电压",用来设置对应的Regulator。voltdm_get_voltage()用来获得该Voltage Domain的当前标称电压nominal_volt。

  • 相关阅读:
    Spring Boot整合JPA
    Emmet Cheat Sheet All In One
    CCTV《航拍中国》系列视频 All In One
    上海市税务局服务 All In One
    CCTV 天气预报 All In One
    Next.js Tutorials All In One
    如何使用 GitHub Actions 发布 Gatsby 静态网站 All In One
    GitHub Code Security & Code Scanning All In One
    数字滚动显示组件 All In One
    Gatsby plugins All In One
  • 原文地址:https://www.cnblogs.com/coryxie/p/2951717.html
Copyright © 2020-2023  润新知