1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2015 Freescale Semiconductor, Inc. 4 */ 5 6 #include <common.h> 7 #include <linux/compiler.h> 8 #include <asm/io.h> 9 #include <asm/processor.h> 10 #include <asm/arch/clock.h> 11 #include <asm/arch/soc.h> 12 #include <fsl_ifc.h> 13 #include "cpu.h" 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 #ifndef CONFIG_SYS_FSL_NUM_CC_PLLS 18 #define CONFIG_SYS_FSL_NUM_CC_PLLS 2 19 #endif 20 21 void get_sys_info(struct sys_info *sys_info) 22 { 23 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 24 #if (defined(CONFIG_FSL_ESDHC) &&\ 25 defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)) ||\ 26 defined(CONFIG_SYS_DPAA_FMAN) 27 28 u32 rcw_tmp; 29 #endif 30 struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR); 31 unsigned int cpu; 32 const u8 core_cplx_pll[8] = { 33 [0] = 0, /* CC1 PPL / 1 */ 34 [1] = 0, /* CC1 PPL / 2 */ 35 [4] = 1, /* CC2 PPL / 1 */ 36 [5] = 1, /* CC2 PPL / 2 */ 37 }; 38 39 const u8 core_cplx_pll_div[8] = { 40 [0] = 1, /* CC1 PPL / 1 */ 41 [1] = 2, /* CC1 PPL / 2 */ 42 [4] = 1, /* CC2 PPL / 1 */ 43 [5] = 2, /* CC2 PPL / 2 */ 44 }; 45 46 uint i, cluster; 47 uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; 48 uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; 49 unsigned long sysclk = CONFIG_SYS_CLK_FREQ; 50 unsigned long cluster_clk; 51 52 sys_info->freq_systembus = sysclk; 53 #ifndef CONFIG_CLUSTER_CLK_FREQ 54 #define CONFIG_CLUSTER_CLK_FREQ CONFIG_SYS_CLK_FREQ 55 #endif 56 cluster_clk = CONFIG_CLUSTER_CLK_FREQ; 57 58 #ifdef CONFIG_DDR_CLK_FREQ 59 sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ; 60 #else 61 sys_info->freq_ddrbus = sysclk; 62 #endif 63 64 /* The freq_systembus is used to record frequency of platform PLL */ 65 sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >> 66 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) & 67 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK; 68 69 #ifdef CONFIG_ARCH_LS1012A 70 sys_info->freq_ddrbus = 2 * sys_info->freq_systembus; 71 #else 72 sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >> 73 FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) & 74 FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK; 75 #endif 76 77 for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) { 78 ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff; 79 if (ratio[i] > 4) 80 freq_c_pll[i] = cluster_clk * ratio[i]; 81 else 82 freq_c_pll[i] = sys_info->freq_systembus * ratio[i]; 83 } 84 85 for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { 86 cluster = fsl_qoriq_core_to_cluster(cpu); 87 u32 c_pll_sel = (in_be32(&clk->clkcsr[cluster].clkcncsr) >> 27) 88 & 0xf; 89 u32 cplx_pll = core_cplx_pll[c_pll_sel]; 90 91 sys_info->freq_processor[cpu] = 92 freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel]; 93 } 94 95 #define HWA_CGA_M1_CLK_SEL 0xe0000000 96 #define HWA_CGA_M1_CLK_SHIFT 29 97 #ifdef CONFIG_SYS_DPAA_FMAN 98 rcw_tmp = in_be32(&gur->rcwsr[7]); 99 switch ((rcw_tmp & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) { 100 case 2: 101 sys_info->freq_fman[0] = freq_c_pll[0] / 2; 102 break; 103 case 3: 104 sys_info->freq_fman[0] = freq_c_pll[0] / 3; 105 break; 106 case 4: 107 sys_info->freq_fman[0] = freq_c_pll[0] / 4; 108 break; 109 case 5: 110 sys_info->freq_fman[0] = sys_info->freq_systembus; 111 break; 112 case 6: 113 sys_info->freq_fman[0] = freq_c_pll[1] / 2; 114 break; 115 case 7: 116 sys_info->freq_fman[0] = freq_c_pll[1] / 3; 117 break; 118 default: 119 printf("Error: Unknown FMan1 clock select!\n"); 120 break; 121 } 122 #endif 123 124 #define HWA_CGA_M2_CLK_SEL 0x00000007 125 #define HWA_CGA_M2_CLK_SHIFT 0 126 #ifdef CONFIG_FSL_ESDHC 127 #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK 128 rcw_tmp = in_be32(&gur->rcwsr[15]); 129 switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) { 130 case 1: 131 sys_info->freq_sdhc = freq_c_pll[1]; 132 break; 133 case 2: 134 sys_info->freq_sdhc = freq_c_pll[1] / 2; 135 break; 136 case 3: 137 sys_info->freq_sdhc = freq_c_pll[1] / 3; 138 break; 139 case 6: 140 sys_info->freq_sdhc = freq_c_pll[0] / 2; 141 break; 142 default: 143 printf("Error: Unknown ESDHC clock select!\n"); 144 break; 145 } 146 #else 147 sys_info->freq_sdhc = (sys_info->freq_systembus / 148 CONFIG_SYS_FSL_PCLK_DIV) / 149 CONFIG_SYS_FSL_SDHC_CLK_DIV; 150 #endif 151 #endif 152 153 #if defined(CONFIG_FSL_IFC) 154 sys_info->freq_localbus = sys_info->freq_systembus / 155 CONFIG_SYS_FSL_IFC_CLK_DIV; 156 #endif 157 #ifdef CONFIG_SYS_DPAA_QBMAN 158 sys_info->freq_qman = (sys_info->freq_systembus / 159 CONFIG_SYS_FSL_PCLK_DIV) / 160 CONFIG_SYS_FSL_QMAN_CLK_DIV; 161 #endif 162 } 163 164 #ifdef CONFIG_SYS_DPAA_QBMAN 165 unsigned long get_qman_freq(void) 166 { 167 struct sys_info sys_info; 168 169 get_sys_info(&sys_info); 170 171 return sys_info.freq_qman; 172 } 173 #endif 174 175 int get_clocks(void) 176 { 177 struct sys_info sys_info; 178 179 get_sys_info(&sys_info); 180 gd->cpu_clk = sys_info.freq_processor[0]; 181 gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV; 182 gd->mem_clk = sys_info.freq_ddrbus; 183 184 #ifdef CONFIG_FSL_ESDHC 185 gd->arch.sdhc_clk = sys_info.freq_sdhc; 186 #endif 187 188 if (gd->cpu_clk != 0) 189 return 0; 190 else 191 return 1; 192 } 193 194 /******************************************** 195 * get_bus_freq 196 * return platform clock in Hz 197 *********************************************/ 198 ulong get_bus_freq(ulong dummy) 199 { 200 if (!gd->bus_clk) 201 get_clocks(); 202 203 return gd->bus_clk; 204 } 205 206 ulong get_ddr_freq(ulong dummy) 207 { 208 if (!gd->mem_clk) 209 get_clocks(); 210 211 return gd->mem_clk; 212 } 213 214 #ifdef CONFIG_FSL_ESDHC 215 int get_sdhc_freq(ulong dummy) 216 { 217 if (!gd->arch.sdhc_clk) 218 get_clocks(); 219 220 return gd->arch.sdhc_clk; 221 } 222 #endif 223 224 int get_serial_clock(void) 225 { 226 return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV; 227 } 228 229 int get_i2c_freq(ulong dummy) 230 { 231 return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV; 232 } 233 234 int get_dspi_freq(ulong dummy) 235 { 236 return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV; 237 } 238 239 #ifdef CONFIG_FSL_LPUART 240 int get_uart_freq(ulong dummy) 241 { 242 return get_bus_freq(0) / CONFIG_SYS_FSL_LPUART_CLK_DIV; 243 } 244 #endif 245 246 unsigned int mxc_get_clock(enum mxc_clock clk) 247 { 248 switch (clk) { 249 case MXC_I2C_CLK: 250 return get_i2c_freq(0); 251 #if defined(CONFIG_FSL_ESDHC) 252 case MXC_ESDHC_CLK: 253 return get_sdhc_freq(0); 254 #endif 255 case MXC_DSPI_CLK: 256 return get_dspi_freq(0); 257 #ifdef CONFIG_FSL_LPUART 258 case MXC_UART_CLK: 259 return get_uart_freq(0); 260 #endif 261 default: 262 printf("Unsupported clock\n"); 263 } 264 return 0; 265 } 266