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