linux/drivers/opp/opp.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Generic OPP Interface
   4 *
   5 * Copyright (C) 2009-2010 Texas Instruments Incorporated.
   6 *      Nishanth Menon
   7 *      Romit Dasgupta
   8 *      Kevin Hilman
   9 */
  10
  11#ifndef __DRIVER_OPP_H__
  12#define __DRIVER_OPP_H__
  13
  14#include <linux/device.h>
  15#include <linux/interconnect.h>
  16#include <linux/kernel.h>
  17#include <linux/kref.h>
  18#include <linux/list.h>
  19#include <linux/limits.h>
  20#include <linux/pm_opp.h>
  21#include <linux/notifier.h>
  22
  23struct clk;
  24struct regulator;
  25
  26/* Lock to allow exclusive modification to the device and opp lists */
  27extern struct mutex opp_table_lock;
  28
  29extern struct list_head opp_tables, lazy_opp_tables;
  30
  31/*
  32 * Internal data structure organization with the OPP layer library is as
  33 * follows:
  34 * opp_tables (root)
  35 *      |- device 1 (represents voltage domain 1)
  36 *      |       |- opp 1 (availability, freq, voltage)
  37 *      |       |- opp 2 ..
  38 *      ...     ...
  39 *      |       `- opp n ..
  40 *      |- device 2 (represents the next voltage domain)
  41 *      ...
  42 *      `- device m (represents mth voltage domain)
  43 * device 1, 2.. are represented by opp_table structure while each opp
  44 * is represented by the opp structure.
  45 */
  46
  47/**
  48 * struct dev_pm_opp - Generic OPP description structure
  49 * @node:       opp table node. The nodes are maintained throughout the lifetime
  50 *              of boot. It is expected only an optimal set of OPPs are
  51 *              added to the library by the SoC framework.
  52 *              IMPORTANT: the opp nodes should be maintained in increasing
  53 *              order.
  54 * @kref:       for reference count of the OPP.
  55 * @available:  true/false - marks if this OPP as available or not
  56 * @dynamic:    not-created from static DT entries.
  57 * @turbo:      true if turbo (boost) OPP
  58 * @suspend:    true if suspend OPP
  59 * @removed:    flag indicating that OPP's reference is dropped by OPP core.
  60 * @pstate: Device's power domain's performance state.
  61 * @rate:       Frequency in hertz
  62 * @level:      Performance level
  63 * @supplies:   Power supplies voltage/current values
  64 * @bandwidth:  Interconnect bandwidth values
  65 * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
  66 *              frequency from any other OPP's frequency.
  67 * @required_opps: List of OPPs that are required by this OPP.
  68 * @opp_table:  points back to the opp_table struct this opp belongs to
  69 * @np:         OPP's device node.
  70 * @dentry:     debugfs dentry pointer (per opp)
  71 *
  72 * This structure stores the OPP information for a given device.
  73 */
  74struct dev_pm_opp {
  75        struct list_head node;
  76        struct kref kref;
  77
  78        bool available;
  79        bool dynamic;
  80        bool turbo;
  81        bool suspend;
  82        bool removed;
  83        unsigned int pstate;
  84        unsigned long rate;
  85        unsigned int level;
  86
  87        struct dev_pm_opp_supply *supplies;
  88        struct dev_pm_opp_icc_bw *bandwidth;
  89
  90        unsigned long clock_latency_ns;
  91
  92        struct dev_pm_opp **required_opps;
  93        struct opp_table *opp_table;
  94
  95        struct device_node *np;
  96
  97#ifdef CONFIG_DEBUG_FS
  98        struct dentry *dentry;
  99#endif
 100};
 101
 102/**
 103 * struct opp_device - devices managed by 'struct opp_table'
 104 * @node:       list node
 105 * @dev:        device to which the struct object belongs
 106 * @dentry:     debugfs dentry pointer (per device)
 107 *
 108 * This is an internal data structure maintaining the devices that are managed
 109 * by 'struct opp_table'.
 110 */
 111struct opp_device {
 112        struct list_head node;
 113        const struct device *dev;
 114
 115#ifdef CONFIG_DEBUG_FS
 116        struct dentry *dentry;
 117#endif
 118};
 119
 120enum opp_table_access {
 121        OPP_TABLE_ACCESS_UNKNOWN = 0,
 122        OPP_TABLE_ACCESS_EXCLUSIVE = 1,
 123        OPP_TABLE_ACCESS_SHARED = 2,
 124};
 125
 126/**
 127 * struct opp_table - Device opp structure
 128 * @node:       table node - contains the devices with OPPs that
 129 *              have been registered. Nodes once added are not modified in this
 130 *              table.
 131 * @head:       notifier head to notify the OPP availability changes.
 132 * @dev_list:   list of devices that share these OPPs
 133 * @opp_list:   table of opps
 134 * @kref:       for reference count of the table.
 135 * @lock:       mutex protecting the opp_list and dev_list.
 136 * @np:         struct device_node pointer for opp's DT node.
 137 * @clock_latency_ns_max: Max clock latency in nanoseconds.
 138 * @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
 139 * @shared_opp: OPP is shared between multiple devices.
 140 * @current_rate: Currently configured frequency.
 141 * @current_opp: Currently configured OPP for the table.
 142 * @suspend_opp: Pointer to OPP to be used during device suspend.
 143 * @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers.
 144 * @genpd_virt_devs: List of virtual devices for multiple genpd support.
 145 * @required_opp_tables: List of device OPP tables that are required by OPPs in
 146 *              this table.
 147 * @required_opp_count: Number of required devices.
 148 * @supported_hw: Array of version number to support.
 149 * @supported_hw_count: Number of elements in supported_hw array.
 150 * @prop_name: A name to postfix to many DT properties, while parsing them.
 151 * @clk: Device's clock handle
 152 * @regulators: Supply regulators
 153 * @regulator_count: Number of power supply regulators. Its value can be -1
 154 * (uninitialized), 0 (no opp-microvolt property) or > 0 (has opp-microvolt
 155 * property).
 156 * @paths: Interconnect path handles
 157 * @path_count: Number of interconnect paths
 158 * @enabled: Set to true if the device's resources are enabled/configured.
 159 * @genpd_performance_state: Device's power domain support performance state.
 160 * @is_genpd: Marks if the OPP table belongs to a genpd.
 161 * @set_opp: Platform specific set_opp callback
 162 * @sod_supplies: Set opp data supplies
 163 * @set_opp_data: Data to be passed to set_opp callback
 164 * @dentry:     debugfs dentry pointer of the real device directory (not links).
 165 * @dentry_name: Name of the real dentry.
 166 *
 167 * @voltage_tolerance_v1: In percentage, for v1 bindings only.
 168 *
 169 * This is an internal data structure maintaining the link to opps attached to
 170 * a device. This structure is not meant to be shared to users as it is
 171 * meant for book keeping and private to OPP library.
 172 */
 173struct opp_table {
 174        struct list_head node, lazy;
 175
 176        struct blocking_notifier_head head;
 177        struct list_head dev_list;
 178        struct list_head opp_list;
 179        struct kref kref;
 180        struct mutex lock;
 181
 182        struct device_node *np;
 183        unsigned long clock_latency_ns_max;
 184
 185        /* For backward compatibility with v1 bindings */
 186        unsigned int voltage_tolerance_v1;
 187
 188        unsigned int parsed_static_opps;
 189        enum opp_table_access shared_opp;
 190        unsigned long current_rate;
 191        struct dev_pm_opp *current_opp;
 192        struct dev_pm_opp *suspend_opp;
 193
 194        struct mutex genpd_virt_dev_lock;
 195        struct device **genpd_virt_devs;
 196        struct opp_table **required_opp_tables;
 197        unsigned int required_opp_count;
 198
 199        unsigned int *supported_hw;
 200        unsigned int supported_hw_count;
 201        const char *prop_name;
 202        struct clk *clk;
 203        struct regulator **regulators;
 204        int regulator_count;
 205        struct icc_path **paths;
 206        unsigned int path_count;
 207        bool enabled;
 208        bool genpd_performance_state;
 209        bool is_genpd;
 210
 211        int (*set_opp)(struct dev_pm_set_opp_data *data);
 212        struct dev_pm_opp_supply *sod_supplies;
 213        struct dev_pm_set_opp_data *set_opp_data;
 214
 215#ifdef CONFIG_DEBUG_FS
 216        struct dentry *dentry;
 217        char dentry_name[NAME_MAX];
 218#endif
 219};
 220
 221/* Routines internal to opp core */
 222void dev_pm_opp_get(struct dev_pm_opp *opp);
 223bool _opp_remove_all_static(struct opp_table *opp_table);
 224void _get_opp_table_kref(struct opp_table *opp_table);
 225int _get_opp_count(struct opp_table *opp_table);
 226struct opp_table *_find_opp_table(struct device *dev);
 227struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
 228struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
 229void _opp_free(struct dev_pm_opp *opp);
 230int _opp_compare_key(struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
 231int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table, bool rate_not_available);
 232int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
 233void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
 234struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
 235void _put_opp_list_kref(struct opp_table *opp_table);
 236void _required_opps_available(struct dev_pm_opp *opp, int count);
 237
 238static inline bool lazy_linking_pending(struct opp_table *opp_table)
 239{
 240        return unlikely(!list_empty(&opp_table->lazy));
 241}
 242
 243#ifdef CONFIG_OF
 244void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
 245void _of_clear_opp_table(struct opp_table *opp_table);
 246struct opp_table *_managed_opp(struct device *dev, int index);
 247void _of_opp_free_required_opps(struct opp_table *opp_table,
 248                                struct dev_pm_opp *opp);
 249#else
 250static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
 251static inline void _of_clear_opp_table(struct opp_table *opp_table) {}
 252static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
 253static inline void _of_opp_free_required_opps(struct opp_table *opp_table,
 254                                              struct dev_pm_opp *opp) {}
 255#endif
 256
 257#ifdef CONFIG_DEBUG_FS
 258void opp_debug_remove_one(struct dev_pm_opp *opp);
 259void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
 260void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
 261void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
 262#else
 263static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
 264
 265static inline void opp_debug_create_one(struct dev_pm_opp *opp,
 266                                        struct opp_table *opp_table) { }
 267
 268static inline void opp_debug_register(struct opp_device *opp_dev,
 269                                      struct opp_table *opp_table) { }
 270
 271static inline void opp_debug_unregister(struct opp_device *opp_dev,
 272                                        struct opp_table *opp_table)
 273{ }
 274#endif          /* DEBUG_FS */
 275
 276#endif          /* __DRIVER_OPP_H__ */
 277