Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3179a1a3 authored by Saravana Kannan's avatar Saravana Kannan
Browse files

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: default avatarDavid Collins <collinsd@codeaurora.org>
Signed-off-by: default avatarDavid Dai <daidavid1@codeaurora.org>
Signed-off-by: default avatarDeepak Katragadda <dkatraga@codeaurora.org>
Signed-off-by: default avatarShefali Jain <shefjain@codeaurora.org>
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
Signed-off-by: default avatarTaniya 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()
	ff5ce501 clk: do not vote for vdd_class level with 0 Hz rate_max
	96f0596c clk: provider: cleanup of unused use_max_uV
	83d12e55 clk: Always vote INT_MAX as maximum voltage for a rail
	352850e6 clk: handle reentrant clk_set_rate() calls from clock supply regulators
	0d8060cd clk: add bus voting to rate_get, rate_set, enable_set debug functions
	d4c36a3d clk: remove prepare lock and bus voting in clk_debug_print_hw
	813f6662 clk: add bus voting ops for debug purposes
	7e056107 clk: qcom: Fix return value check for round rate during clock registration
	c4540b8e clk: fix conflicting bit for measure clock flag
	fa9b3044 clk: correct vdd_class voting scheme used during clock rate changes
	61dad289 clk: Move VDD voltage voting from core clock to top clock
	0cbef8b6 clk: qcom: Add support to log PLL/RCGR values in case of failure
	bcc43f7a clk: qcom: Add support for debugfs measure clock
	1ac9516f clk: Export the clock driver's voltage voting APIs
	c4316254 clk: add/modify debugfs support for clocks
	d30b895f clk: move check for CLK_ENABLE_HAND_OFF at unused tree
	11032174 clk: Add support to provide OPP tables for clocks
	f3494857 clk: Add support to vote to regulator framework from clk framework
	81286aed clk: Check for failure at clk_change_rate
	6a4951a8 clk: qcom: clk-voter: Add support for voter clocks
	b904878a clk: Add support to set custom flags with clk_set_flags ]
Signed-off-by: default avatarSaravana Kannan <saravanak@google.com>
Change-Id: I95574f11053e8f3762c8d660183ce5004ff5cc5b
parent 1d887ea9
Loading
Loading
Loading
Loading
+730 −33

File changed.

Preview size limit exceeded, changes collapsed.

+102 −1
Original line number Diff line number Diff line
@@ -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;