1. 程式人生 > >電源管理之regulator機制流程

電源管理之regulator機制流程

電源管理晶片可以為多裝置供電,且這些裝置電壓電流有所同。為這些裝置提供的穩壓器程式碼模型即為regulator

下面通過下面三個過程分析regulartor供電機制:

1.分析regulator結構體

2.regulator 註冊過程

3.裝置使用regulator過程

.分析regulator結構體

Regulator模組用於控制系統中某些裝置的電壓/電流供應。在嵌入式系統(尤其是手機)中,控制耗電量很重要,直接影響到電池的續航時間。所以,如果系統中某一個模組暫時不需要使用,就可以通過regulator關閉其電源供應;或者降低提供給該模組的電壓、電流大小。

Regulator

的文件在KERNEL/Documentation/Power/Regulator中。

Regulator與模組之間是樹狀關係。父regulator可以給裝置供電,也可以給子regulator供電:

Regulator

--> 子Regulator --> [supply]

--> 裝置[Consumer]

具體細節可參考核心文件machine.txt

regulator_dev

regulator_dev代表一個regulator裝置。

struct regulator_dev {

struct regulator_desc *desc; // 描述符,包括regulator

的名稱、IDregulator_ops

int use_count; // 使用計數

struct list_head list; // regulator通過此結構掛到regulator_list連結串列中

struct list_head slist; // 如果有父regulator,通過此域掛到父regulator的連結串列

struct list_head consumer_list; // 此regulator負責供電的裝置列表

struct list_head supply_list; //regulator負責供電的子regulator

struct blocking_notifier_head notifier; // notifier

,具體的值在consumer.h中,比如REGULATOR_EVENT_FAIL

struct mutex mutex;

struct module *owner;

struct device dev; // device結構,屬於class regulator_class

struct regulation_constraints *constraints; // 限制,比如最大電壓/電流、最小電壓/電流

struct regulator_dev *supply; // 父regulator的指標,即由此regulator 供電

void *reg_data;

};

regulator_init_data

regulator_init_data在初始化時使用,用來建立父子regulator、受電模組之間的樹狀結構,以及一些regulator的基本引數。

struct regulator_init_data {

struct device *supply_regulator_dev; // 父regulator的指標

struct regulation_constraints constraints;

int num_consumer_supplies;

struct regulator_consumer_supply *consumer_supplies; // 負責供電的裝置陣列

int (*regulator_init)(void *driver_data); // 初始化函式,在regulator_register被呼叫

void *driver_data;

};

其它結構體自己可以看看~如

struct regulator               -------> 裝置驅動直接操作的結構體

struct regulation_constraints       ----->regulator限制範圍,其它資訊,在於

                       struct regulator_init_data,用於初始化

struct regulator_consumer_supply   ----->consumer資訊

struct regulator_desc                           ----->這個多關注些,內有正真操作裝置函式結構體~

struct regulator_map                           ----->這個為consumers與regulator對應表

........................................

............................................

. 註冊regulator過程

先說明下兩具在regulatorcore中有兩個關鍵的全域性變數連結串列:

regulator_list 每註冊一個regulator都會掛到這裡

regulator_map_list  每一個regulator都會為多個consumer供電,此表為掛consumer

regulator註冊過程是通過platform平臺註冊,當然一個電源管理晶片可以供幾十個裝置供電,所以不可能每個regulator一個驅動檔案,它們是通過,在電源管理晶片驅動中一塊註冊到regulatocore中。

對於電源管理晶片驅動的註冊則通過I2C註冊的。接下來以中星微方案過下,

首先,在平臺裝置檔案中,有關struct regulator_init_data XX定義~

如:

.........................

static struct regulator_init_data va7882_ldo13_data = {

.constraints = {

.name = "LDO13-HDMI1V2", //Default: 1.5V , Powered By DCDC5, C-class

.min_uV = 1200000,

.max_uV = 1800000,

.apply_uV = 1,

// TEMP_ON

.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE,

.initial_mode = REGULATOR_MODE_NORMAL,

.valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY,

},

.supply_regulator = supply_regulator_name_arrary[ID_VA7882_LDO13],

.num_consumer_supplies = 2,

.consumer_supplies = (struct regulator_consumer_supply []) {

{ .supply = regulator_name_arrary[ID_VA7882_LDO13][0] },

{ .supply = regulator_name_arrary[ID_VA7882_LDO13][1] },

{ .supply = regulator_name_arrary[ID_VA7882_LDO13][2] },

},

};

........................................

其實這些結構體又會被同一檔案中的自定義檔案初始化函式 v8_va7882_init呼叫,其實就是

va7882_register_regulator---->為每個regulator分配對應的struct platform_device---->platform_device_add 

platform_driver在哪?

static struct platform_driver va7882_regulator_driver = {

.driver = {

.name = "va7882-regulator",

.owner = THIS_MODULE,

},

.probe = va7882_regulator_probe,

.remove = __exit_p(va7882_regulator_remove),

.suspend = va7882_regulator_suspend,    //可見休眠喚醒是使用同一個,

.resume = va7882_regulator_resume,      //再次說明它們是一統管理,它們也是為了節省.

.shutdown = va7882_regulator_shutdown,

};

這個platform_driver是每個regulator共用的的,因為name都是" va7882-regulator"

在這個platform_driverprobe中就幹了一件事regulator_register,從而獲得regulator_dev

接下來分析下regulator_register註冊

Regulator的註冊由regulator_register完成。

一般來說,為了新增regulator_dev,需要實現一個裝置驅動程式,以及在板子的裝置列表中增加一個該驅動對應的裝置(比如platform_device)。在這個裝置的struct device->platform_data域,需要設定regulator_init結構,填寫該regulator的相關資訊。另外,還需要定義一個regulator_desc結構。這樣,在這個物理裝置的驅動程式中,就可以通過regulator_register函式登記生成一個regulator_dev

struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, void *driver_data)

struct regulator_init_data *init_data = dev->platform_data;// 得到init_data

// 完整性檢查

// 分配regulator_dev結構

struct regulator_dev *rdev = kzalloc (sizeof(struct regulator_dev), GFP_KERNEL);

// 初始化regulator_dev結構

// 執行regulator_init,該函式中實現regulator代表的硬體裝置的初始化

if (init_data->regulator_init)

ret = init_data->regulator_init(rdev->reg_data);

rdev->dev.class = &regulator_class; // 指定classregulator_class

rdev->dev.parent = dev;

device_register(&rdev->dev); // 註冊裝置

// 設定constraints,其中可能會包括供電狀態的初始化(設定初始電壓,enable/disable等等)

set_machine_constraints(rdev, &init_data->constraints);

add_regulator_attributes (rdev);

// 如果此regulator有父regulator,設定父regulator

if (init_data->supply_regulator_dev) {

ret = set_supply(rdev,

dev_get_drvdata(init_data->supply_regulator_dev));

if (ret < 0)

goto scrub;

}

// 設定此regulator與其負責供電的裝置之間的聯絡

for (i = 0; i < init_data->num_consumer_supplies; i++)

ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev,

init_data->consumer_supplies[i].supply);

// 將regulator加入一個連結串列,該連結串列包含所有regulator

list_add(&rdev->list, &regulator_list);

.............................

那個regulator 根據在regulator_list中用init_data->supply_regulator來匹配

匹配成功用set_supply()來設定註冊的regulator是由那個regulator供電rdev->supply = supply_rdev; list_add(&rdev->slist, &supply_rdev->supply_list);

多個consumerset_consumer_device_supply(),先檢查

list_for_each_entry(node, &regulator_map_list, list) 後新增

list_add(&node->list, &regulator_map_list);當然node已經在

         node->regulator = rdev;

         node->supply = supply;

形成 對於每一個regulator_dev—comsumer_dev的配對

最後在把regulator通過list_add(&rdev->list, &regulator_list);加到 regulator_list連結串列中。

.裝置使用regulator過程

 在裝置驅動使用regulator對其驅動的裝置供電時,首先要確保裝置與對應regulator之間的匹配關係已經被登記到regulator框架中。

之後,裝置驅動通過regulator_get函式得到regulator結構,此函式通過前文所述regulator_map_list找到對應regulator_dev,再生成regulator結構給使用者使用。

通過regulator_enable / regulator_disable開啟、關閉regulator,這兩個函式最終都是呼叫struct regulator_ops裡的對應成員。

除此之外,還有regualtor_set_voltage / regulator_get_voltage等等。

Regulator能夠支援的所有功能列表都在struct regulator_ops中定義,具體可參考程式碼中的註釋。

struct regulator_ops {

int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);

int (*get_voltage) (struct regulator_dev *);

int (*set_current_limit) (struct regulator_dev *,

int min_uA, int max_uA);

int (*get_current_limit) (struct regulator_dev *);

int (*enable) (struct regulator_dev *);

int (*disable) (struct regulator_dev *);

int (*is_enabled) (struct regulator_dev *);

int (*set_mode) (struct regulator_dev *, unsigned int mode);

unsigned int (*get_mode) (struct regulator_dev *);

unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,

int output_uV, int load_uA);

int (*set_suspend_voltage) (struct regulator_dev *, int uV);

int (*set_suspend_enable) (struct regulator_dev *);

int (*set_suspend_disable) (struct regulator_dev *);

int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode);

};

接下來我就以中星型的HDMI驅動使用regulator過一遍。

vc088x_hdmi.c檔案:

HDMI驅動也是通過platform平臺註冊上去,所以在platform_driverprobe中有這個句

ret = v8hdmi_pwr_get(&pdev->dev);

regulator_get(dev,id);

_regulator_get(dev, id, 0);

{

…........

…...........

if (dev)

devname = dev_name(dev);

list_for_each_entry(map, &regulator_map_list, list) {

if (map->dev_name &&(!devname || strcmp(map->dev_name, devname)))

continue;

if (strcmp(map->supply, id) == 0) {//查詢配對

rdev = map->regulator;

goto found;

}

}

相關推薦

電源管理regulator機制流程

電源管理晶片可以為多裝置供電,且這些裝置電壓電流有所同。為這些裝置提供的穩壓器程式碼模型即為regulator。 下面通過下面三個過程分析regulartor供電機制: 1.分析regulator結構體 2.regulator 註冊過程 3.裝置使用regula

Linux電源管理-Linux regulator framework概述

nts RM 成功 一定的 val machine ons 存在 nag 前言 1. 什麽是regulator? regulator翻譯為"調節器",分為voltage regulator(電壓調節器)和current(電流調節器)。一般電源管理芯片(Power

Android電源管理三:PowerManager.WakeLock原始碼詳讀

PowerManager.WakeLock 有加鎖和解鎖兩種狀態,加鎖的方式有兩種,一種是永久的鎖,這樣的鎖除非顯式的放開,是不會解鎖的,所以這種鎖用起來要非常的小心。第二種鎖是超時鎖,這種鎖會在鎖住後一段時間自動解鎖。         在建立了PowerManager.W

Linux記憶體管理slab機制(概述)

通過前面所有程式碼的分析和總結,已經把各個部分熟悉了一遍,在此對Linux核心中slab機制做最後的總結。 夥伴系統演算法採用頁作為基本記憶體區,這適合於大塊記憶體的請求。對於小記憶體區的申請,比如說幾十或幾百個位元組,我們用slab機制。 Slab分配器把物件分組放進快取

Linux記憶體管理slab機制(初始化)

 一、核心啟動早期初始化 start_kernel()->mm_init()->kmem_cache_init() 執行流程: 1,初始化靜態initkmem_list3三鏈; 2,初始化cache_cache的nodelists欄位為1中的三鏈; 3,根據記憶

電源管理android核心suspend to disk的實現(九)--tuxonice實現方案

完成在標準核心基礎上的android系統的suspend to disk後,又採取了tuxonice補丁的方式進行比較,發現由於壓縮的緣故,速度有所提高10s左右。 該範方案的實現我是根據我的一位離職的同事寫學習筆記進行測試,實驗證明是可行的,以下部分程式的講解我也直接進

Android5.1--電源管理省電模式分析

 一、如何開啟5.0省電模式 開啟安卓5.0裝置的設定選項,然後前往電池選單,點選選單鍵,彈出並選擇“節電助手”,隨後點選頂部的開關便可。 此外,要是使用者執行的是原生版安卓,可以下拉安卓通知中心,然後點選電池按鈕,便可進入電池介面,找到“省電模式”。 開啟此模式後,螢幕

Linux記憶體管理slab機制(釋放物件)

 Linux核心中將物件釋放到slab中上層所用函式為kfree()或kmem_cache_free()。兩個函式都會呼叫__cache_free()函式。 程式碼執行流程: 1,當本地CPU cache中空閒物件數小於規定上限時,只需將物件放入本地CPU cache中;

項目研發流程管理我見

準備 處理 日誌 哪些 修復 分代 成功 接口 協作 隨著工作年限的增長,我們從一開始負責一個功能,再到負責一個模塊的數據字典及框架設計。再到負責整個系統的需求評審及架構設計。這一路見證著程序猿的成長。但當我們逐步成為一名架構師,或是一名項目管理人員時,會發現一個項目的成功

asoc行動式裝置的動態音訊電源管理

行動式裝置的動態音訊電源管理 描述 動態音訊電源管理(DAPM)旨在允許行動式Linux裝置始終使用音訊子系統中的最小功率。它獨立於其他核心PM,因此可以輕鬆地與其他PM系統共存。 DAPM對所有使用者空間應用程式也完全透明,因為所有電源切換都在ASoC核心內完成。使用者空間應用程式不需

電子產品方案開發電源管理晶片發展趨勢

電子產品方案開發之電源管理晶片的創新方向,近幾年來看,主要是圍繞一些新材料展開,除此之外,模組化成為一個重要的趨勢,如何實現低功耗、小尺寸、高整合度、高功率密度成了電源廠商普遍的課題。微控制器晶片的小尺寸與微控制器晶片的封裝創新息息相關。 而這種模組化的電源晶片產品對晶片廠商的工藝和封裝技術

Java記憶體管理GC垃圾回收機制是什麼?什麼是垃圾?如何判斷是否為垃圾?

文章目錄 1. 垃圾回收機制是什麼? 2. 什麼是垃圾呢?如何判斷是否為垃圾呢? 3. GC root指的是誰? 1. 垃圾回收機制是什麼? 垃圾回收機制讓開發者無需關注空間的建立和釋放,而是以守護程序的形式在後臺自動回收垃圾

Power Optimization SDK介紹電源管理的兩種模型:reactive和proactive

0.前言     電源管理是指如何將電源有效的分配到裝置的不同的元件。電源管理對於依賴電池電源的移動裝置來說是非常重要的,例如筆記本、手機等等。一個好的電源管理系統能夠使電池的壽命和每次使用的時間大大增加。     本文旨在說明與電源管理相關的兩種模型:無功功率電源管理和

ALSA音效卡驅動中的DAPM詳解二:widget-具備路徑和電源管理資訊的kcontrol

上一篇文章中,我們介紹了音訊驅動中對基本控制單元的封裝:kcontrol。利用kcontrol,我們可以完成對音訊系統中的mixer,mux,音量控制,音效控制,以及各種開關量的控制,通過對各種kcontrol的控制,使得音訊硬體能夠按照我們預想的結果進行工作。同時我

Linux電源管理(6)_Generic PMSuspend功能

1. 前言 Linux核心提供了三種Suspend: Freeze、Standby和STR(Suspend to RAM),在使用者空間向”/sys/power/state”檔案分別寫入”freeze”、”standby”和”mem”,即可觸發它們。 核心中,Suspend及Resume過程

Linux電源管理(3)_Generic PMReboot過程

1. 前言 在使用計算機的過程中,關機和重啟是最先學會的兩個操作。同樣,這兩個操作在Linux中也存在,稱作shutdown和restart。這就是本文要描述的物件。 在Linux Kernel中,主流的shutdown和restart都是通過“reboot”系統呼叫(具體可參考kern

Linux電源管理(2)_Generic PM基本概念和軟體架構

1. 前言 這裡的Generic PM,是蝸蝸自己起的名字,指Linux系統中那些常規的電源管理手段,包括關機(Power off)、待機(Standby or Hibernate)、重啟(Reboot)等。這些手段是在嵌入式Linux普及之前的PC或者伺服器時代使用的。在那個電腦科學的蠻荒時

Linux電源管理(11)_Runtime PM功能描述

1. 前言 終於可以寫Runtime PM(後面簡稱RPM)了,說實話,蝸蝸有點小激動。因為從個人的角度講,我很推崇使用RPM進行日常的動態電源管理,而不是suspend機制。 軟體工程的基本思想就是模組化:高內聚和低耦合。通俗地講呢,就是“各人自掃門前雪”,儘量掃好自己的(高內聚),儘

Android 電源管理 -- wakelock機制

PowerManager.WakeLock 有加鎖和解鎖兩種狀態,加鎖的方式有兩種:     第一種是永久的鎖住,這樣的鎖除非顯式的放開,否則是不會解鎖的,所以這種鎖用起來要非常的小心。     第二種鎖是超時鎖,這種鎖會在鎖住後一段時間解鎖。 在建立了 PowerManager.WakeLock 後,有

Android電源管理系列PowerManagerService(二)

WakeLock機制 PowerManager.WakeLock 為了延長電池的使用壽命,Android裝置會在一段時間後使螢幕變暗,然後關閉螢幕顯示,直至停止CPU進入休眠。WakeLock是Android提供的喚醒鎖機制,用來保持CPU執行或避免螢幕變暗/關閉以及避免鍵盤背光燈熄滅