| 1 |
|
| 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 |
|
| 23 | struct clk;
|
| 24 | struct regulator;
|
| 25 |
|
| 26 |
|
| 27 | extern struct mutex opp_table_lock;
|
| 28 |
|
| 29 | extern struct list_head opp_tables;
|
| 30 |
|
| 31 |
|
| 32 | #define OPP_CONFIG_CLK BIT(0)
|
| 33 | #define OPP_CONFIG_REGULATOR BIT(1)
|
| 34 | #define OPP_CONFIG_REGULATOR_HELPER BIT(2)
|
| 35 | #define OPP_CONFIG_PROP_NAME BIT(3)
|
| 36 | #define OPP_CONFIG_SUPPORTED_HW BIT(4)
|
| 37 | #define OPP_CONFIG_REQUIRED_DEV BIT(5)
|
| 38 |
|
| 39 | |
| 40 | * struct opp_config_data - data for set config operations
|
| 41 | * @opp_table: OPP table
|
| 42 | * @flags: OPP config flags
|
| 43 | * @required_dev_index: The position in the array of required_devs
|
| 44 | *
|
| 45 | * This structure stores the OPP config information for each OPP table
|
| 46 | * configuration by the callers.
|
| 47 |
|
| 48 | struct opp_config_data {
|
| 49 | struct opp_table *opp_table;
|
| 50 | unsigned int flags;
|
| 51 | unsigned int required_dev_index;
|
| 52 | };
|
| 53 |
|
| 54 | |
| 55 | * struct dev_pm_opp_icc_bw - Interconnect bandwidth values
|
| 56 | * @avg: Average bandwidth corresponding to this OPP (in icc units)
|
| 57 | * @peak: Peak bandwidth corresponding to this OPP (in icc units)
|
| 58 | *
|
| 59 | * This structure stores the bandwidth values for a single interconnect path.
|
| 60 |
|
| 61 | struct dev_pm_opp_icc_bw {
|
| 62 | u32 avg;
|
| 63 | u32 peak;
|
| 64 | };
|
| 65 |
|
| 66 | |
| 67 | * Internal data structure organization with the OPP layer library is as
|
| 68 | * follows:
|
| 69 | * opp_tables (root)
|
| 70 | * |- device 1 (represents voltage domain 1)
|
| 71 | * | |- opp 1 (availability, freq, voltage)
|
| 72 | * | |- opp 2 ..
|
| 73 | * ... ...
|
| 74 | * | `- opp n ..
|
| 75 | * |- device 2 (represents the next voltage domain)
|
| 76 | * ...
|
| 77 | * `- device m (represents mth voltage domain)
|
| 78 | * device 1, 2.. are represented by opp_table structure while each opp
|
| 79 | * is represented by the opp structure.
|
| 80 |
|
| 81 |
|
| 82 | |
| 83 | * struct dev_pm_opp - Generic OPP description structure
|
| 84 | * @node: opp table node. The nodes are maintained throughout the lifetime
|
| 85 | * of boot. It is expected only an optimal set of OPPs are
|
| 86 | * added to the library by the SoC framework.
|
| 87 | * IMPORTANT: the opp nodes should be maintained in increasing
|
| 88 | * order.
|
| 89 | * @kref: for reference count of the OPP.
|
| 90 | * @available: true/false - marks if this OPP as available or not
|
| 91 | * @dynamic: not-created from static DT entries.
|
| 92 | * @turbo: true if turbo (boost) OPP
|
| 93 | * @suspend: true if suspend OPP
|
| 94 | * @removed: flag indicating that OPP's reference is dropped by OPP core.
|
| 95 | * @rates: Frequencies in hertz
|
| 96 | * @level: Performance level
|
| 97 | * @supplies: Power supplies voltage/current values
|
| 98 | * @bandwidth: Interconnect bandwidth values
|
| 99 | * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
|
| 100 | * frequency from any other OPP's frequency.
|
| 101 | * @required_opps: List of OPPs that are required by this OPP.
|
| 102 | * @opp_table: points back to the opp_table struct this opp belongs to
|
| 103 | * @np: OPP's device node.
|
| 104 | * @dentry: debugfs dentry pointer (per opp)
|
| 105 | *
|
| 106 | * This structure stores the OPP information for a given device.
|
| 107 |
|
| 108 | struct dev_pm_opp {
|
| 109 | struct list_head node;
|
| 110 | struct kref kref;
|
| 111 |
|
| 112 | bool available;
|
| 113 | bool dynamic;
|
| 114 | bool turbo;
|
| 115 | bool suspend;
|
| 116 | bool removed;
|
| 117 | unsigned long *rates;
|
| 118 | unsigned int level;
|
| 119 |
|
| 120 | struct dev_pm_opp_supply *supplies;
|
| 121 | struct dev_pm_opp_icc_bw *bandwidth;
|
| 122 |
|
| 123 | unsigned long clock_latency_ns;
|
| 124 |
|
| 125 | struct dev_pm_opp **required_opps;
|
| 126 | struct opp_table *opp_table;
|
| 127 |
|
| 128 | struct device_node *np;
|
| 129 |
|
| 130 | #ifdef CONFIG_DEBUG_FS
|
| 131 | struct dentry *dentry;
|
| 132 | const char *of_name;
|
| 133 | #endif
|
| 134 | };
|
| 135 |
|
| 136 | |
| 137 | * struct opp_device - devices managed by 'struct opp_table'
|
| 138 | * @node: list node
|
| 139 | * @dev: device to which the struct object belongs
|
| 140 | * @dentry: debugfs dentry pointer (per device)
|
| 141 | *
|
| 142 | * This is an internal data structure maintaining the devices that are managed
|
| 143 | * by 'struct opp_table'.
|
| 144 |
|
| 145 | struct opp_device {
|
| 146 | struct list_head node;
|
| 147 | const struct device *dev;
|
| 148 |
|
| 149 | #ifdef CONFIG_DEBUG_FS
|
| 150 | struct dentry *dentry;
|
| 151 | #endif
|
| 152 | };
|
| 153 |
|
| 154 | enum opp_table_access {
|
| 155 | OPP_TABLE_ACCESS_UNKNOWN = 0,
|
| 156 | OPP_TABLE_ACCESS_EXCLUSIVE = 1,
|
| 157 | OPP_TABLE_ACCESS_SHARED = 2,
|
| 158 | };
|
| 159 |
|
| 160 | |
| 161 | * struct opp_table - Device opp structure
|
| 162 | * @node: table node - contains the devices with OPPs that
|
| 163 | * have been registered. Nodes once added are not modified in this
|
| 164 | * table.
|
| 165 | * @head: notifier head to notify the OPP availability changes.
|
| 166 | * @dev_list: list of devices that share these OPPs
|
| 167 | * @opp_list: table of opps
|
| 168 | * @kref: for reference count of the table.
|
| 169 | * @lock: mutex protecting the opp_list and dev_list.
|
| 170 | * @np: struct device_node pointer for opp's DT node.
|
| 171 | * @clock_latency_ns_max: Max clock latency in nanoseconds.
|
| 172 | * @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
|
| 173 | * @shared_opp: OPP is shared between multiple devices.
|
| 174 | * @current_rate_single_clk: Currently configured frequency for single clk.
|
| 175 | * @current_opp: Currently configured OPP for the table.
|
| 176 | * @suspend_opp: Pointer to OPP to be used during device suspend.
|
| 177 | * @required_opp_tables: List of device OPP tables that are required by OPPs in
|
| 178 | * this table.
|
| 179 | * @required_devs: List of devices for required OPP tables.
|
| 180 | * @required_opp_count: Number of required devices.
|
| 181 | * @supported_hw: Array of version number to support.
|
| 182 | * @supported_hw_count: Number of elements in supported_hw array.
|
| 183 | * @prop_name: A name to postfix to many DT properties, while parsing them.
|
| 184 | * @config_clks: Platform specific config_clks() callback.
|
| 185 | * @clks: Device's clock handles, for multiple clocks.
|
| 186 | * @clk: Device's clock handle, for single clock.
|
| 187 | * @clk_count: Number of clocks.
|
| 188 | * @config_regulators: Platform specific config_regulators() callback.
|
| 189 | * @regulators: Supply regulators
|
| 190 | * @regulator_count: Number of power supply regulators. Its value can be -1
|
| 191 | * (uninitialized), 0 (no opp-microvolt property) or > 0 (has opp-microvolt
|
| 192 | * property).
|
| 193 | * @paths: Interconnect path handles
|
| 194 | * @path_count: Number of interconnect paths
|
| 195 | * @enabled: Set to true if the device's resources are enabled/configured.
|
| 196 | * @is_genpd: Marks if the OPP table belongs to a genpd.
|
| 197 | * @dentry: debugfs dentry pointer of the real device directory (not links).
|
| 198 | * @dentry_name: Name of the real dentry.
|
| 199 | *
|
| 200 | * @voltage_tolerance_v1: In percentage, for v1 bindings only.
|
| 201 | *
|
| 202 | * This is an internal data structure maintaining the link to opps attached to
|
| 203 | * a device. This structure is not meant to be shared to users as it is
|
| 204 | * meant for book keeping and private to OPP library.
|
| 205 |
|
| 206 | struct opp_table {
|
| 207 | struct list_head node, lazy;
|
| 208 |
|
| 209 | struct blocking_notifier_head head;
|
| 210 | struct list_head dev_list;
|
| 211 | struct list_head opp_list;
|
| 212 | struct kref kref;
|
| 213 | struct mutex lock;
|
| 214 |
|
| 215 | struct device_node *np;
|
| 216 | unsigned long clock_latency_ns_max;
|
| 217 |
|
| 218 |
|
| 219 | unsigned int voltage_tolerance_v1;
|
| 220 |
|
| 221 | unsigned int parsed_static_opps;
|
| 222 | enum opp_table_access shared_opp;
|
| 223 | unsigned long current_rate_single_clk;
|
| 224 | struct dev_pm_opp *current_opp;
|
| 225 | struct dev_pm_opp *suspend_opp;
|
| 226 |
|
| 227 | struct opp_table **required_opp_tables;
|
| 228 | struct device **required_devs;
|
| 229 | unsigned int required_opp_count;
|
| 230 |
|
| 231 | unsigned int *supported_hw;
|
| 232 | unsigned int supported_hw_count;
|
| 233 | const char *prop_name;
|
| 234 | config_clks_t config_clks;
|
| 235 | struct clk **clks;
|
| 236 | struct clk *clk;
|
| 237 | int clk_count;
|
| 238 | config_regulators_t config_regulators;
|
| 239 | struct regulator **regulators;
|
| 240 | int regulator_count;
|
| 241 | struct icc_path **paths;
|
| 242 | unsigned int path_count;
|
| 243 | bool enabled;
|
| 244 | bool is_genpd;
|
| 245 |
|
| 246 | #ifdef CONFIG_DEBUG_FS
|
| 247 | struct dentry *dentry;
|
| 248 | char dentry_name[NAME_MAX];
|
| 249 | #endif
|
| 250 | };
|
| 251 |
|
| 252 |
|
| 253 | bool _opp_remove_all_static(struct opp_table *opp_table);
|
| 254 | int _get_opp_count(struct opp_table *opp_table);
|
| 255 | struct opp_table *_find_opp_table(struct device *dev);
|
| 256 | struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
|
| 257 | struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
|
| 258 | void _opp_free(struct dev_pm_opp *opp);
|
| 259 | int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
|
| 260 | int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
|
| 261 | int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic);
|
| 262 | void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
|
| 263 | struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
|
| 264 | void _required_opps_available(struct dev_pm_opp *opp, int count);
|
| 265 |
|
| 266 | static inline bool lazy_linking_pending(struct opp_table *opp_table)
|
| 267 | {
|
| 268 | return unlikely(!list_empty(&opp_table->lazy));
|
| 269 | }
|
| 270 |
|
| 271 | #ifdef CONFIG_OF
|
| 272 | void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
|
| 273 | void _of_clear_opp_table(struct opp_table *opp_table);
|
| 274 | struct opp_table *_managed_opp(struct device *dev, int index);
|
| 275 | void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp);
|
| 276 | #else
|
| 277 | static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
|
| 278 | static inline void _of_clear_opp_table(struct opp_table *opp_table) {}
|
| 279 | static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
|
| 280 | static inline void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) {}
|
| 281 | #endif
|
| 282 |
|
| 283 | #ifdef CONFIG_DEBUG_FS
|
| 284 | void opp_debug_remove_one(struct dev_pm_opp *opp);
|
| 285 | void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
|
| 286 | void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
|
| 287 | void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
|
| 288 | #else
|
| 289 | static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
|
| 290 |
|
| 291 | static inline void opp_debug_create_one(struct dev_pm_opp *opp,
|
| 292 | struct opp_table *opp_table) { }
|
| 293 |
|
| 294 | static inline void opp_debug_register(struct opp_device *opp_dev,
|
| 295 | struct opp_table *opp_table) { }
|
| 296 |
|
| 297 | static inline void opp_debug_unregister(struct opp_device *opp_dev,
|
| 298 | struct opp_table *opp_table)
|
| 299 | { }
|
| 300 | #endif
|
| 301 |
|
| 302 | #endif
|