/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Generic OPP Interface
*
* Copyright ( C ) 2009 - 2010 Texas Instruments Incorporated .
* Nishanth Menon
* Romit Dasgupta
* Kevin Hilman
*/
#ifndef __DRIVER_OPP_H__
#define __DRIVER_OPP_H__
#include <linux/device.h>
#include <linux/interconnect.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/limits.h>
#include <linux/pm_opp.h>
#include <linux/notifier.h>
struct clk;
struct regulator;
/* Lock to allow exclusive modification to the device and opp lists */
extern struct mutex opp_table_lock;
extern struct list_head opp_tables;
/* OPP Config flags */
#define OPP_CONFIG_CLK BIT(0 )
#define OPP_CONFIG_REGULATOR BIT(1 )
#define OPP_CONFIG_REGULATOR_HELPER BIT(2 )
#define OPP_CONFIG_PROP_NAME BIT(3 )
#define OPP_CONFIG_SUPPORTED_HW BIT(4 )
#define OPP_CONFIG_REQUIRED_DEV BIT(5 )
/**
* struct opp_config_data - data for set config operations
* @ opp_table : OPP table
* @ flags : OPP config flags
* @ required_dev_index : The position in the array of required_devs
*
* This structure stores the OPP config information for each OPP table
* configuration by the callers .
*/
struct opp_config_data {
struct opp_table *opp_table;
unsigned int flags;
unsigned int required_dev_index;
};
/**
* struct dev_pm_opp_icc_bw - Interconnect bandwidth values
* @ avg : Average bandwidth corresponding to this OPP ( in icc units )
* @ peak : Peak bandwidth corresponding to this OPP ( in icc units )
*
* This structure stores the bandwidth values for a single interconnect path .
*/
struct dev_pm_opp_icc_bw {
u32 avg;
u32 peak;
};
/*
* Internal data structure organization with the OPP layer library is as
* follows :
* opp_tables ( root )
* | - device 1 ( represents voltage domain 1 )
* | | - opp 1 ( availability , freq , voltage )
* | | - opp 2 . .
* . . . . . .
* | ` - opp n . .
* | - device 2 ( represents the next voltage domain )
* . . .
* ` - device m ( represents mth voltage domain )
* device 1 , 2 . . are represented by opp_table structure while each opp
* is represented by the opp structure .
*/
/**
* struct dev_pm_opp - Generic OPP description structure
* @ node : opp table node . The nodes are maintained throughout the lifetime
* of boot . It is expected only an optimal set of OPPs are
* added to the library by the SoC framework .
* IMPORTANT : the opp nodes should be maintained in increasing
* order .
* @ kref : for reference count of the OPP .
* @ available : true / false - marks if this OPP as available or not
* @ dynamic : not - created from static DT entries .
* @ turbo : true if turbo ( boost ) OPP
* @ suspend : true if suspend OPP
* @ removed : flag indicating that OPP ' s reference is dropped by OPP core .
* @ rates : Frequencies in hertz
* @ level : Performance level
* @ supplies : Power supplies voltage / current values
* @ bandwidth : Interconnect bandwidth values
* @ clock_latency_ns : Latency ( in nanoseconds ) of switching to this OPP ' s
* frequency from any other OPP ' s frequency .
* @ required_opps : List of OPPs that are required by this OPP .
* @ opp_table : points back to the opp_table struct this opp belongs to
* @ np : OPP ' s device node .
* @ dentry : debugfs dentry pointer ( per opp )
*
* This structure stores the OPP information for a given device .
*/
struct dev_pm_opp {
struct list_head node;
struct kref kref;
bool available;
bool dynamic;
bool turbo;
bool suspend;
bool removed;
unsigned long *rates;
unsigned int level;
struct dev_pm_opp_supply *supplies;
struct dev_pm_opp_icc_bw *bandwidth;
unsigned long clock_latency_ns;
struct dev_pm_opp **required_opps;
struct opp_table *opp_table;
struct device_node *np;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
const char *of_name;
#endif
};
/**
* struct opp_device - devices managed by ' struct opp_table '
* @ node : list node
* @ dev : device to which the struct object belongs
* @ dentry : debugfs dentry pointer ( per device )
*
* This is an internal data structure maintaining the devices that are managed
* by ' struct opp_table ' .
*/
struct opp_device {
struct list_head node;
const struct device *dev;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
#endif
};
enum opp_table_access {
OPP_TABLE_ACCESS_UNKNOWN = 0 ,
OPP_TABLE_ACCESS_EXCLUSIVE = 1 ,
OPP_TABLE_ACCESS_SHARED = 2 ,
};
/**
* struct opp_table - Device opp structure
* @ node : table node - contains the devices with OPPs that
* have been registered . Nodes once added are not modified in this
* table .
* @ head : notifier head to notify the OPP availability changes .
* @ dev_list : list of devices that share these OPPs
* @ opp_list : table of opps
* @ kref : for reference count of the table .
* @ lock : mutex protecting the opp_list and dev_list .
* @ np : struct device_node pointer for opp ' s DT node .
* @ clock_latency_ns_max : Max clock latency in nanoseconds .
* @ parsed_static_opps : Count of devices for which OPPs are initialized from DT .
* @ shared_opp : OPP is shared between multiple devices .
* @ current_rate_single_clk : Currently configured frequency for single clk .
* @ current_opp : Currently configured OPP for the table .
* @ suspend_opp : Pointer to OPP to be used during device suspend .
* @ required_opp_tables : List of device OPP tables that are required by OPPs in
* this table .
* @ required_devs : List of devices for required OPP tables .
* @ required_opp_count : Number of required devices .
* @ supported_hw : Array of version number to support .
* @ supported_hw_count : Number of elements in supported_hw array .
* @ prop_name : A name to postfix to many DT properties , while parsing them .
* @ config_clks : Platform specific config_clks ( ) callback .
* @ clks : Device ' s clock handles , for multiple clocks .
* @ clk : Device ' s clock handle , for single clock .
* @ clk_count : Number of clocks .
* @ config_regulators : Platform specific config_regulators ( ) callback .
* @ regulators : Supply regulators
* @ regulator_count : Number of power supply regulators . Its value can be - 1
* ( uninitialized ) , 0 ( no opp - microvolt property ) or > 0 ( has opp - microvolt
* property ) .
* @ paths : Interconnect path handles
* @ path_count : Number of interconnect paths
* @ enabled : Set to true if the device ' s resources are enabled / configured .
* @ is_genpd : Marks if the OPP table belongs to a genpd .
* @ dentry : debugfs dentry pointer of the real device directory ( not links ) .
* @ dentry_name : Name of the real dentry .
*
* @ voltage_tolerance_v1 : In percentage , for v1 bindings only .
*
* This is an internal data structure maintaining the link to opps attached to
* a device . This structure is not meant to be shared to users as it is
* meant for book keeping and private to OPP library .
*/
struct opp_table {
struct list_head node, lazy;
struct blocking_notifier_head head;
struct list_head dev_list;
struct list_head opp_list;
struct kref kref;
struct mutex lock;
struct device_node *np;
unsigned long clock_latency_ns_max;
/* For backward compatibility with v1 bindings */
unsigned int voltage_tolerance_v1;
unsigned int parsed_static_opps;
enum opp_table_access shared_opp;
unsigned long current_rate_single_clk;
struct dev_pm_opp *current_opp;
struct dev_pm_opp *suspend_opp;
struct opp_table **required_opp_tables;
struct device **required_devs;
unsigned int required_opp_count;
unsigned int *supported_hw;
unsigned int supported_hw_count;
const char *prop_name;
config_clks_t config_clks;
struct clk **clks;
struct clk *clk;
int clk_count;
config_regulators_t config_regulators;
struct regulator **regulators;
int regulator_count;
struct icc_path **paths;
unsigned int path_count;
bool enabled;
bool is_genpd;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
char dentry_name[NAME_MAX];
#endif
};
/* Routines internal to opp core */
bool _opp_remove_all_static(struct opp_table *opp_table);
int _get_opp_count(struct opp_table *opp_table);
struct opp_table *_find_opp_table(struct device *dev);
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
void _opp_free(struct dev_pm_opp *opp);
int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic);
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
void _required_opps_available(struct dev_pm_opp *opp, int count);
static inline bool lazy_linking_pending(struct opp_table *opp_table)
{
return unlikely(!list_empty(&opp_table->lazy));
}
#ifdef CONFIG_OF
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
void _of_clear_opp_table(struct opp_table *opp_table);
struct opp_table *_managed_opp(struct device *dev, int index);
void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp);
#else
static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
static inline void _of_clear_opp_table(struct opp_table *opp_table) {}
static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
static inline void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) {}
#endif
#ifdef CONFIG_DEBUG_FS
void opp_debug_remove_one(struct dev_pm_opp *opp);
void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
#else
static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
static inline void opp_debug_create_one(struct dev_pm_opp *opp,
struct opp_table *opp_table) { }
static inline void opp_debug_register(struct opp_device *opp_dev,
struct opp_table *opp_table) { }
static inline void opp_debug_unregister(struct opp_device *opp_dev,
struct opp_table *opp_table)
{ }
#endif /* DEBUG_FS */
#endif /* __DRIVER_OPP_H__ */
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland