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 * 7b9bb0531SStefano Babic * See file CREDITS for list of people who contributed to this 8b9bb0531SStefano Babic * project. 9b9bb0531SStefano Babic * 10b9bb0531SStefano Babic * This program is free software; you can redistribute it and/or 11b9bb0531SStefano Babic * modify it under the terms of the GNU General Public License as 12b9bb0531SStefano Babic * published by the Free Software Foundation; either version 2 of 13b9bb0531SStefano Babic * the License, or (at your option) any later version. 14b9bb0531SStefano Babic * 15b9bb0531SStefano Babic * This program is distributed in the hope that it will be useful, 16b9bb0531SStefano Babic * but WITHOUT ANY WARRANTY; without even the implied warranty of 17b9bb0531SStefano Babic * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18b9bb0531SStefano Babic * GNU General Public License for more details. 19b9bb0531SStefano Babic * 20b9bb0531SStefano Babic * You should have received a copy of the GNU General Public License 21b9bb0531SStefano Babic * along with this program; if not, write to the Free Software 22b9bb0531SStefano Babic * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23b9bb0531SStefano Babic * MA 02111-1307 USA 24b9bb0531SStefano Babic */ 25b9bb0531SStefano Babic 26b9bb0531SStefano Babic #include <common.h> 27e7619554SBenoît Thébaudeau #include <div64.h> 28b9bb0531SStefano Babic #include <asm/io.h> 29b9bb0531SStefano Babic #include <asm/errno.h> 30b9bb0531SStefano Babic #include <asm/arch/imx-regs.h> 31b9bb0531SStefano Babic #include <asm/arch/crm_regs.h> 32b9bb0531SStefano Babic #include <asm/arch/clock.h> 33b9bb0531SStefano Babic #include <asm/arch/sys_proto.h> 3409bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC 3509bc3d04SBenoît Thébaudeau #include <fsl_esdhc.h> 3609bc3d04SBenoît Thébaudeau #endif 37b9bb0531SStefano Babic #include <netdev.h> 38d41924a2SStefano Babic #include <spl.h> 39b9bb0531SStefano Babic 40b9bb0531SStefano Babic #define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) 41b9bb0531SStefano Babic #define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) 42b9bb0531SStefano Babic #define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) 43b9bb0531SStefano Babic #define CLK_CODE_PATH(c) ((c) & 0xFF) 44b9bb0531SStefano Babic 45b9bb0531SStefano Babic #define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o)) 46b9bb0531SStefano Babic 47b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC 48b9bb0531SStefano Babic DECLARE_GLOBAL_DATA_PTR; 49b9bb0531SStefano Babic #endif 50b9bb0531SStefano Babic 51b9bb0531SStefano Babic static int g_clk_mux_auto[8] = { 52b9bb0531SStefano Babic CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, 53b9bb0531SStefano Babic CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, 54b9bb0531SStefano Babic }; 55b9bb0531SStefano Babic 56b9bb0531SStefano Babic static int g_clk_mux_consumer[16] = { 57b9bb0531SStefano Babic CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1, 58b9bb0531SStefano Babic -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), 59b9bb0531SStefano Babic CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, 60b9bb0531SStefano Babic -1, -1, CLK_CODE(4, 2, 0), -1, 61b9bb0531SStefano Babic }; 62b9bb0531SStefano Babic 63b9bb0531SStefano Babic static int hsp_div_table[3][16] = { 64b9bb0531SStefano Babic {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, 65b9bb0531SStefano Babic {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, 66b9bb0531SStefano Babic {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, 67b9bb0531SStefano Babic }; 68b9bb0531SStefano Babic 69b9bb0531SStefano Babic u32 get_cpu_rev(void) 70b9bb0531SStefano Babic { 71b9bb0531SStefano Babic int reg; 72b9bb0531SStefano Babic struct iim_regs *iim = 73b9bb0531SStefano Babic (struct iim_regs *)IIM_BASE_ADDR; 74b9bb0531SStefano Babic reg = readl(&iim->iim_srev); 75b9bb0531SStefano Babic if (!reg) { 76b9bb0531SStefano Babic reg = readw(ROMPATCH_REV); 77b9bb0531SStefano Babic reg <<= 4; 78b9bb0531SStefano Babic } else { 79b9bb0531SStefano Babic reg += CHIP_REV_1_0; 80b9bb0531SStefano Babic } 81b9bb0531SStefano Babic 82b9bb0531SStefano Babic return 0x35000 + (reg & 0xFF); 83b9bb0531SStefano Babic } 84b9bb0531SStefano Babic 85b9bb0531SStefano Babic static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd) 86b9bb0531SStefano Babic { 87b9bb0531SStefano Babic int *pclk_mux; 88b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { 89b9bb0531SStefano Babic pclk_mux = g_clk_mux_consumer + 90b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> 91b9bb0531SStefano Babic MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); 92b9bb0531SStefano Babic } else { 93b9bb0531SStefano Babic pclk_mux = g_clk_mux_auto + 94b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> 95b9bb0531SStefano Babic MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); 96b9bb0531SStefano Babic } 97b9bb0531SStefano Babic 98b9bb0531SStefano Babic if ((*pclk_mux) == -1) 99b9bb0531SStefano Babic return -1; 100b9bb0531SStefano Babic 101b9bb0531SStefano Babic if (fi && fd) { 102b9bb0531SStefano Babic if (!CLK_CODE_PATH(*pclk_mux)) { 103b9bb0531SStefano Babic *fi = *fd = 1; 104b9bb0531SStefano Babic return CLK_CODE_ARM(*pclk_mux); 105b9bb0531SStefano Babic } 106b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { 107b9bb0531SStefano Babic *fi = 3; 108b9bb0531SStefano Babic *fd = 4; 109b9bb0531SStefano Babic } else { 110b9bb0531SStefano Babic *fi = 2; 111b9bb0531SStefano Babic *fd = 3; 112b9bb0531SStefano Babic } 113b9bb0531SStefano Babic } 114b9bb0531SStefano Babic return CLK_CODE_ARM(*pclk_mux); 115b9bb0531SStefano Babic } 116b9bb0531SStefano Babic 117b9bb0531SStefano Babic static int get_ahb_div(u32 pdr0) 118b9bb0531SStefano Babic { 119b9bb0531SStefano Babic int *pclk_mux; 120b9bb0531SStefano Babic 121b9bb0531SStefano Babic pclk_mux = g_clk_mux_consumer + 122b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> 123b9bb0531SStefano Babic MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); 124b9bb0531SStefano Babic 125b9bb0531SStefano Babic if ((*pclk_mux) == -1) 126b9bb0531SStefano Babic return -1; 127b9bb0531SStefano Babic 128b9bb0531SStefano Babic return CLK_CODE_AHB(*pclk_mux); 129b9bb0531SStefano Babic } 130b9bb0531SStefano Babic 131b9bb0531SStefano Babic static u32 decode_pll(u32 reg, u32 infreq) 132b9bb0531SStefano Babic { 133b9bb0531SStefano Babic u32 mfi = (reg >> 10) & 0xf; 134e7619554SBenoît Thébaudeau s32 mfn = reg & 0x3ff; 135e7619554SBenoît Thébaudeau u32 mfd = (reg >> 16) & 0x3ff; 136b9bb0531SStefano Babic u32 pd = (reg >> 26) & 0xf; 137b9bb0531SStefano Babic 138b9bb0531SStefano Babic mfi = mfi <= 5 ? 5 : mfi; 139e7619554SBenoît Thébaudeau mfn = mfn >= 512 ? mfn - 1024 : mfn; 140b9bb0531SStefano Babic mfd += 1; 141b9bb0531SStefano Babic pd += 1; 142b9bb0531SStefano Babic 143e7619554SBenoît Thébaudeau return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), 144e7619554SBenoît Thébaudeau mfd * pd); 145b9bb0531SStefano Babic } 146b9bb0531SStefano Babic 147b9bb0531SStefano Babic static u32 get_mcu_main_clk(void) 148b9bb0531SStefano Babic { 149b9bb0531SStefano Babic u32 arm_div = 0, fi = 0, fd = 0; 150b9bb0531SStefano Babic struct ccm_regs *ccm = 151b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 152b9bb0531SStefano Babic arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd); 1539c6c5c06SBenoît Thébaudeau fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK); 154b9bb0531SStefano Babic return fi / (arm_div * fd); 155b9bb0531SStefano Babic } 156b9bb0531SStefano Babic 157b9bb0531SStefano Babic static u32 get_ipg_clk(void) 158b9bb0531SStefano Babic { 159b9bb0531SStefano Babic u32 freq = get_mcu_main_clk(); 160b9bb0531SStefano Babic struct ccm_regs *ccm = 161b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 162b9bb0531SStefano Babic u32 pdr0 = readl(&ccm->pdr0); 163b9bb0531SStefano Babic 164b9bb0531SStefano Babic return freq / (get_ahb_div(pdr0) * 2); 165b9bb0531SStefano Babic } 166b9bb0531SStefano Babic 167b9bb0531SStefano Babic static u32 get_ipg_per_clk(void) 168b9bb0531SStefano Babic { 169b9bb0531SStefano Babic u32 freq = get_mcu_main_clk(); 170b9bb0531SStefano Babic struct ccm_regs *ccm = 171b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 172b9bb0531SStefano Babic u32 pdr0 = readl(&ccm->pdr0); 173b9bb0531SStefano Babic u32 pdr4 = readl(&ccm->pdr4); 174b9bb0531SStefano Babic u32 div; 175b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_PER_SEL) { 17682e1b543SBenoît Thébaudeau div = CCM_GET_DIVIDER(pdr4, 177b9bb0531SStefano Babic MXC_CCM_PDR4_PER0_PODF_MASK, 17882e1b543SBenoît Thébaudeau MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1; 179b9bb0531SStefano Babic } else { 180b9bb0531SStefano Babic div = CCM_GET_DIVIDER(pdr0, 181b9bb0531SStefano Babic MXC_CCM_PDR0_PER_PODF_MASK, 182b9bb0531SStefano Babic MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; 18382e1b543SBenoît Thébaudeau div *= get_ahb_div(pdr0); 184b9bb0531SStefano Babic } 185b9bb0531SStefano Babic return freq / div; 186b9bb0531SStefano Babic } 187b9bb0531SStefano Babic 188b9bb0531SStefano Babic u32 imx_get_uartclk(void) 189b9bb0531SStefano Babic { 190b9bb0531SStefano Babic u32 freq; 191b9bb0531SStefano Babic struct ccm_regs *ccm = 192b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 193b9bb0531SStefano Babic u32 pdr4 = readl(&ccm->pdr4); 194b9bb0531SStefano Babic 1959c6c5c06SBenoît Thébaudeau if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) 196b9bb0531SStefano Babic freq = get_mcu_main_clk(); 1979c6c5c06SBenoît Thébaudeau else 1989c6c5c06SBenoît Thébaudeau freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK); 19982e1b543SBenoît Thébaudeau freq /= CCM_GET_DIVIDER(pdr4, 200b9bb0531SStefano Babic MXC_CCM_PDR4_UART_PODF_MASK, 20182e1b543SBenoît Thébaudeau MXC_CCM_PDR4_UART_PODF_OFFSET) + 1; 202b9bb0531SStefano Babic return freq; 203b9bb0531SStefano Babic } 204b9bb0531SStefano Babic 2057c80326dSBenoît Thébaudeau unsigned int mxc_get_main_clock(enum mxc_main_clock clk) 206b9bb0531SStefano Babic { 207b9bb0531SStefano Babic u32 nfc_pdf, hsp_podf; 20882e1b543SBenoît Thébaudeau u32 pll, ret_val = 0, usb_podf; 209b9bb0531SStefano Babic struct ccm_regs *ccm = 210b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 211b9bb0531SStefano Babic 212b9bb0531SStefano Babic u32 reg = readl(&ccm->pdr0); 213b9bb0531SStefano Babic u32 reg4 = readl(&ccm->pdr4); 214b9bb0531SStefano Babic 215b9bb0531SStefano Babic reg |= 0x1; 216b9bb0531SStefano Babic 217b9bb0531SStefano Babic switch (clk) { 218b9bb0531SStefano Babic case CPU_CLK: 219b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 220b9bb0531SStefano Babic break; 221b9bb0531SStefano Babic case AHB_CLK: 222b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 223b9bb0531SStefano Babic break; 224b9bb0531SStefano Babic case HSP_CLK: 225b9bb0531SStefano Babic if (reg & CLKMODE_CONSUMER) { 226b9bb0531SStefano Babic hsp_podf = (reg >> 20) & 0x3; 227b9bb0531SStefano Babic pll = get_mcu_main_clk(); 228b9bb0531SStefano Babic hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF]; 229b9bb0531SStefano Babic if (hsp_podf > 0) { 230b9bb0531SStefano Babic ret_val = pll / hsp_podf; 231b9bb0531SStefano Babic } else { 232b9bb0531SStefano Babic puts("mismatch HSP with ARM clock setting\n"); 233b9bb0531SStefano Babic ret_val = 0; 234b9bb0531SStefano Babic } 235b9bb0531SStefano Babic } else { 236b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 237b9bb0531SStefano Babic } 238b9bb0531SStefano Babic break; 239b9bb0531SStefano Babic case IPG_CLK: 24077f11a99SFabio Estevam ret_val = get_ipg_clk(); 241b9bb0531SStefano Babic break; 242b9bb0531SStefano Babic case IPG_PER_CLK: 243b9bb0531SStefano Babic ret_val = get_ipg_per_clk(); 244b9bb0531SStefano Babic break; 245b9bb0531SStefano Babic case NFC_CLK: 246b9bb0531SStefano Babic nfc_pdf = (reg4 >> 28) & 0xF; 247b9bb0531SStefano Babic pll = get_mcu_main_clk(); 248b9bb0531SStefano Babic /* AHB/nfc_pdf */ 249b9bb0531SStefano Babic ret_val = pll / (nfc_pdf + 1); 250b9bb0531SStefano Babic break; 251b9bb0531SStefano Babic case USB_CLK: 25282e1b543SBenoît Thébaudeau usb_podf = (reg4 >> 22) & 0x3F; 2539c6c5c06SBenoît Thébaudeau if (reg4 & 0x200) 254b9bb0531SStefano Babic pll = get_mcu_main_clk(); 2559c6c5c06SBenoît Thébaudeau else 2569c6c5c06SBenoît Thébaudeau pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK); 257b9bb0531SStefano Babic 25882e1b543SBenoît Thébaudeau ret_val = pll / (usb_podf + 1); 259b9bb0531SStefano Babic break; 260b9bb0531SStefano Babic default: 261b9bb0531SStefano Babic printf("Unknown clock: %d\n", clk); 262b9bb0531SStefano Babic break; 263b9bb0531SStefano Babic } 264b9bb0531SStefano Babic 265b9bb0531SStefano Babic return ret_val; 266b9bb0531SStefano Babic } 2677c80326dSBenoît Thébaudeau unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) 268b9bb0531SStefano Babic { 269b9bb0531SStefano Babic u32 ret_val = 0, pdf, pre_pdf, clk_sel; 270b9bb0531SStefano Babic struct ccm_regs *ccm = 271b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 272b9bb0531SStefano Babic u32 mpdr2 = readl(&ccm->pdr2); 273b9bb0531SStefano Babic u32 mpdr3 = readl(&ccm->pdr3); 274b9bb0531SStefano Babic u32 mpdr4 = readl(&ccm->pdr4); 275b9bb0531SStefano Babic 276b9bb0531SStefano Babic switch (clk) { 277b9bb0531SStefano Babic case UART1_BAUD: 278b9bb0531SStefano Babic case UART2_BAUD: 279b9bb0531SStefano Babic case UART3_BAUD: 280b9bb0531SStefano Babic clk_sel = mpdr3 & (1 << 14); 28182e1b543SBenoît Thébaudeau pdf = (mpdr4 >> 10) & 0x3F; 282b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2839c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 284b9bb0531SStefano Babic break; 285b9bb0531SStefano Babic case SSI1_BAUD: 286b9bb0531SStefano Babic pre_pdf = (mpdr2 >> 24) & 0x7; 287b9bb0531SStefano Babic pdf = mpdr2 & 0x3F; 288b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 6); 289b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2909c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 291b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 292b9bb0531SStefano Babic break; 293b9bb0531SStefano Babic case SSI2_BAUD: 294b9bb0531SStefano Babic pre_pdf = (mpdr2 >> 27) & 0x7; 295b9bb0531SStefano Babic pdf = (mpdr2 >> 8) & 0x3F; 296b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 6); 297b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 2989c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 299b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 300b9bb0531SStefano Babic break; 301b9bb0531SStefano Babic case CSI_BAUD: 302b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 7); 30382e1b543SBenoît Thébaudeau pdf = (mpdr2 >> 16) & 0x3F; 304b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3059c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 306b9bb0531SStefano Babic break; 307b9bb0531SStefano Babic case MSHC_CLK: 308b9bb0531SStefano Babic pre_pdf = readl(&ccm->pdr1); 309b9bb0531SStefano Babic clk_sel = (pre_pdf & 0x80); 310b9bb0531SStefano Babic pdf = (pre_pdf >> 22) & 0x3F; 311b9bb0531SStefano Babic pre_pdf = (pre_pdf >> 28) & 0x7; 312b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3139c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 314b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 315b9bb0531SStefano Babic break; 316b9bb0531SStefano Babic case ESDHC1_CLK: 317b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 31882e1b543SBenoît Thébaudeau pdf = mpdr3 & 0x3F; 319b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3209c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 321b9bb0531SStefano Babic break; 322b9bb0531SStefano Babic case ESDHC2_CLK: 323b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 32482e1b543SBenoît Thébaudeau pdf = (mpdr3 >> 8) & 0x3F; 325b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3269c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 327b9bb0531SStefano Babic break; 328b9bb0531SStefano Babic case ESDHC3_CLK: 329b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 33082e1b543SBenoît Thébaudeau pdf = (mpdr3 >> 16) & 0x3F; 331b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3329c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); 333b9bb0531SStefano Babic break; 334b9bb0531SStefano Babic case SPDIF_CLK: 335b9bb0531SStefano Babic clk_sel = mpdr3 & 0x400000; 336b9bb0531SStefano Babic pre_pdf = (mpdr3 >> 29) & 0x7; 337b9bb0531SStefano Babic pdf = (mpdr3 >> 23) & 0x3F; 338b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 3399c6c5c06SBenoît Thébaudeau decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / 340b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 341b9bb0531SStefano Babic break; 342b9bb0531SStefano Babic default: 343b9bb0531SStefano Babic printf("%s(): This clock: %d not supported yet\n", 344b9bb0531SStefano Babic __func__, clk); 345b9bb0531SStefano Babic break; 346b9bb0531SStefano Babic } 347b9bb0531SStefano Babic 348b9bb0531SStefano Babic return ret_val; 349b9bb0531SStefano Babic } 350b9bb0531SStefano Babic 351b9bb0531SStefano Babic unsigned int mxc_get_clock(enum mxc_clock clk) 352b9bb0531SStefano Babic { 353b9bb0531SStefano Babic switch (clk) { 354b9bb0531SStefano Babic case MXC_ARM_CLK: 355b9bb0531SStefano Babic return get_mcu_main_clk(); 356b9bb0531SStefano Babic case MXC_AHB_CLK: 357b9bb0531SStefano Babic break; 358b9bb0531SStefano Babic case MXC_IPG_CLK: 359b9bb0531SStefano Babic return get_ipg_clk(); 360b9bb0531SStefano Babic case MXC_IPG_PERCLK: 361e7bed5c2SMatthias Weisser case MXC_I2C_CLK: 362b9bb0531SStefano Babic return get_ipg_per_clk(); 363b9bb0531SStefano Babic case MXC_UART_CLK: 364b9bb0531SStefano Babic return imx_get_uartclk(); 3656e3dc127SBenoît Thébaudeau case MXC_ESDHC1_CLK: 366b9bb0531SStefano Babic return mxc_get_peri_clock(ESDHC1_CLK); 3676e3dc127SBenoît Thébaudeau case MXC_ESDHC2_CLK: 3686e3dc127SBenoît Thébaudeau return mxc_get_peri_clock(ESDHC2_CLK); 3696e3dc127SBenoît Thébaudeau case MXC_ESDHC3_CLK: 3706e3dc127SBenoît Thébaudeau return mxc_get_peri_clock(ESDHC3_CLK); 371b9bb0531SStefano Babic case MXC_USB_CLK: 372b9bb0531SStefano Babic return mxc_get_main_clock(USB_CLK); 373b9bb0531SStefano Babic case MXC_FEC_CLK: 374b9bb0531SStefano Babic return get_ipg_clk(); 375b9bb0531SStefano Babic case MXC_CSPI_CLK: 376b9bb0531SStefano Babic return get_ipg_clk(); 377b9bb0531SStefano Babic } 378b9bb0531SStefano Babic return -1; 379b9bb0531SStefano Babic } 380b9bb0531SStefano Babic 381b9bb0531SStefano Babic #ifdef CONFIG_FEC_MXC 382b9bb0531SStefano Babic /* 383b9bb0531SStefano Babic * The MX35 has no fuse for MAC, return a NULL MAC 384b9bb0531SStefano Babic */ 385be252b65SFabio Estevam void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 386b9bb0531SStefano Babic { 387b9bb0531SStefano Babic memset(mac, 0, 6); 388b9bb0531SStefano Babic } 389b9bb0531SStefano Babic 390b9bb0531SStefano Babic u32 imx_get_fecclk(void) 391b9bb0531SStefano Babic { 392b9bb0531SStefano Babic return mxc_get_clock(MXC_IPG_CLK); 393b9bb0531SStefano Babic } 394b9bb0531SStefano Babic #endif 395b9bb0531SStefano Babic 396b9bb0531SStefano Babic int do_mx35_showclocks(cmd_tbl_t *cmdtp, 397b9bb0531SStefano Babic int flag, int argc, char * const argv[]) 398b9bb0531SStefano Babic { 399b9bb0531SStefano Babic u32 cpufreq = get_mcu_main_clk(); 400b9bb0531SStefano Babic printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); 401b9bb0531SStefano Babic printf("ipg clock : %dHz\n", get_ipg_clk()); 402b9bb0531SStefano Babic printf("ipg per clock : %dHz\n", get_ipg_per_clk()); 403b9bb0531SStefano Babic printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); 404b9bb0531SStefano Babic 405b9bb0531SStefano Babic return 0; 406b9bb0531SStefano Babic } 407b9bb0531SStefano Babic 408b9bb0531SStefano Babic U_BOOT_CMD( 4097acec259SStefano Babic clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks, 4107acec259SStefano Babic "display clocks", 411b9bb0531SStefano Babic "" 412b9bb0531SStefano Babic ); 413b9bb0531SStefano Babic 414ec0919f5SFabio Estevam #if defined(CONFIG_DISPLAY_CPUINFO) 415d330883fSStefano Babic static char *get_reset_cause(void) 416d330883fSStefano Babic { 417d330883fSStefano Babic /* read RCSR register from CCM module */ 418d330883fSStefano Babic struct ccm_regs *ccm = 419d330883fSStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 420d330883fSStefano Babic 421d330883fSStefano Babic u32 cause = readl(&ccm->rcsr) & 0x0F; 422d330883fSStefano Babic 423d330883fSStefano Babic switch (cause) { 424d330883fSStefano Babic case 0x0000: 425d330883fSStefano Babic return "POR"; 426d330883fSStefano Babic case 0x0002: 427d330883fSStefano Babic return "JTAG"; 428d330883fSStefano Babic case 0x0004: 429d330883fSStefano Babic return "RST"; 430d330883fSStefano Babic case 0x0008: 431d330883fSStefano Babic return "WDOG"; 432d330883fSStefano Babic default: 433d330883fSStefano Babic return "unknown reset"; 434d330883fSStefano Babic } 435d330883fSStefano Babic } 436d330883fSStefano Babic 437b9bb0531SStefano Babic int print_cpuinfo(void) 438b9bb0531SStefano Babic { 439d330883fSStefano Babic u32 srev = get_cpu_rev(); 440d330883fSStefano Babic 441d330883fSStefano Babic printf("CPU: Freescale i.MX35 rev %d.%d at %d MHz.\n", 442d330883fSStefano Babic (srev & 0xF0) >> 4, (srev & 0x0F), 443b9bb0531SStefano Babic get_mcu_main_clk() / 1000000); 444d330883fSStefano Babic 445d330883fSStefano Babic printf("Reset cause: %s\n", get_reset_cause()); 446d330883fSStefano Babic 447b9bb0531SStefano Babic return 0; 448b9bb0531SStefano Babic } 449b9bb0531SStefano Babic #endif 450b9bb0531SStefano Babic 451b9bb0531SStefano Babic /* 452b9bb0531SStefano Babic * Initializes on-chip ethernet controllers. 453b9bb0531SStefano Babic * to override, implement board_eth_init() 454b9bb0531SStefano Babic */ 455b9bb0531SStefano Babic int cpu_eth_init(bd_t *bis) 456b9bb0531SStefano Babic { 457b9bb0531SStefano Babic int rc = -ENODEV; 458b9bb0531SStefano Babic 459b9bb0531SStefano Babic #if defined(CONFIG_FEC_MXC) 460b9bb0531SStefano Babic rc = fecmxc_initialize(bis); 461b9bb0531SStefano Babic #endif 462b9bb0531SStefano Babic 463b9bb0531SStefano Babic return rc; 464b9bb0531SStefano Babic } 465b9bb0531SStefano Babic 46609bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC 46709bc3d04SBenoît Thébaudeau /* 46809bc3d04SBenoît Thébaudeau * Initializes on-chip MMC controllers. 46909bc3d04SBenoît Thébaudeau * to override, implement board_mmc_init() 47009bc3d04SBenoît Thébaudeau */ 47109bc3d04SBenoît Thébaudeau int cpu_mmc_init(bd_t *bis) 47209bc3d04SBenoît Thébaudeau { 47309bc3d04SBenoît Thébaudeau return fsl_esdhc_mmc_init(bis); 47409bc3d04SBenoît Thébaudeau } 47509bc3d04SBenoît Thébaudeau #endif 47609bc3d04SBenoît Thébaudeau 477b9bb0531SStefano Babic int get_clocks(void) 478b9bb0531SStefano Babic { 479b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC 4806e3dc127SBenoît Thébaudeau #if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR 481*e9adeca3SSimon Glass gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); 4826e3dc127SBenoît Thébaudeau #elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR 483*e9adeca3SSimon Glass gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); 4846e3dc127SBenoît Thébaudeau #else 485*e9adeca3SSimon Glass gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); 4866e3dc127SBenoît Thébaudeau #endif 487b9bb0531SStefano Babic #endif 488b9bb0531SStefano Babic return 0; 489b9bb0531SStefano Babic } 490b9bb0531SStefano Babic 491d41924a2SStefano Babic #define RCSR_MEM_CTL_WEIM 0 492d41924a2SStefano Babic #define RCSR_MEM_CTL_NAND 1 493d41924a2SStefano Babic #define RCSR_MEM_CTL_ATA 2 494d41924a2SStefano Babic #define RCSR_MEM_CTL_EXPANSION 3 495d41924a2SStefano Babic #define RCSR_MEM_TYPE_NOR 0 496d41924a2SStefano Babic #define RCSR_MEM_TYPE_ONENAND 2 497d41924a2SStefano Babic #define RCSR_MEM_TYPE_SD 0 498d41924a2SStefano Babic #define RCSR_MEM_TYPE_I2C 2 499d41924a2SStefano Babic #define RCSR_MEM_TYPE_SPI 3 500d41924a2SStefano Babic 501d41924a2SStefano Babic u32 spl_boot_device(void) 502d41924a2SStefano Babic { 503d41924a2SStefano Babic struct ccm_regs *ccm = 504d41924a2SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 505d41924a2SStefano Babic 506d41924a2SStefano Babic u32 rcsr = readl(&ccm->rcsr); 507d41924a2SStefano Babic u32 mem_type, mem_ctl; 508d41924a2SStefano Babic 509d41924a2SStefano Babic /* In external mode, no boot device is returned */ 510d41924a2SStefano Babic if ((rcsr >> 10) & 0x03) 511d41924a2SStefano Babic return BOOT_DEVICE_NONE; 512d41924a2SStefano Babic 513d41924a2SStefano Babic mem_ctl = (rcsr >> 25) & 0x03; 514d41924a2SStefano Babic mem_type = (rcsr >> 23) & 0x03; 515d41924a2SStefano Babic 516d41924a2SStefano Babic switch (mem_ctl) { 517d41924a2SStefano Babic case RCSR_MEM_CTL_WEIM: 518d41924a2SStefano Babic switch (mem_type) { 519d41924a2SStefano Babic case RCSR_MEM_TYPE_NOR: 520d41924a2SStefano Babic return BOOT_DEVICE_NOR; 521d41924a2SStefano Babic case RCSR_MEM_TYPE_ONENAND: 522d41924a2SStefano Babic return BOOT_DEVICE_ONE_NAND; 523d41924a2SStefano Babic default: 524d41924a2SStefano Babic return BOOT_DEVICE_NONE; 525d41924a2SStefano Babic } 526d41924a2SStefano Babic case RCSR_MEM_CTL_NAND: 527d41924a2SStefano Babic return BOOT_DEVICE_NAND; 528d41924a2SStefano Babic case RCSR_MEM_CTL_EXPANSION: 529d41924a2SStefano Babic switch (mem_type) { 530d41924a2SStefano Babic case RCSR_MEM_TYPE_SD: 531d41924a2SStefano Babic return BOOT_DEVICE_MMC1; 532d41924a2SStefano Babic case RCSR_MEM_TYPE_I2C: 533d41924a2SStefano Babic return BOOT_DEVICE_I2C; 534d41924a2SStefano Babic case RCSR_MEM_TYPE_SPI: 535d41924a2SStefano Babic return BOOT_DEVICE_SPI; 536d41924a2SStefano Babic default: 537d41924a2SStefano Babic return BOOT_DEVICE_NONE; 538d41924a2SStefano Babic } 539d41924a2SStefano Babic } 540d41924a2SStefano Babic 541d41924a2SStefano Babic return BOOT_DEVICE_NONE; 542d41924a2SStefano Babic } 543d41924a2SStefano Babic 544d41924a2SStefano Babic #ifdef CONFIG_SPL_BUILD 545d41924a2SStefano Babic u32 spl_boot_mode(void) 546d41924a2SStefano Babic { 547d41924a2SStefano Babic switch (spl_boot_device()) { 548d41924a2SStefano Babic case BOOT_DEVICE_MMC1: 549d41924a2SStefano Babic #ifdef CONFIG_SPL_FAT_SUPPORT 550d41924a2SStefano Babic return MMCSD_MODE_FAT; 551d41924a2SStefano Babic #else 552d41924a2SStefano Babic return MMCSD_MODE_RAW; 553d41924a2SStefano Babic #endif 554d41924a2SStefano Babic break; 555d41924a2SStefano Babic case BOOT_DEVICE_NAND: 556d41924a2SStefano Babic return 0; 557d41924a2SStefano Babic break; 558d41924a2SStefano Babic default: 559d41924a2SStefano Babic puts("spl: ERROR: unsupported device\n"); 560d41924a2SStefano Babic hang(); 561d41924a2SStefano Babic } 562d41924a2SStefano Babic } 563d41924a2SStefano Babic #endif 564