電源排序 API

作者:

Bartosz Golaszewski

簡介

此框架旨在抽象 Linux 核心中多個邏輯裝置之間共享的複雜加電順序。

目的是允許使用者獲取電源序列提供者公開的電源排序控制代碼,並委派底層資源的實際請求和控制,並允許提供者在幕後減輕多個使用者之間可能存在的衝突。

詞彙表

電源排序 API 使用許多特定於子系統的術語

單元

單元是電源序列的離散塊。例如,一個單元可以啟用一組穩壓器,另一個單元可以啟用特定的 GPIO。單元可以定義依賴關係,即必須在其本身啟用之前啟用的其他單元。

目標

目標是一組單元(由“最終”單元及其依賴項組成),使用者在請求電源排序器控制代碼時按其名稱選擇。透過依賴關係系統,多個目標可以共享電源序列的相同部分,但忽略不相關的部分。

描述符

由 pwrseq 核心傳遞給每個使用者的控制代碼,用作提供者層的入口點。它確保不同使用者之間的一致性,並保持引用計數一致。

使用者介面

使用者 API 旨在儘可能簡單。有興趣從電源排序器獲取描述符的驅動程式應呼叫 pwrseq_get(),並在呼叫 pwrseq_power_up() 之後指定它希望在序列中達到的目標的名稱。可以透過呼叫 pwrseq_put() 釋放描述符,使用者可以使用 pwrseq_power_off() 請求關閉其目標的電源。請注意,不能保證 pwrseq_power_off() 會產生任何影響,因為可能存在底層資源的多個使用者可能使其保持活動狀態。

提供者介面

不可否認,提供者 API 不像使用者的 API 那樣簡單,但它在靈活性方面彌補了這一點。

每個提供者都可以將加電序列從邏輯上拆分為離散的塊(單元)並定義它們的依賴關係。然後,他們可以公開命名目標,使用者可以將這些目標用作他們希望達到的序列中的最終點。

為此,提供者填寫一組配置結構,並透過呼叫 pwrseq_device_register() 向 pwrseq 子系統註冊。

動態使用者匹配

pwrseq 與其他 Linux 核心提供者的主要區別在於動態匹配使用者和提供者的機制。每個電源序列提供者驅動程式都必須實現 match() 回撥,並在向子系統註冊時將其傳遞給 pwrseq 核心。

當客戶端請求排序器控制代碼時,核心將為每個已註冊的提供者呼叫此回撥,並使其靈活地確定提議的客戶端裝置是否確實是其使用者。例如:如果提供者繫結到代表晶片組電源管理單元的裝置樹節點,並且使用者驅動程式控制其模組之一,則提供者驅動程式可以解析裝置樹中相關的穩壓器電源屬性,並檢視它們是否從 PMU 引導到使用者。

API 參考

struct pwrseq_unit_data

單個電源排序單元的配置。

定義:

struct pwrseq_unit_data {
    const char *name;
    const struct pwrseq_unit_data **deps;
    pwrseq_power_state_func enable;
    pwrseq_power_state_func disable;
};

成員

name

單元的名稱。

deps

必須在此單元之前啟用並在其之後停用的單元,順序與此陣列中的順序相同。必須以 NULL 結尾。

enable

回撥執行此單元提供的加電序列的一部分。

disable

回撥執行此單元提供的斷電序列的一部分。

struct pwrseq_target_data

電源排序目標的配置。

定義:

struct pwrseq_target_data {
    const char *name;
    const struct pwrseq_unit_data *unit;
    pwrseq_power_state_func post_enable;
};

成員

name

目標的名稱。

unit

此目標必須達到的最終單元,才能被視為已啟用。

post_enable

在啟用目標單元之後,釋放狀態鎖後執行的回撥。它對於實現啟動延遲而不會阻止其他使用者使用相同的電源排序器來加電非常有用。

struct pwrseq_config

用於註冊新提供者的配置。

定義:

struct pwrseq_config {
    struct device *parent;
    struct module *owner;
    void *drvdata;
    pwrseq_match_func match;
    const struct pwrseq_target_data **targets;
};

成員

parent

排序器的父裝置。必須設定。

owner

提供此裝置的模組。

drvdata

私有驅動程式資料。

match

用於將使用者裝置與排序器匹配的提供者回調。

targets

此電源排序器的目標陣列。必須以 NULL 結尾。

struct pwrseq_device *pwrseq_device_register(const struct pwrseq_config *config)

註冊新的電源排序器。

引數

const struct pwrseq_config *config

新電源排序裝置的配置。

描述

config 結構僅在呼叫期間使用,並且可以在函式返回後釋放。 config 結構必須具有父裝置以及 match() 回撥和至少一個目標集。

返回

返回新 pwrseq 裝置的地址,如果失敗,則返回 ERR_PTR()

void pwrseq_device_unregister(struct pwrseq_device *pwrseq)

登出電源排序器。

引數

struct pwrseq_device *pwrseq

要登出的電源排序器。

struct pwrseq_device *devm_pwrseq_device_register(struct device *dev, const struct pwrseq_config *config)

pwrseq_device_register() 的託管變體。

引數

struct device *dev

管理裝置。

const struct pwrseq_config *config

新電源排序裝置的配置。

返回

返回新 pwrseq 裝置的地址,如果失敗,則返回 ERR_PTR()

void *pwrseq_device_get_drvdata(struct pwrseq_device *pwrseq)

獲取與此排序器關聯的驅動程式私有資料。

引數

struct pwrseq_device *pwrseq

電源排序器物件。

返回

私有驅動程式資料的地址。

struct pwrseq_desc *pwrseq_get(struct device *dev, const char *target)

獲取與此裝置關聯的電源排序器。

引數

struct device *dev

要獲取排序器的裝置。

const char *target

此裝置要達到的排序器公開的目標的名稱。

返回

供使用者驅動程式使用的新電源排序器描述符,如果失敗,則返回 ERR_PTR()

void pwrseq_put(struct pwrseq_desc *desc)

釋放電源排序器描述符。

引數

struct pwrseq_desc *desc

要釋放的描述符。

struct pwrseq_desc *devm_pwrseq_get(struct device *dev, const char *target)

pwrseq_get() 的託管變體。

引數

struct device *dev

用於獲取排序器的裝置,該裝置也管理其生命週期。

const char *target

此裝置要達到的排序器公開的目標的名稱。

返回

供使用者驅動程式使用的新電源排序器描述符,如果失敗,則返回 ERR_PTR()

int pwrseq_power_on(struct pwrseq_desc *desc)

代表使用者裝置發出加電請求。

引數

struct pwrseq_desc *desc

引用電源排序器的描述符。

描述

此函式告訴電源排序器使用者想要加電。排序器可能已經為裝置加電,在這種情況下,函式返回 0。如果加電序列已經在進行中,該函式將阻塞直到完成並返回 0。如果這是第一個請求,則裝置將被加電。

返回

成功時返回 0,失敗時返回負錯誤編號。

int pwrseq_power_off(struct pwrseq_desc *desc)

代表使用者裝置發出斷電請求。

引數

struct pwrseq_desc *desc

引用電源排序器的描述符。

描述

這會撤消 pwrseq_power_on() 的效果。它代表使用者發出斷電請求,當最後剩餘的使用者這樣做時,將啟動斷電序列。如果某個斷電序列正在進行中,該函式將阻塞直到完成然後返回。

返回

成功時返回 0,失敗時返回負錯誤編號。