fsl_lsch3_speed.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2014-2015, Freescale Semiconductor, Inc.
  4. *
  5. * Derived from arch/power/cpu/mpc85xx/speed.c
  6. */
  7. #include <common.h>
  8. #include <linux/compiler.h>
  9. #include <fsl_ifc.h>
  10. #include <asm/processor.h>
  11. #include <asm/io.h>
  12. #include <asm/arch-fsl-layerscape/immap_lsch3.h>
  13. #include <asm/arch/clock.h>
  14. #include <asm/arch/soc.h>
  15. #include "cpu.h"
  16. DECLARE_GLOBAL_DATA_PTR;
  17. #ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
  18. #define CONFIG_SYS_FSL_NUM_CC_PLLS 6
  19. #endif
  20. void get_sys_info(struct sys_info *sys_info)
  21. {
  22. struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  23. struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
  24. (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
  25. (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
  26. };
  27. struct ccsr_clk_ctrl __iomem *clk_ctrl =
  28. (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
  29. unsigned int cpu;
  30. const u8 core_cplx_pll[16] = {
  31. [0] = 0, /* CC1 PPL / 1 */
  32. [1] = 0, /* CC1 PPL / 2 */
  33. [2] = 0, /* CC1 PPL / 4 */
  34. [4] = 1, /* CC2 PPL / 1 */
  35. [5] = 1, /* CC2 PPL / 2 */
  36. [6] = 1, /* CC2 PPL / 4 */
  37. [8] = 2, /* CC3 PPL / 1 */
  38. [9] = 2, /* CC3 PPL / 2 */
  39. [10] = 2, /* CC3 PPL / 4 */
  40. [12] = 3, /* CC4 PPL / 1 */
  41. [13] = 3, /* CC4 PPL / 2 */
  42. [14] = 3, /* CC4 PPL / 4 */
  43. };
  44. const u8 core_cplx_pll_div[16] = {
  45. [0] = 1, /* CC1 PPL / 1 */
  46. [1] = 2, /* CC1 PPL / 2 */
  47. [2] = 4, /* CC1 PPL / 4 */
  48. [4] = 1, /* CC2 PPL / 1 */
  49. [5] = 2, /* CC2 PPL / 2 */
  50. [6] = 4, /* CC2 PPL / 4 */
  51. [8] = 1, /* CC3 PPL / 1 */
  52. [9] = 2, /* CC3 PPL / 2 */
  53. [10] = 4, /* CC3 PPL / 4 */
  54. [12] = 1, /* CC4 PPL / 1 */
  55. [13] = 2, /* CC4 PPL / 2 */
  56. [14] = 4, /* CC4 PPL / 4 */
  57. };
  58. uint i, cluster;
  59. uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
  60. uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
  61. unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
  62. int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
  63. u32 c_pll_sel, cplx_pll;
  64. void *offset;
  65. sys_info->freq_systembus = sysclk;
  66. #ifdef CONFIG_DDR_CLK_FREQ
  67. sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
  68. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  69. sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ;
  70. #endif
  71. #else
  72. sys_info->freq_ddrbus = sysclk;
  73. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  74. sys_info->freq_ddrbus2 = sysclk;
  75. #endif
  76. #endif
  77. /* The freq_systembus is used to record frequency of platform PLL */
  78. sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
  79. FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
  80. FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
  81. sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
  82. FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
  83. FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
  84. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  85. if (soc_has_dp_ddr()) {
  86. sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >>
  87. FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) &
  88. FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK;
  89. } else {
  90. sys_info->freq_ddrbus2 = 0;
  91. }
  92. #endif
  93. for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
  94. /*
  95. * fixme: prefer to combine the following into one line, but
  96. * cannot pass compiling without warning about in_le32.
  97. */
  98. offset = (void *)((size_t)clk_grp[i/3] +
  99. offsetof(struct ccsr_clk_cluster_group,
  100. pllngsr[i%3].gsr));
  101. ratio[i] = (in_le32(offset) >> 1) & 0x3f;
  102. freq_c_pll[i] = sysclk * ratio[i];
  103. }
  104. for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
  105. cluster = fsl_qoriq_core_to_cluster(cpu);
  106. c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
  107. & 0xf;
  108. cplx_pll = core_cplx_pll[c_pll_sel];
  109. cplx_pll += cc_group[cluster] - 1;
  110. sys_info->freq_processor[cpu] =
  111. freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
  112. }
  113. #if defined(CONFIG_FSL_IFC)
  114. sys_info->freq_localbus = sys_info->freq_systembus /
  115. CONFIG_SYS_FSL_IFC_CLK_DIV;
  116. #endif
  117. }
  118. int get_clocks(void)
  119. {
  120. struct sys_info sys_info;
  121. get_sys_info(&sys_info);
  122. gd->cpu_clk = sys_info.freq_processor[0];
  123. gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV;
  124. gd->mem_clk = sys_info.freq_ddrbus;
  125. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  126. gd->arch.mem2_clk = sys_info.freq_ddrbus2;
  127. #endif
  128. #if defined(CONFIG_FSL_ESDHC)
  129. gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV;
  130. #endif /* defined(CONFIG_FSL_ESDHC) */
  131. if (gd->cpu_clk != 0)
  132. return 0;
  133. else
  134. return 1;
  135. }
  136. /********************************************
  137. * get_bus_freq
  138. * return platform clock in Hz
  139. *********************************************/
  140. ulong get_bus_freq(ulong dummy)
  141. {
  142. if (!gd->bus_clk)
  143. get_clocks();
  144. return gd->bus_clk;
  145. }
  146. /********************************************
  147. * get_ddr_freq
  148. * return ddr bus freq in Hz
  149. *********************************************/
  150. ulong get_ddr_freq(ulong ctrl_num)
  151. {
  152. if (!gd->mem_clk)
  153. get_clocks();
  154. /*
  155. * DDR controller 0 & 1 are on memory complex 0
  156. * DDR controller 2 is on memory complext 1
  157. */
  158. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  159. if (ctrl_num >= 2)
  160. return gd->arch.mem2_clk;
  161. #endif
  162. return gd->mem_clk;
  163. }
  164. int get_i2c_freq(ulong dummy)
  165. {
  166. return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
  167. }
  168. int get_dspi_freq(ulong dummy)
  169. {
  170. return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
  171. }
  172. int get_serial_clock(void)
  173. {
  174. return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
  175. }
  176. unsigned int mxc_get_clock(enum mxc_clock clk)
  177. {
  178. switch (clk) {
  179. case MXC_I2C_CLK:
  180. return get_i2c_freq(0);
  181. case MXC_DSPI_CLK:
  182. return get_dspi_freq(0);
  183. default:
  184. printf("Unsupported clock\n");
  185. }
  186. return 0;
  187. }