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