xref: /rk3399_ARM-atf/drivers/ti/clk/include/ti_clk_pll.h (revision a28114d66a6d43db4accef5fd5d6dab6c059e584)
1*28c06333SKamlesh Gurudasani /*
2*28c06333SKamlesh Gurudasani  * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com
3*28c06333SKamlesh Gurudasani  *
4*28c06333SKamlesh Gurudasani  * SPDX-License-Identifier: BSD-3-Clause
5*28c06333SKamlesh Gurudasani  */
6*28c06333SKamlesh Gurudasani 
7*28c06333SKamlesh Gurudasani /*
8*28c06333SKamlesh Gurudasani  * TI Generic PLL API Header
9*28c06333SKamlesh Gurudasani  *
10*28c06333SKamlesh Gurudasani  * This header defines the common PLL data structures and interfaces shared
11*28c06333SKamlesh Gurudasani  * across different PLL variants. It provides PLL table entries, PLL data
12*28c06333SKamlesh Gurudasani  * structures for configuration parameters (VCO ranges, dividers, multipliers),
13*28c06333SKamlesh Gurudasani  * and the common PLL frequency calculation functions.
14*28c06333SKamlesh Gurudasani  */
15*28c06333SKamlesh Gurudasani 
16*28c06333SKamlesh Gurudasani #ifndef TI_CLK_PLL_H
17*28c06333SKamlesh Gurudasani #define TI_CLK_PLL_H
18*28c06333SKamlesh Gurudasani 
19*28c06333SKamlesh Gurudasani #include <ti_clk.h>
20*28c06333SKamlesh Gurudasani #include <ti_devgrps.h>
21*28c06333SKamlesh Gurudasani 
22*28c06333SKamlesh Gurudasani /*
23*28c06333SKamlesh Gurudasani  * PLL table entry
24*28c06333SKamlesh Gurudasani  *
25*28c06333SKamlesh Gurudasani  * This describes a precomputed PLL setting. This should be preferred
26*28c06333SKamlesh Gurudasani  * over brute force calculated settings. Additionally, PLL table entries
27*28c06333SKamlesh Gurudasani  * can be outside spec'd PLL parameters such as minimum VCO frequency.
28*28c06333SKamlesh Gurudasani  *
29*28c06333SKamlesh Gurudasani  * Note that the input frequency is not specified but the input frequency
30*28c06333SKamlesh Gurudasani  * range can be calculated from the given parameters.
31*28c06333SKamlesh Gurudasani  *
32*28c06333SKamlesh Gurudasani  * Current data type sizes are chosen based on currently supported PLLs.
33*28c06333SKamlesh Gurudasani  * If support for an additional PLL with a larger range is added, then
34*28c06333SKamlesh Gurudasani  * the data sizes will either need to increase or be selected at compile
35*28c06333SKamlesh Gurudasani  * time.
36*28c06333SKamlesh Gurudasani  */
37*28c06333SKamlesh Gurudasani struct ti_pll_table_entry {
38*28c06333SKamlesh Gurudasani 	/* Minimum output frequency */
39*28c06333SKamlesh Gurudasani 	uint32_t freq_min_hz;
40*28c06333SKamlesh Gurudasani 
41*28c06333SKamlesh Gurudasani 	/* Maximum output frequency */
42*28c06333SKamlesh Gurudasani 	uint32_t freq_max_hz;
43*28c06333SKamlesh Gurudasani 
44*28c06333SKamlesh Gurudasani 	/* Multiplier setting */
45*28c06333SKamlesh Gurudasani 	uint16_t pllm;
46*28c06333SKamlesh Gurudasani 
47*28c06333SKamlesh Gurudasani 	/* Input divider setting */
48*28c06333SKamlesh Gurudasani 	uint8_t plld;
49*28c06333SKamlesh Gurudasani 
50*28c06333SKamlesh Gurudasani 	/* Output divider setting */
51*28c06333SKamlesh Gurudasani 	uint8_t clkod;
52*28c06333SKamlesh Gurudasani 
53*28c06333SKamlesh Gurudasani 	/* Fractional multiplier part */
54*28c06333SKamlesh Gurudasani 	uint32_t pllfm;
55*28c06333SKamlesh Gurudasani };
56*28c06333SKamlesh Gurudasani 
57*28c06333SKamlesh Gurudasani /* The SoC specific table of precomputed PLL settings */
58*28c06333SKamlesh Gurudasani extern const struct ti_pll_table_entry ti_soc_pll_table[];
59*28c06333SKamlesh Gurudasani 
60*28c06333SKamlesh Gurudasani /* PLL specific const clock data. */
61*28c06333SKamlesh Gurudasani struct ti_clk_data_pll {
62*28c06333SKamlesh Gurudasani 	/* Common const clock data */
63*28c06333SKamlesh Gurudasani 	struct ti_clk_drv_data data;
64*28c06333SKamlesh Gurudasani 
65*28c06333SKamlesh Gurudasani 	/*
66*28c06333SKamlesh Gurudasani 	 * Precomputed PLL entries
67*28c06333SKamlesh Gurudasani 	 *
68*28c06333SKamlesh Gurudasani 	 * Points to an array of indexes into the PLL table. NULL if there are no
69*28c06333SKamlesh Gurudasani 	 * entries.
70*28c06333SKamlesh Gurudasani 	 */
71*28c06333SKamlesh Gurudasani 	const uint8_t *pll_entries;
72*28c06333SKamlesh Gurudasani 
73*28c06333SKamlesh Gurudasani 	/*
74*28c06333SKamlesh Gurudasani 	 * Number of PLL entries
75*28c06333SKamlesh Gurudasani 	 *
76*28c06333SKamlesh Gurudasani 	 * Number of valid entries in pll_entries array.
77*28c06333SKamlesh Gurudasani 	 */
78*28c06333SKamlesh Gurudasani 	size_t pll_entries_count;
79*28c06333SKamlesh Gurudasani 
80*28c06333SKamlesh Gurudasani 	/*
81*28c06333SKamlesh Gurudasani 	 * VCO range.
82*28c06333SKamlesh Gurudasani 	 *
83*28c06333SKamlesh Gurudasani 	 * This points to the valid VCO frequency range in the range table.
84*28c06333SKamlesh Gurudasani 	 */
85*28c06333SKamlesh Gurudasani 	uint8_t vco_range_idx;
86*28c06333SKamlesh Gurudasani 
87*28c06333SKamlesh Gurudasani 	/*
88*28c06333SKamlesh Gurudasani 	 * VCO input range.
89*28c06333SKamlesh Gurudasani 	 *
90*28c06333SKamlesh Gurudasani 	 * This points to the valid VCO input frequency range in the range
91*28c06333SKamlesh Gurudasani 	 * table.
92*28c06333SKamlesh Gurudasani 	 */
93*28c06333SKamlesh Gurudasani 	uint8_t vco_in_range_idx;
94*28c06333SKamlesh Gurudasani 
95*28c06333SKamlesh Gurudasani 	/*
96*28c06333SKamlesh Gurudasani 	 * Default frequency.
97*28c06333SKamlesh Gurudasani 	 *
98*28c06333SKamlesh Gurudasani 	 * This points to an index in the default frequency table. This
99*28c06333SKamlesh Gurudasani 	 * allows the PLL to be programmed to a specific frequency at boot
100*28c06333SKamlesh Gurudasani 	 * time. A table entry of 0 indicates that the current state of
101*28c06333SKamlesh Gurudasani 	 * the hardware should be used.
102*28c06333SKamlesh Gurudasani 	 */
103*28c06333SKamlesh Gurudasani 	uint8_t default_freq_idx;
104*28c06333SKamlesh Gurudasani 
105*28c06333SKamlesh Gurudasani 	/*
106*28c06333SKamlesh Gurudasani 	 * Device Group.
107*28c06333SKamlesh Gurudasani 	 *
108*28c06333SKamlesh Gurudasani 	 * Device group(s) this PLL is contained in or DEVGRP_ALL to
109*28c06333SKamlesh Gurudasani 	 * indicate unspecified.
110*28c06333SKamlesh Gurudasani 	 */
111*28c06333SKamlesh Gurudasani 	devgrp_t devgrp;
112*28c06333SKamlesh Gurudasani 
113*28c06333SKamlesh Gurudasani 	/*
114*28c06333SKamlesh Gurudasani 	 * Enable fractional support.
115*28c06333SKamlesh Gurudasani 	 *
116*28c06333SKamlesh Gurudasani 	 * True to enable fractional support if supported by this PLL. If
117*28c06333SKamlesh Gurudasani 	 * this is false, fractional frequencies can still be read, but
118*28c06333SKamlesh Gurudasani 	 * new fractional frequencies cannot be programmed.
119*28c06333SKamlesh Gurudasani 	 */
120*28c06333SKamlesh Gurudasani 	bool fractional_support;
121*28c06333SKamlesh Gurudasani };
122*28c06333SKamlesh Gurudasani 
123*28c06333SKamlesh Gurudasani /* Const PLL data for use by the pll_calc function. */
124*28c06333SKamlesh Gurudasani struct ti_pll_data {
125*28c06333SKamlesh Gurudasani 	/* Maximum PLL divider. */
126*28c06333SKamlesh Gurudasani 	uint32_t plld_max;
127*28c06333SKamlesh Gurudasani 
128*28c06333SKamlesh Gurudasani 	/* Maximum PLL multiplier. */
129*28c06333SKamlesh Gurudasani 	uint32_t pllm_max;
130*28c06333SKamlesh Gurudasani 
131*28c06333SKamlesh Gurudasani 	/* Bits of fractional PLL multiplier. */
132*28c06333SKamlesh Gurudasani 	uint32_t pllfm_bits;
133*28c06333SKamlesh Gurudasani 
134*28c06333SKamlesh Gurudasani 	/* Maximum PLL post-divider. */
135*28c06333SKamlesh Gurudasani 	uint32_t clkod_max;
136*28c06333SKamlesh Gurudasani 
137*28c06333SKamlesh Gurudasani 	/*
138*28c06333SKamlesh Gurudasani 	 * Indicate if a divider is valid.
139*28c06333SKamlesh Gurudasani 	 *
140*28c06333SKamlesh Gurudasani 	 * Some PLLs cannot use all values in their range, such as odd or
141*28c06333SKamlesh Gurudasani 	 * even values. This callback allows the pll_calc function to skip
142*28c06333SKamlesh Gurudasani 	 * over invalid values.
143*28c06333SKamlesh Gurudasani 	 */
144*28c06333SKamlesh Gurudasani 	bool (*plld_valid)(struct ti_clk *clkp, uint32_t plld);
145*28c06333SKamlesh Gurudasani 
146*28c06333SKamlesh Gurudasani 	/*
147*28c06333SKamlesh Gurudasani 	 * Indicate if a multiplier is valid.
148*28c06333SKamlesh Gurudasani 	 *
149*28c06333SKamlesh Gurudasani 	 * Some PLLs cannot use all values in their range, such as odd or
150*28c06333SKamlesh Gurudasani 	 * even values. This callback allows the pll_calc function to skip
151*28c06333SKamlesh Gurudasani 	 * over invalid values.
152*28c06333SKamlesh Gurudasani 	 */
153*28c06333SKamlesh Gurudasani 	bool (*pllm_valid)(struct ti_clk *clkp, uint32_t pllm, bool is_frac);
154*28c06333SKamlesh Gurudasani 
155*28c06333SKamlesh Gurudasani 	/*
156*28c06333SKamlesh Gurudasani 	 * Stride value for a given pllm.
157*28c06333SKamlesh Gurudasani 	 *
158*28c06333SKamlesh Gurudasani 	 * Some PLLs have additional multipliers enabled to reach certain
159*28c06333SKamlesh Gurudasani 	 * pllm values. Normally, these are handled by treating the values
160*28c06333SKamlesh Gurudasani 	 * in between possible values as invalid. However, when dealing with
161*28c06333SKamlesh Gurudasani 	 * fractional multipliers the pll_calc function must understand that
162*28c06333SKamlesh Gurudasani 	 * the fractional multiplier will also be multiplied by this value.
163*28c06333SKamlesh Gurudasani 	 *
164*28c06333SKamlesh Gurudasani 	 * Provide the extra multiplier value that gets applied at a given
165*28c06333SKamlesh Gurudasani 	 * pllm value.
166*28c06333SKamlesh Gurudasani 	 */
167*28c06333SKamlesh Gurudasani 	uint32_t (*pllm_stride)(struct ti_clk *clkp, uint32_t pllm);
168*28c06333SKamlesh Gurudasani 
169*28c06333SKamlesh Gurudasani 	/*
170*28c06333SKamlesh Gurudasani 	 * Indicate if a post-divider is valid.
171*28c06333SKamlesh Gurudasani 	 *
172*28c06333SKamlesh Gurudasani 	 * Some PLLs cannot use all values in their range, such as odd or
173*28c06333SKamlesh Gurudasani 	 * even values. This callback allows the pll_calc function to skip
174*28c06333SKamlesh Gurudasani 	 * over invalid values.
175*28c06333SKamlesh Gurudasani 	 */
176*28c06333SKamlesh Gurudasani 	bool (*clkod_valid)(struct ti_clk *clkp, uint32_t clkod);
177*28c06333SKamlesh Gurudasani 
178*28c06333SKamlesh Gurudasani 	/*
179*28c06333SKamlesh Gurudasani 	 * Indicate a bin for this setting combination.
180*28c06333SKamlesh Gurudasani 	 *
181*28c06333SKamlesh Gurudasani 	 * Some PLLs prefer certain combinations or ranges of settings over
182*28c06333SKamlesh Gurudasani 	 * others, such as a multiplier below 512. Binning allows pll_calc
183*28c06333SKamlesh Gurudasani 	 * to act on that preference. This function returns a bin number for
184*28c06333SKamlesh Gurudasani 	 * each pllm/plld/clkod combination passed. pll_calc will always
185*28c06333SKamlesh Gurudasani 	 * prefer a setting with a higher bin value over a lower bin value.
186*28c06333SKamlesh Gurudasani 	 */
187*28c06333SKamlesh Gurudasani 	int32_t (*bin)(struct ti_clk *clkp, uint32_t plld, uint32_t pllm,
188*28c06333SKamlesh Gurudasani 		       bool is_frac, uint32_t clkod);
189*28c06333SKamlesh Gurudasani 
190*28c06333SKamlesh Gurudasani 	/*
191*28c06333SKamlesh Gurudasani 	 * Try to find a larger pllm value that exists in a better bin
192*28c06333SKamlesh Gurudasani 	 *
193*28c06333SKamlesh Gurudasani 	 * The pll calculation code functions by testing every allowable plld
194*28c06333SKamlesh Gurudasani 	 * and clkod combination. For each combination, it tests a pllm value
195*28c06333SKamlesh Gurudasani 	 * that produces a frequency at or below the target, and a pllm value
196*28c06333SKamlesh Gurudasani 	 * that produces a frequency above the target. However, this may skip
197*28c06333SKamlesh Gurudasani 	 * certain plld/pllm/clkod combinations that are in a better bin.
198*28c06333SKamlesh Gurudasani 	 * This function allows the pll driver code to return a larger pllm
199*28c06333SKamlesh Gurudasani 	 * value that is in a better bin than the current pllm value. It
200*28c06333SKamlesh Gurudasani 	 * will be called by the pll calculation code until it returns 0.
201*28c06333SKamlesh Gurudasani 	 *
202*28c06333SKamlesh Gurudasani 	 * Note that the pll calculation function will assume the pllm value
203*28c06333SKamlesh Gurudasani 	 * returned is valid and will not call pllm_valid to test it.
204*28c06333SKamlesh Gurudasani 	 */
205*28c06333SKamlesh Gurudasani 	uint32_t (*bin_next_pllm)(struct ti_clk *clkp, uint32_t plld,
206*28c06333SKamlesh Gurudasani 				  uint32_t pllm, uint32_t clkod);
207*28c06333SKamlesh Gurudasani 
208*28c06333SKamlesh Gurudasani 	/*
209*28c06333SKamlesh Gurudasani 	 * Try to find a smaller pllm value that exists in a better bin
210*28c06333SKamlesh Gurudasani 	 *
211*28c06333SKamlesh Gurudasani 	 * The pll calculation code functions by testing every allowable plld
212*28c06333SKamlesh Gurudasani 	 * and clkod combination. For each combination, it tests a pllm value
213*28c06333SKamlesh Gurudasani 	 * that produces a frequency at or below the target, and a pllm value
214*28c06333SKamlesh Gurudasani 	 * that produces a frequency above the target. However, this may skip
215*28c06333SKamlesh Gurudasani 	 * certain plld/pllm/clkod combinations that are in a better bin.
216*28c06333SKamlesh Gurudasani 	 * This function allows the pll driver code to return a smaller pllm
217*28c06333SKamlesh Gurudasani 	 * value that is in a better bin than the current pllm value. It
218*28c06333SKamlesh Gurudasani 	 * will be called by the pll calculation code until it returns 0.
219*28c06333SKamlesh Gurudasani 	 *
220*28c06333SKamlesh Gurudasani 	 * Note that the pll calculation function will assume the pllm value
221*28c06333SKamlesh Gurudasani 	 * returned is valid and will not call pllm_valid to test it.
222*28c06333SKamlesh Gurudasani 	 */
223*28c06333SKamlesh Gurudasani 	uint32_t (*bin_prev_pllm)(struct ti_clk *clkp, uint32_t plld,
224*28c06333SKamlesh Gurudasani 				  uint32_t pllm, uint32_t clkod);
225*28c06333SKamlesh Gurudasani 
226*28c06333SKamlesh Gurudasani 	/*
227*28c06333SKamlesh Gurudasani 	 * Return fitness value based on VCO frequency.
228*28c06333SKamlesh Gurudasani 	 *
229*28c06333SKamlesh Gurudasani 	 * While PLLs already have a maximum and minimum allowable VCO
230*28c06333SKamlesh Gurudasani 	 * frequency, many prefer certain VCO frequencies over others. If the
231*28c06333SKamlesh Gurudasani 	 * bin and frequency delta of a given pllm/plld/clkod combination are
232*28c06333SKamlesh Gurudasani 	 * identical, the vco_fitness function is used to pick a preferred
233*28c06333SKamlesh Gurudasani 	 * combination.
234*28c06333SKamlesh Gurudasani 	 */
235*28c06333SKamlesh Gurudasani 	uint32_t (*vco_fitness)(struct ti_clk *clkp, uint32_t vco, bool is_frac);
236*28c06333SKamlesh Gurudasani };
237*28c06333SKamlesh Gurudasani 
238*28c06333SKamlesh Gurudasani /**
239*28c06333SKamlesh Gurudasani  * ti_pll_calc() - Calculate ideal PLL settings.
240*28c06333SKamlesh Gurudasani  * @clk: The PLL to calculate settings for.
241*28c06333SKamlesh Gurudasani  * @pll_data: The const parameters of the PLL that give allowable settings and preferences.
242*28c06333SKamlesh Gurudasani  * @input: The input frequency in Hz.
243*28c06333SKamlesh Gurudasani  * @output: The desired output frequency in Hz.
244*28c06333SKamlesh Gurudasani  * @min: The minimum acceptable output frequency in Hz.
245*28c06333SKamlesh Gurudasani  * @max: The maximum acceptable output frequency in Hz.
246*28c06333SKamlesh Gurudasani  * @plld: Storage for generated divider value.
247*28c06333SKamlesh Gurudasani  * @pllm: Storage for generated multiplier value.
248*28c06333SKamlesh Gurudasani  * @pllfm: Storage for generated fractional multiplier value.
249*28c06333SKamlesh Gurudasani  * @clkod: Storage for generated post-divider value.
250*28c06333SKamlesh Gurudasani  *
251*28c06333SKamlesh Gurudasani  * This calculates the ideal settings that can be used to generate an output
252*28c06333SKamlesh Gurudasani  * frequenccy given an input frequency and PLL properties. It iterates through
253*28c06333SKamlesh Gurudasani  * possible divider, multiplier, and post-divider values to find the best
254*28c06333SKamlesh Gurudasani  * combination. Preferences are sorted by:
255*28c06333SKamlesh Gurudasani  * - bin
256*28c06333SKamlesh Gurudasani  * - frequency delta
257*28c06333SKamlesh Gurudasani  * - VCO fitness
258*28c06333SKamlesh Gurudasani  * Where bin is the bin value returned by the bin callback, frequency delta
259*28c06333SKamlesh Gurudasani  * is the difference between the desired frequency and generated frequency,
260*28c06333SKamlesh Gurudasani  * and VCO fitness is the fitness value returned by the vco_fitness callback.
261*28c06333SKamlesh Gurudasani  *
262*28c06333SKamlesh Gurudasani  * Return: Frequency produced with the calculated plld/pllm/clkod
263*28c06333SKamlesh Gurudasani  *         values. 0 if no combination could produce an output
264*28c06333SKamlesh Gurudasani  *         between min and max.
265*28c06333SKamlesh Gurudasani  */
266*28c06333SKamlesh Gurudasani uint32_t ti_pll_calc(struct ti_clk *clkp, const struct ti_pll_data *pll_d,
267*28c06333SKamlesh Gurudasani 		     uint32_t input, uint32_t output, uint32_t min, uint32_t max,
268*28c06333SKamlesh Gurudasani 		     uint32_t *plld, uint32_t *pllm, uint32_t *pllfm,
269*28c06333SKamlesh Gurudasani 		     uint32_t *clkod);
270*28c06333SKamlesh Gurudasani 
271*28c06333SKamlesh Gurudasani /**
272*28c06333SKamlesh Gurudasani  * ti_pll_init() - Base PLL initialization function
273*28c06333SKamlesh Gurudasani  * @clk: The PLL to calculate settings for.
274*28c06333SKamlesh Gurudasani  *
275*28c06333SKamlesh Gurudasani  * This contains the common PLL initialization code. This includes setting
276*28c06333SKamlesh Gurudasani  * the default frequency if applicable.
277*28c06333SKamlesh Gurudasani  *
278*28c06333SKamlesh Gurudasani  * Return: 0 on success, error code on error.
279*28c06333SKamlesh Gurudasani  */
280*28c06333SKamlesh Gurudasani int32_t ti_pll_init(struct ti_clk *clkp);
281*28c06333SKamlesh Gurudasani 
282*28c06333SKamlesh Gurudasani #endif /* TI_CLK_PLL_H */
283