1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2013 Freescale Semiconductor, Inc.
8 #include <asm/arch/imx-regs.h>
9 #include <asm/arch/clock.h>
10 #include <asm/arch/crm_regs.h>
11 #include <asm/mach-imx/sys_proto.h>
13 #ifdef CONFIG_FSL_ESDHC_IMX
14 #include <fsl_esdhc_imx.h>
17 #ifdef CONFIG_FSL_ESDHC_IMX
18 DECLARE_GLOBAL_DATA_PTR
;
21 static char soc_type
[] = "xx0";
23 #ifdef CONFIG_MXC_OCOTP
24 void enable_ocotp_clk(unsigned char enable
)
26 struct ccm_reg
*ccm
= (struct ccm_reg
*)CCM_BASE_ADDR
;
29 reg
= readl(&ccm
->ccgr6
);
31 reg
|= CCM_CCGR6_OCOTP_CTRL_MASK
;
33 reg
&= ~CCM_CCGR6_OCOTP_CTRL_MASK
;
34 writel(reg
, &ccm
->ccgr6
);
38 static u32
get_mcu_main_clk(void)
40 struct ccm_reg
*ccm
= (struct ccm_reg
*)CCM_BASE_ADDR
;
41 u32 ccm_ccsr
, ccm_cacrr
, armclk_div
;
42 u32 sysclk_sel
, pll_pfd_sel
= 0;
45 ccm_ccsr
= readl(&ccm
->ccsr
);
46 sysclk_sel
= ccm_ccsr
& CCM_CCSR_SYS_CLK_SEL_MASK
;
47 sysclk_sel
>>= CCM_CCSR_SYS_CLK_SEL_OFFSET
;
49 ccm_cacrr
= readl(&ccm
->cacrr
);
50 armclk_div
= ccm_cacrr
& CCM_CACRR_ARM_CLK_DIV_MASK
;
51 armclk_div
>>= CCM_CACRR_ARM_CLK_DIV_OFFSET
;
62 pll_pfd_sel
= ccm_ccsr
& CCM_CCSR_PLL2_PFD_CLK_SEL_MASK
;
63 pll_pfd_sel
>>= CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET
;
65 freq
= PLL2_MAIN_FREQ
;
66 else if (pll_pfd_sel
== 1)
67 freq
= PLL2_PFD1_FREQ
;
68 else if (pll_pfd_sel
== 2)
69 freq
= PLL2_PFD2_FREQ
;
70 else if (pll_pfd_sel
== 3)
71 freq
= PLL2_PFD3_FREQ
;
72 else if (pll_pfd_sel
== 4)
73 freq
= PLL2_PFD4_FREQ
;
76 freq
= PLL2_MAIN_FREQ
;
79 pll_pfd_sel
= ccm_ccsr
& CCM_CCSR_PLL1_PFD_CLK_SEL_MASK
;
80 pll_pfd_sel
>>= CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET
;
82 freq
= PLL1_MAIN_FREQ
;
83 else if (pll_pfd_sel
== 1)
84 freq
= PLL1_PFD1_FREQ
;
85 else if (pll_pfd_sel
== 2)
86 freq
= PLL1_PFD2_FREQ
;
87 else if (pll_pfd_sel
== 3)
88 freq
= PLL1_PFD3_FREQ
;
89 else if (pll_pfd_sel
== 4)
90 freq
= PLL1_PFD4_FREQ
;
93 freq
= PLL3_MAIN_FREQ
;
96 printf("unsupported system clock select\n");
99 return freq
/ armclk_div
;
102 static u32
get_bus_clk(void)
104 struct ccm_reg
*ccm
= (struct ccm_reg
*)CCM_BASE_ADDR
;
105 u32 ccm_cacrr
, busclk_div
;
107 ccm_cacrr
= readl(&ccm
->cacrr
);
109 busclk_div
= ccm_cacrr
& CCM_CACRR_BUS_CLK_DIV_MASK
;
110 busclk_div
>>= CCM_CACRR_BUS_CLK_DIV_OFFSET
;
113 return get_mcu_main_clk() / busclk_div
;
116 static u32
get_ipg_clk(void)
118 struct ccm_reg
*ccm
= (struct ccm_reg
*)CCM_BASE_ADDR
;
119 u32 ccm_cacrr
, ipgclk_div
;
121 ccm_cacrr
= readl(&ccm
->cacrr
);
123 ipgclk_div
= ccm_cacrr
& CCM_CACRR_IPG_CLK_DIV_MASK
;
124 ipgclk_div
>>= CCM_CACRR_IPG_CLK_DIV_OFFSET
;
127 return get_bus_clk() / ipgclk_div
;
130 static u32
get_uart_clk(void)
132 return get_ipg_clk();
135 static u32
get_sdhc_clk(void)
137 struct ccm_reg
*ccm
= (struct ccm_reg
*)CCM_BASE_ADDR
;
138 u32 ccm_cscmr1
, ccm_cscdr2
, sdhc_clk_sel
, sdhc_clk_div
;
141 ccm_cscmr1
= readl(&ccm
->cscmr1
);
142 sdhc_clk_sel
= ccm_cscmr1
& CCM_CSCMR1_ESDHC1_CLK_SEL_MASK
;
143 sdhc_clk_sel
>>= CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET
;
145 ccm_cscdr2
= readl(&ccm
->cscdr2
);
146 sdhc_clk_div
= ccm_cscdr2
& CCM_CSCDR2_ESDHC1_CLK_DIV_MASK
;
147 sdhc_clk_div
>>= CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET
;
150 switch (sdhc_clk_sel
) {
152 freq
= PLL3_MAIN_FREQ
;
155 freq
= PLL3_PFD3_FREQ
;
158 freq
= PLL1_PFD3_FREQ
;
161 freq
= get_bus_clk();
165 return freq
/ sdhc_clk_div
;
168 u32
get_fec_clk(void)
170 struct ccm_reg
*ccm
= (struct ccm_reg
*)CCM_BASE_ADDR
;
171 u32 ccm_cscmr2
, rmii_clk_sel
;
174 ccm_cscmr2
= readl(&ccm
->cscmr2
);
175 rmii_clk_sel
= ccm_cscmr2
& CCM_CSCMR2_RMII_CLK_SEL_MASK
;
176 rmii_clk_sel
>>= CCM_CSCMR2_RMII_CLK_SEL_OFFSET
;
178 switch (rmii_clk_sel
) {
180 freq
= ENET_EXTERNAL_CLK
;
183 freq
= AUDIO_EXTERNAL_CLK
;
186 freq
= PLL5_MAIN_FREQ
;
189 freq
= PLL5_MAIN_FREQ
/ 2;
196 static u32
get_i2c_clk(void)
198 return get_ipg_clk();
201 static u32
get_dspi_clk(void)
203 return get_ipg_clk();
206 u32
get_lpuart_clk(void)
208 return get_uart_clk();
211 unsigned int mxc_get_clock(enum mxc_clock clk
)
215 return get_mcu_main_clk();
217 return get_bus_clk();
219 return get_ipg_clk();
221 return get_uart_clk();
223 return get_sdhc_clk();
225 return get_fec_clk();
227 return get_i2c_clk();
229 return get_dspi_clk();
236 /* Dump some core clocks */
237 int do_vf610_showclocks(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
241 printf("cpu clock : %8d MHz\n", mxc_get_clock(MXC_ARM_CLK
) / 1000000);
242 printf("bus clock : %8d MHz\n", mxc_get_clock(MXC_BUS_CLK
) / 1000000);
243 printf("ipg clock : %8d MHz\n", mxc_get_clock(MXC_IPG_CLK
) / 1000000);
249 clocks
, CONFIG_SYS_MAXARGS
, 1, do_vf610_showclocks
,
254 #ifdef CONFIG_FEC_MXC
255 __weak
void imx_get_mac_from_fuse(int dev_id
, unsigned char *mac
)
257 struct ocotp_regs
*ocotp
= (struct ocotp_regs
*)OCOTP_BASE_ADDR
;
258 struct fuse_bank
*bank
= &ocotp
->bank
[4];
259 struct fuse_bank4_regs
*fuse
=
260 (struct fuse_bank4_regs
*)bank
->fuse_regs
;
262 u32 value
= readl(&fuse
->mac_addr0
);
263 mac
[0] = (value
>> 8);
266 value
= readl(&fuse
->mac_addr1
);
267 mac
[2] = value
>> 24;
268 mac
[3] = value
>> 16;
274 u32
get_cpu_rev(void)
276 return MXC_CPU_VF610
<< 12;
279 #if defined(CONFIG_DISPLAY_CPUINFO)
280 static char *get_reset_cause(void)
283 struct src
*src_regs
= (struct src
*)SRC_BASE_ADDR
;
285 cause
= readl(&src_regs
->srsr
);
286 writel(cause
, &src_regs
->srsr
);
288 if (cause
& SRC_SRSR_POR_RST
)
289 return "POWER ON RESET";
290 else if (cause
& SRC_SRSR_WDOG_A5
)
292 else if (cause
& SRC_SRSR_WDOG_M4
)
294 else if (cause
& SRC_SRSR_JTAG_RST
)
295 return "JTAG HIGH-Z";
296 else if (cause
& SRC_SRSR_SW_RST
)
298 else if (cause
& SRC_SRSR_RESETB
)
299 return "EXTERNAL RESET";
301 return "unknown reset";
304 int print_cpuinfo(void)
306 printf("CPU: Freescale Vybrid VF%s at %d MHz\n",
307 soc_type
, mxc_get_clock(MXC_ARM_CLK
) / 1000000);
308 printf("Reset cause: %s\n", get_reset_cause());
314 int arch_cpu_init(void)
316 struct mscm
*mscm
= (struct mscm
*)MSCM_BASE_ADDR
;
318 soc_type
[0] = mscm
->cpxcount
? '6' : '5'; /*Dual Core => VF6x0 */
319 soc_type
[1] = mscm
->cpxcfg1
? '1' : '0'; /* L2 Cache => VFx10 */
324 #ifdef CONFIG_ARCH_MISC_INIT
325 int arch_misc_init(void)
330 strcat(soc
, soc_type
);
337 int cpu_eth_init(bd_t
*bis
)
341 #if defined(CONFIG_FEC_MXC)
342 rc
= fecmxc_initialize(bis
);
348 #ifdef CONFIG_FSL_ESDHC_IMX
349 int cpu_mmc_init(bd_t
*bis
)
351 return fsl_esdhc_mmc_init(bis
);
357 #ifdef CONFIG_FSL_ESDHC_IMX
358 gd
->arch
.sdhc_clk
= mxc_get_clock(MXC_ESDHC_CLK
);
363 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
364 void enable_caches(void)
366 #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
367 enum dcache_option option
= DCACHE_WRITETHROUGH
;
369 enum dcache_option option
= DCACHE_WRITEBACK
;
374 /* Enable caching on OCRAM */
375 mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR
, IRAM_SIZE
, option
);
379 #ifdef CONFIG_SYS_I2C_MXC
380 /* i2c_num can be from 0 - 3 */
381 int enable_i2c_clk(unsigned char enable
, unsigned int i2c_num
)
383 struct ccm_reg
*ccm
= (struct ccm_reg
*)CCM_BASE_ADDR
;
387 clrsetbits_le32(&ccm
->ccgr4
, CCM_CCGR4_I2C0_CTRL_MASK
,
388 CCM_CCGR4_I2C0_CTRL_MASK
);
390 clrsetbits_le32(&ccm
->ccgr10
, CCM_CCGR10_I2C2_CTRL_MASK
,
391 CCM_CCGR10_I2C2_CTRL_MASK
);