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 715df61a5dSClément Léger * @get_rates_array: Get the supported clock rates as array 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 74*9a3248fcSEtienne Carriere * 75*9a3248fcSEtienne Carriere * All clock operations are expected to execute in a interruptible thread 76*9a3248fcSEtienne Carriere * context at the exclusion of power management sequence where non secure 77*9a3248fcSEtienne 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 */ 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 */ 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 /** 215f8c1dacbSEtienne Carriere * clk_get_rates_array() - Get supported rates as an array 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 * 253f8c1dacbSEtienne Carriere * The clock is printed with the debug trace level. 254f8c1dacbSEtienne Carriere */ 255cd04d138SEtienne Carriere void clk_print_tree(void); 256f7299836SEtienne Carriere #else 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