fsl_lsch3_speed.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. #ifdef CONFIG_FSL_IFC
  25. struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
  26. u32 ccr;
  27. #endif
  28. struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
  29. (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
  30. (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
  31. };
  32. struct ccsr_clk_ctrl __iomem *clk_ctrl =
  33. (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
  34. unsigned int cpu;
  35. const u8 core_cplx_pll[16] = {
  36. [0] = 0, /* CC1 PPL / 1 */
  37. [1] = 0, /* CC1 PPL / 2 */
  38. [2] = 0, /* CC1 PPL / 4 */
  39. [4] = 1, /* CC2 PPL / 1 */
  40. [5] = 1, /* CC2 PPL / 2 */
  41. [6] = 1, /* CC2 PPL / 4 */
  42. [8] = 2, /* CC3 PPL / 1 */
  43. [9] = 2, /* CC3 PPL / 2 */
  44. [10] = 2, /* CC3 PPL / 4 */
  45. [12] = 3, /* CC4 PPL / 1 */
  46. [13] = 3, /* CC4 PPL / 2 */
  47. [14] = 3, /* CC4 PPL / 4 */
  48. };
  49. const u8 core_cplx_pll_div[16] = {
  50. [0] = 1, /* CC1 PPL / 1 */
  51. [1] = 2, /* CC1 PPL / 2 */
  52. [2] = 4, /* CC1 PPL / 4 */
  53. [4] = 1, /* CC2 PPL / 1 */
  54. [5] = 2, /* CC2 PPL / 2 */
  55. [6] = 4, /* CC2 PPL / 4 */
  56. [8] = 1, /* CC3 PPL / 1 */
  57. [9] = 2, /* CC3 PPL / 2 */
  58. [10] = 4, /* CC3 PPL / 4 */
  59. [12] = 1, /* CC4 PPL / 1 */
  60. [13] = 2, /* CC4 PPL / 2 */
  61. [14] = 4, /* CC4 PPL / 4 */
  62. };
  63. uint i, cluster;
  64. uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
  65. uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
  66. unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
  67. int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
  68. u32 c_pll_sel, cplx_pll;
  69. void *offset;
  70. sys_info->freq_systembus = sysclk;
  71. #ifdef CONFIG_DDR_CLK_FREQ
  72. sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
  73. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  74. sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ;
  75. #endif
  76. #else
  77. sys_info->freq_ddrbus = sysclk;
  78. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  79. sys_info->freq_ddrbus2 = sysclk;
  80. #endif
  81. #endif
  82. sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
  83. FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
  84. FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
  85. /* Platform clock is half of platform PLL */
  86. sys_info->freq_systembus /= 2;
  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. sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >>
  92. FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) &
  93. FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK;
  94. #endif
  95. for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
  96. /*
  97. * fixme: prefer to combine the following into one line, but
  98. * cannot pass compiling without warning about in_le32.
  99. */
  100. offset = (void *)((size_t)clk_grp[i/3] +
  101. offsetof(struct ccsr_clk_cluster_group,
  102. pllngsr[i%3].gsr));
  103. ratio[i] = (in_le32(offset) >> 1) & 0x3f;
  104. freq_c_pll[i] = sysclk * ratio[i];
  105. }
  106. for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
  107. cluster = fsl_qoriq_core_to_cluster(cpu);
  108. c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
  109. & 0xf;
  110. cplx_pll = core_cplx_pll[c_pll_sel];
  111. cplx_pll += cc_group[cluster] - 1;
  112. sys_info->freq_processor[cpu] =
  113. freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
  114. }
  115. #if defined(CONFIG_FSL_IFC)
  116. ccr = ifc_in32(&ifc_regs.gregs->ifc_ccr);
  117. ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
  118. sys_info->freq_localbus = sys_info->freq_systembus / ccr;
  119. #endif
  120. }
  121. int get_clocks(void)
  122. {
  123. struct sys_info sys_info;
  124. get_sys_info(&sys_info);
  125. gd->cpu_clk = sys_info.freq_processor[0];
  126. gd->bus_clk = sys_info.freq_systembus;
  127. gd->mem_clk = sys_info.freq_ddrbus;
  128. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  129. gd->arch.mem2_clk = sys_info.freq_ddrbus2;
  130. #endif
  131. #if defined(CONFIG_FSL_ESDHC)
  132. gd->arch.sdhc_clk = gd->bus_clk / 2;
  133. #endif /* defined(CONFIG_FSL_ESDHC) */
  134. if (gd->cpu_clk != 0)
  135. return 0;
  136. else
  137. return 1;
  138. }
  139. /********************************************
  140. * get_bus_freq
  141. * return system bus freq in Hz
  142. *********************************************/
  143. ulong get_bus_freq(ulong dummy)
  144. {
  145. if (!gd->bus_clk)
  146. get_clocks();
  147. return gd->bus_clk;
  148. }
  149. /********************************************
  150. * get_ddr_freq
  151. * return ddr bus freq in Hz
  152. *********************************************/
  153. ulong get_ddr_freq(ulong ctrl_num)
  154. {
  155. if (!gd->mem_clk)
  156. get_clocks();
  157. /*
  158. * DDR controller 0 & 1 are on memory complex 0
  159. * DDR controler 2 is on memory complext 1
  160. */
  161. #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  162. if (ctrl_num >= 2)
  163. return gd->arch.mem2_clk;
  164. #endif
  165. return gd->mem_clk;
  166. }
  167. unsigned int mxc_get_clock(enum mxc_clock clk)
  168. {
  169. switch (clk) {
  170. case MXC_I2C_CLK:
  171. return get_bus_freq(0) / 2;
  172. case MXC_DSPI_CLK:
  173. return get_bus_freq(0) / 2;
  174. default:
  175. printf("Unsupported clock\n");
  176. }
  177. return 0;
  178. }