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