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