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