Home | History | Annotate | Download | only in fsl-layerscape
      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