fsl_lsch3_speed.c 5.2 KB

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