fsl_lsch3_speed.c 6.3 KB

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