armv8/ls1088a/ls2088a: esdhc: Add esdhc clock support
[oweals/u-boot.git] / arch / arm / cpu / armv8 / fsl-layerscape / fsl_lsch3_speed.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014-2015, Freescale Semiconductor, Inc.
4  *
5  * Derived from arch/power/cpu/mpc85xx/speed.c
6  */
7
8 #include <common.h>
9 #include <linux/compiler.h>
10 #include <fsl_ifc.h>
11 #include <asm/processor.h>
12 #include <asm/io.h>
13 #include <asm/arch-fsl-layerscape/immap_lsch3.h>
14 #include <asm/arch/clock.h>
15 #include <asm/arch/soc.h>
16 #include "cpu.h"
17
18 DECLARE_GLOBAL_DATA_PTR;
19
20 #ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
21 #define CONFIG_SYS_FSL_NUM_CC_PLLS      6
22 #endif
23
24
25 void get_sys_info(struct sys_info *sys_info)
26 {
27         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
28         struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
29                 (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
30                 (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
31         };
32         struct ccsr_clk_ctrl __iomem *clk_ctrl =
33                 (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
34         unsigned int cpu;
35         const u8 core_cplx_pll[16] = {
36                 [0] = 0,        /* CC1 PPL / 1 */
37                 [1] = 0,        /* CC1 PPL / 2 */
38                 [2] = 0,        /* CC1 PPL / 4 */
39                 [4] = 1,        /* CC2 PPL / 1 */
40                 [5] = 1,        /* CC2 PPL / 2 */
41                 [6] = 1,        /* CC2 PPL / 4 */
42                 [8] = 2,        /* CC3 PPL / 1 */
43                 [9] = 2,        /* CC3 PPL / 2 */
44                 [10] = 2,       /* CC3 PPL / 4 */
45                 [12] = 3,       /* CC4 PPL / 1 */
46                 [13] = 3,       /* CC4 PPL / 2 */
47                 [14] = 3,       /* CC4 PPL / 4 */
48         };
49
50         const u8 core_cplx_pll_div[16] = {
51                 [0] = 1,        /* CC1 PPL / 1 */
52                 [1] = 2,        /* CC1 PPL / 2 */
53                 [2] = 4,        /* CC1 PPL / 4 */
54                 [4] = 1,        /* CC2 PPL / 1 */
55                 [5] = 2,        /* CC2 PPL / 2 */
56                 [6] = 4,        /* CC2 PPL / 4 */
57                 [8] = 1,        /* CC3 PPL / 1 */
58                 [9] = 2,        /* CC3 PPL / 2 */
59                 [10] = 4,       /* CC3 PPL / 4 */
60                 [12] = 1,       /* CC4 PPL / 1 */
61                 [13] = 2,       /* CC4 PPL / 2 */
62                 [14] = 4,       /* CC4 PPL / 4 */
63         };
64
65         uint i, cluster;
66         uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
67         uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
68         unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
69         int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
70         u32 c_pll_sel, cplx_pll;
71         void *offset;
72
73         sys_info->freq_systembus = sysclk;
74 #ifdef CONFIG_DDR_CLK_FREQ
75         sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
76 #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
77         sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ;
78 #endif
79 #else
80         sys_info->freq_ddrbus = sysclk;
81 #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
82         sys_info->freq_ddrbus2 = sysclk;
83 #endif
84 #endif
85
86         /* The freq_systembus is used to record frequency of platform PLL */
87         sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
88                         FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
89                         FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
90         sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
91                         FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
92                         FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
93 #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
94         if (soc_has_dp_ddr()) {
95                 sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >>
96                         FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) &
97                         FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK;
98         } else {
99                 sys_info->freq_ddrbus2 = 0;
100         }
101 #endif
102
103         for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
104                 /*
105                  * fixme: prefer to combine the following into one line, but
106                  * cannot pass compiling without warning about in_le32.
107                  */
108                 offset = (void *)((size_t)clk_grp[i/3] +
109                          offsetof(struct ccsr_clk_cluster_group,
110                                   pllngsr[i%3].gsr));
111                 ratio[i] = (in_le32(offset) >> 1) & 0x3f;
112                 freq_c_pll[i] = sysclk * ratio[i];
113         }
114
115         for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
116                 cluster = fsl_qoriq_core_to_cluster(cpu);
117                 c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
118                             & 0xf;
119                 cplx_pll = core_cplx_pll[c_pll_sel];
120                 cplx_pll += cc_group[cluster] - 1;
121                 sys_info->freq_processor[cpu] =
122                         freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
123         }
124
125 #if defined(CONFIG_FSL_IFC)
126         sys_info->freq_localbus = sys_info->freq_systembus /
127                                                 CONFIG_SYS_FSL_IFC_CLK_DIV;
128 #endif
129 }
130
131
132 int get_clocks(void)
133 {
134         struct sys_info sys_info;
135         get_sys_info(&sys_info);
136         gd->cpu_clk = sys_info.freq_processor[0];
137         gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV;
138         gd->mem_clk = sys_info.freq_ddrbus;
139 #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
140         gd->arch.mem2_clk = sys_info.freq_ddrbus2;
141 #endif
142 #if defined(CONFIG_FSL_ESDHC)
143         gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV;
144 #endif /* defined(CONFIG_FSL_ESDHC) */
145
146         if (gd->cpu_clk != 0)
147                 return 0;
148         else
149                 return 1;
150 }
151
152 /********************************************
153  * get_bus_freq
154  * return platform clock in Hz
155  *********************************************/
156 ulong get_bus_freq(ulong dummy)
157 {
158         if (!gd->bus_clk)
159                 get_clocks();
160
161         return gd->bus_clk;
162 }
163
164 /********************************************
165  * get_ddr_freq
166  * return ddr bus freq in Hz
167  *********************************************/
168 ulong get_ddr_freq(ulong ctrl_num)
169 {
170         if (!gd->mem_clk)
171                 get_clocks();
172
173         /*
174          * DDR controller 0 & 1 are on memory complex 0
175          * DDR controller 2 is on memory complext 1
176          */
177 #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
178         if (ctrl_num >= 2)
179                 return gd->arch.mem2_clk;
180 #endif
181
182         return gd->mem_clk;
183 }
184
185 int get_i2c_freq(ulong dummy)
186 {
187         return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
188 }
189
190 int get_dspi_freq(ulong dummy)
191 {
192         return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
193 }
194
195 #ifdef CONFIG_FSL_ESDHC
196 int get_sdhc_freq(ulong dummy)
197 {
198         if (!gd->arch.sdhc_clk)
199                 get_clocks();
200
201         return gd->arch.sdhc_clk;
202 }
203 #endif
204
205 int get_serial_clock(void)
206 {
207         return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
208 }
209
210 unsigned int mxc_get_clock(enum mxc_clock clk)
211 {
212         switch (clk) {
213         case MXC_I2C_CLK:
214                 return get_i2c_freq(0);
215 #if defined(CONFIG_FSL_ESDHC)
216         case MXC_ESDHC_CLK:
217                 return get_sdhc_freq(0);
218 #endif
219         case MXC_DSPI_CLK:
220                 return get_dspi_freq(0);
221         default:
222                 printf("Unsupported clock\n");
223         }
224         return 0;
225 }