fsl_lsch3_speed.c 6.4 KB

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