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