1b9bb0531SStefano Babic /* 2b9bb0531SStefano Babic * (C) Copyright 2007 3b9bb0531SStefano Babic * Sascha Hauer, Pengutronix 4b9bb0531SStefano Babic * 5b9bb0531SStefano Babic * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. 6b9bb0531SStefano Babic * 71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 8b9bb0531SStefano Babic */ 9b9bb0531SStefano Babic 10b9bb0531SStefano Babic #include <common.h> 11e7619554SBenoît Thébaudeau #include <div64.h> 12b9bb0531SStefano Babic #include <asm/io.h> 13b9bb0531SStefano Babic #include <asm/errno.h> 14b9bb0531SStefano Babic #include <asm/arch/imx-regs.h> 15b9bb0531SStefano Babic #include <asm/arch/crm_regs.h> 16b9bb0531SStefano Babic #include <asm/arch/clock.h> 17b9bb0531SStefano Babic #include <asm/arch/sys_proto.h> 1809bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC 1909bc3d04SBenoît Thébaudeau #include <fsl_esdhc.h> 2009bc3d04SBenoît Thébaudeau #endif 21b9bb0531SStefano Babic #include <netdev.h> 22d41924a2SStefano Babic #include <spl.h> 23b9bb0531SStefano Babic 24b9bb0531SStefano Babic #define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) 25b9bb0531SStefano Babic #define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) 26b9bb0531SStefano Babic #define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) 27b9bb0531SStefano Babic #define CLK_CODE_PATH(c) ((c) & 0xFF) 28b9bb0531SStefano Babic 29b9bb0531SStefano Babic #define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o)) 30b9bb0531SStefano Babic 31b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC 32b9bb0531SStefano Babic DECLARE_GLOBAL_DATA_PTR; 33b9bb0531SStefano Babic #endif 34b9bb0531SStefano Babic 35b9bb0531SStefano Babic static int g_clk_mux_auto[8] = { 36b9bb0531SStefano Babic CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, 37b9bb0531SStefano Babic CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, 38b9bb0531SStefano Babic }; 39b9bb0531SStefano Babic 40b9bb0531SStefano Babic static int g_clk_mux_consumer[16] = { 41b9bb0531SStefano Babic CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1, 42b9bb0531SStefano Babic -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), 43b9bb0531SStefano Babic CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, 44b9bb0531SStefano Babic -1, -1, CLK_CODE(4, 2, 0), -1, 45b9bb0531SStefano Babic }; 46b9bb0531SStefano Babic 47b9bb0531SStefano Babic static int hsp_div_table[3][16] = { 48b9bb0531SStefano Babic {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, 49b9bb0531SStefano Babic {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, 50b9bb0531SStefano Babic {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, 51b9bb0531SStefano Babic }; 52b9bb0531SStefano Babic 53b9bb0531SStefano Babic u32 get_cpu_rev(void) 54b9bb0531SStefano Babic { 55b9bb0531SStefano Babic int reg; 56b9bb0531SStefano Babic struct iim_regs *iim = 57b9bb0531SStefano Babic (struct iim_regs *)IIM_BASE_ADDR; 58b9bb0531SStefano Babic reg = readl(&iim->iim_srev); 59b9bb0531SStefano Babic if (!reg) { 60b9bb0531SStefano Babic reg = readw(ROMPATCH_REV); 61b9bb0531SStefano Babic reg <<= 4; 62b9bb0531SStefano Babic } else { 63b9bb0531SStefano Babic reg += CHIP_REV_1_0; 64b9bb0531SStefano Babic } 65b9bb0531SStefano Babic 66b9bb0531SStefano Babic return 0x35000 + (reg & 0xFF); 67b9bb0531SStefano Babic } 68b9bb0531SStefano Babic 69b9bb0531SStefano Babic static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd) 70b9bb0531SStefano Babic { 71b9bb0531SStefano Babic int *pclk_mux; 72b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { 73b9bb0531SStefano Babic pclk_mux = g_clk_mux_consumer + 74b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> 75b9bb0531SStefano Babic MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); 76b9bb0531SStefano Babic } else { 77b9bb0531SStefano Babic pclk_mux = g_clk_mux_auto + 78b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> 79b9bb0531SStefano Babic MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); 80b9bb0531SStefano Babic } 81b9bb0531SStefano Babic 82b9bb0531SStefano Babic if ((*pclk_mux) == -1) 83b9bb0531SStefano Babic return -1; 84b9bb0531SStefano Babic 85b9bb0531SStefano Babic if (fi && fd) { 86b9bb0531SStefano Babic if (!CLK_CODE_PATH(*pclk_mux)) { 87b9bb0531SStefano Babic *fi = *fd = 1; 88b9bb0531SStefano Babic return CLK_CODE_ARM(*pclk_mux); 89b9bb0531SStefano Babic } 90b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { 91b9bb0531SStefano Babic *fi = 3; 92b9bb0531SStefano Babic *fd = 4; 93b9bb0531SStefano Babic } else { 94b9bb0531SStefano Babic *fi = 2; 95b9bb0531SStefano Babic *fd = 3; 96b9bb0531SStefano Babic } 97b9bb0531SStefano Babic } 98b9bb0531SStefano Babic return CLK_CODE_ARM(*pclk_mux); 99b9bb0531SStefano Babic } 100b9bb0531SStefano Babic 101b9bb0531SStefano Babic static int get_ahb_div(u32 pdr0) 102b9bb0531SStefano Babic { 103b9bb0531SStefano Babic int *pclk_mux; 104b9bb0531SStefano Babic 105b9bb0531SStefano Babic pclk_mux = g_clk_mux_consumer + 106b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> 107b9bb0531SStefano Babic MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); 108b9bb0531SStefano Babic 109b9bb0531SStefano Babic if ((*pclk_mux) == -1) 110b9bb0531SStefano Babic return -1; 111b9bb0531SStefano Babic 112b9bb0531SStefano Babic return CLK_CODE_AHB(*pclk_mux); 113b9bb0531SStefano Babic } 114b9bb0531SStefano Babic 115b9bb0531SStefano Babic static u32 decode_pll(u32 reg, u32 infreq) 116b9bb0531SStefano Babic { 117b9bb0531SStefano Babic u32 mfi = (reg >> 10) & 0xf; 118e7619554SBenoît Thébaudeau s32 mfn = reg & 0x3ff; 119e7619554SBenoît Thébaudeau u32 mfd = (reg >> 16) & 0x3ff; 120b9bb0531SStefano Babic u32 pd = (reg >> 26) & 0xf; 121b9bb0531SStefano Babic 122b9bb0531SStefano Babic mfi = mfi <= 5 ? 5 : mfi; 123e7619554SBenoît Thébaudeau mfn = mfn >= 512 ? mfn - 1024 : mfn; 124b9bb0531SStefano Babic mfd += 1; 125b9bb0531SStefano Babic pd += 1; 126b9bb0531SStefano Babic 127e7619554SBenoît Thébaudeau return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), 128e7619554SBenoît Thébaudeau mfd * pd); 129b9bb0531SStefano Babic } 130b9bb0531SStefano Babic 131b9bb0531SStefano Babic static u32 get_mcu_main_clk(void) 132b9bb0531SStefano Babic { 133b9bb0531SStefano Babic u32 arm_div = 0, fi = 0, fd = 0; 134b9bb0531SStefano Babic struct ccm_regs *ccm = 135b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 136b9bb0531SStefano Babic arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd); 1379c6c5c06SBenoît Thébaudeau fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK); 138b9bb0531SStefano Babic return fi / (arm_div * fd); 139b9bb0531SStefano Babic } 140b9bb0531SStefano Babic 141b9bb0531SStefano Babic static u32 get_ipg_clk(void) 142b9bb0531SStefano Babic { 143b9bb0531SStefano Babic u32 freq = get_mcu_main_clk(); 144b9bb0531SStefano Babic struct ccm_regs *ccm = 145b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 146b9bb0531SStefano Babic u32 pdr0 = readl(&ccm->pdr0); 147b9bb0531SStefano Babic 148b9bb0531SStefano Babic return freq / (get_ahb_div(pdr0) * 2); 149b9bb0531SStefano Babic } 150b9bb0531SStefano Babic 151b9bb0531SStefano Babic static u32 get_ipg_per_clk(void) 152b9bb0531SStefano Babic { 153b9bb0531SStefano Babic u32 freq = get_mcu_main_clk(); 154b9bb0531SStefano Babic struct ccm_regs *ccm = 155b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 156b9bb0531SStefano Babic u32 pdr0 = readl(&ccm->pdr0); 157b9bb0531SStefano Babic u32 pdr4 = readl(&ccm->pdr4); 158b9bb0531SStefano Babic u32 div; 159b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_PER_SEL) { 16082e1b543SBenoît Thébaudeau div = CCM_GET_DIVIDER(pdr4, 161b9bb0531SStefano Babic MXC_CCM_PDR4_PER0_PODF_MASK, 16282e1b543SBenoît Thébaudeau MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1; 163b9bb0531SStefano Babic } else { 164b9bb0531SStefano Babic div = CCM_GET_DIVIDER(pdr0, 165b9bb0531SStefano Babic MXC_CCM_PDR0_PER_PODF_MASK, 166b9bb0531SStefano Babic MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; 16782e1b543SBenoît Thébaudeau div *= get_ahb_div(pdr0); 168b9bb0531SStefano Babic } 169b9bb0531SStefano Babic return freq / div; 170b9bb0531SStefano Babic } 171b9bb0531SStefano Babic 172b9bb0531SStefano Babic u32 imx_get_uartclk(void) 173b9bb0531SStefano Babic { 174b9bb0531SStefano Babic u32 freq; 175b9bb0531SStefano Babic struct ccm_regs *ccm = 176b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 177b9bb0531SStefano Babic u32 pdr4 = readl(&ccm->pdr4); 178b9bb0531SStefano Babic 1799c6c5c06SBenoît Thébaudeau if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) 180b9bb0531SStefano Babic freq = get_mcu_main_clk(); 1819c6c5c06SBenoît Thébaudeau else 1829c6c5c06SBenoît Thébaudeau freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK); 18382e1b543SBenoît Thébaudeau freq /= CCM_GET_DIVIDER(pdr4, 184b9bb0531SStefano Babic MXC_CCM_PDR4_UART_PODF_MASK, 18582e1b543SBenoît Thébaudeau MXC_CCM_PDR4_UART_PODF_OFFSET) + 1; 186b9bb0531SStefano Babic return freq; 187b9bb0531SStefano Babic } 188b9bb0531SStefano Babic 1897c80326dSBenoît Thébaudeau unsigned int mxc_get_main_clock(enum mxc_main_clock clk) 190b9bb0531SStefano Babic { 191b9bb0531SStefano Babic u32 nfc_pdf, hsp_podf; 19282e1b543SBenoît Thébaudeau u32 pll, ret_val = 0, usb_podf; 193b9bb0531SStefano Babic struct ccm_regs *ccm = 194b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 195b9bb0531SStefano Babic 196b9bb0531SStefano Babic u32 reg = readl(&ccm->pdr0); 197b9bb0531SStefano Babic u32 reg4 = readl(&ccm->pdr4); 198b9bb0531SStefano Babic 199b9bb0531SStefano Babic reg |= 0x1; 200b9bb0531SStefano Babic 201b9bb0531SStefano Babic switch (clk) { 202b9bb0531SStefano Babic case CPU_CLK: 203b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 204b9bb0531SStefano Babic break; 205b9bb0531SStefano Babic case AHB_CLK: 206b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 207b9bb0531SStefano Babic break; 208b9bb0531SStefano Babic case HSP_CLK: 209b9bb0531SStefano Babic if (reg & CLKMODE_CONSUMER) { 210b9bb0531SStefano Babic hsp_podf = (reg >> 20) & 0x3; 211b9bb0531SStefano Babic pll = get_mcu_main_clk(); 212b9bb0531SStefano Babic hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF]; 213b9bb0531SStefano Babic if (hsp_podf > 0) { 214b9bb0531SStefano Babic ret_val = pll / hsp_podf; 215b9bb0531SStefano Babic } else { 216b9bb0531SStefano Babic puts("mismatch HSP with ARM clock setting\n"); 217b9bb0531SStefano Babic ret_val = 0; 218b9bb0531SStefano Babic } 219b9bb0531SStefano Babic } else { 220b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 221b9bb0531SStefano Babic } 222b9bb0531SStefano Babic break; 223b9bb0531SStefano Babic case IPG_CLK: 22477f11a99SFabio Estevam ret_val = get_ipg_clk(); 225b9bb0531SStefano Babic break; 226b9bb0531SStefano Babic case IPG_PER_CLK: 227b9bb0531SStefano Babic ret_val = get_ipg_per_clk(); 228b9bb0531SStefano Babic break; 229b9bb0531SStefano Babic case NFC_CLK: 230b9bb0531SStefano Babic nfc_pdf = (reg4 >> 28) & 0xF; 231b9bb0531SStefano Babic pll = get_mcu_main_clk(); 232b9bb0531SStefano Babic /* AHB/nfc_pdf */ 233b9bb0531SStefano Babic ret_val = pll / (nfc_pdf + 1); 234b9bb0531SStefano Babic break; 235b9bb0531SStefano Babic case USB_CLK: 23682e1b543SBenoît Thébaudeau usb_podf = (reg4 >> 22) & 0x3F; 2379c6c5c06SBenoît Thébaudeau if (reg4 & 0x200) 238b9bb0531SStefano Babic pll = get_mcu_main_clk(); 2399c6c5c06SBenoît Thébaudeau else 2409c6c5c06SBenoît Thébaudeau pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK); 241b9bb0531SStefano Babic 24282e1b543SBenoît Thébaudeau ret_val = pll / (usb_podf + 1); 243b9bb0531SStefano Babic break; 244b9bb0531SStefano Babic default: 245b9bb0531SStefano Babic printf("Unknown clock: %d\n", clk); 246b9bb0531SStefano Babic break; 247b9bb0531SStefano Babic } 248b9bb0531SStefano Babic 249b9bb0531SStefano Babic return ret_val; 250b9bb0531SStefano Babic } 2517c80326dSBenoît Thébaudeau unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) 252b9bb0531SStefano Babic { 253b9bb0531SStefano Babic u32 ret_val = 0, pdf, pre_pdf, clk_sel; 254b9bb0531SStefano Babic struct ccm_regs *ccm = 255b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 256b9bb0531SStefano Babic u32 mpdr2 = readl(&ccm->pdr2); 257b9bb0531SStefano Babic u32 mpdr3 = readl(&ccm->pdr3); 258b9bb0531SStefano Babic u32 mpdr4 = readl(&ccm->pdr4); 259b9bb0531SStefano Babic 260b9bb0531SStefano Babic switch (clk) { 261b9bb0531SStefano Babic case UART1_BAUD: 262b9bb0531SStefano Babic case UART2_BAUD: 263b9bb0531SStefano Babic case UART3_BAUD: 264b9bb0531SStefano Babic clk_sel = mpdr3 & (1 << 14); 26582e1b543SBenoît Thébaudeau pdf = (mpdr4 >> 10) & 0x3F; 266b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2679c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 268b9bb0531SStefano Babic break; 269b9bb0531SStefano Babic case SSI1_BAUD: 270b9bb0531SStefano Babic pre_pdf = (mpdr2 >> 24) & 0x7; 271b9bb0531SStefano Babic pdf = mpdr2 & 0x3F; 272b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 6); 273b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2749c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 275b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 276b9bb0531SStefano Babic break; 277b9bb0531SStefano Babic case SSI2_BAUD: 278b9bb0531SStefano Babic pre_pdf = (mpdr2 >> 27) & 0x7; 279b9bb0531SStefano Babic pdf = (mpdr2 >> 8) & 0x3F; 280b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 6); 281b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2829c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 283b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 284b9bb0531SStefano Babic break; 285b9bb0531SStefano Babic case CSI_BAUD: 286b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 7); 28782e1b543SBenoît Thébaudeau pdf = (mpdr2 >> 16) & 0x3F; 288b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2899c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 290b9bb0531SStefano Babic break; 291b9bb0531SStefano Babic case MSHC_CLK: 292b9bb0531SStefano Babic pre_pdf = readl(&ccm->pdr1); 293b9bb0531SStefano Babic clk_sel = (pre_pdf & 0x80); 294b9bb0531SStefano Babic pdf = (pre_pdf >> 22) & 0x3F; 295b9bb0531SStefano Babic pre_pdf = (pre_pdf >> 28) & 0x7; 296b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2979c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 298b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 299b9bb0531SStefano Babic break; 300b9bb0531SStefano Babic case ESDHC1_CLK: 301b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 30282e1b543SBenoît Thébaudeau pdf = mpdr3 & 0x3F; 303b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3049c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 305b9bb0531SStefano Babic break; 306b9bb0531SStefano Babic case ESDHC2_CLK: 307b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 30882e1b543SBenoît Thébaudeau pdf = (mpdr3 >> 8) & 0x3F; 309b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3109c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 311b9bb0531SStefano Babic break; 312b9bb0531SStefano Babic case ESDHC3_CLK: 313b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 31482e1b543SBenoît Thébaudeau pdf = (mpdr3 >> 16) & 0x3F; 315b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3169c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 317b9bb0531SStefano Babic break; 318b9bb0531SStefano Babic case SPDIF_CLK: 319b9bb0531SStefano Babic clk_sel = mpdr3 & 0x400000; 320b9bb0531SStefano Babic pre_pdf = (mpdr3 >> 29) & 0x7; 321b9bb0531SStefano Babic pdf = (mpdr3 >> 23) & 0x3F; 322b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3239c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 324b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 325b9bb0531SStefano Babic break; 326b9bb0531SStefano Babic default: 327b9bb0531SStefano Babic printf("%s(): This clock: %d not supported yet\n", 328b9bb0531SStefano Babic __func__, clk); 329b9bb0531SStefano Babic break; 330b9bb0531SStefano Babic } 331b9bb0531SStefano Babic 332b9bb0531SStefano Babic return ret_val; 333b9bb0531SStefano Babic } 334b9bb0531SStefano Babic 335b9bb0531SStefano Babic unsigned int mxc_get_clock(enum mxc_clock clk) 336b9bb0531SStefano Babic { 337b9bb0531SStefano Babic switch (clk) { 338b9bb0531SStefano Babic case MXC_ARM_CLK: 339b9bb0531SStefano Babic return get_mcu_main_clk(); 340b9bb0531SStefano Babic case MXC_AHB_CLK: 341b9bb0531SStefano Babic break; 342b9bb0531SStefano Babic case MXC_IPG_CLK: 343b9bb0531SStefano Babic return get_ipg_clk(); 344b9bb0531SStefano Babic case MXC_IPG_PERCLK: 345e7bed5c2SMatthias Weisser case MXC_I2C_CLK: 346b9bb0531SStefano Babic return get_ipg_per_clk(); 347b9bb0531SStefano Babic case MXC_UART_CLK: 348b9bb0531SStefano Babic return imx_get_uartclk(); 3496e3dc127SBenoît Thébaudeau case MXC_ESDHC1_CLK: 350b9bb0531SStefano Babic return mxc_get_peri_clock(ESDHC1_CLK); 3516e3dc127SBenoît Thébaudeau case MXC_ESDHC2_CLK: 3526e3dc127SBenoît Thébaudeau return mxc_get_peri_clock(ESDHC2_CLK); 3536e3dc127SBenoît Thébaudeau case MXC_ESDHC3_CLK: 3546e3dc127SBenoît Thébaudeau return mxc_get_peri_clock(ESDHC3_CLK); 355b9bb0531SStefano Babic case MXC_USB_CLK: 356b9bb0531SStefano Babic return mxc_get_main_clock(USB_CLK); 357b9bb0531SStefano Babic case MXC_FEC_CLK: 358b9bb0531SStefano Babic return get_ipg_clk(); 359b9bb0531SStefano Babic case MXC_CSPI_CLK: 360b9bb0531SStefano Babic return get_ipg_clk(); 361b9bb0531SStefano Babic } 362b9bb0531SStefano Babic return -1; 363b9bb0531SStefano Babic } 364b9bb0531SStefano Babic 365b9bb0531SStefano Babic #ifdef CONFIG_FEC_MXC 366b9bb0531SStefano Babic /* 367b9bb0531SStefano Babic * The MX35 has no fuse for MAC, return a NULL MAC 368b9bb0531SStefano Babic */ 369be252b65SFabio Estevam void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 370b9bb0531SStefano Babic { 371b9bb0531SStefano Babic memset(mac, 0, 6); 372b9bb0531SStefano Babic } 373b9bb0531SStefano Babic 374b9bb0531SStefano Babic u32 imx_get_fecclk(void) 375b9bb0531SStefano Babic { 376b9bb0531SStefano Babic return mxc_get_clock(MXC_IPG_CLK); 377b9bb0531SStefano Babic } 378b9bb0531SStefano Babic #endif 379b9bb0531SStefano Babic 380b9bb0531SStefano Babic int do_mx35_showclocks(cmd_tbl_t *cmdtp, 381b9bb0531SStefano Babic int flag, int argc, char * const argv[]) 382b9bb0531SStefano Babic { 383b9bb0531SStefano Babic u32 cpufreq = get_mcu_main_clk(); 384b9bb0531SStefano Babic printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); 385b9bb0531SStefano Babic printf("ipg clock : %dHz\n", get_ipg_clk()); 386b9bb0531SStefano Babic printf("ipg per clock : %dHz\n", get_ipg_per_clk()); 387b9bb0531SStefano Babic printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); 388b9bb0531SStefano Babic 389b9bb0531SStefano Babic return 0; 390b9bb0531SStefano Babic } 391b9bb0531SStefano Babic 392b9bb0531SStefano Babic U_BOOT_CMD( 3937acec259SStefano Babic clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks, 3947acec259SStefano Babic "display clocks", 395b9bb0531SStefano Babic "" 396b9bb0531SStefano Babic ); 397b9bb0531SStefano Babic 398ec0919f5SFabio Estevam #if defined(CONFIG_DISPLAY_CPUINFO) 399d330883fSStefano Babic static char *get_reset_cause(void) 400d330883fSStefano Babic { 401d330883fSStefano Babic /* read RCSR register from CCM module */ 402d330883fSStefano Babic struct ccm_regs *ccm = 403d330883fSStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 404d330883fSStefano Babic 405d330883fSStefano Babic u32 cause = readl(&ccm->rcsr) & 0x0F; 406d330883fSStefano Babic 407d330883fSStefano Babic switch (cause) { 408d330883fSStefano Babic case 0x0000: 409d330883fSStefano Babic return "POR"; 410d330883fSStefano Babic case 0x0002: 411d330883fSStefano Babic return "JTAG"; 412d330883fSStefano Babic case 0x0004: 413d330883fSStefano Babic return "RST"; 414d330883fSStefano Babic case 0x0008: 415d330883fSStefano Babic return "WDOG"; 416d330883fSStefano Babic default: 417d330883fSStefano Babic return "unknown reset"; 418d330883fSStefano Babic } 419d330883fSStefano Babic } 420d330883fSStefano Babic 421b9bb0531SStefano Babic int print_cpuinfo(void) 422b9bb0531SStefano Babic { 423d330883fSStefano Babic u32 srev = get_cpu_rev(); 424d330883fSStefano Babic 425d330883fSStefano Babic printf("CPU: Freescale i.MX35 rev %d.%d at %d MHz.\n", 426d330883fSStefano Babic (srev & 0xF0) >> 4, (srev & 0x0F), 427b9bb0531SStefano Babic get_mcu_main_clk() / 1000000); 428d330883fSStefano Babic 429d330883fSStefano Babic printf("Reset cause: %s\n", get_reset_cause()); 430d330883fSStefano Babic 431b9bb0531SStefano Babic return 0; 432b9bb0531SStefano Babic } 433b9bb0531SStefano Babic #endif 434b9bb0531SStefano Babic 435b9bb0531SStefano Babic /* 436b9bb0531SStefano Babic * Initializes on-chip ethernet controllers. 437b9bb0531SStefano Babic * to override, implement board_eth_init() 438b9bb0531SStefano Babic */ 439b9bb0531SStefano Babic int cpu_eth_init(bd_t *bis) 440b9bb0531SStefano Babic { 441b9bb0531SStefano Babic int rc = -ENODEV; 442b9bb0531SStefano Babic 443b9bb0531SStefano Babic #if defined(CONFIG_FEC_MXC) 444b9bb0531SStefano Babic rc = fecmxc_initialize(bis); 445b9bb0531SStefano Babic #endif 446b9bb0531SStefano Babic 447b9bb0531SStefano Babic return rc; 448b9bb0531SStefano Babic } 449b9bb0531SStefano Babic 45009bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC 45109bc3d04SBenoît Thébaudeau /* 45209bc3d04SBenoît Thébaudeau * Initializes on-chip MMC controllers. 45309bc3d04SBenoît Thébaudeau * to override, implement board_mmc_init() 45409bc3d04SBenoît Thébaudeau */ 45509bc3d04SBenoît Thébaudeau int cpu_mmc_init(bd_t *bis) 45609bc3d04SBenoît Thébaudeau { 45709bc3d04SBenoît Thébaudeau return fsl_esdhc_mmc_init(bis); 45809bc3d04SBenoît Thébaudeau } 45909bc3d04SBenoît Thébaudeau #endif 46009bc3d04SBenoît Thébaudeau 461b9bb0531SStefano Babic int get_clocks(void) 462b9bb0531SStefano Babic { 463b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC 4646e3dc127SBenoît Thébaudeau #if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR 465e9adeca3SSimon Glass gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); 4666e3dc127SBenoît Thébaudeau #elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR 467e9adeca3SSimon Glass gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); 4686e3dc127SBenoît Thébaudeau #else 469e9adeca3SSimon Glass gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); 4706e3dc127SBenoît Thébaudeau #endif 471b9bb0531SStefano Babic #endif 472b9bb0531SStefano Babic return 0; 473b9bb0531SStefano Babic } 474b9bb0531SStefano Babic 475d41924a2SStefano Babic #define RCSR_MEM_CTL_WEIM 0 476d41924a2SStefano Babic #define RCSR_MEM_CTL_NAND 1 477d41924a2SStefano Babic #define RCSR_MEM_CTL_ATA 2 478d41924a2SStefano Babic #define RCSR_MEM_CTL_EXPANSION 3 479d41924a2SStefano Babic #define RCSR_MEM_TYPE_NOR 0 480d41924a2SStefano Babic #define RCSR_MEM_TYPE_ONENAND 2 481d41924a2SStefano Babic #define RCSR_MEM_TYPE_SD 0 482d41924a2SStefano Babic #define RCSR_MEM_TYPE_I2C 2 483d41924a2SStefano Babic #define RCSR_MEM_TYPE_SPI 3 484d41924a2SStefano Babic 485d41924a2SStefano Babic u32 spl_boot_device(void) 486d41924a2SStefano Babic { 487d41924a2SStefano Babic struct ccm_regs *ccm = 488d41924a2SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 489d41924a2SStefano Babic 490d41924a2SStefano Babic u32 rcsr = readl(&ccm->rcsr); 491d41924a2SStefano Babic u32 mem_type, mem_ctl; 492d41924a2SStefano Babic 493d41924a2SStefano Babic /* In external mode, no boot device is returned */ 494d41924a2SStefano Babic if ((rcsr >> 10) & 0x03) 495d41924a2SStefano Babic return BOOT_DEVICE_NONE; 496d41924a2SStefano Babic 497d41924a2SStefano Babic mem_ctl = (rcsr >> 25) & 0x03; 498d41924a2SStefano Babic mem_type = (rcsr >> 23) & 0x03; 499d41924a2SStefano Babic 500d41924a2SStefano Babic switch (mem_ctl) { 501d41924a2SStefano Babic case RCSR_MEM_CTL_WEIM: 502d41924a2SStefano Babic switch (mem_type) { 503d41924a2SStefano Babic case RCSR_MEM_TYPE_NOR: 504d41924a2SStefano Babic return BOOT_DEVICE_NOR; 505d41924a2SStefano Babic case RCSR_MEM_TYPE_ONENAND: 50666c7f399SEnric Balletbo i Serra return BOOT_DEVICE_ONENAND; 507d41924a2SStefano Babic default: 508d41924a2SStefano Babic return BOOT_DEVICE_NONE; 509d41924a2SStefano Babic } 510d41924a2SStefano Babic case RCSR_MEM_CTL_NAND: 511d41924a2SStefano Babic return BOOT_DEVICE_NAND; 512d41924a2SStefano Babic case RCSR_MEM_CTL_EXPANSION: 513d41924a2SStefano Babic switch (mem_type) { 514d41924a2SStefano Babic case RCSR_MEM_TYPE_SD: 515d41924a2SStefano Babic return BOOT_DEVICE_MMC1; 516d41924a2SStefano Babic case RCSR_MEM_TYPE_I2C: 517d41924a2SStefano Babic return BOOT_DEVICE_I2C; 518d41924a2SStefano Babic case RCSR_MEM_TYPE_SPI: 519d41924a2SStefano Babic return BOOT_DEVICE_SPI; 520d41924a2SStefano Babic default: 521d41924a2SStefano Babic return BOOT_DEVICE_NONE; 522d41924a2SStefano Babic } 523d41924a2SStefano Babic } 524d41924a2SStefano Babic 525d41924a2SStefano Babic return BOOT_DEVICE_NONE; 526d41924a2SStefano Babic } 527d41924a2SStefano Babic 528d41924a2SStefano Babic #ifdef CONFIG_SPL_BUILD 529d41924a2SStefano Babic u32 spl_boot_mode(void) 530d41924a2SStefano Babic { 531d41924a2SStefano Babic switch (spl_boot_device()) { 532d41924a2SStefano Babic case BOOT_DEVICE_MMC1: 533d41924a2SStefano Babic #ifdef CONFIG_SPL_FAT_SUPPORT 534*205b4f33SGuillaume GARDET return MMCSD_MODE_FS; 535d41924a2SStefano Babic #else 536d41924a2SStefano Babic return MMCSD_MODE_RAW; 537d41924a2SStefano Babic #endif 538d41924a2SStefano Babic break; 539d41924a2SStefano Babic case BOOT_DEVICE_NAND: 540d41924a2SStefano Babic return 0; 541d41924a2SStefano Babic break; 542d41924a2SStefano Babic default: 543d41924a2SStefano Babic puts("spl: ERROR: unsupported device\n"); 544d41924a2SStefano Babic hang(); 545d41924a2SStefano Babic } 546d41924a2SStefano Babic } 547d41924a2SStefano Babic #endif 548