ANDROID: GKI: clk: Add support for voltage voting

This change adds support for voltage voting in the clock framework. This
will NOT be carried over to newer kernels.

Bug: 150506629
Signed-off-by: David Collins <collinsd@codeaurora.org>
Signed-off-by: David Dai <daidavid1@codeaurora.org>
Signed-off-by: Deepak Katragadda <dkatraga@codeaurora.org>
Signed-off-by: Shefali Jain <shefjain@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Taniya Das <tdas@codeaurora.org>
[saravanak: Squashed the following commits and dropped some debug code
	    and code whose functionality that's replaced by clk_sync_state()
	ff5ce501ba clk: do not vote for vdd_class level with 0 Hz rate_max
	96f0596cc0 clk: provider: cleanup of unused use_max_uV
	83d12e55ba clk: Always vote INT_MAX as maximum voltage for a rail
	352850e657 clk: handle reentrant clk_set_rate() calls from clock supply regulators
	0d8060cd6b clk: add bus voting to rate_get, rate_set, enable_set debug functions
	d4c36a3d10 clk: remove prepare lock and bus voting in clk_debug_print_hw
	813f666281 clk: add bus voting ops for debug purposes
	7e0561072d clk: qcom: Fix return value check for round rate during clock registration
	c4540b8ee3 clk: fix conflicting bit for measure clock flag
	fa9b30447f clk: correct vdd_class voting scheme used during clock rate changes
	61dad2894f clk: Move VDD voltage voting from core clock to top clock
	0cbef8b6fc clk: qcom: Add support to log PLL/RCGR values in case of failure
	bcc43f7a19 clk: qcom: Add support for debugfs measure clock
	1ac9516f74 clk: Export the clock driver's voltage voting APIs
	c4316254d2 clk: add/modify debugfs support for clocks
	d30b895f21 clk: move check for CLK_ENABLE_HAND_OFF at unused tree
	11032174ca clk: Add support to provide OPP tables for clocks
	f349485712 clk: Add support to vote to regulator framework from clk framework
	81286aed66 clk: Check for failure at clk_change_rate
	6a4951a830 clk: qcom: clk-voter: Add support for voter clocks
	b904878a04 clk: Add support to set custom flags with clk_set_flags ]
Signed-off-by: Saravana Kannan <saravanak@google.com>
Change-Id: I95574f11053e8f3762c8d660183ce5004ff5cc5b
This commit is contained in:
Saravana Kannan
2020-02-03 18:49:54 -08:00
parent 1d887ea976
commit 3179a1a38d
2 changed files with 832 additions and 34 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_clk.h>
#include <linux/mutex.h>
#ifdef CONFIG_COMMON_CLK
@@ -41,6 +42,12 @@
/* duty cycle call may be forwarded to the parent clock */
#define CLK_DUTY_CYCLE_PARENT BIT(13)
#define CLK_DONT_HOLD_STATE BIT(14) /* Don't hold state */
#define CLK_ENABLE_HAND_OFF BIT(15) /* enable clock when registered. */
/*
* hand-off enable_count & prepare_count
* to first consumer that enables clk
*/
#define CLK_IS_MEASURE BIT(16) /* measure clock */
struct clk;
struct clk_hw;
@@ -203,6 +210,18 @@ struct clk_duty {
* directory is provided as an argument. Called with
* prepare_lock held. Returns 0 on success, -EERROR otherwise.
*
* @set_flags: Set custom flags which deal with hardware specifics. Returns 0
* on success, -EERROR otherwise.
*
* @list_registers: Queries the hardware to get the current register contents.
* This callback is optional.
*
* @list_rate: On success, return the nth supported frequency for a given
* clock that is below rate_max. Return -ENXIO in case there is
* no frequency table.
*
* @bus_vote: Votes for bandwidth on certain config slaves to connect
* ports in order to gain access to clock controllers.
*
* The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
* implementations to split any work between atomic (enable) and sleepable
@@ -247,6 +266,12 @@ struct clk_ops {
struct clk_duty *duty);
void (*init)(struct clk_hw *hw);
void (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
int (*set_flags)(struct clk_hw *hw, unsigned int flags);
void (*list_registers)(struct seq_file *f,
struct clk_hw *hw);
long (*list_rate)(struct clk_hw *hw, unsigned int n,
unsigned long rate_max);
void (*bus_vote)(struct clk_hw *hw, bool enable);
};
/**
@@ -258,15 +283,86 @@ struct clk_ops {
* @parent_names: array of string names for all possible parents
* @num_parents: number of possible parents
* @flags: framework-level hints and quirks
* @vdd_class: voltage scaling requirement class
* @rate_max: maximum clock rate in Hz supported at each voltage level
* @num_rate_max: number of maximum voltage level supported
* @bus_cl_id: client id registered with the bus driver used for bw votes
*/
struct clk_init_data {
const char *name;
const struct clk_ops *ops;
const char * const *parent_names;
u8 num_parents;
unsigned int num_parents;
unsigned long flags;
struct clk_vdd_class *vdd_class;
unsigned long *rate_max;
int num_rate_max;
unsigned int bus_cl_id;
};
struct regulator;
/**
* struct clk_vdd_class - Voltage scaling class
* @class_name: name of the class
* @regulator: array of regulators
* @num_regulators: size of regulator array. Standard regulator APIs will be
used if this field > 0
* @set_vdd: function to call when applying a new voltage setting
* @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then
regulator
* @level_votes: array of votes for each level
* @num_levels: specifies the size of level_votes array
* @skip_handoff: do not vote for the max possible voltage during init
* @cur_level: the currently set voltage level
* @lock: lock to protect this struct
*/
struct clk_vdd_class {
const char *class_name;
struct regulator **regulator;
int num_regulators;
int (*set_vdd)(struct clk_vdd_class *v_class, int level);
int *vdd_uv;
int *level_votes;
int num_levels;
bool skip_handoff;
unsigned long cur_level;
struct mutex lock;
};
#define DEFINE_VDD_CLASS(_name, _set_vdd, _num_levels) \
struct clk_vdd_class _name = { \
.class_name = #_name, \
.set_vdd = _set_vdd, \
.level_votes = (int [_num_levels]) {}, \
.num_levels = _num_levels, \
.cur_level = _num_levels, \
.lock = __MUTEX_INITIALIZER(_name.lock) \
}
#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv) \
struct clk_vdd_class _name = { \
.class_name = #_name, \
.vdd_uv = _vdd_uv, \
.regulator = (struct regulator * [_num_regulators]) {}, \
.num_regulators = _num_regulators, \
.level_votes = (int [_num_levels]) {}, \
.num_levels = _num_levels, \
.cur_level = _num_levels, \
.lock = __MUTEX_INITIALIZER(_name.lock) \
}
#define DEFINE_VDD_REGS_INIT(_name, _num_regulators) \
struct clk_vdd_class _name = { \
.class_name = #_name, \
.regulator = (struct regulator * [_num_regulators]) {}, \
.num_regulators = _num_regulators, \
.lock = __MUTEX_INITIALIZER(_name.lock) \
}
int clk_vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
int clk_unvote_vdd_level(struct clk_vdd_class *vdd_class, int level);
/**
* struct clk_hw - handle for traversing from a struct clk to its corresponding
* hardware-specific structure. struct clk_hw should be declared within struct
@@ -804,6 +900,11 @@ void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
unsigned long max_rate);
unsigned long clk_aggregate_rate(struct clk_hw *hw,
const struct clk_core *parent);
int clk_vote_rate_vdd(struct clk_core *core, unsigned long rate);
void clk_unvote_rate_vdd(struct clk_core *core, unsigned long rate);
static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
{
dst->clk = src->clk;