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 Divider API Header 9 * 10 * This header defines the data structures and interfaces for programmable 11 * clock dividers. It provides divider data structures, driver interfaces, 12 * and APIs for divider value get/set operations supporting both power-of-2 13 * and arbitrary integer division ratios. 14 */ 15 16 #ifndef TI_CLK_DIV_H 17 #define TI_CLK_DIV_H 18 19 #include <ti_clk.h> 20 21 /* 22 * Base divider clock data structure 23 * 24 * This structure contains the fundamental divider configuration including 25 * the maximum divider value and default divider ratio. 26 */ 27 struct ti_clk_data_div { 28 /* Base driver data structure */ 29 struct ti_clk_drv_data data; 30 /* Maximum divider value (divider range is 1 to max_div) */ 31 uint16_t max_div; 32 /* Default divider value at initialization */ 33 uint16_t default_div; 34 }; 35 36 /* 37 * Register-based divider clock data structure 38 * 39 * This structure defines a divider implemented via a hardware register field. 40 * The divider value is stored in a bit field within the specified register. 41 */ 42 struct ti_clk_data_div_reg { 43 /* Register address containing divider field */ 44 uint32_t reg; 45 /* Base divider data */ 46 struct ti_clk_data_div data_div; 47 /* Starting bit position of divider field */ 48 uint8_t bit; 49 /* If true, divider values start at 1 (not 0) */ 50 uint8_t start_at_1; 51 }; 52 53 /* 54 * Register-based divider with GO bit for change propagation 55 * 56 * This structure extends the basic register divider with a GO bit mechanism. 57 * After modifying the divider value, the GO bit must be set to propagate 58 * the change through the clock tree. 59 */ 60 struct ti_clk_data_div_reg_go { 61 /* Register address containing divider field */ 62 uint32_t reg; 63 /* Base divider data */ 64 struct ti_clk_data_div data_div; 65 /* Starting bit position of divider field */ 66 uint8_t bit; 67 /* If true, divider values start at 1 (not 0) */ 68 uint8_t start_at_1; 69 /* GO bit number to trigger divider change */ 70 uint8_t go; 71 }; 72 73 /* 74 * Divider clock driver operations structure 75 * 76 * This structure extends the base clock driver with divider-specific operations 77 * for getting, setting, and validating divider values. 78 */ 79 struct ti_clk_drv_div { 80 /* Base clock driver operations */ 81 struct ti_clk_drv drv; 82 83 /* 84 * Set the divider value for a clock 85 */ 86 bool (*set_div)(struct ti_clk *clkp, uint32_t div); 87 88 /* 89 * Get the current divider value for a clock 90 */ 91 uint32_t (*get_div)(struct ti_clk *clkp); 92 93 /* 94 * Validate if a divider value is supported 95 */ 96 bool (*valid_div)(struct ti_clk *clkp, uint32_t div); 97 }; 98 99 /* Divider driver for read-write register-based dividers */ 100 extern const struct ti_clk_drv_div ti_clk_drv_div_reg; 101 102 /* Divider driver for read-only register-based dividers */ 103 extern const struct ti_clk_drv_div ti_clk_drv_div_reg_ro; 104 105 /* Divider driver for register-based dividers with GO bit propagation */ 106 extern const struct ti_clk_drv_div ti_clk_drv_div_reg_go; 107 108 /* Divider driver for fixed (non-programmable) dividers */ 109 extern const struct ti_clk_drv_div ti_clk_drv_div_fixed; 110 111 /** 112 * ti_clk_div_set_freq() - Sets the frequency of a divider clock 113 * @clkp: The divider clock to configure 114 * @target_hz: Target frequency in Hz 115 * @min_hz: Minimum acceptable frequency in Hz 116 * @max_hz: Maximum acceptable frequency in Hz 117 * @changed: Output parameter set to true if frequency changed 118 * 119 * This function adjusts the divider value to achieve the target frequency. 120 * It can also propagate frequency changes to the parent if allowed. 121 * 122 * Return: Best achievable frequency in Hz, 0 on failure 123 */ 124 uint32_t ti_clk_div_set_freq(struct ti_clk *clkp, uint32_t target_hz, 125 uint32_t min_hz, uint32_t max_hz, 126 bool *changed); 127 128 /** 129 * ti_clk_div_get_freq() - Gets the current frequency of a divider clock 130 * @clkp: The divider clock to query 131 * 132 * Return: Current frequency in Hz 133 */ 134 uint32_t ti_clk_div_get_freq(struct ti_clk *clkp); 135 136 /** 137 * ti_clk_div_set_freq_static_parent() - Sets frequency for dividers with fixed parent frequency 138 * @clkp: The divider clock to configure 139 * @target_hz: Target frequency in Hz 140 * @min_hz: Minimum acceptable frequency in Hz 141 * @max_hz: Maximum acceptable frequency in Hz 142 * @changed: Output parameter set to true if frequency changed 143 * 144 * This variant is optimized for dividers whose parent frequency cannot 145 * be changed. It only adjusts the divider value itself. 146 * 147 * Return: Best achievable frequency in Hz, 0 on failure 148 */ 149 uint32_t ti_clk_div_set_freq_static_parent(struct ti_clk *clkp, uint32_t target_hz, 150 uint32_t min_hz, uint32_t max_hz, 151 bool *changed); 152 153 /** 154 * ti_clk_div_reg_go_get_div() - Gets divider value for GO-bit register divider 155 * @clkp: The divider clock to query 156 * 157 * Return: Current divider value 158 */ 159 uint32_t ti_clk_div_reg_go_get_div(struct ti_clk *clkp); 160 161 /** 162 * ti_clk_div_reg_go_set_div() - Sets divider value for GO-bit register divider 163 * @clkp: The divider clock to modify 164 * @div: The divider value to set 165 * 166 * Sets the divider value and triggers the GO bit to propagate the change. 167 * 168 * Return: True if successful 169 */ 170 bool ti_clk_div_reg_go_set_div(struct ti_clk *clkp, uint32_t div); 171 172 /** 173 * ti_clk_div_reg_get_div() - Gets divider value from register-based divider 174 * @clkp: The divider clock to query 175 * 176 * Return: Current divider value 177 */ 178 uint32_t ti_clk_div_reg_get_div(struct ti_clk *clkp); 179 180 /** 181 * ti_clk_div_reg_set_div() - Sets divider value for register-based divider 182 * @clkp: The divider clock to modify 183 * @div: The divider value to set 184 * 185 * Return: True if successful 186 */ 187 bool ti_clk_div_reg_set_div(struct ti_clk *clkp, uint32_t div); 188 189 /** 190 * ti_clk_get_div() - Generic divider value getter 191 * @clkp: The divider clock to query 192 * 193 * Dispatches to the appropriate driver-specific get_div function. 194 * 195 * Return: Current divider value 196 */ 197 uint32_t ti_clk_get_div(struct ti_clk *clkp); 198 199 /** 200 * ti_clk_div_init() - Initializes a divider clock 201 * @clkp: The divider clock to initialize 202 * 203 * Performs initialization including setting default divider value and 204 * configuring hardware registers. 205 * 206 * Return: 0 on success, error code otherwise 207 */ 208 int32_t ti_clk_div_init(struct ti_clk *clkp); 209 210 #endif /* TI_CLK_DIV_H */ 211