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 */
208baaac1cSEtienne Carriere #define CLK_SET_PARENT_PRE_ENABLE BIT(5) /* enable new parent if needed */
212305544bSClément Léger
222305544bSClément Léger /**
232305544bSClément Léger * struct clk - Clock structure
242305544bSClément Léger *
252305544bSClément Léger * @name: Clock name
262305544bSClément Léger * @priv: Private data for the clock provider
272305544bSClément Léger * @ops: Clock operations
282305544bSClément Léger * @parent: Current parent
292305544bSClément Léger * @rate: Current clock rate (cached after init or rate change)
302305544bSClément Léger * @flags: Specific clock flags
312305544bSClément Léger * @enabled_count: Enable/disable reference counter
322305544bSClément Léger * @num_parents: Number of parents
332305544bSClément Léger * @parents: Array of possible parents of the clock
34cd04d138SEtienne Carriere * @link: Link the clock list
352305544bSClément Léger */
362305544bSClément Léger struct clk {
372305544bSClément Léger const char *name;
382305544bSClément Léger void *priv;
392305544bSClément Léger const struct clk_ops *ops;
402305544bSClément Léger struct clk *parent;
412305544bSClément Léger unsigned long rate;
422305544bSClément Léger unsigned int flags;
432305544bSClément Léger struct refcount enabled_count;
44cd04d138SEtienne Carriere #ifdef CFG_DRIVERS_CLK_PRINT_TREE
452b13eca6SEtienne Carriere SLIST_ENTRY(clk) link;
46cd04d138SEtienne Carriere #endif
472305544bSClément Léger size_t num_parents;
482305544bSClément Léger struct clk *parents[];
492305544bSClément Léger };
502305544bSClément Léger
512305544bSClément Léger /**
5259db7f68SEtienne Carriere * struct clk_duty_cycle - Encoding the duty cycle ratio of a clock
5359db7f68SEtienne Carriere *
5459db7f68SEtienne Carriere * @num: Numerator of the duty cycle ratio
5559db7f68SEtienne Carriere * @den: Denominator of the duty cycle ratio
5659db7f68SEtienne Carriere */
5759db7f68SEtienne Carriere struct clk_duty_cycle {
5859db7f68SEtienne Carriere unsigned int num;
5959db7f68SEtienne Carriere unsigned int den;
6059db7f68SEtienne Carriere };
6159db7f68SEtienne Carriere
6259db7f68SEtienne Carriere /**
63f8c1dacbSEtienne Carriere * struct clk_ops - Clock operations
642305544bSClément Léger *
652305544bSClément Léger * @enable: Enable the clock
662305544bSClément Léger * @disable: Disable the clock
672305544bSClément Léger * @set_parent: Set the clock parent based on index
682305544bSClément Léger * @get_parent: Get the current parent index of the clock
692305544bSClément Léger * @set_rate: Set the clock rate
702305544bSClément Léger * @get_rate: Get the clock rate
71fa31123dSEtienne Carriere * @get_rates_array: Get the supported clock rates as array in ascending order
728fbc0056SEtienne Carriere * @get_rates_steps: Get support clock rates by min/max/step representation
7359db7f68SEtienne Carriere * @get_duty_cycle: Get duty cytcle of the clock
749a3248fcSEtienne Carriere *
759a3248fcSEtienne Carriere * All clock operations are expected to execute in a interruptible thread
769a3248fcSEtienne Carriere * context at the exclusion of power management sequence where non secure
779a3248fcSEtienne Carriere * world is not operating (power off, suspend, resume).
782305544bSClément Léger */
792305544bSClément Léger struct clk_ops {
802305544bSClément Léger TEE_Result (*enable)(struct clk *clk);
812305544bSClément Léger void (*disable)(struct clk *clk);
822305544bSClément Léger TEE_Result (*set_parent)(struct clk *clk, size_t index);
832305544bSClément Léger size_t (*get_parent)(struct clk *clk);
842305544bSClément Léger TEE_Result (*set_rate)(struct clk *clk, unsigned long rate,
852305544bSClément Léger unsigned long parent_rate);
862305544bSClément Léger unsigned long (*get_rate)(struct clk *clk,
872305544bSClément Léger unsigned long parent_rate);
885df61a5dSClément Léger TEE_Result (*get_rates_array)(struct clk *clk, size_t start_index,
895df61a5dSClément Léger unsigned long *rates, size_t *nb_elts);
908fbc0056SEtienne Carriere TEE_Result (*get_rates_steps)(struct clk *clk, unsigned long *min,
918fbc0056SEtienne Carriere unsigned long *max, unsigned long *step);
9259db7f68SEtienne Carriere TEE_Result (*get_duty_cycle)(struct clk *clk,
9359db7f68SEtienne Carriere struct clk_duty_cycle *duty_cycle);
942305544bSClément Léger };
952305544bSClément Léger
962305544bSClément Léger /**
97f8c1dacbSEtienne Carriere * clk_get_name() - Return the clock name
982305544bSClément Léger *
992305544bSClément Léger * @clk: Clock for which the name is needed
1002305544bSClément Léger * Return a const char * pointing to the clock name
1012305544bSClément Léger */
clk_get_name(struct clk * clk)1022305544bSClément Léger static inline const char *clk_get_name(struct clk *clk)
1032305544bSClément Léger {
1042305544bSClément Léger return clk->name;
1052305544bSClément Léger }
1062305544bSClément Léger
1072305544bSClément Léger /**
108f8c1dacbSEtienne Carriere * clk_alloc() - Allocate a clock structure
1092305544bSClément Léger *
1102305544bSClément Léger * @name: Clock name
1112305544bSClément Léger * @ops: Clock operations
1122305544bSClément Léger * @parent_clks: Parents of the clock
1132305544bSClément Léger * @parent_count: Number of parents of the clock
1142305544bSClément Léger *
1152305544bSClément Léger * Return a clock struct properly initialized or NULL if allocation failed
1162305544bSClément Léger */
1172305544bSClément Léger struct clk *clk_alloc(const char *name, const struct clk_ops *ops,
1182305544bSClément Léger struct clk **parent_clks, size_t parent_count);
1192305544bSClément Léger
1202305544bSClément Léger /**
121f8c1dacbSEtienne Carriere * clk_free() - Free a clock structure
1222305544bSClément Léger *
1232305544bSClément Léger * @clk: Clock to be freed or NULL
1242305544bSClément Léger */
1252305544bSClément Léger void clk_free(struct clk *clk);
1262305544bSClément Léger
1272305544bSClément Léger /**
128f8c1dacbSEtienne Carriere * clk_register() - Register a clock within the clock framework
1292305544bSClément Léger *
1302305544bSClément Léger * @clk: Clock struct to be registered
1312305544bSClément Léger * Return a TEE_Result compliant value
1322305544bSClément Léger */
1332305544bSClément Léger TEE_Result clk_register(struct clk *clk);
1342305544bSClément Léger
1352305544bSClément Léger /**
136f8c1dacbSEtienne Carriere * clk_get_rate() - Get clock rate
1372305544bSClément Léger *
1382305544bSClément Léger * @clk: Clock for which the rate is needed
1392305544bSClément Léger * Return the clock rate in Hz
1402305544bSClément Léger */
1412305544bSClément Léger unsigned long clk_get_rate(struct clk *clk);
1422305544bSClément Léger
1432305544bSClément Léger /**
144f8c1dacbSEtienne Carriere * clk_set_rate() - Set a clock rate
1452305544bSClément Léger *
1462305544bSClément Léger * @clk: Clock to be set with the rate
1472305544bSClément Léger * @rate: Rate to set in Hz
1482305544bSClément Léger * Return a TEE_Result compliant value
1492305544bSClément Léger */
1502305544bSClément Léger TEE_Result clk_set_rate(struct clk *clk, unsigned long rate);
1512305544bSClément Léger
1522305544bSClément Léger /**
153f8c1dacbSEtienne Carriere * clk_enable() - Enable a clock and its ascendance
1542305544bSClément Léger *
1552305544bSClément Léger * @clk: Clock to be enabled
1562305544bSClément Léger * Return a TEE_Result compliant value
1572305544bSClément Léger */
1582305544bSClément Léger TEE_Result clk_enable(struct clk *clk);
1592305544bSClément Léger
1602305544bSClément Léger /**
161f8c1dacbSEtienne Carriere * clk_disable() - Disable a clock
1622305544bSClément Léger *
1632305544bSClément Léger * @clk: Clock to be disabled
1642305544bSClément Léger */
1652305544bSClément Léger void clk_disable(struct clk *clk);
1662305544bSClément Léger
1672305544bSClément Léger /**
168f8c1dacbSEtienne Carriere * clk_is_enabled() - Informative state on the clock
1696c9ed842SEtienne Carriere *
1706c9ed842SEtienne Carriere * This function is useful during specific system sequences where core
1716c9ed842SEtienne Carriere * executes atomically (primary core boot, some low power sequences).
1726c9ed842SEtienne Carriere *
1736c9ed842SEtienne Carriere * @clk: Clock refernece
1746c9ed842SEtienne Carriere */
1756c9ed842SEtienne Carriere bool clk_is_enabled(struct clk *clk);
1766c9ed842SEtienne Carriere
1776c9ed842SEtienne Carriere /**
178f8c1dacbSEtienne Carriere * clk_get_parent() - Get the current clock parent
1792305544bSClément Léger *
1802305544bSClément Léger * @clk: Clock for which the parent is needed
1812305544bSClément Léger * Return the clock parent or NULL if there is no parent
1822305544bSClément Léger */
1832305544bSClément Léger struct clk *clk_get_parent(struct clk *clk);
1842305544bSClément Léger
1852305544bSClément Léger /**
186f8c1dacbSEtienne Carriere * clk_get_num_parents() - Get the number of parents for a clock
1872305544bSClément Léger *
1882305544bSClément Léger * @clk: Clock for which the number of parents is needed
1892305544bSClément Léger * Return the number of parents
1902305544bSClément Léger */
clk_get_num_parents(struct clk * clk)1912305544bSClément Léger static inline size_t clk_get_num_parents(struct clk *clk)
1922305544bSClément Léger {
1932305544bSClément Léger return clk->num_parents;
1942305544bSClément Léger }
1952305544bSClément Léger
1962305544bSClément Léger /**
197f8c1dacbSEtienne Carriere * clk_get_parent_by_index() - Get a clock parent by its index
1982305544bSClément Léger *
1992305544bSClément Léger * @clk: Clock for which the parent is needed
2002305544bSClément Léger * @pidx: Parent index for the clock
2012305544bSClément Léger * Return the clock parent at index @pidx or NULL if out of bound
2022305544bSClément Léger */
2032305544bSClément Léger struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx);
2042305544bSClément Léger
2052305544bSClément Léger /**
206f8c1dacbSEtienne Carriere * clk_set_parent() - Set the current clock parent
2072305544bSClément Léger *
2082305544bSClément Léger * @clk: Clock for which the parent should be set
2092305544bSClément Léger * @parent: Parent clock to set
2102305544bSClément Léger * Return a TEE_Result compliant value
2112305544bSClément Léger */
2122305544bSClément Léger TEE_Result clk_set_parent(struct clk *clk, struct clk *parent);
2132305544bSClément Léger
2145df61a5dSClément Léger /**
215fa31123dSEtienne Carriere * clk_get_rates_array() - Get supported rates in ascending order
2165df61a5dSClément Léger *
2175df61a5dSClément Léger * @clk: Clock for which the rates are requested
2185df61a5dSClément Léger * @start_index: start index of requested rates
2195df61a5dSClément Léger * @rates: Array of rates allocated by caller or NULL to query count of rates
2205df61a5dSClément Léger * @nb_elts: Max number of elements that the array can hold as input. Contains
2215df61a5dSClément Léger * the number of elements that was added in the array as output.
2225df61a5dSClément Léger * Returns a TEE_Result compliant value
2235df61a5dSClément Léger */
2245df61a5dSClément Léger TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index,
2255df61a5dSClément Léger unsigned long *rates, size_t *nb_elts);
2265df61a5dSClément Léger
22759db7f68SEtienne Carriere /**
228f8c1dacbSEtienne Carriere * clk_get_rates_steps() - Get supported rates as min/max/step triplet
2298fbc0056SEtienne Carriere *
2308fbc0056SEtienne Carriere * @clk: Clock for which the rates are requested
2318fbc0056SEtienne Carriere * @min: Output min supported rate in Hz
2328fbc0056SEtienne Carriere * @max: Output max supported rate in Hz
2338fbc0056SEtienne Carriere * @step: Output rate step in Hz
2348fbc0056SEtienne Carriere * Returns a TEE_Result compliant value
2358fbc0056SEtienne Carriere */
2368fbc0056SEtienne Carriere TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min,
2378fbc0056SEtienne Carriere unsigned long *max, unsigned long *step);
2388fbc0056SEtienne Carriere
2398fbc0056SEtienne Carriere /**
240f8c1dacbSEtienne Carriere * clk_get_duty_cycle() - Get clock duty cycle
24159db7f68SEtienne Carriere *
24259db7f68SEtienne Carriere * @clk: Clock for which the duty cycle is requested
24359db7f68SEtienne Carriere * @duty: Output duty cycle info
24459db7f68SEtienne Carriere * Return a TEE_Result compliant value
24559db7f68SEtienne Carriere */
24659db7f68SEtienne Carriere TEE_Result clk_get_duty_cycle(struct clk *clk,
24759db7f68SEtienne Carriere struct clk_duty_cycle *duty_cycle);
24859db7f68SEtienne Carriere
249f7299836SEtienne Carriere #ifdef CFG_DRIVERS_CLK
250f8c1dacbSEtienne Carriere /**
251f8c1dacbSEtienne Carriere * clk_print_tree() - Print current clock tree summary to output console
252f8c1dacbSEtienne Carriere *
253*6226e120SPascal Paillet * The clock is printed with the info trace level.
254f8c1dacbSEtienne Carriere */
255cd04d138SEtienne Carriere void clk_print_tree(void);
256f7299836SEtienne Carriere #else
clk_print_tree(void)257f7299836SEtienne Carriere static inline void clk_print_tree(void)
258f7299836SEtienne Carriere {
259f7299836SEtienne Carriere }
260f7299836SEtienne Carriere #endif /* CFG_DRIVERS_CLK */
2612305544bSClément Léger #endif /* __DRIVERS_CLK_H */
262