xref: /rk3399_ARM-atf/drivers/ti/clk/include/ti_clk.h (revision a28114d66a6d43db4accef5fd5d6dab6c059e584)
1*8a46d04dSKamlesh Gurudasani /*
2*8a46d04dSKamlesh Gurudasani  * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com
3*8a46d04dSKamlesh Gurudasani  *
4*8a46d04dSKamlesh Gurudasani  * SPDX-License-Identifier: BSD-3-Clause
5*8a46d04dSKamlesh Gurudasani  */
6*8a46d04dSKamlesh Gurudasani 
7*8a46d04dSKamlesh Gurudasani /*
8*8a46d04dSKamlesh Gurudasani  * TI Clock Framework API Header
9*8a46d04dSKamlesh Gurudasani  *
10*8a46d04dSKamlesh Gurudasani  * This header defines the core clock framework data structures and API
11*8a46d04dSKamlesh Gurudasani  * functions. It provides clock data types, clock driver interfaces, parent-
12*8a46d04dSKamlesh Gurudasani  * child relationships, frequency ranges, and the main API for clock
13*8a46d04dSKamlesh Gurudasani  * operations including get/put, frequency control, and state management.
14*8a46d04dSKamlesh Gurudasani  */
15*8a46d04dSKamlesh Gurudasani 
16*8a46d04dSKamlesh Gurudasani #ifndef TI_CLK_H
17*8a46d04dSKamlesh Gurudasani #define TI_CLK_H
18*8a46d04dSKamlesh Gurudasani 
19*8a46d04dSKamlesh Gurudasani #include <assert.h>
20*8a46d04dSKamlesh Gurudasani #include <stddef.h>
21*8a46d04dSKamlesh Gurudasani 
22*8a46d04dSKamlesh Gurudasani #include <common/debug.h>
23*8a46d04dSKamlesh Gurudasani #include <lib/utils_def.h>
24*8a46d04dSKamlesh Gurudasani 
25*8a46d04dSKamlesh Gurudasani #include <ti_pm_types.h>
26*8a46d04dSKamlesh Gurudasani 
27*8a46d04dSKamlesh Gurudasani /*
28*8a46d04dSKamlesh Gurudasani  * Generates a 32-bit mask that covers all set bits in a number.
29*8a46d04dSKamlesh Gurudasani  * number must be non-zero; __builtin_clz(0) is undefined behavior.
30*8a46d04dSKamlesh Gurudasani  */
ti_mask_cover_for_number(uint32_t number)31*8a46d04dSKamlesh Gurudasani static inline uint32_t ti_mask_cover_for_number(uint32_t number)
32*8a46d04dSKamlesh Gurudasani {
33*8a46d04dSKamlesh Gurudasani 	assert(number != 0U);
34*8a46d04dSKamlesh Gurudasani 	return (uint32_t)((1UL << (32U - (uint32_t)__builtin_clz(number))) - 1UL);
35*8a46d04dSKamlesh Gurudasani }
36*8a46d04dSKamlesh Gurudasani 
37*8a46d04dSKamlesh Gurudasani #define TI_MASK_COVER_FOR_NUMBER(number) ti_mask_cover_for_number(number)
38*8a46d04dSKamlesh Gurudasani 
39*8a46d04dSKamlesh Gurudasani /*
40*8a46d04dSKamlesh Gurudasani  * Initializes a clock range entry with min and max frequencies
41*8a46d04dSKamlesh Gurudasani  */
42*8a46d04dSKamlesh Gurudasani #define TI_CLK_RANGE(id, min, max)[(id)] =            \
43*8a46d04dSKamlesh Gurudasani 		{ .min_hz = (uint32_t) (min),         \
44*8a46d04dSKamlesh Gurudasani 		  .max_hz = (uint32_t) (max) }
45*8a46d04dSKamlesh Gurudasani 
46*8a46d04dSKamlesh Gurudasani /*
47*8a46d04dSKamlesh Gurudasani  * Initializes a clock default frequency entry with min, target, and max
48*8a46d04dSKamlesh Gurudasani  */
49*8a46d04dSKamlesh Gurudasani #define TI_CLK_DEFAULT(id, min, target, max)[(id)] =		\
50*8a46d04dSKamlesh Gurudasani 		{ .min_hz = (uint32_t) (min),			\
51*8a46d04dSKamlesh Gurudasani 		  .target_hz = (uint32_t) (target),		\
52*8a46d04dSKamlesh Gurudasani 		  .max_hz = (uint32_t) (max) }
53*8a46d04dSKamlesh Gurudasani 
54*8a46d04dSKamlesh Gurudasani /* Clock type identifier for divider clocks */
55*8a46d04dSKamlesh Gurudasani #define TI_CLK_TYPE_DIV	1U
56*8a46d04dSKamlesh Gurudasani 
57*8a46d04dSKamlesh Gurudasani /* Clock type identifier for multiplexer clocks */
58*8a46d04dSKamlesh Gurudasani #define TI_CLK_TYPE_MUX	2U
59*8a46d04dSKamlesh Gurudasani 
60*8a46d04dSKamlesh Gurudasani /* Allows clock to modify its parent's frequency */
61*8a46d04dSKamlesh Gurudasani #define TI_CLK_DATA_FLAG_MODIFY_PARENT_FREQ	BIT(0)
62*8a46d04dSKamlesh Gurudasani 
63*8a46d04dSKamlesh Gurudasani /* Skips hardware reinitialization during clock setup */
64*8a46d04dSKamlesh Gurudasani #define TI_CLK_DATA_FLAG_NO_HW_REINIT		BIT(2)
65*8a46d04dSKamlesh Gurudasani 
66*8a46d04dSKamlesh Gurudasani /* Clock should be enabled during power-up */
67*8a46d04dSKamlesh Gurudasani #define TI_CLK_FLAG_PWR_UP_EN			((uint8_t) BIT(0))
68*8a46d04dSKamlesh Gurudasani 
69*8a46d04dSKamlesh Gurudasani /* Clock has been initialized */
70*8a46d04dSKamlesh Gurudasani #define TI_CLK_FLAG_INITIALIZED			((uint8_t) BIT(2))
71*8a46d04dSKamlesh Gurudasani 
72*8a46d04dSKamlesh Gurudasani /*
73*8a46d04dSKamlesh Gurudasani  * Clock has a cached frequency value stored in soc_clock_values[] array.
74*8a46d04dSKamlesh Gurudasani  * Used for clocks like PLLs where the frequency is programmed and stored
75*8a46d04dSKamlesh Gurudasani  * rather than derived from parent clocks or hardware registers.
76*8a46d04dSKamlesh Gurudasani  */
77*8a46d04dSKamlesh Gurudasani #define TI_CLK_FLAG_CACHED				((uint8_t) BIT(3))
78*8a46d04dSKamlesh Gurudasani 
79*8a46d04dSKamlesh Gurudasani /* Clock hardware is disabled */
80*8a46d04dSKamlesh Gurudasani #define TI_CLK_HW_STATE_DISABLED	0U
81*8a46d04dSKamlesh Gurudasani 
82*8a46d04dSKamlesh Gurudasani /* Clock hardware is enabled */
83*8a46d04dSKamlesh Gurudasani #define TI_CLK_HW_STATE_ENABLED	1U
84*8a46d04dSKamlesh Gurudasani 
85*8a46d04dSKamlesh Gurudasani /* Clock hardware is in transition state */
86*8a46d04dSKamlesh Gurudasani #define TI_CLK_HW_STATE_TRANSITION	2U
87*8a46d04dSKamlesh Gurudasani 
88*8a46d04dSKamlesh Gurudasani /*
89*8a46d04dSKamlesh Gurudasani  * Defines a frequency range with minimum and maximum values
90*8a46d04dSKamlesh Gurudasani  */
91*8a46d04dSKamlesh Gurudasani struct ti_clk_range {
92*8a46d04dSKamlesh Gurudasani 	/* Minimum frequency in Hz */
93*8a46d04dSKamlesh Gurudasani 	uint32_t min_hz;
94*8a46d04dSKamlesh Gurudasani 	/* Maximum frequency in Hz */
95*8a46d04dSKamlesh Gurudasani 	uint32_t max_hz;
96*8a46d04dSKamlesh Gurudasani };
97*8a46d04dSKamlesh Gurudasani 
98*8a46d04dSKamlesh Gurudasani /*
99*8a46d04dSKamlesh Gurudasani  * Defines a default frequency configuration with min, target, and max
100*8a46d04dSKamlesh Gurudasani  */
101*8a46d04dSKamlesh Gurudasani struct ti_clk_default {
102*8a46d04dSKamlesh Gurudasani 	/* Minimum acceptable frequency in Hz */
103*8a46d04dSKamlesh Gurudasani 	uint32_t min_hz;
104*8a46d04dSKamlesh Gurudasani 	/* Target frequency in Hz */
105*8a46d04dSKamlesh Gurudasani 	uint32_t target_hz;
106*8a46d04dSKamlesh Gurudasani 	/* Maximum acceptable frequency in Hz */
107*8a46d04dSKamlesh Gurudasani 	uint32_t max_hz;
108*8a46d04dSKamlesh Gurudasani };
109*8a46d04dSKamlesh Gurudasani 
110*8a46d04dSKamlesh Gurudasani /*
111*8a46d04dSKamlesh Gurudasani  * Represents a clock's parent and associated divider
112*8a46d04dSKamlesh Gurudasani  */
113*8a46d04dSKamlesh Gurudasani struct ti_clk_parent {
114*8a46d04dSKamlesh Gurudasani 	/* Parent clock ID */
115*8a46d04dSKamlesh Gurudasani 	uint16_t clk;
116*8a46d04dSKamlesh Gurudasani 	/* Divider value applied to parent frequency */
117*8a46d04dSKamlesh Gurudasani 	uint8_t div;
118*8a46d04dSKamlesh Gurudasani };
119*8a46d04dSKamlesh Gurudasani 
120*8a46d04dSKamlesh Gurudasani /*
121*8a46d04dSKamlesh Gurudasani  * Clock driver-specific data (placeholder for extensibility)
122*8a46d04dSKamlesh Gurudasani  */
123*8a46d04dSKamlesh Gurudasani struct ti_clk_drv_data {
124*8a46d04dSKamlesh Gurudasani };
125*8a46d04dSKamlesh Gurudasani 
126*8a46d04dSKamlesh Gurudasani /*
127*8a46d04dSKamlesh Gurudasani  * Clock structure combining runtime state and configuration
128*8a46d04dSKamlesh Gurudasani  *
129*8a46d04dSKamlesh Gurudasani  * This structure merges what was previously ti_clk (runtime) and ti_clk_data
130*8a46d04dSKamlesh Gurudasani  * (configuration). Since everything runs from RAM on this platform, there's no
131*8a46d04dSKamlesh Gurudasani  * benefit to separating them into parallel arrays.
132*8a46d04dSKamlesh Gurudasani  */
133*8a46d04dSKamlesh Gurudasani struct ti_clk {
134*8a46d04dSKamlesh Gurudasani 	/* Runtime state - modified during operation */
135*8a46d04dSKamlesh Gurudasani 	/* Reference count for clock usage */
136*8a46d04dSKamlesh Gurudasani 	uint8_t ref_count;
137*8a46d04dSKamlesh Gurudasani 	/* Runtime flags (TI_CLK_FLAG_*) */
138*8a46d04dSKamlesh Gurudasani 	uint8_t flags;
139*8a46d04dSKamlesh Gurudasani 
140*8a46d04dSKamlesh Gurudasani 	/* Configuration - set at initialization, read-only afterwards */
141*8a46d04dSKamlesh Gurudasani 	/* Clock driver operations */
142*8a46d04dSKamlesh Gurudasani 	const struct ti_clk_drv *drv;
143*8a46d04dSKamlesh Gurudasani 	/* Driver-specific data */
144*8a46d04dSKamlesh Gurudasani 	const struct ti_clk_drv_data *data;
145*8a46d04dSKamlesh Gurudasani 	/* Parent clock and divider */
146*8a46d04dSKamlesh Gurudasani 	const struct ti_clk_parent parent;
147*8a46d04dSKamlesh Gurudasani 	/* soc_clock_values[] index for cached clocks */
148*8a46d04dSKamlesh Gurudasani 	const uint16_t freq_idx;
149*8a46d04dSKamlesh Gurudasani 	/* Index into shared range table */
150*8a46d04dSKamlesh Gurudasani 	const uint8_t range_idx;
151*8a46d04dSKamlesh Gurudasani 	/* Clock type (TI_CLK_TYPE_*) */
152*8a46d04dSKamlesh Gurudasani 	const uint8_t type;
153*8a46d04dSKamlesh Gurudasani 	/* Configuration flags (TI_CLK_DATA_FLAG_*) */
154*8a46d04dSKamlesh Gurudasani 	const uint8_t data_flags;
155*8a46d04dSKamlesh Gurudasani };
156*8a46d04dSKamlesh Gurudasani 
157*8a46d04dSKamlesh Gurudasani struct ti_clk_drv {
158*8a46d04dSKamlesh Gurudasani 	/* Perform any necessary initialization */
159*8a46d04dSKamlesh Gurudasani 	int32_t (*init)(struct ti_clk *clkp);
160*8a46d04dSKamlesh Gurudasani 
161*8a46d04dSKamlesh Gurudasani 	/*
162*8a46d04dSKamlesh Gurudasani 	 * Set the current state of a clock.
163*8a46d04dSKamlesh Gurudasani 	 */
164*8a46d04dSKamlesh Gurudasani 	bool (*set_state)(struct ti_clk *clkp, bool enabled);
165*8a46d04dSKamlesh Gurudasani 
166*8a46d04dSKamlesh Gurudasani 	/*
167*8a46d04dSKamlesh Gurudasani 	 * Get the current state of a clock.
168*8a46d04dSKamlesh Gurudasani 	 */
169*8a46d04dSKamlesh Gurudasani 	uint32_t (*get_state)(struct ti_clk *clkp);
170*8a46d04dSKamlesh Gurudasani 
171*8a46d04dSKamlesh Gurudasani 	/*
172*8a46d04dSKamlesh Gurudasani 	 * Program a clock to run at a given frequency. The minimum
173*8a46d04dSKamlesh Gurudasani 	 * and maximum frequency parameters allow the best nearest
174*8a46d04dSKamlesh Gurudasani 	 * match to be chosen. The clock tree is walked to accomplish
175*8a46d04dSKamlesh Gurudasani 	 * this.
176*8a46d04dSKamlesh Gurudasani 	 */
177*8a46d04dSKamlesh Gurudasani 	uint32_t (*set_freq)(struct ti_clk *clkp, uint32_t target_hz,
178*8a46d04dSKamlesh Gurudasani 			     uint32_t min_hz, uint32_t max_hz,
179*8a46d04dSKamlesh Gurudasani 			     bool *changed);
180*8a46d04dSKamlesh Gurudasani 
181*8a46d04dSKamlesh Gurudasani 	/*
182*8a46d04dSKamlesh Gurudasani 	 * Return the frequency this clock runs at.
183*8a46d04dSKamlesh Gurudasani 	 */
184*8a46d04dSKamlesh Gurudasani 	uint32_t (*get_freq)(struct ti_clk *clkp);
185*8a46d04dSKamlesh Gurudasani 
186*8a46d04dSKamlesh Gurudasani };
187*8a46d04dSKamlesh Gurudasani 
188*8a46d04dSKamlesh Gurudasani /* The table of clock structures */
189*8a46d04dSKamlesh Gurudasani extern struct ti_clk soc_clocks[];
190*8a46d04dSKamlesh Gurudasani extern const size_t soc_clock_count;
191*8a46d04dSKamlesh Gurudasani 
192*8a46d04dSKamlesh Gurudasani /* The table of shared const clock ranges */
193*8a46d04dSKamlesh Gurudasani extern const struct ti_clk_range soc_clock_ranges[];
194*8a46d04dSKamlesh Gurudasani extern const size_t soc_clock_range_count;
195*8a46d04dSKamlesh Gurudasani 
196*8a46d04dSKamlesh Gurudasani /* The table of default frequencies */
197*8a46d04dSKamlesh Gurudasani extern const struct ti_clk_default soc_clock_freq_defaults[];
198*8a46d04dSKamlesh Gurudasani extern const size_t soc_clock_freq_defaults_count;
199*8a46d04dSKamlesh Gurudasani 
200*8a46d04dSKamlesh Gurudasani /*
201*8a46d04dSKamlesh Gurudasani  * The table of cached clock frequency values.
202*8a46d04dSKamlesh Gurudasani  * Some clocks (e.g., PLLs) store their programmed frequency in this array
203*8a46d04dSKamlesh Gurudasani  * indexed by clk->freq_idx, rather than deriving it from parent clocks or
204*8a46d04dSKamlesh Gurudasani  * hardware registers. Clocks using this mechanism have TI_CLK_FLAG_CACHED set.
205*8a46d04dSKamlesh Gurudasani  */
206*8a46d04dSKamlesh Gurudasani extern uint32_t soc_clock_values[];
207*8a46d04dSKamlesh Gurudasani extern const size_t soc_clock_value_count;
208*8a46d04dSKamlesh Gurudasani 
209*8a46d04dSKamlesh Gurudasani /**
210*8a46d04dSKamlesh Gurudasani  * ti_clk_value_set_freq() - Sets frequency for clocks with cached frequency values
211*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to modify (must have valid freq_idx)
212*8a46d04dSKamlesh Gurudasani  * @target_hz: Target frequency in Hz
213*8a46d04dSKamlesh Gurudasani  * @min_hz: Minimum acceptable frequency
214*8a46d04dSKamlesh Gurudasani  * @max_hz: Maximum acceptable frequency
215*8a46d04dSKamlesh Gurudasani  * @changed: Output parameter indicating if frequency changed
216*8a46d04dSKamlesh Gurudasani  *
217*8a46d04dSKamlesh Gurudasani  * Used by clocks that store their frequency in soc_clock_values[] array
218*8a46d04dSKamlesh Gurudasani  * (e.g., PLLs). The frequency is validated against min/max range and stored
219*8a46d04dSKamlesh Gurudasani  * at the index specified by clk->freq_idx.
220*8a46d04dSKamlesh Gurudasani  *
221*8a46d04dSKamlesh Gurudasani  * Return: Target frequency in Hz on success, 0 on failure
222*8a46d04dSKamlesh Gurudasani  */
223*8a46d04dSKamlesh Gurudasani uint32_t ti_clk_value_set_freq(struct ti_clk *clkp, uint32_t target_hz,
224*8a46d04dSKamlesh Gurudasani 			       uint32_t min_hz, uint32_t max_hz,
225*8a46d04dSKamlesh Gurudasani 			       bool *changed);
226*8a46d04dSKamlesh Gurudasani 
227*8a46d04dSKamlesh Gurudasani /**
228*8a46d04dSKamlesh Gurudasani  * ti_clk_value_get_freq() - Gets the cached frequency value for a clock
229*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to query (must have valid freq_idx)
230*8a46d04dSKamlesh Gurudasani  *
231*8a46d04dSKamlesh Gurudasani  * Retrieves the frequency stored in soc_clock_values[] array for clocks
232*8a46d04dSKamlesh Gurudasani  * that cache their frequency (e.g., PLLs). The value is read from the index
233*8a46d04dSKamlesh Gurudasani  * specified by clk->freq_idx.
234*8a46d04dSKamlesh Gurudasani  *
235*8a46d04dSKamlesh Gurudasani  * Return: The cached frequency in Hz, or 0 if freq_idx is out of bounds
236*8a46d04dSKamlesh Gurudasani  */
237*8a46d04dSKamlesh Gurudasani uint32_t ti_clk_value_get_freq(struct ti_clk *clkp);
238*8a46d04dSKamlesh Gurudasani 
239*8a46d04dSKamlesh Gurudasani /**
240*8a46d04dSKamlesh Gurudasani  * ti_clk_get_parent_freq() - Gets the parent clock's current frequency
241*8a46d04dSKamlesh Gurudasani  * @clkp: The clock whose parent frequency to retrieve
242*8a46d04dSKamlesh Gurudasani  *
243*8a46d04dSKamlesh Gurudasani  * Return: Parent frequency in Hz
244*8a46d04dSKamlesh Gurudasani  */
245*8a46d04dSKamlesh Gurudasani uint32_t ti_clk_get_parent_freq(struct ti_clk *clkp);
246*8a46d04dSKamlesh Gurudasani 
247*8a46d04dSKamlesh Gurudasani /**
248*8a46d04dSKamlesh Gurudasani  * ti_clk_generic_set_freq_parent() - Generic frequency setter that adjusts parent frequency
249*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to modify
250*8a46d04dSKamlesh Gurudasani  * @parent: The parent clock
251*8a46d04dSKamlesh Gurudasani  * @target_hz: Target frequency in Hz
252*8a46d04dSKamlesh Gurudasani  * @min_hz: Minimum acceptable frequency
253*8a46d04dSKamlesh Gurudasani  * @max_hz: Maximum acceptable frequency
254*8a46d04dSKamlesh Gurudasani  * @changed: Output parameter indicating if frequency changed
255*8a46d04dSKamlesh Gurudasani  * @div: Divider from parent to child (child = parent/div).
256*8a46d04dSKamlesh Gurudasani  *        Used to translate child frequency to parent frequency.
257*8a46d04dSKamlesh Gurudasani  *
258*8a46d04dSKamlesh Gurudasani  * Return: Best frequency found in Hz, 0 on failure
259*8a46d04dSKamlesh Gurudasani  */
260*8a46d04dSKamlesh Gurudasani uint32_t ti_clk_generic_set_freq_parent(struct ti_clk *clkp, struct ti_clk *parent,
261*8a46d04dSKamlesh Gurudasani 					uint32_t target_hz, uint32_t min_hz,
262*8a46d04dSKamlesh Gurudasani 					uint32_t max_hz,
263*8a46d04dSKamlesh Gurudasani 					bool *changed, uint32_t div);
264*8a46d04dSKamlesh Gurudasani 
265*8a46d04dSKamlesh Gurudasani /**
266*8a46d04dSKamlesh Gurudasani  * ti_clk_set_freq() - Sets a clock's frequency
267*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to modify
268*8a46d04dSKamlesh Gurudasani  * @target_hz: Target frequency in Hz
269*8a46d04dSKamlesh Gurudasani  * @min_hz: Minimum acceptable frequency
270*8a46d04dSKamlesh Gurudasani  * @max_hz: Maximum acceptable frequency
271*8a46d04dSKamlesh Gurudasani  * @changed: Output parameter indicating if frequency changed
272*8a46d04dSKamlesh Gurudasani  *
273*8a46d04dSKamlesh Gurudasani  * Return: Best frequency found in Hz, 0 on failure
274*8a46d04dSKamlesh Gurudasani  */
275*8a46d04dSKamlesh Gurudasani uint32_t ti_clk_set_freq(struct ti_clk *clkp, uint32_t target_hz, uint32_t min_hz,
276*8a46d04dSKamlesh Gurudasani 			 uint32_t max_hz, bool *changed);
277*8a46d04dSKamlesh Gurudasani 
278*8a46d04dSKamlesh Gurudasani /**
279*8a46d04dSKamlesh Gurudasani  * ti_clk_get_freq() - Gets a clock's current frequency
280*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to query
281*8a46d04dSKamlesh Gurudasani  *
282*8a46d04dSKamlesh Gurudasani  * Return: Current frequency in Hz
283*8a46d04dSKamlesh Gurudasani  */
284*8a46d04dSKamlesh Gurudasani uint32_t ti_clk_get_freq(struct ti_clk *clkp);
285*8a46d04dSKamlesh Gurudasani 
286*8a46d04dSKamlesh Gurudasani /**
287*8a46d04dSKamlesh Gurudasani  * ti_clk_get_state() - Gets a clock's hardware state
288*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to query
289*8a46d04dSKamlesh Gurudasani  *
290*8a46d04dSKamlesh Gurudasani  * Return: Clock state (TI_CLK_HW_STATE_*)
291*8a46d04dSKamlesh Gurudasani  */
292*8a46d04dSKamlesh Gurudasani uint32_t ti_clk_get_state(struct ti_clk *clkp);
293*8a46d04dSKamlesh Gurudasani 
294*8a46d04dSKamlesh Gurudasani /**
295*8a46d04dSKamlesh Gurudasani  * ti_clk_set_state() - Sets a clock's hardware state (enable/disable)
296*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to modify
297*8a46d04dSKamlesh Gurudasani  * @enable: True to enable, false to disable
298*8a46d04dSKamlesh Gurudasani  *
299*8a46d04dSKamlesh Gurudasani  * Return: True if successful
300*8a46d04dSKamlesh Gurudasani  */
301*8a46d04dSKamlesh Gurudasani bool ti_clk_set_state(struct ti_clk *clkp, bool enable);
302*8a46d04dSKamlesh Gurudasani 
303*8a46d04dSKamlesh Gurudasani /**
304*8a46d04dSKamlesh Gurudasani  * ti_clk_get() - Increments a clock's reference count and enables it
305*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to get
306*8a46d04dSKamlesh Gurudasani  *
307*8a46d04dSKamlesh Gurudasani  * Return: True if successful
308*8a46d04dSKamlesh Gurudasani  */
309*8a46d04dSKamlesh Gurudasani bool ti_clk_get(struct ti_clk *clkp);
310*8a46d04dSKamlesh Gurudasani 
311*8a46d04dSKamlesh Gurudasani /**
312*8a46d04dSKamlesh Gurudasani  * ti_clk_put() - Decrements a clock's reference count and disables if zero
313*8a46d04dSKamlesh Gurudasani  * @clkp: The clock to put
314*8a46d04dSKamlesh Gurudasani  */
315*8a46d04dSKamlesh Gurudasani void ti_clk_put(struct ti_clk *clkp);
316*8a46d04dSKamlesh Gurudasani 
317*8a46d04dSKamlesh Gurudasani /**
318*8a46d04dSKamlesh Gurudasani  * ti_clk_init() - Initializes the TI clock framework
319*8a46d04dSKamlesh Gurudasani  *
320*8a46d04dSKamlesh Gurudasani  * Performs one pass of clock initialization. Clocks are processed in array
321*8a46d04dSKamlesh Gurudasani  * order. Each clock is skipped if its parent clock is not yet initialized,
322*8a46d04dSKamlesh Gurudasani  * allowing the function to handle parent-child dependencies.
323*8a46d04dSKamlesh Gurudasani  *
324*8a46d04dSKamlesh Gurudasani  * Design for arbitrary clock ordering:
325*8a46d04dSKamlesh Gurudasani  * - The function can be called multiple times to initialize clocks with
326*8a46d04dSKamlesh Gurudasani  *   multi-level dependencies
327*8a46d04dSKamlesh Gurudasani  * - Each call initializes clocks whose parent dependencies are now met
328*8a46d04dSKamlesh Gurudasani  * - Returns 0 if progress was made, -EAGAIN if no progress possible
329*8a46d04dSKamlesh Gurudasani  *
330*8a46d04dSKamlesh Gurudasani  * Current implementation:
331*8a46d04dSKamlesh Gurudasani  * - The clock table is topologically sorted (parents before children)
332*8a46d04dSKamlesh Gurudasani  * - A single call initializes all clocks
333*8a46d04dSKamlesh Gurudasani  * - Multiple calls are not necessary but are safe (subsequent calls
334*8a46d04dSKamlesh Gurudasani  *   detect all clocks initialized and return 0 quickly)
335*8a46d04dSKamlesh Gurudasani  *
336*8a46d04dSKamlesh Gurudasani  * Return: 0 on success (clocks initialized or no clocks need init),
337*8a46d04dSKamlesh Gurudasani  *         -EAGAIN if no progress made (circular dependency - fatal),
338*8a46d04dSKamlesh Gurudasani  *         -ENODEV if a power-up clock failed to enable,
339*8a46d04dSKamlesh Gurudasani  *         or other negative error code on failure
340*8a46d04dSKamlesh Gurudasani  */
341*8a46d04dSKamlesh Gurudasani int32_t ti_clk_init(void);
342*8a46d04dSKamlesh Gurudasani 
343*8a46d04dSKamlesh Gurudasani /**
344*8a46d04dSKamlesh Gurudasani  * ti_clk_drop_pwr_up_en() - Clears power-up enable flag on all clocks
345*8a46d04dSKamlesh Gurudasani  */
346*8a46d04dSKamlesh Gurudasani void ti_clk_drop_pwr_up_en(void);
347*8a46d04dSKamlesh Gurudasani 
348*8a46d04dSKamlesh Gurudasani /**
349*8a46d04dSKamlesh Gurudasani  * ti_clk_id_valid() - Determine if a clock ID is valid.
350*8a46d04dSKamlesh Gurudasani  * @id: The internal clock API ID.
351*8a46d04dSKamlesh Gurudasani  *
352*8a46d04dSKamlesh Gurudasani  * Return: True if the clock ID refers to a valid SoC clock, false otherwise
353*8a46d04dSKamlesh Gurudasani  */
ti_clk_id_valid(ti_clk_idx_t id)354*8a46d04dSKamlesh Gurudasani static inline bool ti_clk_id_valid(ti_clk_idx_t id)
355*8a46d04dSKamlesh Gurudasani {
356*8a46d04dSKamlesh Gurudasani 	return (id < soc_clock_count) && (soc_clocks[id].drv != NULL);
357*8a46d04dSKamlesh Gurudasani }
358*8a46d04dSKamlesh Gurudasani 
359*8a46d04dSKamlesh Gurudasani /*
360*8a46d04dSKamlesh Gurudasani  * Lookup an internal clock based on a clock ID
361*8a46d04dSKamlesh Gurudasani  *
362*8a46d04dSKamlesh Gurudasani  * This does a lookup of a clock based on the clock ID.
363*8a46d04dSKamlesh Gurudasani  */
ti_clk_lookup(ti_clk_idx_t id)364*8a46d04dSKamlesh Gurudasani static inline struct ti_clk *ti_clk_lookup(ti_clk_idx_t id)
365*8a46d04dSKamlesh Gurudasani {
366*8a46d04dSKamlesh Gurudasani 	return ti_clk_id_valid(id) ? (soc_clocks + id) : NULL;
367*8a46d04dSKamlesh Gurudasani }
368*8a46d04dSKamlesh Gurudasani 
369*8a46d04dSKamlesh Gurudasani /*
370*8a46d04dSKamlesh Gurudasani  * Return the clock ID based on a clock pointer.
371*8a46d04dSKamlesh Gurudasani  *
372*8a46d04dSKamlesh Gurudasani  * The clock pointer is just an index into the array of clocks. This is
373*8a46d04dSKamlesh Gurudasani  * used to return a clock ID. This function has no error checking for NULL
374*8a46d04dSKamlesh Gurudasani  * pointers.
375*8a46d04dSKamlesh Gurudasani  */
ti_clk_id(struct ti_clk * clkp)376*8a46d04dSKamlesh Gurudasani static inline ti_clk_idx_t ti_clk_id(struct ti_clk *clkp)
377*8a46d04dSKamlesh Gurudasani {
378*8a46d04dSKamlesh Gurudasani 	return (ti_clk_idx_t) (clkp - soc_clocks);
379*8a46d04dSKamlesh Gurudasani }
380*8a46d04dSKamlesh Gurudasani 
381*8a46d04dSKamlesh Gurudasani /*
382*8a46d04dSKamlesh Gurudasani  * Return a shared clock range with bounds checking.
383*8a46d04dSKamlesh Gurudasani  *
384*8a46d04dSKamlesh Gurudasani  * The clock infrastructure contains a set of shared clock ranges. Many
385*8a46d04dSKamlesh Gurudasani  * clocks and PLLs have min/max ranges. However, these min/max ranges can
386*8a46d04dSKamlesh Gurudasani  * take up a significant amount of storage. As many clocks share the same
387*8a46d04dSKamlesh Gurudasani  * ranges, we use a shared table of ranges. The clocks can then index that
388*8a46d04dSKamlesh Gurudasani  * table with a small uint8_t.
389*8a46d04dSKamlesh Gurudasani  */
ti_clk_get_range(ti_clk_idx_t idx)390*8a46d04dSKamlesh Gurudasani static inline const struct ti_clk_range *ti_clk_get_range(ti_clk_idx_t idx)
391*8a46d04dSKamlesh Gurudasani {
392*8a46d04dSKamlesh Gurudasani 	if (idx >= soc_clock_range_count) {
393*8a46d04dSKamlesh Gurudasani 		return NULL;
394*8a46d04dSKamlesh Gurudasani 	}
395*8a46d04dSKamlesh Gurudasani 	return soc_clock_ranges + idx;
396*8a46d04dSKamlesh Gurudasani }
397*8a46d04dSKamlesh Gurudasani 
398*8a46d04dSKamlesh Gurudasani /**
399*8a46d04dSKamlesh Gurudasani  * ti_clk_set_value() - Set a cached clock frequency value with bounds checking.
400*8a46d04dSKamlesh Gurudasani  * @idx: The index into soc_clock_values[] array (from clk->freq_idx).
401*8a46d04dSKamlesh Gurudasani  * @value_hz: The frequency value in Hz to cache.
402*8a46d04dSKamlesh Gurudasani  *
403*8a46d04dSKamlesh Gurudasani  * Stores a frequency value in the soc_clock_values[] array for clocks that
404*8a46d04dSKamlesh Gurudasani  * cache their frequency (e.g., PLLs with TI_CLK_FLAG_CACHED set). Validates
405*8a46d04dSKamlesh Gurudasani  * the index is within array bounds before writing.
406*8a46d04dSKamlesh Gurudasani  *
407*8a46d04dSKamlesh Gurudasani  * Return: True if the value was cached successfully, false if index is out of bounds.
408*8a46d04dSKamlesh Gurudasani  */
ti_clk_set_value(uint16_t idx,uint32_t value_hz)409*8a46d04dSKamlesh Gurudasani static inline bool ti_clk_set_value(uint16_t idx, uint32_t value_hz)
410*8a46d04dSKamlesh Gurudasani {
411*8a46d04dSKamlesh Gurudasani 	if (idx >= soc_clock_value_count) {
412*8a46d04dSKamlesh Gurudasani 		return false;
413*8a46d04dSKamlesh Gurudasani 	}
414*8a46d04dSKamlesh Gurudasani 	soc_clock_values[idx] = value_hz;
415*8a46d04dSKamlesh Gurudasani 	return true;
416*8a46d04dSKamlesh Gurudasani }
417*8a46d04dSKamlesh Gurudasani 
418*8a46d04dSKamlesh Gurudasani /**
419*8a46d04dSKamlesh Gurudasani  * ti_clk_get_value() - Get a cached clock frequency value with bounds checking.
420*8a46d04dSKamlesh Gurudasani  * @idx: The index into soc_clock_values[] array (from clk->freq_idx).
421*8a46d04dSKamlesh Gurudasani  *
422*8a46d04dSKamlesh Gurudasani  * Retrieves a frequency value from the soc_clock_values[] array for clocks
423*8a46d04dSKamlesh Gurudasani  * that cache their frequency (e.g., PLLs with TI_CLK_FLAG_CACHED set).
424*8a46d04dSKamlesh Gurudasani  * Validates the index is within array bounds before reading.
425*8a46d04dSKamlesh Gurudasani  *
426*8a46d04dSKamlesh Gurudasani  * Return: The cached frequency value in Hz, or 0 if index is out of bounds.
427*8a46d04dSKamlesh Gurudasani  */
ti_clk_get_value(uint16_t idx)428*8a46d04dSKamlesh Gurudasani static inline uint32_t ti_clk_get_value(uint16_t idx)
429*8a46d04dSKamlesh Gurudasani {
430*8a46d04dSKamlesh Gurudasani 	if (idx >= soc_clock_value_count) {
431*8a46d04dSKamlesh Gurudasani 		return 0;
432*8a46d04dSKamlesh Gurudasani 	}
433*8a46d04dSKamlesh Gurudasani 	return soc_clock_values[idx];
434*8a46d04dSKamlesh Gurudasani }
435*8a46d04dSKamlesh Gurudasani 
436*8a46d04dSKamlesh Gurudasani #endif /* TI_CLK_H */
437