0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

電源管理入門-7 DevFreq

yzcdx ? 來源:OS與AUTOSAR研究 ? 2023-10-16 17:06 ? 次閱讀

上一小節(jié)介紹了CPU的調(diào)頻,那么其他設(shè)備例如DDR、USB、SPI,還有很多子系統(tǒng)有自己的R核或者M(jìn)核例如NPU、ISP等都需要調(diào)頻,那必須OPP給安排上,然后調(diào)頻就需要我們這里說的DevFreq框架。

1. 整體介紹

1.1 Devfreq基礎(chǔ)概念

OPP:

復(fù)雜SoC由多個(gè)子模塊協(xié)同工作組成,在運(yùn)行中并非SoC中的所有模塊都需要始終保持最高性能。為方便起見,將SoC中的子模塊分組為域,從而允許某些域以較低的電壓和頻率運(yùn)行,而其他域以較高的電壓/頻率對(duì)運(yùn)行。對(duì)于這些設(shè)備支持的頻率和電壓對(duì),我們稱之為OPP(Operating Performance Point)。對(duì)于具有OPP功能的非CPU設(shè)備,本文稱之為OPP device,需要通過devfreq進(jìn)行動(dòng)態(tài)的調(diào)頻調(diào)壓。

Devfreq:

devfreq:Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework for Non-CPU Devices。是由三星電子MyungJoo Ham myungjoo.ham@samsung.com,提交到社區(qū)。原理和/deivers/cpufreq 非常近似。但是cpufreq驅(qū)動(dòng)并不允許多個(gè)設(shè)備來注冊(cè),而且也不適合不同的設(shè)備具有不同的governor。devfreq則支持多個(gè)設(shè)備,并且允許每個(gè)設(shè)備有自己對(duì)應(yīng)的governor。

如下圖,devfreq framework是功耗子系統(tǒng)的一部分,與cpufreq,cpuidle,powermanager相互配合協(xié)作,達(dá)到節(jié)省系統(tǒng)功耗的目的。

0963d5ea-6bf9-11ee-939d-92fbcf53809c.png

1.2 devfreq框圖

097fc4d0-6bf9-11ee-939d-92fbcf53809c.png整個(gè)devfreq framework中的三大部分組成:

  1. Devfreq core:devfreq framework的核心,一方面提供需要調(diào)頻調(diào)壓設(shè)備及governor的注冊(cè)方法,通過devfreq_list及governor_list分別管理所有的調(diào)頻調(diào)壓設(shè)備及注冊(cè)進(jìn)系統(tǒng)的governor。另一方面,提供具體調(diào)頻調(diào)壓的處理邏輯,通過從governor獲取目標(biāo)頻率,提供update_devfreq方法供governor調(diào)用,從而實(shí)現(xiàn)調(diào)頻調(diào)壓。
  2. Governor:具體的調(diào)頻策略,需要devfreq framework提供的接口進(jìn)行注冊(cè)。內(nèi)核中已經(jīng)支持如下策略:
  • simple_ondemand:按需調(diào)整模式;根據(jù)系統(tǒng)負(fù)載,動(dòng)態(tài)地調(diào)整頻率、電壓,平衡性能和功耗。
  • Performance:性能優(yōu)先模式,將頻率及電壓調(diào)整到最大。
  • Powersave:功耗優(yōu)先模式,將頻率及電壓調(diào)整到最小。
  • Userspace:用戶指定模式,用戶通過提供的文件節(jié)點(diǎn),根據(jù)需要設(shè)置的頻率及電壓。
  • Passive:被動(dòng)模式,使用設(shè)備指定方法做頻率、電壓調(diào)整,或跟隨父devfreq設(shè)備的governor進(jìn)行調(diào)整。
  1. Devfreq device driver:需要調(diào)頻調(diào)壓的設(shè)備驅(qū)動(dòng),需要通過devfreq framework提供的接口進(jìn)行注冊(cè)。會(huì)通過opp庫提供的dts解析函數(shù)解析opp頻率、電壓對(duì)。在調(diào)頻的時(shí)候,根據(jù)opp庫提供頻率、電壓調(diào)整接口借助clk、regulator框架進(jìn)行調(diào)頻調(diào)壓。在查詢當(dāng)前頻率時(shí),通過get_cur_freq查詢當(dāng)前的頻率。

可以看到這里DevFreq和CPUFreq的套路基本一樣。

1.3 sysfs用戶接口

這里以DDR為例:/sys/devices/platform/dmc0/devfreq/devfreq0目錄下面

099f188a-6bf9-11ee-939d-92fbcf53809c.png
  • available_frequencies: 可用的頻率列表
  • available_governors:可用的governor
  • cur_freq:當(dāng)前頻率
  • governor: 當(dāng)前governor
  • max_freq:最大頻率
  • min_freq :最小頻率
  • polling_interval:governor調(diào)度的時(shí)間間隔,單位是ms
  • target_freq:目標(biāo)頻率
  • trans_stat:狀態(tài)調(diào)整表

代碼實(shí)現(xiàn)在kernel/drivers/devfreq/devfreq.c中

static struct attribute *devfreq_attrs[] = {
        &dev_attr_governor.attr,
        &dev_attr_available_governors.attr,
        &dev_attr_cur_freq.attr,
        &dev_attr_available_frequencies.attr,
        &dev_attr_target_freq.attr,
        &dev_attr_polling_interval.attr,
        &dev_attr_min_freq.attr,
        &dev_attr_max_freq.attr,
        &dev_attr_trans_stat.attr,
        NULL,
};
ATTRIBUTE_GROUPS(devfreq);

2. Linux 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)和API實(shí)現(xiàn)

2.1 主要數(shù)據(jù)結(jié)構(gòu)

09bdfebc-6bf9-11ee-939d-92fbcf53809c.png

devfreq數(shù)據(jù)結(jié)構(gòu)和模塊關(guān)系圖

09d8ced6-6bf9-11ee-939d-92fbcf53809c.png

2.1.1 devfreq_dev_profile

devfreq profile結(jié)構(gòu)體,是OPP device注冊(cè)到devfreq framework的數(shù)據(jù)結(jié)構(gòu),主要包含OPP設(shè)備的頻率相關(guān)信息和相關(guān)的回調(diào)函數(shù),是devfreq framework和OPP device driver的交互接口。

struct devfreq_dev_profile {
    /*devfreq初始化頻率*/
    unsigned long initial_freq;
    /*governor輪詢的時(shí)間間隔,單位ms,0禁止*/
    unsigned int polling_ms;

    /*devfreq framework設(shè)置OPP device頻率的回掉函數(shù)*/int (*target)(struct device *dev, unsigned long *freq, u32 flags);
    /*devfreq framework獲取OPP device負(fù)載狀態(tài)的回掉函數(shù)*/int (*get_dev_status)(struct device *dev, struct devfreq_dev_status *stat);
    /*devfreq framework獲取OPP device當(dāng)前頻率的回掉函數(shù)*/int (*get_cur_freq)(struct device *dev, unsigned long *freq);
    /*devfreq framework退出時(shí)對(duì)OPP device的回掉函數(shù)*/void (*exit)(struct device *dev);

    /*OPP device支持的頻率表*/
    unsigned long *freq_table;
    /*freq_table表的大小*/
    unsigned int max_state;
};

初始化使用:

static struct devfreq_dev_profile xxx_devfreq_dmc_profile = {
        .polling_ms        = 300,
        .target                = xxx_dmcfreq_target,
        .get_dev_status        = xxx_dmcfreq_get_dev_status,
        .get_cur_freq        = xxx_dmcfreq_get_cur_freq,
};

2.1.2 devfreq_governor

devfreq governor結(jié)構(gòu)體,是governor注冊(cè)到devfreq framework的數(shù)據(jù)結(jié)構(gòu),主要包含governor的相關(guān)屬性和具體的函數(shù)實(shí)現(xiàn)。是devfreq framework和governor交互接口。

struct devfreq_governor {
    struct list_head node;

    /*該governor的名稱*/const char name[DEVFREQ_NAME_LEN];
    /*governor是否可以切換的標(biāo)志,若為1表示不可切換*/const unsigned int immutable;
    /*governor注冊(cè)到devfreq framework的算法實(shí)現(xiàn)函數(shù),返回調(diào)整后的頻率*/int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
    /*governor注冊(cè)到devfreq framework的event處理函數(shù),處理start,stop,suspend,resume等event*/int (*event_handler)(struct devfreq *devfreq, unsigned int event, void *data);
};

例如使用simple_ondemand

static struct devfreq_governor devfreq_simple_ondemand = {
        .name = "simple_ondemand",
        .get_target_freq = devfreq_simple_ondemand_func,
        .event_handler = devfreq_simple_ondemand_handler,
};

2.1.3 devfreq

devfreq設(shè)備結(jié)構(gòu)體,這個(gè)是devfreq設(shè)備的核心數(shù)據(jù)結(jié)構(gòu)。將上述的OPP device driver的devfreq_dev_profile和governor的devfreq_governor連接到一起,并通過設(shè)備驅(qū)動(dòng)模型中device類,為user 空間提供接口。

struct devfreq {
    struct list_head node;

    struct mutex lock;
    struct mutex event_lock;
    /*其class屬于devfreq_class,父節(jié)點(diǎn)指向使用devfreq的device*/struct device dev;
    /*OPP device注冊(cè)到devfreq framework的配置信息*/struct devfreq_dev_profile *profile;
    /*governor注冊(cè)到devfreq framework的配置信息*/const struct devfreq_governor *governor;
    /*devfreq的governor的名字*/char governor_name[DEVFREQ_NAME_LEN];
    struct notifier_block nb;
    /*負(fù)載監(jiān)控使用的delayed_work*/struct delayed_work work;

    unsigned long previous_freq;
    struct devfreq_dev_status last_status;
    /*OPP device傳遞給governor的私有數(shù)據(jù)*/void *data; /* private data for governors */

    ......
};

這個(gè)數(shù)據(jù)結(jié)構(gòu)是生成的,沒有初始化值。

2.2 devfreq初始化

三個(gè)模塊:framework、governor、device相關(guān)的初始化,其中device靠后。

09f6d944-6bf9-11ee-939d-92fbcf53809c.png0a096f78-6bf9-11ee-939d-92fbcf53809c.png

2.2.1 Devfreq framework初始化

在drivers/devfreq/devfreq.c中,devfreq_init()函數(shù)

static int __init devfreq_init(void)
{
        devfreq_class = class_create(THIS_MODULE, "devfreq"); //創(chuàng)建devfreq設(shè)備類
        if (IS_ERR(devfreq_class)) {
                pr_err("%s: couldn't create class
", __FILE__);
                return PTR_ERR(devfreq_class);
        }
        //創(chuàng)建工作隊(duì)列,用于負(fù)載監(jiān)控work調(diào)用運(yùn)行
        devfreq_wq = create_freezable_workqueue("devfreq_wq");
        if (!devfreq_wq) {
                class_destroy(devfreq_class);
                pr_err("%s: couldn't create workqueue
", __FILE__);
                return -ENOMEM;
        }
        //加入到subsys_initcall,系統(tǒng)啟動(dòng)時(shí)初始化
        devfreq_class->dev_groups = devfreq_groups;

        return 0;
}
subsys_initcall(devfreq_init);

devfreq_groups就是上面說的sysfs用戶接口

ATTRIBUTE_GROUPS(devfreq);
#define ATTRIBUTE_GROUPS(_name)                                        
static const struct attribute_group _name##_group = {                
        .attrs = _name##_attrs,                                        
};

2.2.2 governors 初始化

系統(tǒng)中可支持多個(gè)governors,在系統(tǒng)啟動(dòng)時(shí)進(jìn)行初始化,并注冊(cè)到devfreq framework中, 后續(xù)OPP device創(chuàng)建devfreq設(shè)備,會(huì)根據(jù)governor名字從已經(jīng)初始化好的governor 列表中,查找對(duì)應(yīng)的governor實(shí)例。

0a24b4b8-6bf9-11ee-939d-92fbcf53809c.png下面以simple_ondemand為例子,看下初始化過程:在drivers/devfreq/governor_simpleondemand.c中

//填充governor的結(jié)構(gòu)體,不同的governor,會(huì)有不同的實(shí)現(xiàn)。
static struct devfreq_governor devfreq_simple_ondemand = {
        .name = "simple_ondemand",
        .get_target_freq = devfreq_simple_ondemand_func,
        .event_handler = devfreq_simple_ondemand_handler,
};

static int __init devfreq_simple_ondemand_init(void)
{
        return devfreq_add_governor(&devfreq_simple_ondemand);
}

//加入到subsys_initcall,系統(tǒng)啟動(dòng)時(shí)初始化。
subsys_initcall(devfreq_simple_ondemand_init);

初始化將governor加入到devfreq framework的governor列表中。

devfreq_add_governor->list_add(&governor->node, &devfreq_governor_list);

2.2.3 OPP device初始化

這里我們就以DDR為例子 drivers/devfreq/dmc.c中,系統(tǒng)根據(jù)DTS描述添加對(duì)應(yīng)驅(qū)動(dòng)程序

static const struct of_device_id xxxdmc_devfreq_of_match[] = {
        { .compatible = "xxx-dmc" },
        { },
};
MODULE_DEVICE_TABLE(of, xxxdmc_devfreq_of_match);
static struct platform_driver xxx_dmcfreq_driver = {
        .probe        = xxx_dmcfreq_probe,
        .driver = {
                .name        = "xxx-dmc-freq",
                .pm        = &xxx_dmcfreq_pm,
                .of_match_table = xxxdmc_devfreq_of_match,
        },
};
module_platform_driver(xxx_dmcfreq_driver);
xxx_dmcfreq_probe

匹配"xxx-dmc"會(huì)執(zhí)行掃描函數(shù)xxx_dmcfreq_probe()

static int xxx_dmcfreq_probe(struct platform_device *pdev)
{
    //ctx是自定義的一個(gè)數(shù)據(jù)結(jié)構(gòu),用于存放各種DDR dvfs相關(guān)信息
    ctx = devm_kzalloc(dev, sizeof(struct xxx_dmcfreq), GFP_KERNEL);
    
    //找到clk信息
    struct device *dev = &pdev->dev;
    ctx->dmc_clk = devm_clk_get(dev, "dmc_clk");

    //負(fù)載計(jì)數(shù)啟動(dòng)
    ctx->edev = devfreq_event_get_edev_by_phandle(dev, 0);
    if (IS_ERR(ctx->edev))
            return -EPROBE_DEFER;
    ret = devfreq_event_enable_edev(ctx->edev);

    //給dev添加opp信息
    if (dev_pm_opp_of_add_table(dev)) {
            dev_err(dev, "Invalid operating-points in device tree.
");
            return -EINVAL;
    }

    ctx->rate = clk_get_rate(ctx->dmc_clk);

    opp = devfreq_recommended_opp(dev, &ctx->rate, 0);
    ctx->rate = dev_pm_opp_get_freq(opp);
    dev_pm_opp_put(opp);
    xxx_devfreq_dmc_profile.initial_freq = ctx->rate;

    ctx->devfreq = devm_devfreq_add_device(dev,
                                       &xxx_devfreq_dmc_profile,
                                       "simple_ondemand",
                                       &ctx->ondemand_data);

    //計(jì)算出最大最小值
    ctx->devfreq->min_freq = ULONG_MAX;
    ctx->devfreq->max_freq = 0;
    max_opps = dev_pm_opp_get_opp_count(dev);
    for (i = 0, rate = 0; i < max_opps; i++, rate++) {
            opp = dev_pm_opp_find_freq_ceil(dev, &rate);
            if (ctx->devfreq->min_freq > rate)
                    ctx->devfreq->min_freq = rate;
            if (ctx->devfreq->max_freq < rate)
                    ctx->devfreq->max_freq = rate;
    }

    devm_devfreq_register_opp_notifier(dev, ctx->devfreq);

    ctx->dev = dev;
    platform_set_drvdata(pdev, ctx);

    return 0;
}

pdev的名字是dmc0,對(duì)應(yīng)dts中

    dmc_0: dmc0 {
                compatible = "xxx-dmc";
                devfreq-events = <&ddr_monitor0>;
                operating-points-v2 = <&dmc_opp_table>;
                clocks = <&dmc0_clk>;
                clock-names = "dmc_clk";
    };

其他信息都是在這里定義的。

struct xxx_dmcfreq {
        struct device *dev;
        struct devfreq *devfreq;
        struct devfreq_simple_ondemand_data ondemand_data;
        struct clk *dmc_clk;
        struct devfreq_event_dev *edev;
        struct mutex lock;

        unsigned long rate, target_rate;
};

devm_devfreq_add_device()函數(shù)會(huì)調(diào)用devfreq_add_device()進(jìn)行注冊(cè)devfreq

devfreq_add_device devfreq_add_device 創(chuàng)建devfreq設(shè)備的主要流程如下:

//devfreq device申請(qǐng)內(nèi)存空間 初始化devfreq device結(jié)構(gòu)體后,注冊(cè)設(shè)備。
device_register(&devfreq->dev);

//根據(jù)傳入的governor名字,從governor列表中,獲取對(duì)應(yīng)的governor實(shí)例。
governor = find_devfreq_governor(devfreq->governor_name);

//發(fā)送DEVFREQ_GOV_START到governor,開始管理OPP device的頻率。
err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START, NULL);

##2.3 simple_ondemand調(diào)頻

0a4155a0-6bf9-11ee-939d-92fbcf53809c.png
  • devfreq framework是大管家負(fù)責(zé)監(jiān)控程序的運(yùn)行,
  • governor提供管理算法,
  • OPP device提供自身的負(fù)載狀態(tài)和頻率設(shè)置的方法實(shí)現(xiàn)。
0a631a46-6bf9-11ee-939d-92fbcf53809c.png

exynos芯片,simple_ondemend策略調(diào)頻調(diào)壓流程圖

2.3.1 governor啟動(dòng)監(jiān)控

初始化的時(shí)候在上面2.2.3過程中,會(huì)調(diào)用devfreq_add_device()會(huì)給governor發(fā)DEVFREQ_GOV_START消息,simple_ondemand governor收到處理函數(shù)為:

static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
                                unsigned int event, void *data)
{
        switch (event) {
        case DEVFREQ_GOV_START:
                devfreq_monitor_start(devfreq);
                break;

devfreq_monitor_start()開始啟動(dòng)調(diào)度程序devfreq_monitor

void devfreq_monitor_start(struct devfreq *devfreq)
{
        INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
        if (devfreq->profile->polling_ms)
                queue_delayed_work(devfreq_wq, &devfreq->work,
                        msecs_to_jiffies(devfreq->profile->polling_ms));
}
EXPORT_SYMBOL(devfreq_monitor_start);

2.3.2 monitor輪詢監(jiān)控

devfreq_monitor每隔devfreq->profile->polling_ms時(shí)間,會(huì)調(diào)度監(jiān)控程序工作。工作函數(shù)為update_devfreq()

int update_devfreq(struct devfreq *devfreq)
{
        //獲取頻率
        devfreq->governor->get_target_freq(devfreq, &freq);

        devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
      
        freqs.old = cur_freq;
        freqs.new = freq;
        devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
        
        //設(shè)置頻率
        devfreq->profile->target(devfreq->dev.parent, &freq, flags);

        freqs.new = freq;
        devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
  }

這里獲取頻率和設(shè)置頻率每次都執(zhí)行,不比較頻率是否相同,在設(shè)置處理的時(shí)候才比較。

2.3.3 governor計(jì)算頻率

devfreq->governor->get_target_freq對(duì)應(yīng)函數(shù)為:devfreq_simple_ondemand_func()

static int devfreq_simple_ondemand_func(struct devfreq *df,
                                        unsigned long *freq)
{
        //通過device回調(diào)函數(shù),獲取當(dāng)前狀態(tài),然后計(jì)算新的頻率
        err = devfreq_update_stats(df);
        
        //新頻率的算法,根據(jù)閾值和當(dāng)前負(fù)載計(jì)算
        a = stat->busy_time;
        a *= stat->current_frequency;
        b = div_u64(a, stat->total_time);
        b *= 100;
        b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
        *freq = (unsigned long) b;
        if (df->min_freq && *freq < df->min_freq)
                *freq = df->min_freq;
        if (df->max_freq && *freq > df->max_freq)
                *freq = df->max_freq;
}

devfreq_update_stats會(huì)執(zhí)行:df->profile->get_dev_status(df->dev.parent, &df->last_status); 見2.3.4分析

2.3.4 device獲取和設(shè)置頻率

static struct devfreq_dev_profile xxx_devfreq_dmc_profile = {
        .polling_ms        = 200,
        .target                = xxx_dmcfreq_target,
        .get_dev_status        = xxx_dmcfreq_get_dev_status,
        .get_cur_freq        = xxx_dmcfreq_get_cur_freq,
};

xxx_dmcfreq_get_dev_status()獲取當(dāng)前device負(fù)載信息,根據(jù)算法,返回調(diào)整頻率。

        ret = devfreq_event_get_event(dmcfreq->edev, &edata);
        if (ret < 0)
                return ret;

        stat->current_frequency = dmcfreq->rate;
        stat->busy_time = edata.load_count;
        stat->total_time = edata.total_count;

獲取運(yùn)行狀態(tài)信息,供monitor中devfreq_update_stats()函數(shù)使用

update_devfreq中最后會(huì)設(shè)置頻率xxx_dmcfreq_target() xxx_dmcfreq_target()->clk_set_rate()->dmc_set_rate()->SMC指令 xxx_ddr在dtsi中定義

                xxx_ddr: xxx_ddr {
                        compatible = "xxx-ddr";
                        method = "smc";
                        fid = <0x82000008>;
                        test_cmd = <0x00000000>;
                        get_channels_cmd = <0x00000001>;
                        set_cmd = <0x00000010>;
                        get_cmd = <0x00000011>;
                };

執(zhí)行這個(gè)smc指令后返回值為2,是channel的最大值,用于校驗(yàn)。

注冊(cè)完了之后,clk會(huì)獲取rate調(diào)用dmc_recalc_rate()函數(shù),發(fā)送smc命令0x82000008 0x00000011 0 獲取了rate值為4266000 這里利用ATF把這個(gè)寄存器設(shè)置給封裝了。

3. ATF相關(guān)軟件標(biāo)準(zhǔn)流程

為什么操作的動(dòng)作要放在ATF里面?

  • 為了安全,進(jìn)入安全世界才能操作,普通應(yīng)用app進(jìn)不去
  • 為了進(jìn)入AON(Always ON)一直運(yùn)行的非DDR區(qū)域運(yùn)行,例如SRAM

0x82000008 SMC可以查詢ARM的SMC手冊(cè)

0a6835da-6bf9-11ee-939d-92fbcf53809c.png

可以參考atf中rk的實(shí)現(xiàn),ddr_get_rate()函數(shù) 在plat/rockchip/common/rockchip_sip_svc.c中

/* Define a runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC(
rockchip_sip_svc,
OEN_SIP_START,
OEN_SIP_END,
SMC_TYPE_FAST,
NULL,
sip_smc_handler
);

sip_smc_handler--》rockchip_plat_sip_handler--》ddr_smc_handler

uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1,
 uint64_t id, uint64_t arg2)
{
switch (id) {
case DRAM_SET_RATE:
return ddr_set_rate((uint32_t)arg0);
case DRAM_ROUND_RATE:
return ddr_round_rate((uint32_t)arg0);
case DRAM_GET_RATE:
return ddr_get_rate();
case DRAM_SET_ODT_PD:
dram_set_odt_pd(arg0, arg1, arg2);
break;
default:
break;
}

return 0;
}

這里對(duì)于DDR的調(diào)頻代碼需要放到AON區(qū)域,系統(tǒng)中除了DDR還有SRAM,DDR調(diào)頻的代碼不能放到DDR里面,或者使用硬件DMC實(shí)現(xiàn)。

DMC調(diào)頻 是用軟件來升頻或者降頻,軟件是運(yùn)行在SOC的system controller上的,常常是Cortex-M CPU,調(diào)頻的時(shí)候DMC不會(huì)阻止CPU transfers,DMC自己有buffer,可以繼續(xù)接收,只是不會(huì)發(fā)給DDR,這些對(duì)CPU是透明的,但如果buffer滿了的話,CPU自然就發(fā)不了了,調(diào)頻之后可能需要ddr calibration,我們也都是通過DMC驅(qū)動(dòng)程序來完成的,只是在做這些操作的時(shí)候并不會(huì)讓系統(tǒng)停下來。

后記

學(xué)習(xí)ARMV8,RK也就是rockchip是不錯(cuò)的板子選擇,還記得以前買過螢火蟲的rk板卡,所有軟硬件資料都很全,還挺不錯(cuò)的。這里的電源管理也算是驅(qū)動(dòng),學(xué)習(xí)驅(qū)動(dòng)還是能有個(gè)板子調(diào)下,主要區(qū)分是32位還是64位,目前的大型SoC基本都是ARMv8的64位,甚至ARMv9了。


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 電源管理
    +關(guān)注

    關(guān)注

    115

    文章

    6122

    瀏覽量

    143957
  • sram
    +關(guān)注

    關(guān)注

    6

    文章

    760

    瀏覽量

    114555
  • DDR
    DDR
    +關(guān)注

    關(guān)注

    11

    文章

    701

    瀏覽量

    65098

原文標(biāo)題:電源管理入門-7 DevFreq

文章出處:【微信號(hào):OS與AUTOSAR研究,微信公眾號(hào):OS與AUTOSAR研究】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    電源管理入門-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解

    當(dāng)我們接觸電源管理的時(shí)候,最簡單的流程就是關(guān)機(jī)重啟,但是仔細(xì)分析其涉及的所有源代碼就會(huì)發(fā)現(xiàn),關(guān)機(jī)重啟雖然簡單
    發(fā)表于 09-19 11:41 ?2429次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解

    電源管理入門-什么是OPP?怎么用?

    在SoC內(nèi),某些domain可以運(yùn)行在較低的頻率和電壓下,而其他domain可以運(yùn)行在較高的頻率和電壓下,某個(gè)domain所支持的對(duì)的集合被稱為Operating Performance Point,縮寫OPP。
    的頭像 發(fā)表于 11-16 16:49 ?1771次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>-什么是OPP?怎么用?

    電源管理入門-Regulator驅(qū)動(dòng)是什么?Regulator的作用是什么?

    Regulator是Linux系統(tǒng)中電源管理的基礎(chǔ)設(shè)施之一,用于穩(wěn)壓電源管理,是各種驅(qū)動(dòng)子系統(tǒng)中設(shè)置 電壓的標(biāo)準(zhǔn)接口。
    的頭像 發(fā)表于 11-16 16:51 ?8826次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>-Regulator驅(qū)動(dòng)是什么?Regulator的作用是什么?

    電源管理入門:Thermal熱管理

    管理指的是在電子設(shè)備或系統(tǒng)中通過各種方式控制其溫度來保證其正常工作或延長壽命的過程。其中包括散熱設(shè)計(jì)、溫度監(jiān)測(cè)、溫度控制等方面。熱管理的重要性越來越凸顯,尤其在高性能計(jì)算、人工智能等領(lǐng)域的應(yīng)用中更為重要。
    的頭像 發(fā)表于 11-29 10:09 ?3940次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>:Thermal熱<b class='flag-5'>管理</b>

    電源管理入門:驅(qū)動(dòng)Runtime PM管理

    Runtime PM管理也就是設(shè)備驅(qū)動(dòng)里面的電源管理,即設(shè)備驅(qū)動(dòng)結(jié)構(gòu)體里面的struct dev_pm_ops,只控制設(shè)備自己的電源。這樣可以在設(shè)備不需要工作的時(shí)候可以進(jìn)入到低功耗狀態(tài)
    的頭像 發(fā)表于 11-29 10:13 ?2414次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>:驅(qū)動(dòng)Runtime PM<b class='flag-5'>管理</b>

    電源管理入門:Power supply子系統(tǒng)

    對(duì)于便攜設(shè)備來說,電源管理更加的重要,因?yàn)殡姵仉娏坑邢?,容易電量焦慮。除了省電管理外,還需要對(duì)電池進(jìn)行監(jiān)控管理和充放電管理,這樣保護(hù)好電池和
    的頭像 發(fā)表于 11-29 10:15 ?3694次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>:Power supply子系統(tǒng)

    電源管理入門:Power Domain管理

    SoC中通常有很多IP,按邏輯可以把幾個(gè)相關(guān)功能的IP劃為一個(gè)電源域。一個(gè)電源域內(nèi)的IP,通常按相同的方式由同一個(gè)硬件模塊PMIC供電,電壓一樣并且電源管理例如休眠喚醒一致。
    的頭像 發(fā)表于 11-29 10:16 ?2941次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>:Power Domain<b class='flag-5'>管理</b>

    電源管理入門-芯片設(shè)計(jì)中的電源管理介紹

    SCP直接控制SoC的電源和時(shí)鐘,而AP通過硬件和軟件接口協(xié)同管理。
    的頭像 發(fā)表于 12-06 09:16 ?2793次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>-芯片設(shè)計(jì)中的<b class='flag-5'>電源</b><b class='flag-5'>管理</b>介紹

    電源管理入門:Hypervisor中的電源管理

    很多時(shí)候聽說Hypervisor,但是對(duì)底層軟件技術(shù)不了解的人感覺挺神秘。本篇文章簡單介紹下Hypervisor的基本概念,另外介紹下電源管理在Hypervisor之上多OS間怎么應(yīng)用。
    的頭像 發(fā)表于 12-06 09:27 ?1269次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>:Hypervisor中的<b class='flag-5'>電源</b><b class='flag-5'>管理</b>

    NI視覺助手入門教程完全版

    本帖最后由 Z52352389 于 2016-3-7 22:44 編輯 NI視覺助手入門教程完全版,圖像處理入門
    發(fā)表于 12-20 22:58

    防火墻原理入門

    防火墻原理入門 防火墻能增強(qiáng)機(jī)構(gòu)內(nèi)部網(wǎng)絡(luò)的安全性。防火墻系統(tǒng)決定了哪些內(nèi)部服務(wù)可以被外界訪問;外界的哪些人可以訪問內(nèi)部的服務(wù)以及哪
    發(fā)表于 08-01 10:21 ?1004次閱讀
    防火墻原<b class='flag-5'>理入門</b>

    數(shù)字信號(hào)處理入門指南

    數(shù)字信號(hào)處理入門指南什么是DSP? 數(shù)字信號(hào)處理器(DSP)采集已被數(shù)字化的現(xiàn)實(shí)世界的聲音、音頻、視頻、溫度、壓力或位置等信號(hào),并從數(shù)學(xué)的角度對(duì)其進(jìn)
    發(fā)表于 09-15 08:55 ?1331次閱讀
    數(shù)字信號(hào)處<b class='flag-5'>理入門</b>指南

    單片機(jī)原理及應(yīng)用ppt入門課程

    微機(jī)原理入門課程ppt,比較簡單,適合新手。。
    發(fā)表于 01-12 17:52 ?0次下載

    電源管理入門之CPU熱插拔詳解

    之前介紹了電源的開機(jī)和關(guān)機(jī)重啟,本小節(jié)開始介紹省電的技術(shù),其中最暴力的省電方法就是直接拔核hotplug處理,就像需要10個(gè)人干活都要吃飯,但是現(xiàn)在活少了最節(jié)省的方法就是砍掉幾個(gè)人,有點(diǎn)像裁員啊。
    的頭像 發(fā)表于 10-16 15:28 ?4700次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>之CPU熱插拔詳解

    電源管理入門-6 CPUFreq

    僅僅降低時(shí)鐘頻率并不節(jié)約能量,因?yàn)闀r(shí)鐘頻率的降低會(huì)帶來任務(wù)執(zhí)行時(shí)間的增加。調(diào)節(jié)電壓需要以相同的比例調(diào)節(jié)頻率以滿足信號(hào)傳播延遲要求。然而不管是電壓調(diào)節(jié)還是頻率調(diào)節(jié),都會(huì)造成系統(tǒng)性能的損失,并增加系統(tǒng)的響應(yīng)延遲。
    的頭像 發(fā)表于 10-16 17:07 ?2047次閱讀
    <b class='flag-5'>電源</b><b class='flag-5'>管理入門</b>-6 CPUFreq