devfreq 内核框架介绍

 

目录

 

一 应用背景

二 软件框架介绍

三 API和用户接口

3.1 device注册接口介绍

3.2 governor使用接口介绍

3.2.1 governor注册接口

3.2.2  governor调频接口

3.2.3 monitor机制接口

3.3 用户层接口

四 编程模板

4.1 dts配置

4.1.1 定义工作性能表:

4.1.2 引用工作性能表:

4.2 底层driver实现

4.2.1 底层driver需要实现的回调函数

4.2.2 probe时注册devfreq框架

4.3 governor的注册

4.3.1 governor需要实现的回调函数

4.3.2 governor向devfreq的注册

五 框架分析

5.1 devfreq框架初始化

5.2 对device的管理


一 应用背景

对于可以调频的设备,我们可以通过在不同场景和需求下调节设备的频率,可以达到节省功耗的目的。CPU有单独的cpufreq框架来控制和管理其频率,但是不兼容普通的设备。对于普通设备,我们可以通过devfreq 框架来方便地实现调频操作。

二 软件框架介绍

devfreq框架存在的意义,是为了将调频逻辑的公共部分,比如数据结构,调频方法等抽象出来,减少重复代码的产生,方便驱动工程师实现设备的调频操作。

我们这里将有调频需求的设备称为device_freq,以便后续的讨论。有了devfreq框架,驱动工程师只需要按照devfreq框架提供的函数原型,实现具体设备的具体调频操作,同时选取合适的governor,并将device_freq和底层调频方法一同注册进devfreq框架,就能够实现调频。

这里的governor ,其实指的是不同的调频策略。所谓的调频策略,包括什么时候对设备进行调频,以及将设备的频率调整到多大。不同的设备,有不同的调频策略,因此devfreq将设备的调频策略抽象出来,以供设备选择。具体的设备也可以根据自己的需求,实现自己的governor,并注册进devfreq框架。以内核提供的最简单的userspace_governor为例 ,其调频策略就很简单——调频的时机是当用户通过给定的文件节点输入目标频率F时,就执行调频操作;且将设备的频率调整为F。

以上提到的两个概念,device_freq和 governor,是devfreq框架的两个核心主题,这里做一个总结:

1. device_freq,是需要调频的设备,需要通过devfreq框架提供的接口进行注册;

2. governor,是具体的调频策略,也需要通过devfreq框架提供的接口进行注册;governor可由用户自己实现,也可以选用内核已有的governor。

整体上,devfreq的软件框架如下所示:

上图中,devfreq框架内部维护了两个链表,一个链表Governor_list是用于管理系统中所有注册进来的governor,还有一个devfreq_list 是用于管理系统中所有的可调频的设备device_freq。

一个拥有opp_table的可调频设备,需要实现自己的调频函数(图中的xxx_devfreq_profile),再通过devfreq提供的接口(devm_devfreq_add_device)来注册进devfreq框架。在注册时,device_freq会指定自己的governor,devfreq框架负责将device_freq和governor进行匹配 。

用户可以实现自己的governor,并通过接口(devfreq_add_governor)注册进devfreq框架。

三 API和用户接口

3.1 device注册接口介绍

device_freq通过接口devm_devfreq_add_device注册进devfreq框架:该接口的定义如下所示:

struct devfreq *devm_devfreq_add_device(struct device *dev,
                    struct devfreq_dev_profile *profile,
                    const char *governor_name,
                    void *data);

设备在调用该函数时,device_freq需要传递四个参数:

1. @dev:设备的device结构体

2. @governor_name:调频设备必须指定一个governor,因为没有governor就无法实现调频。device_freq注册时,devfreq框架会根据该字段自动寻找匹配的governor ,将二者关联。

3. @data:该字段用于governor和device_freq之间传递信息,由用户自己定义,框架并不关心这个数据。

4. @profile: 该profile是一个结构体,类似于去银行注册银行卡时填写的信息表,定义如下(讲解见注释):

struct devfreq_dev_profile {
    /* 在注册时,设备初始的工作频率,必须 */
    unsigned long initial_freq;
    /* 
     * 当governor启动monitor机制时,monitor会每隔一定的时间更新设备的频率,这个位段就指定了该            
     * 时间间隔。当该值为0时,表示不启用monitor机制。
     */
    unsigned int polling_ms;
    /* 底层设备的调频函数,设备必须自己实现该函数,并在注册时通过该结构体提供给框架 */
    int (*target)(struct device *dev, unsigned long *freq, u32 flags);
    /* 该函数目前很少被用到,可以不实现 */
    int (*get_dev_status)(struct device *dev,
            ¦   ¦ struct devfreq_dev_status *stat);
    /* 底层设备的获取当前设备频率的函数,设备必须自己实现该函数,并提供给框架 */
    int (*get_cur_freq)(struct device *dev, unsigned long *freq);
    /* 可选的退出函数,当devfreq设备发生错误时,框架会回调该函数。一般不需要实现。 */
    void (*exit)(struct device *dev);
    /* 
     * 设备支持的频点表。如果已经在dts中引用了opp_table,并通过dev_pm_opp_of_add_table 
     * 关联到opp_table,以下两个字段会由devfreq自动填入。
     */
    unsigned long *freq_table;
    /* 该设备最多支持的频点数 */
    unsigned int max_state;
};

 可见,该profile结构体包含了device_freq设备在注册进devfreq框架时需要填写的所有信息,其中必须提供的信息包括:

  • 初始频率initial_freq;
  • 设备调频函数target 
  • 设备当前频率的获取函数get_cur_freq

另外,devfreq框架需要知道设备支持的所有频点。因此可以在profile中将freq_table和max_state填写,注册的时候由devfreq框架读取;但是更加规范的方法是在dts中引用一个opp_table,然后在设备注册进devfreq框架前,调用dev_pm_opp_of_add_table将设备和opp_table相关联;这样,devfreq框架会自动读取设备的opp_table,将信息整合,代替freq_table和 max_state字段。

3.2 governor使用接口介绍

3.2.1 governor注册接口

governor的注册接口比较简单:

int devfreq_add_governor(struct devfreq_governor *governor);

这里,重点关注传参类型struct devfreq_governor:

struct devfreq_governor {
    struct list_head node;

    const char name[DEVFREQ_NAME_LEN];
    const unsigned int immutable;
    int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
    int (*event_handler)(struct devfreq *devfreq,
                unsigned int event, void *data);
};

governor结构体由以下几个部分组成:

  1. 节点node,用于加入全局链表governor_list
  2. governor的名字,用于在device注册进来时进行匹配
  3. immutable 标志位,当置为1时,表示使用该governor的设备不可以动态更换其他的governor
  4. get_target_freq回调函数&
  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值