1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2016 Freescale Semiconductor, Inc. 4 */ 5 6#include <common.h> 7#include <clock_legacy.h> 8#include <command.h> 9#include <div64.h> 10#include <asm/global_data.h> 11#include <asm/io.h> 12#include <errno.h> 13#include <asm/arch/clock.h> 14#include <asm/arch/sys_proto.h> 15 16DECLARE_GLOBAL_DATA_PTR; 17 18int get_clocks(void) 19{ 20#ifdef CONFIG_FSL_ESDHC_IMX 21#if CFG_SYS_FSL_ESDHC_ADDR == USDHC0_RBASE 22 gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); 23#elif CFG_SYS_FSL_ESDHC_ADDR == USDHC1_RBASE 24 gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); 25#endif 26#endif 27 return 0; 28} 29 30static u32 get_fast_plat_clk(void) 31{ 32 return scg_clk_get_rate(SCG_NIC0_CLK); 33} 34 35static u32 get_slow_plat_clk(void) 36{ 37 return scg_clk_get_rate(SCG_NIC1_CLK); 38} 39 40static u32 get_ipg_clk(void) 41{ 42 return scg_clk_get_rate(SCG_NIC1_BUS_CLK); 43} 44 45u32 get_lpuart_clk(void) 46{ 47 int index = 0; 48 49 const u32 lpuart_array[] = { 50 LPUART0_RBASE, 51 LPUART1_RBASE, 52 LPUART2_RBASE, 53 LPUART3_RBASE, 54 LPUART4_RBASE, 55 LPUART5_RBASE, 56 LPUART6_RBASE, 57 LPUART7_RBASE, 58 }; 59 60 const enum pcc_clk lpuart_pcc_clks[] = { 61 PER_CLK_LPUART4, 62 PER_CLK_LPUART5, 63 PER_CLK_LPUART6, 64 PER_CLK_LPUART7, 65 }; 66 67 for (index = 0; index < 8; index++) { 68 if (lpuart_array[index] == LPUART_BASE) 69 break; 70 } 71 72 if (index < 4 || index > 7) 73 return 0; 74 75 return pcc_clock_get_rate(lpuart_pcc_clks[index - 4]); 76} 77 78#ifdef CONFIG_SYS_I2C_IMX_LPI2C 79int enable_i2c_clk(unsigned char enable, unsigned i2c_num) 80{ 81 /* Set parent to FIRC DIV2 clock */ 82 const enum pcc_clk lpi2c_pcc_clks[] = { 83 PER_CLK_LPI2C4, 84 PER_CLK_LPI2C5, 85 PER_CLK_LPI2C6, 86 PER_CLK_LPI2C7, 87 }; 88 89 if (i2c_num < 4 || i2c_num > 7) 90 return -EINVAL; 91 92 if (enable) { 93 pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4], false); 94 pcc_clock_sel(lpi2c_pcc_clks[i2c_num - 4], SCG_FIRC_DIV2_CLK); 95 pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4], true); 96 } else { 97 pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4], false); 98 } 99 return 0; 100} 101 102u32 imx_get_i2cclk(unsigned i2c_num) 103{ 104 const enum pcc_clk lpi2c_pcc_clks[] = { 105 PER_CLK_LPI2C4, 106 PER_CLK_LPI2C5, 107 PER_CLK_LPI2C6, 108 PER_CLK_LPI2C7, 109 }; 110 111 if (i2c_num < 4 || i2c_num > 7) 112 return 0; 113 114 return pcc_clock_get_rate(lpi2c_pcc_clks[i2c_num - 4]); 115} 116#endif 117 118unsigned int mxc_get_clock(enum mxc_clock clk) 119{ 120 switch (clk) { 121 case MXC_ARM_CLK: 122 return scg_clk_get_rate(SCG_CORE_CLK); 123 case MXC_AXI_CLK: 124 return get_fast_plat_clk(); 125 case MXC_AHB_CLK: 126 return get_slow_plat_clk(); 127 case MXC_IPG_CLK: 128 return get_ipg_clk(); 129 case MXC_I2C_CLK: 130 return pcc_clock_get_rate(PER_CLK_LPI2C4); 131 case MXC_UART_CLK: 132 return get_lpuart_clk(); 133 case MXC_ESDHC_CLK: 134 return pcc_clock_get_rate(PER_CLK_USDHC0); 135 case MXC_ESDHC2_CLK: 136 return pcc_clock_get_rate(PER_CLK_USDHC1); 137 case MXC_DDR_CLK: 138 return scg_clk_get_rate(SCG_DDR_CLK); 139 default: 140 printf("Unsupported mxc_clock %d\n", clk); 141 break; 142 } 143 144 return 0; 145} 146 147void init_clk_usdhc(u32 index) 148{ 149 switch (index) { 150 case 0: 151 /*Disable the clock before configure it */ 152 pcc_clock_enable(PER_CLK_USDHC0, false); 153 154 /* 158MHz / 1 = 158MHz */ 155 pcc_clock_sel(PER_CLK_USDHC0, SCG_NIC1_CLK); 156 pcc_clock_div_config(PER_CLK_USDHC0, false, 1); 157 pcc_clock_enable(PER_CLK_USDHC0, true); 158 break; 159 case 1: 160 /*Disable the clock before configure it */ 161 pcc_clock_enable(PER_CLK_USDHC1, false); 162 163 /* 158MHz / 1 = 158MHz */ 164 pcc_clock_sel(PER_CLK_USDHC1, SCG_NIC1_CLK); 165 pcc_clock_div_config(PER_CLK_USDHC1, false, 1); 166 pcc_clock_enable(PER_CLK_USDHC1, true); 167 break; 168 default: 169 printf("Invalid index for USDHC %d\n", index); 170 break; 171 } 172} 173 174#ifdef CONFIG_MXC_OCOTP 175 176#define OCOTP_CTRL_PCC1_SLOT (38) 177#define OCOTP_CTRL_HIGH4K_PCC1_SLOT (39) 178 179void enable_ocotp_clk(unsigned char enable) 180{ 181 u32 val; 182 183 /* 184 * Seems the OCOTP CLOCKs have been enabled at default, 185 * check its inuse flag 186 */ 187 188 val = readl(PCC1_RBASE + 4 * OCOTP_CTRL_PCC1_SLOT); 189 if (!(val & PCC_INUSE_MASK)) 190 writel(PCC_CGC_MASK, (PCC1_RBASE + 4 * OCOTP_CTRL_PCC1_SLOT)); 191 192 val = readl(PCC1_RBASE + 4 * OCOTP_CTRL_HIGH4K_PCC1_SLOT); 193 if (!(val & PCC_INUSE_MASK)) 194 writel(PCC_CGC_MASK, 195 (PCC1_RBASE + 4 * OCOTP_CTRL_HIGH4K_PCC1_SLOT)); 196} 197#endif 198 199void enable_usboh3_clk(unsigned char enable) 200{ 201 if (enable) { 202 pcc_clock_enable(PER_CLK_USB0, false); 203 pcc_clock_sel(PER_CLK_USB0, SCG_NIC1_BUS_CLK); 204 pcc_clock_enable(PER_CLK_USB0, true); 205 206#ifdef CONFIG_USB_MAX_CONTROLLER_COUNT 207 if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1) { 208 pcc_clock_enable(PER_CLK_USB1, false); 209 pcc_clock_sel(PER_CLK_USB1, SCG_NIC1_BUS_CLK); 210 pcc_clock_enable(PER_CLK_USB1, true); 211 } 212#endif 213 214 pcc_clock_enable(PER_CLK_USB_PHY, true); 215 pcc_clock_enable(PER_CLK_USB_PL301, true); 216 } else { 217 pcc_clock_enable(PER_CLK_USB0, false); 218 pcc_clock_enable(PER_CLK_USB1, false); 219 pcc_clock_enable(PER_CLK_USB_PHY, false); 220 pcc_clock_enable(PER_CLK_USB_PL301, false); 221 } 222} 223 224static void lpuart_set_clk(uint32_t index, enum scg_clk clk) 225{ 226 const enum pcc_clk lpuart_pcc_clks[] = { 227 PER_CLK_LPUART4, 228 PER_CLK_LPUART5, 229 PER_CLK_LPUART6, 230 PER_CLK_LPUART7, 231 }; 232 233 if (index < 4 || index > 7) 234 return; 235 236#ifndef CONFIG_CLK_DEBUG 237 pcc_clock_enable(lpuart_pcc_clks[index - 4], false); 238#endif 239 pcc_clock_sel(lpuart_pcc_clks[index - 4], clk); 240 pcc_clock_enable(lpuart_pcc_clks[index - 4], true); 241} 242 243static void init_clk_lpuart(void) 244{ 245 u32 index = 0, i; 246 247 const u32 lpuart_array[] = { 248 LPUART0_RBASE, 249 LPUART1_RBASE, 250 LPUART2_RBASE, 251 LPUART3_RBASE, 252 LPUART4_RBASE, 253 LPUART5_RBASE, 254 LPUART6_RBASE, 255 LPUART7_RBASE, 256 }; 257 258 for (i = 0; i < 8; i++) { 259 if (lpuart_array[i] == LPUART_BASE) { 260 index = i; 261 break; 262 } 263 } 264 265 lpuart_set_clk(index, SCG_SOSC_DIV2_CLK); 266} 267 268static void init_clk_rgpio2p(void) 269{ 270 /*Enable RGPIO2P1 clock */ 271 pcc_clock_enable(PER_CLK_RGPIO2P1, true); 272 273 /* 274 * Hard code to enable RGPIO2P0 clock since it is not 275 * in clock frame for A7 domain 276 */ 277 writel(PCC_CGC_MASK, (PCC0_RBASE + 0x3C)); 278} 279 280/* Configure PLL/PFD freq */ 281void clock_init(void) 282{ 283 /* 284 * ROM has enabled clocks: 285 * A4 side: SIRC 16Mhz (DIV1-3 off), FIRC 48Mhz (DIV1-2 on), 286 * Non-LP-boot: SOSC, SPLL PFD0 (scs selected) 287 * A7 side: SPLL PFD0 (scs selected, 413Mhz), 288 * APLL PFD0 (352Mhz), DDRCLK, all NIC clocks 289 * A7 Plat0 (NIC0) = 176Mhz, Plat1 (NIC1) = 176Mhz, 290 * IP BUS (NIC1_BUS) = 58.6Mhz 291 * 292 * In u-boot: 293 * 1. Enable PFD1-3 of APLL for A7 side. Enable FIRC and DIVs. 294 * 2. Enable USB PLL 295 * 3. Init the clocks of peripherals used in u-boot bu 296 * without set rate interface.The clocks for these 297 * peripherals are enabled in this intialization. 298 * 4.Other peripherals with set clock rate interface 299 * does not be set in this function. 300 */ 301 302 scg_a7_firc_init(); 303 304 scg_a7_soscdiv_init(); 305 306 scg_a7_init_core_clk(); 307 308 /* APLL PFD1 = 270Mhz, PFD2=345.6Mhz, PFD3=800Mhz */ 309 scg_enable_pll_pfd(SCG_APLL_PFD1_CLK, 35); 310 scg_enable_pll_pfd(SCG_APLL_PFD2_CLK, 28); 311 scg_enable_pll_pfd(SCG_APLL_PFD3_CLK, 12); 312 313 init_clk_lpuart(); 314 315 init_clk_rgpio2p(); 316 317 enable_usboh3_clk(1); 318} 319 320#ifdef CONFIG_IMX_HAB 321void hab_caam_clock_enable(unsigned char enable) 322{ 323 if (enable) 324 pcc_clock_enable(PER_CLK_CAAM, true); 325 else 326 pcc_clock_enable(PER_CLK_CAAM, false); 327} 328#endif 329 330#ifndef CONFIG_SPL_BUILD 331/* 332 * Dump some core clockes. 333 */ 334int do_mx7_showclocks(struct cmd_tbl *cmdtp, int flag, int argc, 335 char *const argv[]) 336{ 337 338 u32 freq; 339 freq = decode_pll(PLL_A7_SPLL); 340 printf("PLL_A7_SPLL %8d MHz\n", freq / 1000000); 341 342 freq = decode_pll(PLL_A7_APLL); 343 printf("PLL_A7_APLL %8d MHz\n", freq / 1000000); 344 345 freq = decode_pll(PLL_USB); 346 printf("PLL_USB %8d MHz\n", freq / 1000000); 347 348 printf("\n"); 349 350 printf("CORE %8d kHz\n", scg_clk_get_rate(SCG_CORE_CLK) / 1000); 351 printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000); 352 printf("UART %8d kHz\n", mxc_get_clock(MXC_UART_CLK) / 1000); 353 printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000); 354 printf("AXI %8d kHz\n", mxc_get_clock(MXC_AXI_CLK) / 1000); 355 printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000); 356 printf("USDHC1 %8d kHz\n", mxc_get_clock(MXC_ESDHC_CLK) / 1000); 357 printf("USDHC2 %8d kHz\n", mxc_get_clock(MXC_ESDHC2_CLK) / 1000); 358 printf("I2C4 %8d kHz\n", mxc_get_clock(MXC_I2C_CLK) / 1000); 359 360 scg_a7_info(); 361 362 return 0; 363} 364 365U_BOOT_CMD( 366 clocks, CONFIG_SYS_MAXARGS, 1, do_mx7_showclocks, 367 "display clocks", 368 "" 369); 370#endif 371