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 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 #ifdef CONFIG_FSL_IFC 25 struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; 26 u32 ccr; 27 #endif 28 #if (defined(CONFIG_FSL_ESDHC) &&\ 29 defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)) ||\ 30 defined(CONFIG_SYS_DPAA_FMAN) 31 32 u32 rcw_tmp; 33 #endif 34 struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR); 35 unsigned int cpu; 36 const u8 core_cplx_pll[8] = { 37 [0] = 0, /* CC1 PPL / 1 */ 38 [1] = 0, /* CC1 PPL / 2 */ 39 [4] = 1, /* CC2 PPL / 1 */ 40 [5] = 1, /* CC2 PPL / 2 */ 41 }; 42 43 const u8 core_cplx_pll_div[8] = { 44 [0] = 1, /* CC1 PPL / 1 */ 45 [1] = 2, /* CC1 PPL / 2 */ 46 [4] = 1, /* CC2 PPL / 1 */ 47 [5] = 2, /* CC2 PPL / 2 */ 48 }; 49 50 uint i; 51 uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; 52 uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; 53 unsigned long sysclk = CONFIG_SYS_CLK_FREQ; 54 55 sys_info->freq_systembus = sysclk; 56 #ifdef CONFIG_DDR_CLK_FREQ 57 sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ; 58 #else 59 sys_info->freq_ddrbus = sysclk; 60 #endif 61 62 #ifdef CONFIG_LS1012A 63 sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >> 64 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) & 65 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK; 66 #else 67 sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >> 68 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) & 69 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK; 70 sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >> 71 FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) & 72 FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK; 73 #endif 74 75 for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) { 76 ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff; 77 if (ratio[i] > 4) 78 freq_c_pll[i] = sysclk * ratio[i]; 79 else 80 freq_c_pll[i] = sys_info->freq_systembus * ratio[i]; 81 } 82 83 for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) { 84 u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27) 85 & 0xf; 86 u32 cplx_pll = core_cplx_pll[c_pll_sel]; 87 88 sys_info->freq_processor[cpu] = 89 freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel]; 90 } 91 92 #ifdef CONFIG_LS1012A 93 sys_info->freq_systembus = sys_info->freq_ddrbus / 2; 94 sys_info->freq_ddrbus *= 2; 95 #endif 96 97 #define HWA_CGA_M1_CLK_SEL 0xe0000000 98 #define HWA_CGA_M1_CLK_SHIFT 29 99 #ifdef CONFIG_SYS_DPAA_FMAN 100 rcw_tmp = in_be32(&gur->rcwsr[7]); 101 switch ((rcw_tmp & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) { 102 case 2: 103 sys_info->freq_fman[0] = freq_c_pll[0] / 2; 104 break; 105 case 3: 106 sys_info->freq_fman[0] = freq_c_pll[0] / 3; 107 break; 108 case 6: 109 sys_info->freq_fman[0] = freq_c_pll[1] / 2; 110 break; 111 case 7: 112 sys_info->freq_fman[0] = freq_c_pll[1] / 3; 113 break; 114 default: 115 printf("Error: Unknown FMan1 clock select!\n"); 116 break; 117 } 118 #endif 119 120 #define HWA_CGA_M2_CLK_SEL 0x00000007 121 #define HWA_CGA_M2_CLK_SHIFT 0 122 #ifdef CONFIG_FSL_ESDHC 123 #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK 124 rcw_tmp = in_be32(&gur->rcwsr[15]); 125 rcw_tmp = (rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT; 126 sys_info->freq_sdhc = freq_c_pll[1] / rcw_tmp; 127 #else 128 sys_info->freq_sdhc = sys_info->freq_systembus; 129 #endif 130 #endif 131 132 #if defined(CONFIG_FSL_IFC) 133 ccr = ifc_in32(&ifc_regs.gregs->ifc_ccr); 134 ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1; 135 136 sys_info->freq_localbus = sys_info->freq_systembus / ccr; 137 #endif 138 } 139 140 int get_clocks(void) 141 { 142 struct sys_info sys_info; 143 144 get_sys_info(&sys_info); 145 gd->cpu_clk = sys_info.freq_processor[0]; 146 gd->bus_clk = sys_info.freq_systembus; 147 gd->mem_clk = sys_info.freq_ddrbus; 148 149 #ifdef CONFIG_FSL_ESDHC 150 gd->arch.sdhc_clk = sys_info.freq_sdhc; 151 #endif 152 153 if (gd->cpu_clk != 0) 154 return 0; 155 else 156 return 1; 157 } 158 159 ulong get_bus_freq(ulong dummy) 160 { 161 return gd->bus_clk; 162 } 163 164 ulong get_ddr_freq(ulong dummy) 165 { 166 return gd->mem_clk; 167 } 168 169 #ifdef CONFIG_FSL_ESDHC 170 int get_sdhc_freq(ulong dummy) 171 { 172 return gd->arch.sdhc_clk; 173 } 174 #endif 175 176 int get_serial_clock(void) 177 { 178 return gd->bus_clk; 179 } 180 181 unsigned int mxc_get_clock(enum mxc_clock clk) 182 { 183 switch (clk) { 184 case MXC_I2C_CLK: 185 return get_bus_freq(0); 186 #if defined(CONFIG_FSL_ESDHC) 187 case MXC_ESDHC_CLK: 188 return get_sdhc_freq(0); 189 #endif 190 case MXC_DSPI_CLK: 191 return get_bus_freq(0); 192 case MXC_UART_CLK: 193 return get_bus_freq(0); 194 default: 195 printf("Unsupported clock\n"); 196 } 197 return 0; 198 } 199