xref: /openbmc/u-boot/tools/omap/clocks_get_m_n.c (revision ae03661f)
1 /*
2  * Program for finding M & N values for DPLLs
3  * To be run on Host PC
4  *
5  * (C) Copyright 2010
6  * Texas Instruments, <www.ti.com>
7  *
8  * Aneesh V <aneesh@ti.com>
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation; either version 2 of
16  * the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26  * MA 02111-1307 USA
27  */
28 #include <stdlib.h>
29 #include <stdio.h>
30 typedef unsigned int u32;
31 #define MAX_N	127
32 
33 /*
34  * get_m_n_optimized() - Finds optimal DPLL multiplier(M) and divider(N)
35  * values based on the reference frequency, required output frequency,
36  * maximum tolerance for output frequency etc.
37  *
38  * target_freq_khz - output frequency required in KHz
39  * ref_freq_khz - reference(input) frequency in KHz
40  * m - pointer to computed M value
41  * n - pointer to computed N value
42  * tolerance_khz - tolerance for the output frequency. When the algorithm
43  * succeeds in finding vialble M and N values the corresponding output
44  * frequency will be in the range:
45  *	[target_freq_khz - tolerance_khz, target_freq_khz]
46  *
47  * Formula:
48  *	Fdpll = (2 * M * Fref) / (N + 1)
49  *
50  * Considerations for lock-time:
51  *	- Smaller the N, better lock-time, especially lock-time will be
52  *	- For acceptable lock-times:
53  *		Fref / (M + 1) >= 1 MHz
54  *
55  * Considerations for power:
56  *	- The difference in power for different N values giving the same
57  *	  output is negligible. So, we optimize for lock-time
58  *
59  * Hard-constraints:
60  *	- N can not be greater than 127(7 bit field for representing N)
61  *
62  * Usage:
63  *	$ gcc clocks_get_m_n.c
64  *	$ ./a.out
65  */
66 int get_m_n_optimized(u32 target_freq_khz, u32 ref_freq_khz, u32 *M, u32 *N)
67 {
68 	u32 freq = target_freq_khz;
69 	u32 m_optimal, n_optimal, freq_optimal = 0, freq_old;
70 	u32 m, n;
71 	n = 1;
72 	while (1) {
73 		m = target_freq_khz / ref_freq_khz / 2 * n;
74 		freq_old = 0;
75 		while (1) {
76 			freq = ref_freq_khz * 2 * m / n;
77 			if (freq > target_freq_khz) {
78 				freq = freq_old;
79 				m--;
80 				break;
81 			}
82 			m++;
83 			freq_old = freq;
84 		}
85 		if (freq > freq_optimal) {
86 			freq_optimal = freq;
87 			m_optimal = m;
88 			n_optimal = n;
89 		}
90 		n++;
91 		if ((freq_optimal == target_freq_khz) ||
92 			((ref_freq_khz / n) < 1000)) {
93 			break;
94 		}
95 	}
96 	n--;
97 	*M = m_optimal;
98 	*N = n_optimal - 1;
99 	printf("ref %d m %d n %d target %d locked %d\n", ref_freq_khz,
100 		m_optimal, n_optimal - 1, target_freq_khz, freq_optimal);
101 	return 0;
102 }
103 
104 void main(void)
105 {
106 	u32 m, n;
107 	printf("\nMPU - 2000000\n");
108 	get_m_n_optimized(2000000, 12000, &m, &n);
109 	get_m_n_optimized(2000000, 13000, &m, &n);
110 	get_m_n_optimized(2000000, 16800, &m, &n);
111 	get_m_n_optimized(2000000, 19200, &m, &n);
112 	get_m_n_optimized(2000000, 26000, &m, &n);
113 	get_m_n_optimized(2000000, 27000, &m, &n);
114 	get_m_n_optimized(2000000, 38400, &m, &n);
115 
116 	printf("\nMPU - 1200000\n");
117 	get_m_n_optimized(1200000, 12000, &m, &n);
118 	get_m_n_optimized(1200000, 13000, &m, &n);
119 	get_m_n_optimized(1200000, 16800, &m, &n);
120 	get_m_n_optimized(1200000, 19200, &m, &n);
121 	get_m_n_optimized(1200000, 26000, &m, &n);
122 	get_m_n_optimized(1200000, 27000, &m, &n);
123 	get_m_n_optimized(1200000, 38400, &m, &n);
124 
125 	printf("\nMPU - 1584000\n");
126 	get_m_n_optimized(1584000, 12000, &m, &n);
127 	get_m_n_optimized(1584000, 13000, &m, &n);
128 	get_m_n_optimized(1584000, 16800, &m, &n);
129 	get_m_n_optimized(1584000, 19200, &m, &n);
130 	get_m_n_optimized(1584000, 26000, &m, &n);
131 	get_m_n_optimized(1584000, 27000, &m, &n);
132 	get_m_n_optimized(1584000, 38400, &m, &n);
133 
134 	printf("\nCore 1600000\n");
135 	get_m_n_optimized(1600000, 12000, &m, &n);
136 	get_m_n_optimized(1600000, 13000, &m, &n);
137 	get_m_n_optimized(1600000, 16800, &m, &n);
138 	get_m_n_optimized(1600000, 19200, &m, &n);
139 	get_m_n_optimized(1600000, 26000, &m, &n);
140 	get_m_n_optimized(1600000, 27000, &m, &n);
141 	get_m_n_optimized(1600000, 38400, &m, &n);
142 
143 	printf("\nPER 1536000\n");
144 	get_m_n_optimized(1536000, 12000, &m, &n);
145 	get_m_n_optimized(1536000, 13000, &m, &n);
146 	get_m_n_optimized(1536000, 16800, &m, &n);
147 	get_m_n_optimized(1536000, 19200, &m, &n);
148 	get_m_n_optimized(1536000, 26000, &m, &n);
149 	get_m_n_optimized(1536000, 27000, &m, &n);
150 	get_m_n_optimized(1536000, 38400, &m, &n);
151 
152 	printf("\nIVA 1862000\n");
153 	get_m_n_optimized(1862000, 12000, &m, &n);
154 	get_m_n_optimized(1862000, 13000, &m, &n);
155 	get_m_n_optimized(1862000, 16800, &m, &n);
156 	get_m_n_optimized(1862000, 19200, &m, &n);
157 	get_m_n_optimized(1862000, 26000, &m, &n);
158 	get_m_n_optimized(1862000, 27000, &m, &n);
159 	get_m_n_optimized(1862000, 38400, &m, &n);
160 
161 	printf("\nIVA Nitro - 1290000\n");
162 	get_m_n_optimized(1290000, 12000, &m, &n);
163 	get_m_n_optimized(1290000, 13000, &m, &n);
164 	get_m_n_optimized(1290000, 16800, &m, &n);
165 	get_m_n_optimized(1290000, 19200, &m, &n);
166 	get_m_n_optimized(1290000, 26000, &m, &n);
167 	get_m_n_optimized(1290000, 27000, &m, &n);
168 	get_m_n_optimized(1290000, 38400, &m, &n);
169 
170 	printf("\nABE 196608 sys clk\n");
171 	get_m_n_optimized(196608, 12000, &m, &n);
172 	get_m_n_optimized(196608, 13000, &m, &n);
173 	get_m_n_optimized(196608, 16800, &m, &n);
174 	get_m_n_optimized(196608, 19200, &m, &n);
175 	get_m_n_optimized(196608, 26000, &m, &n);
176 	get_m_n_optimized(196608, 27000, &m, &n);
177 	get_m_n_optimized(196608, 38400, &m, &n);
178 
179 	printf("\nABE 196608 32K\n");
180 	get_m_n_optimized(196608000/4, 32768, &m, &n);
181 
182 	printf("\nUSB 1920000\n");
183 	get_m_n_optimized(1920000, 12000, &m, &n);
184 	get_m_n_optimized(1920000, 13000, &m, &n);
185 	get_m_n_optimized(1920000, 16800, &m, &n);
186 	get_m_n_optimized(1920000, 19200, &m, &n);
187 	get_m_n_optimized(1920000, 26000, &m, &n);
188 	get_m_n_optimized(1920000, 27000, &m, &n);
189 	get_m_n_optimized(1920000, 38400, &m, &n);
190 
191 	printf("\nCore ES1 1523712\n");
192 	get_m_n_optimized(1524000, 12000, &m, &n);
193 	get_m_n_optimized(1524000, 13000, &m, &n);
194 	get_m_n_optimized(1524000, 16800, &m, &n);
195 	get_m_n_optimized(1524000, 19200, &m, &n);
196 	get_m_n_optimized(1524000, 26000, &m, &n);
197 	get_m_n_optimized(1524000, 27000, &m, &n);
198 
199 	/* exact recommendation for SDPs */
200 	get_m_n_optimized(1523712, 38400, &m, &n);
201 
202 }
203