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