blob: 7a337e1c5bc434c86ed8ff2dff7a0d935b397d5b [file] [log] [blame]
Wang Huand60a2092014-09-05 13:52:34 +08001/*
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
13DECLARE_GLOBAL_DATA_PTR;
14
15#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
16#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
17#endif
18
19void 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
Jaiprakash Singh39b0bbb2015-03-20 19:28:27 -070023 struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
Wang Huand60a2092014-09-05 13:52:34 +080024 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)
Jaiprakash Singh39b0bbb2015-03-20 19:28:27 -070077 ccr = in_be32(&ifc_regs.gregs->ifc_ccr);
Wang Huand60a2092014-09-05 13:52:34 +080078 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
84int 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
100ulong get_bus_freq(ulong dummy)
101{
102 return gd->bus_clk;
103}
104
105ulong get_ddr_freq(ulong dummy)
106{
107 return gd->mem_clk;
108}
109
110int get_serial_clock(void)
111{
112 return gd->bus_clk / 2;
113}
114
115unsigned 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}