1 /* 2 * Copyright 2013 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 #include <asm/arch/imx-regs.h> 10 #include <asm/arch/clock.h> 11 #include <asm/arch/crm_regs.h> 12 #include <asm/imx-common/sys_proto.h> 13 #include <netdev.h> 14 #ifdef CONFIG_FSL_ESDHC 15 #include <fsl_esdhc.h> 16 #endif 17 18 #ifdef CONFIG_FSL_ESDHC 19 DECLARE_GLOBAL_DATA_PTR; 20 #endif 21 22 static char soc_type[] = "xx0"; 23 24 #ifdef CONFIG_MXC_OCOTP 25 void enable_ocotp_clk(unsigned char enable) 26 { 27 struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; 28 u32 reg; 29 30 reg = readl(&ccm->ccgr6); 31 if (enable) 32 reg |= CCM_CCGR6_OCOTP_CTRL_MASK; 33 else 34 reg &= ~CCM_CCGR6_OCOTP_CTRL_MASK; 35 writel(reg, &ccm->ccgr6); 36 } 37 #endif 38 39 static u32 get_mcu_main_clk(void) 40 { 41 struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; 42 u32 ccm_ccsr, ccm_cacrr, armclk_div; 43 u32 sysclk_sel, pll_pfd_sel = 0; 44 u32 freq = 0; 45 46 ccm_ccsr = readl(&ccm->ccsr); 47 sysclk_sel = ccm_ccsr & CCM_CCSR_SYS_CLK_SEL_MASK; 48 sysclk_sel >>= CCM_CCSR_SYS_CLK_SEL_OFFSET; 49 50 ccm_cacrr = readl(&ccm->cacrr); 51 armclk_div = ccm_cacrr & CCM_CACRR_ARM_CLK_DIV_MASK; 52 armclk_div >>= CCM_CACRR_ARM_CLK_DIV_OFFSET; 53 armclk_div += 1; 54 55 switch (sysclk_sel) { 56 case 0: 57 freq = FASE_CLK_FREQ; 58 break; 59 case 1: 60 freq = SLOW_CLK_FREQ; 61 break; 62 case 2: 63 pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL2_PFD_CLK_SEL_MASK; 64 pll_pfd_sel >>= CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET; 65 if (pll_pfd_sel == 0) 66 freq = PLL2_MAIN_FREQ; 67 else if (pll_pfd_sel == 1) 68 freq = PLL2_PFD1_FREQ; 69 else if (pll_pfd_sel == 2) 70 freq = PLL2_PFD2_FREQ; 71 else if (pll_pfd_sel == 3) 72 freq = PLL2_PFD3_FREQ; 73 else if (pll_pfd_sel == 4) 74 freq = PLL2_PFD4_FREQ; 75 break; 76 case 3: 77 freq = PLL2_MAIN_FREQ; 78 break; 79 case 4: 80 pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL1_PFD_CLK_SEL_MASK; 81 pll_pfd_sel >>= CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET; 82 if (pll_pfd_sel == 0) 83 freq = PLL1_MAIN_FREQ; 84 else if (pll_pfd_sel == 1) 85 freq = PLL1_PFD1_FREQ; 86 else if (pll_pfd_sel == 2) 87 freq = PLL1_PFD2_FREQ; 88 else if (pll_pfd_sel == 3) 89 freq = PLL1_PFD3_FREQ; 90 else if (pll_pfd_sel == 4) 91 freq = PLL1_PFD4_FREQ; 92 break; 93 case 5: 94 freq = PLL3_MAIN_FREQ; 95 break; 96 default: 97 printf("unsupported system clock select\n"); 98 } 99 100 return freq / armclk_div; 101 } 102 103 static u32 get_bus_clk(void) 104 { 105 struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; 106 u32 ccm_cacrr, busclk_div; 107 108 ccm_cacrr = readl(&ccm->cacrr); 109 110 busclk_div = ccm_cacrr & CCM_CACRR_BUS_CLK_DIV_MASK; 111 busclk_div >>= CCM_CACRR_BUS_CLK_DIV_OFFSET; 112 busclk_div += 1; 113 114 return get_mcu_main_clk() / busclk_div; 115 } 116 117 static u32 get_ipg_clk(void) 118 { 119 struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; 120 u32 ccm_cacrr, ipgclk_div; 121 122 ccm_cacrr = readl(&ccm->cacrr); 123 124 ipgclk_div = ccm_cacrr & CCM_CACRR_IPG_CLK_DIV_MASK; 125 ipgclk_div >>= CCM_CACRR_IPG_CLK_DIV_OFFSET; 126 ipgclk_div += 1; 127 128 return get_bus_clk() / ipgclk_div; 129 } 130 131 static u32 get_uart_clk(void) 132 { 133 return get_ipg_clk(); 134 } 135 136 static u32 get_sdhc_clk(void) 137 { 138 struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; 139 u32 ccm_cscmr1, ccm_cscdr2, sdhc_clk_sel, sdhc_clk_div; 140 u32 freq = 0; 141 142 ccm_cscmr1 = readl(&ccm->cscmr1); 143 sdhc_clk_sel = ccm_cscmr1 & CCM_CSCMR1_ESDHC1_CLK_SEL_MASK; 144 sdhc_clk_sel >>= CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET; 145 146 ccm_cscdr2 = readl(&ccm->cscdr2); 147 sdhc_clk_div = ccm_cscdr2 & CCM_CSCDR2_ESDHC1_CLK_DIV_MASK; 148 sdhc_clk_div >>= CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET; 149 sdhc_clk_div += 1; 150 151 switch (sdhc_clk_sel) { 152 case 0: 153 freq = PLL3_MAIN_FREQ; 154 break; 155 case 1: 156 freq = PLL3_PFD3_FREQ; 157 break; 158 case 2: 159 freq = PLL1_PFD3_FREQ; 160 break; 161 case 3: 162 freq = get_bus_clk(); 163 break; 164 } 165 166 return freq / sdhc_clk_div; 167 } 168 169 u32 get_fec_clk(void) 170 { 171 struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; 172 u32 ccm_cscmr2, rmii_clk_sel; 173 u32 freq = 0; 174 175 ccm_cscmr2 = readl(&ccm->cscmr2); 176 rmii_clk_sel = ccm_cscmr2 & CCM_CSCMR2_RMII_CLK_SEL_MASK; 177 rmii_clk_sel >>= CCM_CSCMR2_RMII_CLK_SEL_OFFSET; 178 179 switch (rmii_clk_sel) { 180 case 0: 181 freq = ENET_EXTERNAL_CLK; 182 break; 183 case 1: 184 freq = AUDIO_EXTERNAL_CLK; 185 break; 186 case 2: 187 freq = PLL5_MAIN_FREQ; 188 break; 189 case 3: 190 freq = PLL5_MAIN_FREQ / 2; 191 break; 192 } 193 194 return freq; 195 } 196 197 static u32 get_i2c_clk(void) 198 { 199 return get_ipg_clk(); 200 } 201 202 static u32 get_dspi_clk(void) 203 { 204 return get_ipg_clk(); 205 } 206 207 unsigned int mxc_get_clock(enum mxc_clock clk) 208 { 209 switch (clk) { 210 case MXC_ARM_CLK: 211 return get_mcu_main_clk(); 212 case MXC_BUS_CLK: 213 return get_bus_clk(); 214 case MXC_IPG_CLK: 215 return get_ipg_clk(); 216 case MXC_UART_CLK: 217 return get_uart_clk(); 218 case MXC_ESDHC_CLK: 219 return get_sdhc_clk(); 220 case MXC_FEC_CLK: 221 return get_fec_clk(); 222 case MXC_I2C_CLK: 223 return get_i2c_clk(); 224 case MXC_DSPI_CLK: 225 return get_dspi_clk(); 226 default: 227 break; 228 } 229 return -1; 230 } 231 232 /* Dump some core clocks */ 233 int do_vf610_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, 234 char * const argv[]) 235 { 236 printf("\n"); 237 printf("cpu clock : %8d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); 238 printf("bus clock : %8d MHz\n", mxc_get_clock(MXC_BUS_CLK) / 1000000); 239 printf("ipg clock : %8d MHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000000); 240 241 return 0; 242 } 243 244 U_BOOT_CMD( 245 clocks, CONFIG_SYS_MAXARGS, 1, do_vf610_showclocks, 246 "display clocks", 247 "" 248 ); 249 250 #ifdef CONFIG_FEC_MXC 251 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 252 { 253 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; 254 struct fuse_bank *bank = &ocotp->bank[4]; 255 struct fuse_bank4_regs *fuse = 256 (struct fuse_bank4_regs *)bank->fuse_regs; 257 258 u32 value = readl(&fuse->mac_addr0); 259 mac[0] = (value >> 8); 260 mac[1] = value; 261 262 value = readl(&fuse->mac_addr1); 263 mac[2] = value >> 24; 264 mac[3] = value >> 16; 265 mac[4] = value >> 8; 266 mac[5] = value; 267 } 268 #endif 269 270 u32 get_cpu_rev(void) 271 { 272 return MXC_CPU_VF610 << 12; 273 } 274 275 #if defined(CONFIG_DISPLAY_CPUINFO) 276 static char *get_reset_cause(void) 277 { 278 u32 cause; 279 struct src *src_regs = (struct src *)SRC_BASE_ADDR; 280 281 cause = readl(&src_regs->srsr); 282 writel(cause, &src_regs->srsr); 283 284 if (cause & SRC_SRSR_POR_RST) 285 return "POWER ON RESET"; 286 else if (cause & SRC_SRSR_WDOG_A5) 287 return "WDOG A5"; 288 else if (cause & SRC_SRSR_WDOG_M4) 289 return "WDOG M4"; 290 else if (cause & SRC_SRSR_JTAG_RST) 291 return "JTAG HIGH-Z"; 292 else if (cause & SRC_SRSR_SW_RST) 293 return "SW RESET"; 294 else if (cause & SRC_SRSR_RESETB) 295 return "EXTERNAL RESET"; 296 else 297 return "unknown reset"; 298 } 299 300 int print_cpuinfo(void) 301 { 302 printf("CPU: Freescale Vybrid VF%s at %d MHz\n", 303 soc_type, mxc_get_clock(MXC_ARM_CLK) / 1000000); 304 printf("Reset cause: %s\n", get_reset_cause()); 305 306 return 0; 307 } 308 #endif 309 310 int arch_cpu_init(void) 311 { 312 struct mscm *mscm = (struct mscm *)MSCM_BASE_ADDR; 313 314 soc_type[0] = mscm->cpxcount ? '6' : '5'; /*Dual Core => VF6x0 */ 315 soc_type[1] = mscm->cpxcfg1 ? '1' : '0'; /* L2 Cache => VFx10 */ 316 317 return 0; 318 } 319 320 #ifdef CONFIG_ARCH_MISC_INIT 321 int arch_misc_init(void) 322 { 323 char soc[6]; 324 325 strcat(soc, "vf"); 326 strcat(soc, soc_type); 327 setenv("soc", soc); 328 329 return 0; 330 } 331 #endif 332 333 int cpu_eth_init(bd_t *bis) 334 { 335 int rc = -ENODEV; 336 337 #if defined(CONFIG_FEC_MXC) 338 rc = fecmxc_initialize(bis); 339 #endif 340 341 return rc; 342 } 343 344 #ifdef CONFIG_FSL_ESDHC 345 int cpu_mmc_init(bd_t *bis) 346 { 347 return fsl_esdhc_mmc_init(bis); 348 } 349 #endif 350 351 int get_clocks(void) 352 { 353 #ifdef CONFIG_FSL_ESDHC 354 gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); 355 #endif 356 return 0; 357 } 358 359 #ifndef CONFIG_SYS_DCACHE_OFF 360 void enable_caches(void) 361 { 362 #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) 363 enum dcache_option option = DCACHE_WRITETHROUGH; 364 #else 365 enum dcache_option option = DCACHE_WRITEBACK; 366 #endif 367 dcache_enable(); 368 icache_enable(); 369 370 /* Enable caching on OCRAM */ 371 mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, IRAM_SIZE, option); 372 } 373 #endif 374