4fc31862278f2a7a6e5c968c387937020e90c3d5
[oweals/u-boot.git] / arch / arm / cpu / armv8 / fsl-layerscape / fsl_lsch2_speed.c
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         sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
63                         FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
64                         FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
65         sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
66                         FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) &
67                         FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK;
68
69         for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
70                 ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff;
71                 if (ratio[i] > 4)
72                         freq_c_pll[i] = sysclk * ratio[i];
73                 else
74                         freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
75         }
76
77         for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) {
78                 u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27)
79                                 & 0xf;
80                 u32 cplx_pll = core_cplx_pll[c_pll_sel];
81
82                 sys_info->freq_processor[cpu] =
83                         freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
84         }
85
86 #define HWA_CGA_M1_CLK_SEL      0xe0000000
87 #define HWA_CGA_M1_CLK_SHIFT    29
88 #ifdef CONFIG_SYS_DPAA_FMAN
89         rcw_tmp = in_be32(&gur->rcwsr[7]);
90         switch ((rcw_tmp & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) {
91         case 2:
92                 sys_info->freq_fman[0] = freq_c_pll[0] / 2;
93                 break;
94         case 3:
95                 sys_info->freq_fman[0] = freq_c_pll[0] / 3;
96                 break;
97         case 6:
98                 sys_info->freq_fman[0] = freq_c_pll[1] / 2;
99                 break;
100         case 7:
101                 sys_info->freq_fman[0] = freq_c_pll[1] / 3;
102                 break;
103         default:
104                 printf("Error: Unknown FMan1 clock select!\n");
105                 break;
106         }
107 #endif
108
109 #define HWA_CGA_M2_CLK_SEL      0x00000007
110 #define HWA_CGA_M2_CLK_SHIFT    0
111 #ifdef CONFIG_FSL_ESDHC
112 #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
113         rcw_tmp = in_be32(&gur->rcwsr[15]);
114         rcw_tmp = (rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT;
115         sys_info->freq_sdhc = freq_c_pll[1] / rcw_tmp;
116 #else
117         sys_info->freq_sdhc = sys_info->freq_systembus;
118 #endif
119 #endif
120
121 #if defined(CONFIG_FSL_IFC)
122         ccr = ifc_in32(&ifc_regs.gregs->ifc_ccr);
123         ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
124
125         sys_info->freq_localbus = sys_info->freq_systembus / ccr;
126 #endif
127 }
128
129 int get_clocks(void)
130 {
131         struct sys_info sys_info;
132
133         get_sys_info(&sys_info);
134         gd->cpu_clk = sys_info.freq_processor[0];
135         gd->bus_clk = sys_info.freq_systembus;
136         gd->mem_clk = sys_info.freq_ddrbus;
137
138 #ifdef CONFIG_FSL_ESDHC
139         gd->arch.sdhc_clk = sys_info.freq_sdhc;
140 #endif
141
142         if (gd->cpu_clk != 0)
143                 return 0;
144         else
145                 return 1;
146 }
147
148 ulong get_bus_freq(ulong dummy)
149 {
150         return gd->bus_clk;
151 }
152
153 ulong get_ddr_freq(ulong dummy)
154 {
155         return gd->mem_clk;
156 }
157
158 #ifdef CONFIG_FSL_ESDHC
159 int get_sdhc_freq(ulong dummy)
160 {
161         return gd->arch.sdhc_clk;
162 }
163 #endif
164
165 int get_serial_clock(void)
166 {
167         return gd->bus_clk;
168 }
169
170 unsigned int mxc_get_clock(enum mxc_clock clk)
171 {
172         switch (clk) {
173         case MXC_I2C_CLK:
174                 return get_bus_freq(0);
175 #if defined(CONFIG_FSL_ESDHC)
176         case MXC_ESDHC_CLK:
177                 return get_sdhc_freq(0);
178 #endif
179         case MXC_DSPI_CLK:
180                 return get_bus_freq(0);
181         case MXC_UART_CLK:
182                 return get_bus_freq(0);
183         default:
184                 printf("Unsupported clock\n");
185         }
186         return 0;
187 }