xref: /openbmc/u-boot/arch/arm/cpu/armv7/ls102xa/clock.c (revision ad3098f7)
1 /*
2  * Copyright 2014 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <asm/io.h>
9 #include <asm/arch/immap_ls102xa.h>
10 #include <asm/arch/clock.h>
11 #include <fsl_ifc.h>
12 
13 DECLARE_GLOBAL_DATA_PTR;
14 
15 #ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
16 #define CONFIG_SYS_FSL_NUM_CC_PLLS      2
17 #endif
18 
19 void get_sys_info(struct sys_info *sys_info)
20 {
21 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
22 #ifdef CONFIG_FSL_IFC
23 	struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
24 	u32 ccr;
25 #endif
26 	struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_LS1_CLK_ADDR);
27 	unsigned int cpu;
28 	const u8 core_cplx_pll[6] = {
29 		[0] = 0,	/* CC1 PPL / 1 */
30 		[1] = 0,	/* CC1 PPL / 2 */
31 		[4] = 1,	/* CC2 PPL / 1 */
32 		[5] = 1,	/* CC2 PPL / 2 */
33 	};
34 
35 	const u8 core_cplx_pll_div[6] = {
36 		[0] = 1,	/* CC1 PPL / 1 */
37 		[1] = 2,	/* CC1 PPL / 2 */
38 		[4] = 1,	/* CC2 PPL / 1 */
39 		[5] = 2,	/* CC2 PPL / 2 */
40 	};
41 
42 	uint i;
43 	uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
44 	uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
45 	unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
46 
47 	sys_info->freq_systembus = sysclk;
48 #ifdef CONFIG_DDR_CLK_FREQ
49 	sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
50 #else
51 	sys_info->freq_ddrbus = sysclk;
52 #endif
53 
54 	sys_info->freq_systembus *= (in_be32(&gur->rcwsr[0]) >>
55 		RCWSR0_SYS_PLL_RAT_SHIFT) & RCWSR0_SYS_PLL_RAT_MASK;
56 	sys_info->freq_ddrbus *= (in_be32(&gur->rcwsr[0]) >>
57 		RCWSR0_MEM_PLL_RAT_SHIFT) & RCWSR0_MEM_PLL_RAT_MASK;
58 
59 	for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
60 		ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0x3f;
61 		if (ratio[i] > 4)
62 			freq_c_pll[i] = sysclk * ratio[i];
63 		else
64 			freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
65 	}
66 
67 	for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) {
68 		u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27)
69 				& 0xf;
70 		u32 cplx_pll = core_cplx_pll[c_pll_sel];
71 
72 		sys_info->freq_processor[cpu] =
73 			freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
74 	}
75 
76 #if defined(CONFIG_FSL_IFC)
77 	ccr = in_be32(&ifc_regs.gregs->ifc_ccr);
78 	ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
79 
80 	sys_info->freq_localbus = sys_info->freq_systembus / ccr;
81 #endif
82 }
83 
84 int get_clocks(void)
85 {
86 	struct sys_info sys_info;
87 
88 	get_sys_info(&sys_info);
89 	gd->cpu_clk = sys_info.freq_processor[0];
90 	gd->bus_clk = sys_info.freq_systembus;
91 	gd->mem_clk = sys_info.freq_ddrbus * 2;
92 
93 #if defined(CONFIG_FSL_ESDHC)
94 	gd->arch.sdhc_clk = gd->bus_clk;
95 #endif
96 
97 	return 0;
98 }
99 
100 ulong get_bus_freq(ulong dummy)
101 {
102 	return gd->bus_clk;
103 }
104 
105 ulong get_ddr_freq(ulong dummy)
106 {
107 	return gd->mem_clk;
108 }
109 
110 int get_serial_clock(void)
111 {
112 	return gd->bus_clk / 2;
113 }
114 
115 unsigned int mxc_get_clock(enum mxc_clock clk)
116 {
117 	switch (clk) {
118 	case MXC_I2C_CLK:
119 		return get_bus_freq(0) / 2;
120 	case MXC_ESDHC_CLK:
121 		return get_bus_freq(0);
122 	case MXC_DSPI_CLK:
123 		return get_bus_freq(0) / 2;
124 	case MXC_UART_CLK:
125 		return get_bus_freq(0) / 2;
126 	default:
127 		printf("Unsupported clock\n");
128 	}
129 	return 0;
130 }
131