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> 27b9bb0531SStefano Babic #include <asm/io.h> 28b9bb0531SStefano Babic #include <asm/errno.h> 29b9bb0531SStefano Babic #include <asm/arch/imx-regs.h> 30b9bb0531SStefano Babic #include <asm/arch/crm_regs.h> 31b9bb0531SStefano Babic #include <asm/arch/clock.h> 32b9bb0531SStefano Babic #include <asm/arch/sys_proto.h> 33*09bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC 34*09bc3d04SBenoît Thébaudeau #include <fsl_esdhc.h> 35*09bc3d04SBenoît Thébaudeau #endif 36b9bb0531SStefano Babic #include <netdev.h> 37b9bb0531SStefano Babic 38b9bb0531SStefano Babic #define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) 39b9bb0531SStefano Babic #define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) 40b9bb0531SStefano Babic #define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) 41b9bb0531SStefano Babic #define CLK_CODE_PATH(c) ((c) & 0xFF) 42b9bb0531SStefano Babic 43b9bb0531SStefano Babic #define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o)) 44b9bb0531SStefano Babic 45b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC 46b9bb0531SStefano Babic DECLARE_GLOBAL_DATA_PTR; 47b9bb0531SStefano Babic #endif 48b9bb0531SStefano Babic 49b9bb0531SStefano Babic static int g_clk_mux_auto[8] = { 50b9bb0531SStefano Babic CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, 51b9bb0531SStefano Babic CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, 52b9bb0531SStefano Babic }; 53b9bb0531SStefano Babic 54b9bb0531SStefano Babic static int g_clk_mux_consumer[16] = { 55b9bb0531SStefano Babic CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1, 56b9bb0531SStefano Babic -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), 57b9bb0531SStefano Babic CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, 58b9bb0531SStefano Babic -1, -1, CLK_CODE(4, 2, 0), -1, 59b9bb0531SStefano Babic }; 60b9bb0531SStefano Babic 61b9bb0531SStefano Babic static int hsp_div_table[3][16] = { 62b9bb0531SStefano Babic {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, 63b9bb0531SStefano Babic {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, 64b9bb0531SStefano Babic {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, 65b9bb0531SStefano Babic }; 66b9bb0531SStefano Babic 67b9bb0531SStefano Babic u32 get_cpu_rev(void) 68b9bb0531SStefano Babic { 69b9bb0531SStefano Babic int reg; 70b9bb0531SStefano Babic struct iim_regs *iim = 71b9bb0531SStefano Babic (struct iim_regs *)IIM_BASE_ADDR; 72b9bb0531SStefano Babic reg = readl(&iim->iim_srev); 73b9bb0531SStefano Babic if (!reg) { 74b9bb0531SStefano Babic reg = readw(ROMPATCH_REV); 75b9bb0531SStefano Babic reg <<= 4; 76b9bb0531SStefano Babic } else { 77b9bb0531SStefano Babic reg += CHIP_REV_1_0; 78b9bb0531SStefano Babic } 79b9bb0531SStefano Babic 80b9bb0531SStefano Babic return 0x35000 + (reg & 0xFF); 81b9bb0531SStefano Babic } 82b9bb0531SStefano Babic 83b9bb0531SStefano Babic static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd) 84b9bb0531SStefano Babic { 85b9bb0531SStefano Babic int *pclk_mux; 86b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { 87b9bb0531SStefano Babic pclk_mux = g_clk_mux_consumer + 88b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> 89b9bb0531SStefano Babic MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); 90b9bb0531SStefano Babic } else { 91b9bb0531SStefano Babic pclk_mux = g_clk_mux_auto + 92b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> 93b9bb0531SStefano Babic MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); 94b9bb0531SStefano Babic } 95b9bb0531SStefano Babic 96b9bb0531SStefano Babic if ((*pclk_mux) == -1) 97b9bb0531SStefano Babic return -1; 98b9bb0531SStefano Babic 99b9bb0531SStefano Babic if (fi && fd) { 100b9bb0531SStefano Babic if (!CLK_CODE_PATH(*pclk_mux)) { 101b9bb0531SStefano Babic *fi = *fd = 1; 102b9bb0531SStefano Babic return CLK_CODE_ARM(*pclk_mux); 103b9bb0531SStefano Babic } 104b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { 105b9bb0531SStefano Babic *fi = 3; 106b9bb0531SStefano Babic *fd = 4; 107b9bb0531SStefano Babic } else { 108b9bb0531SStefano Babic *fi = 2; 109b9bb0531SStefano Babic *fd = 3; 110b9bb0531SStefano Babic } 111b9bb0531SStefano Babic } 112b9bb0531SStefano Babic return CLK_CODE_ARM(*pclk_mux); 113b9bb0531SStefano Babic } 114b9bb0531SStefano Babic 115b9bb0531SStefano Babic static int get_ahb_div(u32 pdr0) 116b9bb0531SStefano Babic { 117b9bb0531SStefano Babic int *pclk_mux; 118b9bb0531SStefano Babic 119b9bb0531SStefano Babic pclk_mux = g_clk_mux_consumer + 120b9bb0531SStefano Babic ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> 121b9bb0531SStefano Babic MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); 122b9bb0531SStefano Babic 123b9bb0531SStefano Babic if ((*pclk_mux) == -1) 124b9bb0531SStefano Babic return -1; 125b9bb0531SStefano Babic 126b9bb0531SStefano Babic return CLK_CODE_AHB(*pclk_mux); 127b9bb0531SStefano Babic } 128b9bb0531SStefano Babic 129b9bb0531SStefano Babic static u32 decode_pll(u32 reg, u32 infreq) 130b9bb0531SStefano Babic { 131b9bb0531SStefano Babic u32 mfi = (reg >> 10) & 0xf; 132b9bb0531SStefano Babic u32 mfn = reg & 0x3f; 133b9bb0531SStefano Babic u32 mfd = (reg >> 16) & 0x3f; 134b9bb0531SStefano Babic u32 pd = (reg >> 26) & 0xf; 135b9bb0531SStefano Babic 136b9bb0531SStefano Babic mfi = mfi <= 5 ? 5 : mfi; 137b9bb0531SStefano Babic mfd += 1; 138b9bb0531SStefano Babic pd += 1; 139b9bb0531SStefano Babic 140b9bb0531SStefano Babic return ((2 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000; 141b9bb0531SStefano Babic } 142b9bb0531SStefano Babic 143b9bb0531SStefano Babic static u32 get_mcu_main_clk(void) 144b9bb0531SStefano Babic { 145b9bb0531SStefano Babic u32 arm_div = 0, fi = 0, fd = 0; 146b9bb0531SStefano Babic struct ccm_regs *ccm = 147b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 148b9bb0531SStefano Babic arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd); 149b9bb0531SStefano Babic fi *= 150b9bb0531SStefano Babic decode_pll(readl(&ccm->mpctl), 151b9bb0531SStefano Babic CONFIG_MX35_HCLK_FREQ); 152b9bb0531SStefano Babic return fi / (arm_div * fd); 153b9bb0531SStefano Babic } 154b9bb0531SStefano Babic 155b9bb0531SStefano Babic static u32 get_ipg_clk(void) 156b9bb0531SStefano Babic { 157b9bb0531SStefano Babic u32 freq = get_mcu_main_clk(); 158b9bb0531SStefano Babic struct ccm_regs *ccm = 159b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 160b9bb0531SStefano Babic u32 pdr0 = readl(&ccm->pdr0); 161b9bb0531SStefano Babic 162b9bb0531SStefano Babic return freq / (get_ahb_div(pdr0) * 2); 163b9bb0531SStefano Babic } 164b9bb0531SStefano Babic 165b9bb0531SStefano Babic static u32 get_ipg_per_clk(void) 166b9bb0531SStefano Babic { 167b9bb0531SStefano Babic u32 freq = get_mcu_main_clk(); 168b9bb0531SStefano Babic struct ccm_regs *ccm = 169b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 170b9bb0531SStefano Babic u32 pdr0 = readl(&ccm->pdr0); 171b9bb0531SStefano Babic u32 pdr4 = readl(&ccm->pdr4); 172b9bb0531SStefano Babic u32 div; 173b9bb0531SStefano Babic if (pdr0 & MXC_CCM_PDR0_PER_SEL) { 174b9bb0531SStefano Babic div = (CCM_GET_DIVIDER(pdr4, 175b9bb0531SStefano Babic MXC_CCM_PDR4_PER0_PRDF_MASK, 176b9bb0531SStefano Babic MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1) * 177b9bb0531SStefano Babic (CCM_GET_DIVIDER(pdr4, 178b9bb0531SStefano Babic MXC_CCM_PDR4_PER0_PODF_MASK, 179b9bb0531SStefano Babic MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1); 180b9bb0531SStefano Babic } else { 181b9bb0531SStefano Babic div = CCM_GET_DIVIDER(pdr0, 182b9bb0531SStefano Babic MXC_CCM_PDR0_PER_PODF_MASK, 183b9bb0531SStefano Babic MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; 184b9bb0531SStefano Babic freq /= get_ahb_div(pdr0); 185b9bb0531SStefano Babic } 186b9bb0531SStefano Babic return freq / div; 187b9bb0531SStefano Babic } 188b9bb0531SStefano Babic 189b9bb0531SStefano Babic u32 imx_get_uartclk(void) 190b9bb0531SStefano Babic { 191b9bb0531SStefano Babic u32 freq; 192b9bb0531SStefano Babic struct ccm_regs *ccm = 193b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 194b9bb0531SStefano Babic u32 pdr4 = readl(&ccm->pdr4); 195b9bb0531SStefano Babic 196b9bb0531SStefano Babic if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) { 197b9bb0531SStefano Babic freq = get_mcu_main_clk(); 198b9bb0531SStefano Babic } else { 199b9bb0531SStefano Babic freq = decode_pll(readl(&ccm->ppctl), 200b9bb0531SStefano Babic CONFIG_MX35_HCLK_FREQ); 201b9bb0531SStefano Babic } 202b9bb0531SStefano Babic freq /= ((CCM_GET_DIVIDER(pdr4, 203b9bb0531SStefano Babic MXC_CCM_PDR4_UART_PRDF_MASK, 204b9bb0531SStefano Babic MXC_CCM_PDR4_UART_PRDF_OFFSET) + 1) * 205b9bb0531SStefano Babic (CCM_GET_DIVIDER(pdr4, 206b9bb0531SStefano Babic MXC_CCM_PDR4_UART_PODF_MASK, 207b9bb0531SStefano Babic MXC_CCM_PDR4_UART_PODF_OFFSET) + 1)); 208b9bb0531SStefano Babic return freq; 209b9bb0531SStefano Babic } 210b9bb0531SStefano Babic 211b9bb0531SStefano Babic unsigned int mxc_get_main_clock(enum mxc_main_clocks clk) 212b9bb0531SStefano Babic { 213b9bb0531SStefano Babic u32 nfc_pdf, hsp_podf; 214b9bb0531SStefano Babic u32 pll, ret_val = 0, usb_prdf, usb_podf; 215b9bb0531SStefano Babic struct ccm_regs *ccm = 216b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 217b9bb0531SStefano Babic 218b9bb0531SStefano Babic u32 reg = readl(&ccm->pdr0); 219b9bb0531SStefano Babic u32 reg4 = readl(&ccm->pdr4); 220b9bb0531SStefano Babic 221b9bb0531SStefano Babic reg |= 0x1; 222b9bb0531SStefano Babic 223b9bb0531SStefano Babic switch (clk) { 224b9bb0531SStefano Babic case CPU_CLK: 225b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 226b9bb0531SStefano Babic break; 227b9bb0531SStefano Babic case AHB_CLK: 228b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 229b9bb0531SStefano Babic break; 230b9bb0531SStefano Babic case HSP_CLK: 231b9bb0531SStefano Babic if (reg & CLKMODE_CONSUMER) { 232b9bb0531SStefano Babic hsp_podf = (reg >> 20) & 0x3; 233b9bb0531SStefano Babic pll = get_mcu_main_clk(); 234b9bb0531SStefano Babic hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF]; 235b9bb0531SStefano Babic if (hsp_podf > 0) { 236b9bb0531SStefano Babic ret_val = pll / hsp_podf; 237b9bb0531SStefano Babic } else { 238b9bb0531SStefano Babic puts("mismatch HSP with ARM clock setting\n"); 239b9bb0531SStefano Babic ret_val = 0; 240b9bb0531SStefano Babic } 241b9bb0531SStefano Babic } else { 242b9bb0531SStefano Babic ret_val = get_mcu_main_clk(); 243b9bb0531SStefano Babic } 244b9bb0531SStefano Babic break; 245b9bb0531SStefano Babic case IPG_CLK: 24677f11a99SFabio Estevam ret_val = get_ipg_clk(); 247b9bb0531SStefano Babic break; 248b9bb0531SStefano Babic case IPG_PER_CLK: 249b9bb0531SStefano Babic ret_val = get_ipg_per_clk(); 250b9bb0531SStefano Babic break; 251b9bb0531SStefano Babic case NFC_CLK: 252b9bb0531SStefano Babic nfc_pdf = (reg4 >> 28) & 0xF; 253b9bb0531SStefano Babic pll = get_mcu_main_clk(); 254b9bb0531SStefano Babic /* AHB/nfc_pdf */ 255b9bb0531SStefano Babic ret_val = pll / (nfc_pdf + 1); 256b9bb0531SStefano Babic break; 257b9bb0531SStefano Babic case USB_CLK: 258b9bb0531SStefano Babic usb_prdf = (reg4 >> 25) & 0x7; 259b9bb0531SStefano Babic usb_podf = (reg4 >> 22) & 0x7; 260b9bb0531SStefano Babic if (reg4 & 0x200) { 261b9bb0531SStefano Babic pll = get_mcu_main_clk(); 262b9bb0531SStefano Babic } else { 263b9bb0531SStefano Babic pll = decode_pll(readl(&ccm->ppctl), 264b9bb0531SStefano Babic CONFIG_MX35_HCLK_FREQ); 265b9bb0531SStefano Babic } 266b9bb0531SStefano Babic 267b9bb0531SStefano Babic ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1)); 268b9bb0531SStefano Babic break; 269b9bb0531SStefano Babic default: 270b9bb0531SStefano Babic printf("Unknown clock: %d\n", clk); 271b9bb0531SStefano Babic break; 272b9bb0531SStefano Babic } 273b9bb0531SStefano Babic 274b9bb0531SStefano Babic return ret_val; 275b9bb0531SStefano Babic } 276b9bb0531SStefano Babic unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk) 277b9bb0531SStefano Babic { 278b9bb0531SStefano Babic u32 ret_val = 0, pdf, pre_pdf, clk_sel; 279b9bb0531SStefano Babic struct ccm_regs *ccm = 280b9bb0531SStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 281b9bb0531SStefano Babic u32 mpdr2 = readl(&ccm->pdr2); 282b9bb0531SStefano Babic u32 mpdr3 = readl(&ccm->pdr3); 283b9bb0531SStefano Babic u32 mpdr4 = readl(&ccm->pdr4); 284b9bb0531SStefano Babic 285b9bb0531SStefano Babic switch (clk) { 286b9bb0531SStefano Babic case UART1_BAUD: 287b9bb0531SStefano Babic case UART2_BAUD: 288b9bb0531SStefano Babic case UART3_BAUD: 289b9bb0531SStefano Babic clk_sel = mpdr3 & (1 << 14); 290b9bb0531SStefano Babic pre_pdf = (mpdr4 >> 13) & 0x7; 291b9bb0531SStefano Babic pdf = (mpdr4 >> 10) & 0x7; 292b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 293b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 294b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 295b9bb0531SStefano Babic break; 296b9bb0531SStefano Babic case SSI1_BAUD: 297b9bb0531SStefano Babic pre_pdf = (mpdr2 >> 24) & 0x7; 298b9bb0531SStefano Babic pdf = mpdr2 & 0x3F; 299b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 6); 300b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 301b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 302b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 303b9bb0531SStefano Babic break; 304b9bb0531SStefano Babic case SSI2_BAUD: 305b9bb0531SStefano Babic pre_pdf = (mpdr2 >> 27) & 0x7; 306b9bb0531SStefano Babic pdf = (mpdr2 >> 8) & 0x3F; 307b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 6); 308b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 309b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 310b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 311b9bb0531SStefano Babic break; 312b9bb0531SStefano Babic case CSI_BAUD: 313b9bb0531SStefano Babic clk_sel = mpdr2 & (1 << 7); 314b9bb0531SStefano Babic pre_pdf = (mpdr2 >> 16) & 0x7; 315b9bb0531SStefano Babic pdf = (mpdr2 >> 19) & 0x7; 316b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 317b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 318b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 319b9bb0531SStefano Babic break; 320b9bb0531SStefano Babic case MSHC_CLK: 321b9bb0531SStefano Babic pre_pdf = readl(&ccm->pdr1); 322b9bb0531SStefano Babic clk_sel = (pre_pdf & 0x80); 323b9bb0531SStefano Babic pdf = (pre_pdf >> 22) & 0x3F; 324b9bb0531SStefano Babic pre_pdf = (pre_pdf >> 28) & 0x7; 325b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 326b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 327b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 328b9bb0531SStefano Babic break; 329b9bb0531SStefano Babic case ESDHC1_CLK: 330b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 331b9bb0531SStefano Babic pre_pdf = mpdr3 & 0x7; 332b9bb0531SStefano Babic pdf = (mpdr3>>3) & 0x7; 333b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 334b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 335b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 336b9bb0531SStefano Babic break; 337b9bb0531SStefano Babic case ESDHC2_CLK: 338b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 339b9bb0531SStefano Babic pre_pdf = (mpdr3 >> 8) & 0x7; 340b9bb0531SStefano Babic pdf = (mpdr3 >> 11) & 0x7; 341b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 342b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 343b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 344b9bb0531SStefano Babic break; 345b9bb0531SStefano Babic case ESDHC3_CLK: 346b9bb0531SStefano Babic clk_sel = mpdr3 & 0x40; 347b9bb0531SStefano Babic pre_pdf = (mpdr3 >> 16) & 0x7; 348b9bb0531SStefano Babic pdf = (mpdr3 >> 19) & 0x7; 349b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 350b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 351b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 352b9bb0531SStefano Babic break; 353b9bb0531SStefano Babic case SPDIF_CLK: 354b9bb0531SStefano Babic clk_sel = mpdr3 & 0x400000; 355b9bb0531SStefano Babic pre_pdf = (mpdr3 >> 29) & 0x7; 356b9bb0531SStefano Babic pdf = (mpdr3 >> 23) & 0x3F; 357b9bb0531SStefano Babic ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : 358b9bb0531SStefano Babic decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / 359b9bb0531SStefano Babic ((pre_pdf + 1) * (pdf + 1)); 360b9bb0531SStefano Babic break; 361b9bb0531SStefano Babic default: 362b9bb0531SStefano Babic printf("%s(): This clock: %d not supported yet\n", 363b9bb0531SStefano Babic __func__, clk); 364b9bb0531SStefano Babic break; 365b9bb0531SStefano Babic } 366b9bb0531SStefano Babic 367b9bb0531SStefano Babic return ret_val; 368b9bb0531SStefano Babic } 369b9bb0531SStefano Babic 370b9bb0531SStefano Babic unsigned int mxc_get_clock(enum mxc_clock clk) 371b9bb0531SStefano Babic { 372b9bb0531SStefano Babic switch (clk) { 373b9bb0531SStefano Babic case MXC_ARM_CLK: 374b9bb0531SStefano Babic return get_mcu_main_clk(); 375b9bb0531SStefano Babic case MXC_AHB_CLK: 376b9bb0531SStefano Babic break; 377b9bb0531SStefano Babic case MXC_IPG_CLK: 378b9bb0531SStefano Babic return get_ipg_clk(); 379b9bb0531SStefano Babic case MXC_IPG_PERCLK: 380b9bb0531SStefano Babic return get_ipg_per_clk(); 381b9bb0531SStefano Babic case MXC_UART_CLK: 382b9bb0531SStefano Babic return imx_get_uartclk(); 383b9bb0531SStefano Babic case MXC_ESDHC_CLK: 384b9bb0531SStefano Babic return mxc_get_peri_clock(ESDHC1_CLK); 385b9bb0531SStefano Babic case MXC_USB_CLK: 386b9bb0531SStefano Babic return mxc_get_main_clock(USB_CLK); 387b9bb0531SStefano Babic case MXC_FEC_CLK: 388b9bb0531SStefano Babic return get_ipg_clk(); 389b9bb0531SStefano Babic case MXC_CSPI_CLK: 390b9bb0531SStefano Babic return get_ipg_clk(); 391b9bb0531SStefano Babic } 392b9bb0531SStefano Babic return -1; 393b9bb0531SStefano Babic } 394b9bb0531SStefano Babic 395b9bb0531SStefano Babic #ifdef CONFIG_FEC_MXC 396b9bb0531SStefano Babic /* 397b9bb0531SStefano Babic * The MX35 has no fuse for MAC, return a NULL MAC 398b9bb0531SStefano Babic */ 399be252b65SFabio Estevam void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 400b9bb0531SStefano Babic { 401b9bb0531SStefano Babic memset(mac, 0, 6); 402b9bb0531SStefano Babic } 403b9bb0531SStefano Babic 404b9bb0531SStefano Babic u32 imx_get_fecclk(void) 405b9bb0531SStefano Babic { 406b9bb0531SStefano Babic return mxc_get_clock(MXC_IPG_CLK); 407b9bb0531SStefano Babic } 408b9bb0531SStefano Babic #endif 409b9bb0531SStefano Babic 410b9bb0531SStefano Babic int do_mx35_showclocks(cmd_tbl_t *cmdtp, 411b9bb0531SStefano Babic int flag, int argc, char * const argv[]) 412b9bb0531SStefano Babic { 413b9bb0531SStefano Babic u32 cpufreq = get_mcu_main_clk(); 414b9bb0531SStefano Babic printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); 415b9bb0531SStefano Babic printf("ipg clock : %dHz\n", get_ipg_clk()); 416b9bb0531SStefano Babic printf("ipg per clock : %dHz\n", get_ipg_per_clk()); 417b9bb0531SStefano Babic printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); 418b9bb0531SStefano Babic 419b9bb0531SStefano Babic return 0; 420b9bb0531SStefano Babic } 421b9bb0531SStefano Babic 422b9bb0531SStefano Babic U_BOOT_CMD( 4237acec259SStefano Babic clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks, 4247acec259SStefano Babic "display clocks", 425b9bb0531SStefano Babic "" 426b9bb0531SStefano Babic ); 427b9bb0531SStefano Babic 428ec0919f5SFabio Estevam #if defined(CONFIG_DISPLAY_CPUINFO) 429d330883fSStefano Babic static char *get_reset_cause(void) 430d330883fSStefano Babic { 431d330883fSStefano Babic /* read RCSR register from CCM module */ 432d330883fSStefano Babic struct ccm_regs *ccm = 433d330883fSStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 434d330883fSStefano Babic 435d330883fSStefano Babic u32 cause = readl(&ccm->rcsr) & 0x0F; 436d330883fSStefano Babic 437d330883fSStefano Babic switch (cause) { 438d330883fSStefano Babic case 0x0000: 439d330883fSStefano Babic return "POR"; 440d330883fSStefano Babic case 0x0002: 441d330883fSStefano Babic return "JTAG"; 442d330883fSStefano Babic case 0x0004: 443d330883fSStefano Babic return "RST"; 444d330883fSStefano Babic case 0x0008: 445d330883fSStefano Babic return "WDOG"; 446d330883fSStefano Babic default: 447d330883fSStefano Babic return "unknown reset"; 448d330883fSStefano Babic } 449d330883fSStefano Babic } 450d330883fSStefano Babic 451b9bb0531SStefano Babic int print_cpuinfo(void) 452b9bb0531SStefano Babic { 453d330883fSStefano Babic u32 srev = get_cpu_rev(); 454d330883fSStefano Babic 455d330883fSStefano Babic printf("CPU: Freescale i.MX35 rev %d.%d at %d MHz.\n", 456d330883fSStefano Babic (srev & 0xF0) >> 4, (srev & 0x0F), 457b9bb0531SStefano Babic get_mcu_main_clk() / 1000000); 458d330883fSStefano Babic 459d330883fSStefano Babic printf("Reset cause: %s\n", get_reset_cause()); 460d330883fSStefano Babic 461b9bb0531SStefano Babic return 0; 462b9bb0531SStefano Babic } 463b9bb0531SStefano Babic #endif 464b9bb0531SStefano Babic 465b9bb0531SStefano Babic /* 466b9bb0531SStefano Babic * Initializes on-chip ethernet controllers. 467b9bb0531SStefano Babic * to override, implement board_eth_init() 468b9bb0531SStefano Babic */ 469b9bb0531SStefano Babic int cpu_eth_init(bd_t *bis) 470b9bb0531SStefano Babic { 471b9bb0531SStefano Babic int rc = -ENODEV; 472b9bb0531SStefano Babic 473b9bb0531SStefano Babic #if defined(CONFIG_FEC_MXC) 474b9bb0531SStefano Babic rc = fecmxc_initialize(bis); 475b9bb0531SStefano Babic #endif 476b9bb0531SStefano Babic 477b9bb0531SStefano Babic return rc; 478b9bb0531SStefano Babic } 479b9bb0531SStefano Babic 480*09bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC 481*09bc3d04SBenoît Thébaudeau /* 482*09bc3d04SBenoît Thébaudeau * Initializes on-chip MMC controllers. 483*09bc3d04SBenoît Thébaudeau * to override, implement board_mmc_init() 484*09bc3d04SBenoît Thébaudeau */ 485*09bc3d04SBenoît Thébaudeau int cpu_mmc_init(bd_t *bis) 486*09bc3d04SBenoît Thébaudeau { 487*09bc3d04SBenoît Thébaudeau return fsl_esdhc_mmc_init(bis); 488*09bc3d04SBenoît Thébaudeau } 489*09bc3d04SBenoît Thébaudeau #endif 490*09bc3d04SBenoît Thébaudeau 491b9bb0531SStefano Babic int get_clocks(void) 492b9bb0531SStefano Babic { 493b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC 494b9bb0531SStefano Babic gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); 495b9bb0531SStefano Babic #endif 496b9bb0531SStefano Babic return 0; 497b9bb0531SStefano Babic } 498b9bb0531SStefano Babic 499b9bb0531SStefano Babic void reset_cpu(ulong addr) 500b9bb0531SStefano Babic { 501b9bb0531SStefano Babic struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; 502b9bb0531SStefano Babic writew(4, &wdog->wcr); 503b9bb0531SStefano Babic } 504