clocks_get_m_n.c 5.6 KB

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