Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 488 lines (413 sloc) 16.689 kb
4bc042b initial public release v1.50
Patrick Titiano authored
1 /*
2 *
3 * @Component OMAPCONF
4 * @Filename dpll.c
5 * @Description OMAP DPLL Common Definitions & Functions
6 * @Author Patrick Titiano (p-titiano@ti.com)
7 * @Date 2006
8 * @Copyright Texas Instruments Incorporated
9 *
10 *
11 * Copyright (C) 2006 Texas Instruments Incorporated - http://www.ti.com/
12 *
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 * its contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 */
43
44
45 #include <dpll.h>
46 #include <dpll44xx.h>
47 #include <cm44xx.h>
48 #include <lib.h>
49 #include <cpuinfo.h>
50 #include <string.h>
51
52
53 /* #define DPLL_DEBUG */
54 #ifdef DPLL_DEBUG
55 #define dprintf(format, ...) printf(format, ## __VA_ARGS__)
56 #else
57 #define dprintf(format, ...)
58 #endif
59
60
61 static const char
62 dpll_mode_names[DPLL_MODE_MAX][DPLL_MODE_MAX_NAME_LENGTH] = {
63 "RESERVED",
64 "LPST",
65 "FRST",
66 "RESERVED",
67 "MNBP",
68 "LPBP",
69 "FRBP",
70 "Lock"};
71
72
73 static const char
74 dpll_ramp_level_names[DPLL_RAMP_LEVEL_MAX][DPLL_RAMP_LEVEL_MAX_NAME_LENGTH] = {
75 "No Ramp",
76 "8,4,2",
77 "4,2,1.5",
78 "RESERVED"};
79
80
81 static const char
82 dpll_autoidle_mode_names[DPLL_AUTOIDLE_MODE_MAX][DPLL_AUTOIDLE_MODE_MAX_NAME_LENGTH] = {
83 "Disabled",
84 "Auto LPST",
85 "Auto FRST",
86 "RESERVED",
87 "RESERVED",
88 "Auto LPBP",
89 "Auto FRBP",
90 "RESERVED"};
91
92
93 static const char
94 dpll_status_names[DPLL_STATUS_MAX][DPLL_STATUS_MAX_NAME_LENGTH] = {
95 "Bypassed",
96 "Locked",
97 "Stopped",
98 "Reserved"};
99
100
101 static const char
102 dpll_bp_clk_src_names[DPLL_BP_CLK_SRC_ID_MAX][DPLL_BP_CLK_SRC_MAX_NAME_LENGTH] = {
103 "CLKINP",
104 "CLKINPULOW"};
105
106
107 static const char
108 dpll_clkouthif_src_names[DPLL_CLKOUTHIF_SRC_ID_MAX][DPLL_CLKOUTHIF_SRC_MAX_NAME_LENGTH] = {
109 "DCO",
110 "CLKINPHIF"};
111
112
113 /* ------------------------------------------------------------------------*//**
114 * @FUNCTION dpll_mode_name_get
115 * @BRIEF return DPLL mode name
116 * @RETURNS pointer towards const string containing DPLL mode name
117 * "RESERVED" in case of 'mode' is invalid
118 * @param[in] mode: dpll mode extracted from register
119 * @DESCRIPTION return DPLL mode name
120 *//*------------------------------------------------------------------------ */
121 const char *dpll_mode_name_get(dpll_mode mode)
122 {
123 if (mode >= DPLL_MODE_MAX) {
124 fprintf(stderr, "%s(): bad mode! (%u)\n", __func__, mode);
125 return (char *) dpll_mode_names[DPLL_RESERVED_0];
126 }
127
128 return (char *) dpll_mode_names[mode];
129 }
130
131
132 /* ------------------------------------------------------------------------*//**
133 * @FUNCTION dpll_ramp_level_name_get
134 * @BRIEF return RAMP LEVEL string
135 * @RETURNS pointer towards const string containing
136 * DPLL RAMP LEVEL name
137 * "RESERVED" in case of 'mode' is invalid
138 * @param[in] level: RAMP LEVEL mode extracted from register
139 * @DESCRIPTION return RAMP LEVEL string
140 *//*------------------------------------------------------------------------ */
141 const char *dpll_ramp_level_name_get(dpll_ramp_level level)
142 {
143 if (level >= DPLL_RAMP_LEVEL_MAX) {
144 fprintf(stderr, "%s(): bad level! (%u)\n", __func__, level);
145 return (char *) dpll_ramp_level_names[DPLL_RAMP_RESERVED];
146 }
147
148 return (char *) dpll_ramp_level_names[level];
149 }
150
151
152 /* ------------------------------------------------------------------------*//**
153 * @FUNCTION dpll_autoidle_mode_name_get
154 * @BRIEF return DPLL autoidle mode name
155 * @RETURNS pointer towards const string containing
156 * DPLL autoidle mode name
157 * "RESERVED" in case of 'mode' is invalid
158 * @param[in] mode: dpll autoidle mode extracted from register
159 * @DESCRIPTION return DPLL autoidle mode name
160 *//*------------------------------------------------------------------------ */
161 const char *dpll_autoidle_mode_name_get(dpll_autoidle_mode mode)
162 {
163 if (mode >= DPLL_AUTOIDLE_MODE_MAX) {
164 fprintf(stderr, "%s(): bad mode! (%u)\n", __func__, mode);
165 return (char *) dpll_autoidle_mode_names[DPLL_AUTO_RESERVED_7];
166 }
167
168 return (char *) dpll_autoidle_mode_names[mode];
169 }
170
171
172 /* ------------------------------------------------------------------------*//**
173 * @FUNCTION dpll_status_name_get
174 * @BRIEF return DPLL status name
175 * @RETURNS pointer towards const string containing DPLL status name
176 * "RESERVED" in case of 'status' is invalid
177 * @param[in] status: dpll status extracted from register
178 * @DESCRIPTION return DPLL status name
179 *//*------------------------------------------------------------------------ */
180 const char *dpll_status_name_get(dpll_status status)
181 {
182 if (status >= DPLL_STATUS_MAX) {
183 fprintf(stderr, "%s(): bad status! (%u)\n", __func__, status);
184 return (char *) dpll_status_names[DPLL_STATUS_RESERVED];
185 }
186
187 return (char *) dpll_status_names[status];
188 }
189
190
191 /* ------------------------------------------------------------------------*//**
192 * @FUNCTION dpll_bp_clk_src_name_get
193 * @BRIEF return DPLL bypass source clock name
194 * @RETURNS bypass source clock name on success
195 * NULL in case of error
196 * @param[in] id: valid DPLL bypass source clock ID
197 * @DESCRIPTION return DPLL bypass source clock name
198 *//*------------------------------------------------------------------------ */
199 const char *dpll_bp_clk_src_name_get(dpll_bp_clk_src id)
200 {
201 CHECK_ARG_LESS_THAN(id, DPLL_BP_CLK_SRC_ID_MAX, NULL);
202
203 return (char *) dpll_bp_clk_src_names[id];
204 }
205
206
207 /* ------------------------------------------------------------------------*//**
208 * @FUNCTION dpll_clkouthif_src_name_get
209 * @BRIEF return DPLL clkouthif source clock name
210 * @RETURNS clkouthif source clock name on success
211 * NULL in case of error
212 * @param[in] id: valid DPLL clkouthif source clock ID
213 * @DESCRIPTION return DPLL clkouthif source clock name
214 *//*------------------------------------------------------------------------ */
215 const char *dpll_clkouthif_src_name_get(dpll_clkouthif_src id)
216 {
217 CHECK_ARG_LESS_THAN(id, DPLL_CLKOUTHIF_SRC_ID_MAX, NULL);
218
219 return (char *) dpll_clkouthif_src_names[id];
220 }
221
222
223 #ifndef DPLL_DEBUG
224 /* #define DPLL_SETTINGS_EXTRACT_DEBUG */
225 #ifdef DPLL_SETTINGS_EXTRACT_DEBUG
226 #undef dprintf
227 #define dprintf(format, ...) printf(format, ## __VA_ARGS__)
228 #else
229 #define dprintf(format, ...)
230 #endif
231 #endif
232 /* ------------------------------------------------------------------------*//**
233 * @FUNCTION dpll_settings_extract
234 * @BRIEF extract DPLL settings from registers
235 * @RETURNS 0 in case of success
236 * OMAPCONF_ERR_ARG
237 * OMAPCONF_ERR_REG_ACCESS
238 * @param[in] id: valid DPLL ID
239 * @param[in] type: DPLL type
240 * @param[in] dpll_regs: dpll registers to extract settings from
241 * @param[in,out] settings: struct with extracted DPLL settings
242 * @DESCRIPTION extract DPLL settings from registers
243 *//*------------------------------------------------------------------------ */
244 int dpll_settings_extract(unsigned int id, dpll_type type,
245 dpll_settings_regs *dpll_regs, dpll_settings *settings)
246 {
247 unsigned int val;
248 CHECK_NULL_ARG(dpll_regs, OMAPCONF_ERR_ARG);
249 CHECK_NULL_ARG(settings, OMAPCONF_ERR_ARG);
250
251 settings->id = id;
252 settings->type = type;
253
254 /* Extract data from CM_CLKMODE_DPLL_xyz */
255 val = reg_read(dpll_regs->cm_clkmode_dpll);
256 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
257 (dpll_regs->cm_clkmode_dpll)->name, val);
258
259 settings->mode = extract_bitfield(val, 0, 3);
260 (settings->ramp).ramp_level = extract_bitfield(val, 3, 2);
261 (settings->ramp).ramp_rate = 1 << (extract_bitfield(val,
262 5, 3) + 1);
263 settings->driftguard_en = extract_bit(val, 8);
264 (settings->ramp).relock_ramp_en = extract_bit(val, 9);
265 settings->lpmode_en = extract_bit(val, 10);
266 settings->regm4xen = extract_bit(val, 11);
267 (settings->SSC).mode = extract_bit(val, 12);
268 (settings->SSC).ack = extract_bit(val, 13);
269 (settings->SSC).downspread = extract_bit(val, 14);
270
271 dprintf("%s(): mode=0x%X (%s), lp_mode=%u, REGM4XEN=%u, "
272 "DRIFTGUARD_EN=%u\n", __func__, settings->mode,
273 dpll_mode_name_get(settings->mode), settings->lpmode_en,
274 settings->regm4xen, settings->driftguard_en);
275 dprintf("%s(): RAMP_EN=%u, RAMP_RATE=%uxREFCLK, RAMP_LEVEL=%u (%s)\n",
276 __func__, (settings->ramp).relock_ramp_en,
277 (settings->ramp).ramp_rate, (settings->ramp).ramp_level,
278 dpll_ramp_level_name_get((settings->ramp).ramp_level));
279 dprintf("%s(): SSC_EN=%u, SSC_ACK=%u, SSC_DOWNSPREAD=%u\n",
280 __func__, (settings->SSC).mode,
281 (settings->SSC).ack, (settings->SSC).downspread);
282
283 /* Extract data from CM_IDLEST_DPLL_xyz */
284 val = reg_read(dpll_regs->cm_idlest_dpll);
285 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
286 (dpll_regs->cm_idlest_dpll)->name, val);
287
288 settings->lock_status = extract_bit(val, 0);
289 settings->mn_bypass_status = extract_bit(val, 8);
290
291 dprintf("%s(): ST_DPLL_CLK=%u, ST_MN_BYPASS=%u\n",
292 __func__, settings->lock_status, settings->mn_bypass_status);
293
294 /* Extract data from CM_AUTOIDLE_DPLL_xyz */
295 val = reg_read(dpll_regs->cm_autoidle_dpll);
296 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
297 (dpll_regs->cm_autoidle_dpll)->name, val);
298
299 settings->autoidle_mode = extract_bitfield(val, 0, 3);
300
301 dprintf("%s(): AUTO_DPLL_MODE=%u (%s)\n", __func__,
302 settings->autoidle_mode,
303 dpll_autoidle_mode_name_get(settings->autoidle_mode));
304
305 /* Extract data from CM_CLKSEL_DPLL_xyz */
306 val = reg_read(dpll_regs->cm_clksel_dpll);
307 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
308 (dpll_regs->cm_clksel_dpll)->name, val);
309
310 if (settings->type == DPLL_TYPE_A) {
311 (settings->MN).N = extract_bitfield(val, 0, 7);
312 (settings->MN).M = extract_bitfield(val, 8, 11);
313 settings->clkouthif_src = extract_bit(val, 20);
314 if (!cpu_is_omap4430()) {
315 (settings->DCC).en = extract_bit(val, 22);
316 (settings->DCC).count = extract_bitfield(val, 24, 8);
317 } else {
318 (settings->DCC).en = 0;
319 (settings->DCC).count = 0;
320 }
321 settings->bypass_clk = extract_bit(val, 23);
322 } else {
323 (settings->MN).N = extract_bitfield(val, 0, 8);
324 (settings->MN).M = extract_bitfield(val, 8, 12);
325 settings->selfreqdco = extract_bit(val, 21);
326 settings->sd_div = extract_bitfield(val, 24, 8);
327 dprintf("%s(): SELFREQDCO=%u, SD_DIV=%u\n", __func__,
328 settings->selfreqdco, settings->sd_div);
329 }
330 dprintf("%s(): M=%u, N=%u, CLKOUTHIF_CLK=%u, BP_CLK=%u\n", __func__,
331 (settings->MN).M, (settings->MN).N, settings->clkouthif_src,
332 settings->bypass_clk);
333 dprintf("%s(): DCC_EN=%u, DCC_COUNT=%u\n", __func__,
334 (settings->DCC).en, (settings->DCC).count);
335
336 /* Extract data from CM_BYPCLK_DPLL_XYZ */
337 if ((void *) dpll_regs->cm_bypclk_dpll != NULL) {
338 val = reg_read(dpll_regs->cm_bypclk_dpll);
339 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
340 (dpll_regs->cm_bypclk_dpll)->name, val);
341
342 settings->bypass_clk_div = 1 << extract_bitfield(val, 0, 2);
343
344 dprintf("%s(): BP_CLK_DIV=%u\n", __func__,
345 settings->bypass_clk_div);
346
347 } else {
348 settings->bypass_clk_div = 1;
349
350 dprintf("%s(): BYPCLK register does not exist.\n", __func__);
351 }
352
353 /* Extract data from CM_DIV_M2_DPLL_XYZ */
354 if ((void *) dpll_regs->cm_div_m2_dpll != NULL) {
355 val = reg_read(dpll_regs->cm_div_m2_dpll);
356 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
357 (dpll_regs->cm_div_m2_dpll)->name, val);
358
359 (settings->MN).M2_present = 1;
360 if (settings->type == DPLL_TYPE_A) {
361 (settings->MN).M2 = extract_bitfield(val, 0, 5);
362 (settings->MN).X2_M2_autogating =
363 !extract_bit(val, 10);
364 (settings->MN).X2_M2_clkout_st = extract_bit(val, 11);
365 } else {
366 (settings->MN).M2 = extract_bitfield(val, 0, 7);
367 }
368 (settings->MN).M2_autogating = !extract_bit(val, 8);
369 (settings->MN).M2_clkout_st = extract_bit(val, 9);
370
371 dprintf("%s(): M2 DIV=%u, AUTOGATING=%u, CLKST=%u\n",
372 __func__, (settings->MN).M2,
373 (settings->MN).M2_autogating,
374 (settings->MN).M2_clkout_st);
375 if (settings->type == DPLL_TYPE_A) {
376 dprintf("%s(): X2_M2 AUTOGATING=%u, CLKST=%u\n",
377 __func__, (settings->MN).X2_M2_autogating,
378 (settings->MN).X2_M2_clkout_st);
379 }
380 } else {
381 (settings->MN).M2_present = 0;
382
383 dprintf("%s(): DIV_M2 register does not exist.\n", __func__);
384 }
385
386 /* Extract data from CM_DIV_M3_DPLL_XYZ */
387 if ((void *) dpll_regs->cm_div_m3_dpll != NULL) {
388 val = reg_read(dpll_regs->cm_div_m3_dpll);
389 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
390 (dpll_regs->cm_div_m3_dpll)->name, val);
391
392 (settings->MN).M3_present = 1;
393 (settings->MN).M3 = extract_bitfield(val, 0, 5);
394 (settings->MN).X2_M3_autogating = !extract_bit(val, 8);
395 (settings->MN).X2_M3_clkout_st = extract_bit(val, 9);
396
397 dprintf("%s(): X2_M3 DIV=%u, AUTOGATING=%u, CLKST=%u\n",
398 __func__, (settings->MN).M3,
399 (settings->MN).X2_M3_autogating,
400 (settings->MN).X2_M3_clkout_st);
401 } else {
402 (settings->MN).M3_present = 0;
403
404 dprintf("%s(): DIV_M3 register does not exist.\n", __func__);
405 }
406
407 /* Extract data from CM_DELTAMSTEP_DPLL_xyz */
408 val = reg_read(dpll_regs->cm_ssc_deltamstep_dpll);
409 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
410 (dpll_regs->cm_ssc_deltamstep_dpll)->name, val);
411
412 (settings->SSC).deltaMStep = extract_bitfield(val, 0, 20);
413
414 dprintf("%s(): deltaMStep=0x%X\n", __func__,
415 (settings->SSC).deltaMStep);
416
417 /* Extract data from CM_MODFREQDIV_DPLL_xyz */
418 val = reg_read(dpll_regs->cm_ssc_modfreqdiv_dpll);
419 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
420 (dpll_regs->cm_ssc_modfreqdiv_dpll)->name, val);
421
422 (settings->SSC).mantissa = extract_bitfield(val, 0, 7);
423 (settings->SSC).exponent = extract_bitfield(val, 8, 3);
424
425 dprintf("%s(): mantissa=0x%X, exponent=0x%X\n", __func__,
426 (settings->SSC).mantissa, (settings->SSC).exponent);
427
428 /* Extract data from CM_CLKDCOLDO_DPLL_xyz */
429 if ((void *) dpll_regs->cm_clkdcoldo_dpll != NULL) {
430 val = reg_read(dpll_regs->cm_clkdcoldo_dpll);
431 dprintf("%s(): DPLL reg: %s = 0x%08X\n", __func__,
432 (dpll_regs->cm_clkdcoldo_dpll)->name, val);
433
434 (settings->MN).clkdcoldo_autogating = !extract_bit(val, 8);
435 (settings->MN).clkdcoldo_clkout_st = extract_bit(val, 9);
436
437 dprintf("%s(): CLKDCOLDO AUTOGATING=%u, CLKST=%u\n",
438 __func__,
439 (settings->MN).clkdcoldo_autogating,
440 (settings->MN).clkdcoldo_clkout_st);
441 }
442 return 0;
443 }
444 #ifdef DPLL_SETTINGS_EXTRACT_DEBUG
445 #undef dprintf
446 #define dprintf(format, ...)
447 #endif
448
449
450 /* ------------------------------------------------------------------------*//**
451 * @FUNCTION dpll_lock_freq_calc
452 * @BRIEF compute DPLL lock frequency (in MHz)
453 * @RETURNS lock frequency in case of success (in MHz)
454 * 0.0 in case of error.
455 * @param[in] settings: DPLL settings with fields
456 * regm4xen, fref, MN.M, MN.N INITIALIZED
457 * @DESCRIPTION compute DPLL lock frequency (in MHz)
458 *//*------------------------------------------------------------------------ */
459 double dpll_lock_freq_calc(dpll_settings *settings)
460 {
461 CHECK_NULL_ARG(settings, 0.0);
462
463 if (settings->type == DPLL_TYPE_A) {
464 if (settings->regm4xen == 0)
465 settings->fdpll =
466 (settings->fref * 2.0 * (double) (settings->MN).M) /
467 ((double) (settings->MN).N + 1.0);
468 else
469 settings->fdpll =
470 (settings->fref * 8.0 * (double) (settings->MN).M) /
471 ((double) (settings->MN).N + 1.0);
472 dprintf("%s(%u): type=A regm4xen=%u fref=%lfMHz M=%u N=%u => "
473 "fdpll=%lfMHz\n", __func__, settings->id,
474 settings->regm4xen, settings->fref, (settings->MN).M,
475 (settings->MN).N, settings->fdpll);
476 } else {
477 settings->fdpll =
478 (settings->fref * (double) (settings->MN).M) /
479 ((double) (settings->MN).N + 1.0);
480 dprintf("%s(%u): type=B fref=%lfMHz M=%u N=%u => "
481 "fdpll=%lfMHz\n", __func__, settings->id,
482 settings->fref, (settings->MN).M,
483 (settings->MN).N, settings->fdpll);
484 }
485
486 return settings->fdpll;
487 }
Something went wrong with that request. Please try again.