Alternative library and kernel for add-in development on fx-9860G and fx-CG50 under Linux.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
3.2KB

  1. //---
  2. // gint:clock:freq - Clock frequency management
  3. //---
  4. #include <gint/drivers.h>
  5. #include <gint/clock.h>
  6. #include <core/std.h>
  7. #include <gint/mpu.h>
  8. #include <gint/mpu/cpg.h>
  9. //---
  10. // Driver storage
  11. //---
  12. /* Local copy of the CPG settings */
  13. GBSS static clock_frequency_t freq;
  14. /* clock_freq() - get the frequency of the main clocks */
  15. const clock_frequency_t *clock_freq(void)
  16. {
  17. return &freq;
  18. }
  19. //---
  20. // SH7705 Clock signals
  21. //---
  22. #ifdef FX9860G
  23. #define CPG SH7705_CPG
  24. static void sh7705_probe(void)
  25. {
  26. /* According to Sentaro21 in the sources of Ftune 1.0.1, the clock mode
  27. is thought to be 5, which means that:
  28. - CPG input is XTAL (14.745'600 MHz)
  29. - PLL2 is active and *2 (29.491'200 MHz)
  30. - CKIO is output from PLL2 (29.491'200 MHz) */
  31. int xtal = 14745600;
  32. int pll2 = 2;
  33. int ckio = xtal * pll2;
  34. /* This signal is multiplied by the PLL1 circuit */
  35. int pll1 = CPG.FRQCR.STC + 1;
  36. /* Iphi and Pphi have dividers (Bphi is always equal to CKIO) */
  37. int idiv = CPG.FRQCR.IFC;
  38. int pdiv = CPG.FRQCR.PFC;
  39. /* Fill in the setting structure */
  40. freq.PLL1 = pll1;
  41. freq.PLL2 = pll2;
  42. freq.Bphi_div = 1;
  43. freq.Iphi_div = idiv + 1;
  44. freq.Pphi_div = pdiv + 1;
  45. /* Deduce the frequency of the main clocks. This value is ckio/3 */
  46. int ckio_3 = 9830400;
  47. /* Exchange the setting values 2 and 3 */
  48. idiv = idiv ^ (idiv >> 1);
  49. pdiv = pdiv ^ (pdiv >> 1);
  50. freq.CKIO_f = ckio;
  51. freq.Bphi_f = ckio;
  52. freq.Iphi_f = (idiv == 3) ? ckio_3 : ckio >> idiv;
  53. freq.Pphi_f = (pdiv == 3) ? ckio_3 : ckio >> pdiv;
  54. }
  55. #undef CPG
  56. #endif /* FX9860G */
  57. //---
  58. // SH7305 clock signals
  59. //---
  60. #define CPG SH7305_CPG
  61. static void sh7305_probe(void)
  62. {
  63. /* The meaning of the PLL setting on SH7305 differs from the
  64. documentation of SH7224; the value must not be doubled. */
  65. int pll = CPG.FRQCRA.STC + 1;
  66. freq.PLL = pll;
  67. /* The FLL ratio is the value of the setting, halved if SELXM=1 */
  68. int fll = CPG.FLLFRQ.FLF;
  69. if(CPG.FLLFRQ.SELXM == 1) fll >>= 1;
  70. freq.FLL = fll;
  71. /* On SH7724, the divider ratio is given by 1 / (setting + 1), but
  72. SH7305 behaves as 1 / (2^setting + 1). */
  73. int divb = CPG.FRQCRA.BFC;
  74. int divi = CPG.FRQCRA.IFC;
  75. int divp = CPG.FRQCRA.P1FC;
  76. freq.Bphi_div = 1 << (divb + 1);
  77. freq.Iphi_div = 1 << (divi + 1);
  78. freq.Pphi_div = 1 << (divp + 1);
  79. /* Deduce the input frequency of divider 1 */
  80. int base = 32768;
  81. if(CPG.PLLCR.FLLE) base *= fll;
  82. if(CPG.PLLCR.PLLE) base *= pll;
  83. /* And the frequency of all other input clocks */
  84. freq.RTCCLK_f = 32768;
  85. freq.Bphi_f = base >> (divb + 1);
  86. freq.Iphi_f = base >> (divi + 1);
  87. freq.Pphi_f = base >> (divp + 1);
  88. }
  89. #undef CPG
  90. //---
  91. // Other driver stuff
  92. //---
  93. #ifdef GINT_BOOT_LOG
  94. static const char *cpg_status(void)
  95. {
  96. static char status[18];
  97. sprintf(status, "I%3d B%3d P%3d C%c",
  98. freq.Iphi_f / 1000000,
  99. freq.Bphi_f / 1000000,
  100. freq.Pphi_f / 1000000,
  101. isSH3() ? 'e' : 'E'
  102. );
  103. return status;
  104. }
  105. #endif /* GINT_BOOT_LOG */
  106. static void init(void)
  107. {
  108. /* This avoids warnings about sh7705() not being defined on fxcg50 */
  109. #ifdef FX9860G
  110. isSH3() ? sh7705_probe() :
  111. #endif
  112. sh7305_probe();
  113. }
  114. gint_driver_t drv_cpg = {
  115. .name = "CPG",
  116. .init = init,
  117. .status = GINT_DRIVER_STATUS(cpg_status),
  118. .ctx_size = 0,
  119. .sys_ctx = NULL,
  120. .ctx_save = NULL,
  121. .ctx_restore = NULL,
  122. };
  123. GINT_DECLARE_DRIVER(1, drv_cpg);