clocks_get_m_n.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. * SPDX-License-Identifier: GPL-2.0+
  11. */
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. typedef unsigned int u32;
  15. #define MAX_N 127
  16. /*
  17. * get_m_n_optimized() - Finds optimal DPLL multiplier(M) and divider(N)
  18. * values based on the reference frequency, required output frequency,
  19. * maximum tolerance for output frequency etc.
  20. *
  21. * target_freq_khz - output frequency required in KHz
  22. * ref_freq_khz - reference(input) frequency in KHz
  23. * m - pointer to computed M value
  24. * n - pointer to computed N value
  25. * tolerance_khz - tolerance for the output frequency. When the algorithm
  26. * succeeds in finding vialble M and N values the corresponding output
  27. * frequency will be in the range:
  28. * [target_freq_khz - tolerance_khz, target_freq_khz]
  29. *
  30. * Formula:
  31. * Fdpll = (2 * M * Fref) / (N + 1)
  32. *
  33. * Considerations for lock-time:
  34. * - Smaller the N, better lock-time, especially lock-time will be
  35. * - For acceptable lock-times:
  36. * Fref / (M + 1) >= 1 MHz
  37. *
  38. * Considerations for power:
  39. * - The difference in power for different N values giving the same
  40. * output is negligible. So, we optimize for lock-time
  41. *
  42. * Hard-constraints:
  43. * - N can not be greater than 127(7 bit field for representing N)
  44. *
  45. * Usage:
  46. * $ gcc clocks_get_m_n.c
  47. * $ ./a.out
  48. */
  49. int get_m_n_optimized(u32 target_freq_khz, u32 ref_freq_khz, u32 *M, u32 *N)
  50. {
  51. u32 freq = target_freq_khz;
  52. u32 m_optimal, n_optimal, freq_optimal = 0, freq_old;
  53. u32 m, n;
  54. n = 1;
  55. while (1) {
  56. m = target_freq_khz / ref_freq_khz / 2 * n;
  57. freq_old = 0;
  58. while (1) {
  59. freq = ref_freq_khz * 2 * m / n;
  60. if (freq > target_freq_khz) {
  61. freq = freq_old;
  62. m--;
  63. break;
  64. }
  65. m++;
  66. freq_old = freq;
  67. }
  68. if (freq > freq_optimal) {
  69. freq_optimal = freq;
  70. m_optimal = m;
  71. n_optimal = n;
  72. }
  73. n++;
  74. if ((freq_optimal == target_freq_khz) ||
  75. ((ref_freq_khz / n) < 1000)) {
  76. break;
  77. }
  78. }
  79. n--;
  80. *M = m_optimal;
  81. *N = n_optimal - 1;
  82. printf("ref %d m %d n %d target %d locked %d\n", ref_freq_khz,
  83. m_optimal, n_optimal - 1, target_freq_khz, freq_optimal);
  84. return 0;
  85. }
  86. void main(void)
  87. {
  88. u32 m, n;
  89. printf("\nMPU - 2000000\n");
  90. get_m_n_optimized(2000000, 12000, &m, &n);
  91. get_m_n_optimized(2000000, 13000, &m, &n);
  92. get_m_n_optimized(2000000, 16800, &m, &n);
  93. get_m_n_optimized(2000000, 19200, &m, &n);
  94. get_m_n_optimized(2000000, 26000, &m, &n);
  95. get_m_n_optimized(2000000, 27000, &m, &n);
  96. get_m_n_optimized(2000000, 38400, &m, &n);
  97. printf("\nMPU - 1200000\n");
  98. get_m_n_optimized(1200000, 12000, &m, &n);
  99. get_m_n_optimized(1200000, 13000, &m, &n);
  100. get_m_n_optimized(1200000, 16800, &m, &n);
  101. get_m_n_optimized(1200000, 19200, &m, &n);
  102. get_m_n_optimized(1200000, 26000, &m, &n);
  103. get_m_n_optimized(1200000, 27000, &m, &n);
  104. get_m_n_optimized(1200000, 38400, &m, &n);
  105. printf("\nMPU - 1584000\n");
  106. get_m_n_optimized(1584000, 12000, &m, &n);
  107. get_m_n_optimized(1584000, 13000, &m, &n);
  108. get_m_n_optimized(1584000, 16800, &m, &n);
  109. get_m_n_optimized(1584000, 19200, &m, &n);
  110. get_m_n_optimized(1584000, 26000, &m, &n);
  111. get_m_n_optimized(1584000, 27000, &m, &n);
  112. get_m_n_optimized(1584000, 38400, &m, &n);
  113. printf("\nCore 1600000\n");
  114. get_m_n_optimized(1600000, 12000, &m, &n);
  115. get_m_n_optimized(1600000, 13000, &m, &n);
  116. get_m_n_optimized(1600000, 16800, &m, &n);
  117. get_m_n_optimized(1600000, 19200, &m, &n);
  118. get_m_n_optimized(1600000, 26000, &m, &n);
  119. get_m_n_optimized(1600000, 27000, &m, &n);
  120. get_m_n_optimized(1600000, 38400, &m, &n);
  121. printf("\nPER 1536000\n");
  122. get_m_n_optimized(1536000, 12000, &m, &n);
  123. get_m_n_optimized(1536000, 13000, &m, &n);
  124. get_m_n_optimized(1536000, 16800, &m, &n);
  125. get_m_n_optimized(1536000, 19200, &m, &n);
  126. get_m_n_optimized(1536000, 26000, &m, &n);
  127. get_m_n_optimized(1536000, 27000, &m, &n);
  128. get_m_n_optimized(1536000, 38400, &m, &n);
  129. printf("\nIVA 1862000\n");
  130. get_m_n_optimized(1862000, 12000, &m, &n);
  131. get_m_n_optimized(1862000, 13000, &m, &n);
  132. get_m_n_optimized(1862000, 16800, &m, &n);
  133. get_m_n_optimized(1862000, 19200, &m, &n);
  134. get_m_n_optimized(1862000, 26000, &m, &n);
  135. get_m_n_optimized(1862000, 27000, &m, &n);
  136. get_m_n_optimized(1862000, 38400, &m, &n);
  137. printf("\nIVA Nitro - 1290000\n");
  138. get_m_n_optimized(1290000, 12000, &m, &n);
  139. get_m_n_optimized(1290000, 13000, &m, &n);
  140. get_m_n_optimized(1290000, 16800, &m, &n);
  141. get_m_n_optimized(1290000, 19200, &m, &n);
  142. get_m_n_optimized(1290000, 26000, &m, &n);
  143. get_m_n_optimized(1290000, 27000, &m, &n);
  144. get_m_n_optimized(1290000, 38400, &m, &n);
  145. printf("\nABE 196608 sys clk\n");
  146. get_m_n_optimized(196608, 12000, &m, &n);
  147. get_m_n_optimized(196608, 13000, &m, &n);
  148. get_m_n_optimized(196608, 16800, &m, &n);
  149. get_m_n_optimized(196608, 19200, &m, &n);
  150. get_m_n_optimized(196608, 26000, &m, &n);
  151. get_m_n_optimized(196608, 27000, &m, &n);
  152. get_m_n_optimized(196608, 38400, &m, &n);
  153. printf("\nABE 196608 32K\n");
  154. get_m_n_optimized(196608000/4, 32768, &m, &n);
  155. printf("\nUSB 1920000\n");
  156. get_m_n_optimized(1920000, 12000, &m, &n);
  157. get_m_n_optimized(1920000, 13000, &m, &n);
  158. get_m_n_optimized(1920000, 16800, &m, &n);
  159. get_m_n_optimized(1920000, 19200, &m, &n);
  160. get_m_n_optimized(1920000, 26000, &m, &n);
  161. get_m_n_optimized(1920000, 27000, &m, &n);
  162. get_m_n_optimized(1920000, 38400, &m, &n);
  163. printf("\nCore ES1 1523712\n");
  164. get_m_n_optimized(1524000, 12000, &m, &n);
  165. get_m_n_optimized(1524000, 13000, &m, &n);
  166. get_m_n_optimized(1524000, 16800, &m, &n);
  167. get_m_n_optimized(1524000, 19200, &m, &n);
  168. get_m_n_optimized(1524000, 26000, &m, &n);
  169. get_m_n_optimized(1524000, 27000, &m, &n);
  170. /* exact recommendation for SDPs */
  171. get_m_n_optimized(1523712, 38400, &m, &n);
  172. }