xref: /rk3399_ARM-atf/drivers/ti/pd/include/ti_device_clk.h (revision 945de0f736703b42f64fbc1256fe1e1ed7749d3d)
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  * Device Clock Management API
9  *
10  * This header defines the device clock API for managing clocks attached to
11  * devices. It provides clock type definitions, device clock data structures,
12  * and functions for clock control including enable/disable, parent selection,
13  * frequency configuration, and state management.
14  */
15 
16 #ifndef TI_DEVICE_CLK_H
17 #define TI_DEVICE_CLK_H
18 
19 #include <ti_build_assert.h>
20 #include <ti_pm_types.h>
21 
22 /*
23  * Sentinel value for invalid or non-existent device clock ID
24  *
25  * Used to indicate that a device clock index is invalid, uninitialized, or
26  * that no clock exists at the requested position. Functions returning
27  * ti_dev_clk_idx_t use this value to signal errors or missing clocks.
28  */
29 #define TI_DEV_CLK_ID_NONE ((ti_dev_clk_idx_t) (~0U))
30 
31 /*
32  * Input clock type.
33  *
34  * This is a normal clock, it's an input to the IP from elsewhere.
35  */
36 #define TI_DEV_CLK_TABLE_TYPE_INPUT	0U
37 
38 /*
39  * Mux clock type.
40  *
41  * This is a clock mux that is meant to be controlled directly. The potential
42  * parents of the mux are listed after the mux as TYPE_PARENT. Set frequency
43  * calls to a mux are passed to the current parent.
44  */
45 #define TI_DEV_CLK_TABLE_TYPE_MUX		1U
46 
47 /*
48  * Mux parent clock type.
49  *
50  * This is a potential parent for a mux. Normal clocks are set to follow the
51  * device state (requested when device is enabled, unrequested otherwise) but
52  * mux parents are set to always unrequested by default. If they are selected
53  * they will get a ref count from the mux clock.
54  *
55  * Mux parents are present so they can be enabled and configured before being
56  * selected via the mux.
57  */
58 #define TI_DEV_CLK_TABLE_TYPE_PARENT	2U
59 
60 /*
61  * Output clock type.
62  *
63  * This is an output clock from the device. Setting the frequency informs
64  * potential consumers of the frequency but otherwise has no effect.
65  */
66 #define TI_DEV_CLK_TABLE_TYPE_OUTPUT	3U
67 
68 struct ti_device;
69 
70 /*
71  * Const clock device data
72  *
73  * This is the fixed data for tracking clocks attached to devices.
74  */
75 struct ti_dev_clk_data {
76 	/* Type of table entry */
77 	uint8_t type;
78 
79 	/*
80 	 * Modifying the frequency of this clock will attempt to modify
81 	 * the parent freq.
82 	 */
83 	uint8_t modify_parent_freq;
84 
85 	/*
86 	 * Clock divider, not valid for output, max 255 for parent otherwise
87 	 * up to USHORT_MAX/8.
88 	 */
89 	uint16_t div;
90 
91 	/* For mux, the number of parents, for parents the index for the mux */
92 	uint8_t idx;
93 
94 	/* For mux, the number of reserved parent slots */
95 	uint8_t n_reserved_parents;
96 
97 	/* Which SoC clock this plugs into */
98 	uint16_t clk;
99 };
100 
101 /*
102  * Dynamic clock device data
103  *
104  * This tracks the current state of a device attached clock via flags.
105  * This is just how the upstream clock is configured for the current
106  * device. The upstream clock still has its own data and state.
107  *
108  * A pointer to a bss that has been reserved for this data is pointed
109  * to by the device. If there is only one clock on the device, the field
110  * is shared with the device flags and a forced cast is made to return
111  * the field.
112  */
113 struct ti_dev_clk {
114 	uint8_t flags;
115 };
116 
117 /* Declare a device clock of type input */
118 #define TI_DEV_CLK(base, id, parent, _div)[(base) + (id)] =	\
119 		{ .clk = (parent), .div = (_div),		\
120 		  .type = TI_DEV_CLK_TABLE_TYPE_INPUT,		\
121 		  .modify_parent_freq	= 1U }
122 
123 /* Declare a device clock of type mux */
124 #define TI_DEV_CLK_MUX(base, id, parent, _div, n_parents, n_reserved)[(base) + (id)] = \
125 		{ .clk = (parent), .div = (_div),			\
126 		  .type = TI_DEV_CLK_TABLE_TYPE_MUX,			\
127 		  .idx = (n_parents),					\
128 		  .n_reserved_parents = (n_reserved),			\
129 		  .modify_parent_freq = 1U }
130 
131 /*
132  * Declare a device clock of type mux parent. To match clk_mux_parent,
133  * divider here can only be 8 bit
134  */
135 #define TI_DEV_CLK_PARENT(base, id, parent, _div, _idx)[(base) + (id)] =	\
136 		{ .clk = (parent),					\
137 		  .type = TI_DEV_CLK_TABLE_TYPE_PARENT,			\
138 		  .div = (_div) + (int) TI_BUILD_ASSERT_OR_ZERO(_div < 256), \
139 		  .idx = (_idx),					\
140 		  .modify_parent_freq	= 1U }
141 
142 /* Declare a device clock of type output. */
143 #define TI_DEV_CLK_OUTPUT(base, id, child)[(base) + (id)] =		\
144 		{ .clk = (child),					\
145 		  .type = TI_DEV_CLK_TABLE_TYPE_OUTPUT,			\
146 		  .modify_parent_freq = 1U }
147 
148 /*
149  * Get the dynamic data associated with a device clock.
150  */
151 struct ti_dev_clk *ti_get_dev_clk(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
152 
153 /*
154  * Get the const data associated with a device clock.
155  */
156 const struct ti_dev_clk_data *ti_get_dev_clk_data(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
157 
158 /*
159  * Lookup the clock API clock associated with a device clock index.
160  */
161 struct ti_clk *ti_dev_get_clk(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
162 
163 /**
164  * ti_device_clk_set_gated() - Set the gate/ungate property for a device clock
165  * @dev: The device ID that the clock is connected to.
166  * @clk_idx: The index of the clock on this device.
167  * @gated: True to gate the clock, false to ungate.
168  *
169  * This sets/clears the gate/ungate property for a device clock. If a clock
170  * is gated, the internal clock API clock that it references is not ref
171  * counted. If it is ungated, then the refcount is incremented when the device
172  * is enabled and decremented when the device is disabled.
173  *
174  * Return: True if operation succeeded, false if it failed or clk_idx was invalid.
175  */
176 bool ti_device_clk_set_gated(struct ti_device *dev, ti_dev_clk_idx_t clk_idx, bool gated);
177 
178 /**
179  * ti_device_clk_get_sw_gated() - Get the current state of the gated flag.
180  * @dev: The device ID that the clock is connected to.
181  * @clk_idx: The index of the clock on this device.
182  *
183  * Return: The current state of the gated flag as set by ti_device_clk_set_gated.
184  */
185 bool ti_device_clk_get_sw_gated(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
186 
187 /**
188  * ti_device_clk_set_parent() - Change a device mux clocks's parent.
189  * @dev: The device ID that the clock mux and new parent is connected to.
190  * @clk_idx: The index of the clock mux on this device.
191  * @parent_idx: The index of the new clock parent on this device.
192  *
193  * Return: True if parent change was successful, false if it
194  *         failed or one of the clock indexes was invalid.
195  */
196 bool ti_device_clk_set_parent(struct ti_device *dev, ti_dev_clk_idx_t clk_idx,
197 			      ti_dev_clk_idx_t parent_idx);
198 
199 /*
200  * Get the current parent of a device mux clock.
201  */
202 ti_dev_clk_idx_t ti_device_clk_get_parent(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
203 
204 /*
205  * Get the number of parents of a given device mux clock.
206  */
207 ti_dev_clk_idx_t ti_device_clk_get_num_parents(struct ti_device *dev,
208 					       ti_dev_clk_idx_t clk_idx);
209 
210 /**
211  * ti_device_clk_set_freq() - Set the frequency of a device's clock
212  * @dev: The device ID that the clock is connected to.
213  * @clk_idx: The index of the clock on this device.
214  * @min_freq_hz: The minimum acceptable frequency (Hz).
215  * @target_freq_hz: The target frequency in Hz. The clock API will
216  *                  attempt to set a frequency as close as possible.
217  * @max_freq_hz: The maximum acceptable frequency (Hz).
218  *
219  * This locates the correct clock and calls the internal clock API
220  * set function. If the clock is a mux type, we instead send the request to
221  * the parent. This is because calling set freq on the mux may switch the mux
222  * which is not what we want on muxes that are exposed on devices.
223  *
224  * Return: True if the new frequency was accepted, false otherwise.
225  */
226 bool ti_device_clk_set_freq(struct ti_device *dev, ti_dev_clk_idx_t clk_idx,
227 			    uint32_t min_freq_hz, uint32_t target_freq_hz,
228 			    uint32_t max_freq_hz);
229 
230 /**
231  * ti_device_clk_get_freq() - Get the current frequency of a device clock.
232  * @dev: The device ID that the clock is connected to.
233  * @clk_idx: The index of the clock on this device.
234  *
235  * Return: Current clock frequency in Hz if enabled, or the
236  *         frequency it would run at if enabled. Returns 0 if
237  *         clk_idx is invalid or the clock cannot run.
238  */
239 uint32_t ti_device_clk_get_freq(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
240 
241 /**
242  * ti_device_clk_enable() - Enable a device clock
243  * @dev: The device ID that the clock is connected to.
244  * @clk_idx: The index of the clock on this device.
245  *
246  * This is called by the device pm code for each clock when the device is
247  * enabled. This allows the device clk code to take appropriate action.
248  */
249 void ti_device_clk_enable(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
250 
251 /**
252  * ti_device_clk_disable() - Disable a device clock
253  * @dev: The device ID that the clock is connected to.
254  * @clk_idx: The index of the clock on this device.
255  *
256  * This is called by the device pm code for each clock when the device is
257  * disabled. This allows the device clk code to take appropriate action.
258  */
259 void ti_device_clk_disable(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
260 
261 /**
262  * ti_device_clk_init() - Initialize a device clock
263  * @dev: The device ID that the clock is connected to.
264  * @clk_idx: The index of the clock on this device.
265  *
266  * This is called by the device pm code for each clock when the device is
267  * disabled. This allows the device clk code to take appropriate action such
268  * setting default state.
269  */
270 void ti_device_clk_init(struct ti_device *dev, ti_dev_clk_idx_t clk_idx);
271 
272 #endif /* TI_DEVICE_CLK_H */
273