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