xref: /optee_os/core/include/drivers/clk.h (revision 8fbc005673cdc5af2100277a45ea5b27d914609a)
12305544bSClément Léger /* SPDX-License-Identifier: BSD-2-Clause */
22305544bSClément Léger /*
32305544bSClément Léger  * Copyright (c) 2021, Bootlin
42305544bSClément Léger  */
52305544bSClément Léger 
62305544bSClément Léger #ifndef __DRIVERS_CLK_H
72305544bSClément Léger #define __DRIVERS_CLK_H
82305544bSClément Léger 
92305544bSClément Léger #include <kernel/refcount.h>
102305544bSClément Léger #include <stdint.h>
11cd04d138SEtienne Carriere #include <sys/queue.h>
122305544bSClément Léger #include <tee_api_types.h>
132305544bSClément Léger 
142305544bSClément Léger /* Flags for clock */
152305544bSClément Léger #define CLK_SET_RATE_GATE	BIT(0) /* must be gated across rate change */
162305544bSClément Léger #define CLK_SET_PARENT_GATE	BIT(1) /* must be gated across re-parent */
1705771552SEtienne Carriere #define CLK_DUTY_CYCLE_PARENT	BIT(2) /* forward duty cycle call to parent */
180ba7ae74SEtienne Carriere #define CLK_SET_RATE_PARENT	BIT(3) /* propagate rate change up to parent */
1920f97d98SEtienne Carriere #define CLK_SET_RATE_UNGATE	BIT(4) /* clock needs to run to set rate */
202305544bSClément Léger 
212305544bSClément Léger /**
222305544bSClément Léger  * struct clk - Clock structure
232305544bSClément Léger  *
242305544bSClément Léger  * @name: Clock name
252305544bSClément Léger  * @priv: Private data for the clock provider
262305544bSClément Léger  * @ops: Clock operations
272305544bSClément Léger  * @parent: Current parent
282305544bSClément Léger  * @rate: Current clock rate (cached after init or rate change)
292305544bSClément Léger  * @flags: Specific clock flags
302305544bSClément Léger  * @enabled_count: Enable/disable reference counter
312305544bSClément Léger  * @num_parents: Number of parents
322305544bSClément Léger  * @parents: Array of possible parents of the clock
33cd04d138SEtienne Carriere  * @link: Link the clock list
342305544bSClément Léger  */
352305544bSClément Léger struct clk {
362305544bSClément Léger 	const char *name;
372305544bSClément Léger 	void *priv;
382305544bSClément Léger 	const struct clk_ops *ops;
392305544bSClément Léger 	struct clk *parent;
402305544bSClément Léger 	unsigned long rate;
412305544bSClément Léger 	unsigned int flags;
422305544bSClément Léger 	struct refcount enabled_count;
43cd04d138SEtienne Carriere #ifdef CFG_DRIVERS_CLK_PRINT_TREE
442b13eca6SEtienne Carriere 	SLIST_ENTRY(clk) link;
45cd04d138SEtienne Carriere #endif
462305544bSClément Léger 	size_t num_parents;
472305544bSClément Léger 	struct clk *parents[];
482305544bSClément Léger };
492305544bSClément Léger 
502305544bSClément Léger /**
5159db7f68SEtienne Carriere  * struct clk_duty_cycle - Encoding the duty cycle ratio of a clock
5259db7f68SEtienne Carriere  *
5359db7f68SEtienne Carriere  * @num:	Numerator of the duty cycle ratio
5459db7f68SEtienne Carriere  * @den:	Denominator of the duty cycle ratio
5559db7f68SEtienne Carriere  */
5659db7f68SEtienne Carriere struct clk_duty_cycle {
5759db7f68SEtienne Carriere 	unsigned int num;
5859db7f68SEtienne Carriere 	unsigned int den;
5959db7f68SEtienne Carriere };
6059db7f68SEtienne Carriere 
6159db7f68SEtienne Carriere /**
622305544bSClément Léger  * struct clk_ops
632305544bSClément Léger  *
642305544bSClément Léger  * @enable: Enable the clock
652305544bSClément Léger  * @disable: Disable the clock
662305544bSClément Léger  * @set_parent: Set the clock parent based on index
672305544bSClément Léger  * @get_parent: Get the current parent index of the clock
682305544bSClément Léger  * @set_rate: Set the clock rate
692305544bSClément Léger  * @get_rate: Get the clock rate
705df61a5dSClément Léger  * @get_rates_array: Get the supported clock rates as array
71*8fbc0056SEtienne Carriere  * @get_rates_steps: Get support clock rates by min/max/step representation
7259db7f68SEtienne Carriere  * @get_duty_cycle: Get duty cytcle of the clock
732305544bSClément Léger  */
742305544bSClément Léger struct clk_ops {
752305544bSClément Léger 	TEE_Result (*enable)(struct clk *clk);
762305544bSClément Léger 	void (*disable)(struct clk *clk);
772305544bSClément Léger 	TEE_Result (*set_parent)(struct clk *clk, size_t index);
782305544bSClément Léger 	size_t (*get_parent)(struct clk *clk);
792305544bSClément Léger 	TEE_Result (*set_rate)(struct clk *clk, unsigned long rate,
802305544bSClément Léger 			       unsigned long parent_rate);
812305544bSClément Léger 	unsigned long (*get_rate)(struct clk *clk,
822305544bSClément Léger 				  unsigned long parent_rate);
835df61a5dSClément Léger 	TEE_Result (*get_rates_array)(struct clk *clk, size_t start_index,
845df61a5dSClément Léger 				      unsigned long *rates, size_t *nb_elts);
85*8fbc0056SEtienne Carriere 	TEE_Result (*get_rates_steps)(struct clk *clk, unsigned long *min,
86*8fbc0056SEtienne Carriere 				      unsigned long *max, unsigned long *step);
8759db7f68SEtienne Carriere 	TEE_Result (*get_duty_cycle)(struct clk *clk,
8859db7f68SEtienne Carriere 				     struct clk_duty_cycle *duty_cycle);
892305544bSClément Léger };
902305544bSClément Léger 
912305544bSClément Léger /**
922305544bSClément Léger  * Return the clock name
932305544bSClément Léger  *
942305544bSClément Léger  * @clk: Clock for which the name is needed
952305544bSClément Léger  * Return a const char * pointing to the clock name
962305544bSClément Léger  */
972305544bSClément Léger static inline const char *clk_get_name(struct clk *clk)
982305544bSClément Léger {
992305544bSClément Léger 	return clk->name;
1002305544bSClément Léger }
1012305544bSClément Léger 
1022305544bSClément Léger /**
1032305544bSClément Léger  * clk_alloc - Allocate a clock structure
1042305544bSClément Léger  *
1052305544bSClément Léger  * @name: Clock name
1062305544bSClément Léger  * @ops: Clock operations
1072305544bSClément Léger  * @parent_clks: Parents of the clock
1082305544bSClément Léger  * @parent_count: Number of parents of the clock
1092305544bSClément Léger  *
1102305544bSClément Léger  * Return a clock struct properly initialized or NULL if allocation failed
1112305544bSClément Léger  */
1122305544bSClément Léger struct clk *clk_alloc(const char *name, const struct clk_ops *ops,
1132305544bSClément Léger 		      struct clk **parent_clks, size_t parent_count);
1142305544bSClément Léger 
1152305544bSClément Léger /**
1162305544bSClément Léger  * clk_free - Free a clock structure
1172305544bSClément Léger  *
1182305544bSClément Léger  * @clk: Clock to be freed or NULL
1192305544bSClément Léger  */
1202305544bSClément Léger void clk_free(struct clk *clk);
1212305544bSClément Léger 
1222305544bSClément Léger /**
1232305544bSClément Léger  * clk_register - Register a clock within the clock framework
1242305544bSClément Léger  *
1252305544bSClément Léger  * @clk: Clock struct to be registered
1262305544bSClément Léger  * Return a TEE_Result compliant value
1272305544bSClément Léger  */
1282305544bSClément Léger TEE_Result clk_register(struct clk *clk);
1292305544bSClément Léger 
1302305544bSClément Léger /**
1312305544bSClément Léger  * clk_get_rate - Get clock rate
1322305544bSClément Léger  *
1332305544bSClément Léger  * @clk: Clock for which the rate is needed
1342305544bSClément Léger  * Return the clock rate in Hz
1352305544bSClément Léger  */
1362305544bSClément Léger unsigned long clk_get_rate(struct clk *clk);
1372305544bSClément Léger 
1382305544bSClément Léger /**
1392305544bSClément Léger  * clk_set_rate - Set a clock rate
1402305544bSClément Léger  *
1412305544bSClément Léger  * @clk: Clock to be set with the rate
1422305544bSClément Léger  * @rate: Rate to set in Hz
1432305544bSClément Léger  * Return a TEE_Result compliant value
1442305544bSClément Léger  */
1452305544bSClément Léger TEE_Result clk_set_rate(struct clk *clk, unsigned long rate);
1462305544bSClément Léger 
1472305544bSClément Léger /**
1482305544bSClément Léger  * clk_enable - Enable a clock and its ascendance
1492305544bSClément Léger  *
1502305544bSClément Léger  * @clk: Clock to be enabled
1512305544bSClément Léger  * Return a TEE_Result compliant value
1522305544bSClément Léger  */
1532305544bSClément Léger TEE_Result clk_enable(struct clk *clk);
1542305544bSClément Léger 
1552305544bSClément Léger /**
1562305544bSClément Léger  * clk_disable - Disable a clock
1572305544bSClément Léger  *
1582305544bSClément Léger  * @clk: Clock to be disabled
1592305544bSClément Léger  */
1602305544bSClément Léger void clk_disable(struct clk *clk);
1612305544bSClément Léger 
1622305544bSClément Léger /**
1636c9ed842SEtienne Carriere  * clk_is_enabled - Informative state on the clock
1646c9ed842SEtienne Carriere  *
1656c9ed842SEtienne Carriere  * This function is useful during specific system sequences where core
1666c9ed842SEtienne Carriere  * executes atomically (primary core boot, some low power sequences).
1676c9ed842SEtienne Carriere  *
1686c9ed842SEtienne Carriere  * @clk: Clock refernece
1696c9ed842SEtienne Carriere  */
1706c9ed842SEtienne Carriere bool clk_is_enabled(struct clk *clk);
1716c9ed842SEtienne Carriere 
1726c9ed842SEtienne Carriere /**
1732305544bSClément Léger  * clk_get_parent - Get the current clock parent
1742305544bSClément Léger  *
1752305544bSClément Léger  * @clk: Clock for which the parent is needed
1762305544bSClément Léger  * Return the clock parent or NULL if there is no parent
1772305544bSClément Léger  */
1782305544bSClément Léger struct clk *clk_get_parent(struct clk *clk);
1792305544bSClément Léger 
1802305544bSClément Léger /**
1812305544bSClément Léger  * clk_get_num_parents - Get the number of parents for a clock
1822305544bSClément Léger  *
1832305544bSClément Léger  * @clk: Clock for which the number of parents is needed
1842305544bSClément Léger  * Return the number of parents
1852305544bSClément Léger  */
1862305544bSClément Léger static inline size_t clk_get_num_parents(struct clk *clk)
1872305544bSClément Léger {
1882305544bSClément Léger 	return clk->num_parents;
1892305544bSClément Léger }
1902305544bSClément Léger 
1912305544bSClément Léger /**
1922305544bSClément Léger  * Get a clock parent by its index
1932305544bSClément Léger  *
1942305544bSClément Léger  * @clk: Clock for which the parent is needed
1952305544bSClément Léger  * @pidx: Parent index for the clock
1962305544bSClément Léger  * Return the clock parent at index @pidx or NULL if out of bound
1972305544bSClément Léger  */
1982305544bSClément Léger struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx);
1992305544bSClément Léger 
2002305544bSClément Léger /**
2012305544bSClément Léger  * clk_set_parent - Set the current clock parent
2022305544bSClément Léger  *
2032305544bSClément Léger  * @clk: Clock for which the parent should be set
2042305544bSClément Léger  * @parent: Parent clock to set
2052305544bSClément Léger  * Return a TEE_Result compliant value
2062305544bSClément Léger  */
2072305544bSClément Léger TEE_Result clk_set_parent(struct clk *clk, struct clk *parent);
2082305544bSClément Léger 
2095df61a5dSClément Léger /**
2105df61a5dSClément Léger  * clk_get_rates_array - Get supported rates as an array
2115df61a5dSClément Léger  *
2125df61a5dSClément Léger  * @clk: Clock for which the rates are requested
2135df61a5dSClément Léger  * @start_index: start index of requested rates
2145df61a5dSClément Léger  * @rates: Array of rates allocated by caller or NULL to query count of rates
2155df61a5dSClément Léger  * @nb_elts: Max number of elements that the array can hold as input. Contains
2165df61a5dSClément Léger  * the number of elements that was added in the array as output.
2175df61a5dSClément Léger  * Returns a TEE_Result compliant value
2185df61a5dSClément Léger  */
2195df61a5dSClément Léger TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index,
2205df61a5dSClément Léger 			       unsigned long *rates, size_t *nb_elts);
2215df61a5dSClément Léger 
22259db7f68SEtienne Carriere /**
223*8fbc0056SEtienne Carriere  * clk_get_rates_steps - Get supported rates as min/max/step triplet
224*8fbc0056SEtienne Carriere  *
225*8fbc0056SEtienne Carriere  * @clk: Clock for which the rates are requested
226*8fbc0056SEtienne Carriere  * @min: Output min supported rate in Hz
227*8fbc0056SEtienne Carriere  * @max: Output max supported rate in Hz
228*8fbc0056SEtienne Carriere  * @step: Output rate step in Hz
229*8fbc0056SEtienne Carriere  * Returns a TEE_Result compliant value
230*8fbc0056SEtienne Carriere  */
231*8fbc0056SEtienne Carriere TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min,
232*8fbc0056SEtienne Carriere 			       unsigned long *max, unsigned long *step);
233*8fbc0056SEtienne Carriere 
234*8fbc0056SEtienne Carriere /**
23559db7f68SEtienne Carriere  * clk_get_duty_cycle - Get clock duty cycle
23659db7f68SEtienne Carriere  *
23759db7f68SEtienne Carriere  * @clk: Clock for which the duty cycle is requested
23859db7f68SEtienne Carriere  * @duty: Output duty cycle info
23959db7f68SEtienne Carriere  * Return a TEE_Result compliant value
24059db7f68SEtienne Carriere  */
24159db7f68SEtienne Carriere TEE_Result clk_get_duty_cycle(struct clk *clk,
24259db7f68SEtienne Carriere 			      struct clk_duty_cycle *duty_cycle);
24359db7f68SEtienne Carriere 
244aac2c716SEtienne Carriere /* Print current clock tree summary to output console with debug trace level */
245f7299836SEtienne Carriere #ifdef CFG_DRIVERS_CLK
246cd04d138SEtienne Carriere void clk_print_tree(void);
247f7299836SEtienne Carriere #else
248f7299836SEtienne Carriere static inline void clk_print_tree(void)
249f7299836SEtienne Carriere {
250f7299836SEtienne Carriere }
251f7299836SEtienne Carriere #endif /* CFG_DRIVERS_CLK */
2522305544bSClément Léger #endif /* __DRIVERS_CLK_H */
253