184ad6884SPeter Tyser /* 284ad6884SPeter Tyser * (C) Copyright 2009 DENX Software Engineering 384ad6884SPeter Tyser * Author: John Rigby <jrigby@gmail.com> 484ad6884SPeter Tyser * 584ad6884SPeter Tyser * Based on mx27/generic.c: 684ad6884SPeter Tyser * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> 784ad6884SPeter Tyser * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> 884ad6884SPeter Tyser * 984ad6884SPeter Tyser * This program is free software; you can redistribute it and/or 1084ad6884SPeter Tyser * modify it under the terms of the GNU General Public License as 1184ad6884SPeter Tyser * published by the Free Software Foundation; either version 2 of 1284ad6884SPeter Tyser * the License, or (at your option) any later version. 1384ad6884SPeter Tyser * 1484ad6884SPeter Tyser * This program is distributed in the hope that it will be useful, 1584ad6884SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 1684ad6884SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1784ad6884SPeter Tyser * GNU General Public License for more details. 1884ad6884SPeter Tyser * 1984ad6884SPeter Tyser * You should have received a copy of the GNU General Public License 2084ad6884SPeter Tyser * along with this program; if not, write to the Free Software 2184ad6884SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2284ad6884SPeter Tyser * MA 02111-1307 USA 2384ad6884SPeter Tyser */ 2484ad6884SPeter Tyser 2584ad6884SPeter Tyser #include <common.h> 2684ad6884SPeter Tyser #include <div64.h> 2784ad6884SPeter Tyser #include <netdev.h> 2884ad6884SPeter Tyser #include <asm/io.h> 2984ad6884SPeter Tyser #include <asm/arch/imx-regs.h> 3084ad6884SPeter Tyser #include <asm/arch/imx25-pinmux.h> 3142d25327STimo Ketola #include <asm/arch/clock.h> 3284ad6884SPeter Tyser #ifdef CONFIG_MXC_MMC 3384ad6884SPeter Tyser #include <asm/arch/mxcmmc.h> 3484ad6884SPeter Tyser #endif 3584ad6884SPeter Tyser 3642d25327STimo Ketola #ifdef CONFIG_FSL_ESDHC 3742d25327STimo Ketola DECLARE_GLOBAL_DATA_PTR; 3842d25327STimo Ketola #endif 3942d25327STimo Ketola 4084ad6884SPeter Tyser /* 4184ad6884SPeter Tyser * get the system pll clock in Hz 4284ad6884SPeter Tyser * 4384ad6884SPeter Tyser * mfi + mfn / (mfd +1) 4484ad6884SPeter Tyser * f = 2 * f_ref * -------------------- 4584ad6884SPeter Tyser * pd + 1 4684ad6884SPeter Tyser */ 4784ad6884SPeter Tyser static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) 4884ad6884SPeter Tyser { 4984ad6884SPeter Tyser unsigned int mfi = (pll >> CCM_PLL_MFI_SHIFT) 5084ad6884SPeter Tyser & CCM_PLL_MFI_MASK; 5184ad6884SPeter Tyser unsigned int mfn = (pll >> CCM_PLL_MFN_SHIFT) 5284ad6884SPeter Tyser & CCM_PLL_MFN_MASK; 5384ad6884SPeter Tyser unsigned int mfd = (pll >> CCM_PLL_MFD_SHIFT) 5484ad6884SPeter Tyser & CCM_PLL_MFD_MASK; 5584ad6884SPeter Tyser unsigned int pd = (pll >> CCM_PLL_PD_SHIFT) 5684ad6884SPeter Tyser & CCM_PLL_PD_MASK; 5784ad6884SPeter Tyser 5884ad6884SPeter Tyser mfi = mfi <= 5 ? 5 : mfi; 5984ad6884SPeter Tyser 6084ad6884SPeter Tyser return lldiv(2 * (u64) f_ref * (mfi * (mfd + 1) + mfn), 6184ad6884SPeter Tyser (mfd + 1) * (pd + 1)); 6284ad6884SPeter Tyser } 6384ad6884SPeter Tyser 6484ad6884SPeter Tyser static ulong imx_get_mpllclk(void) 6584ad6884SPeter Tyser { 6684ad6884SPeter Tyser struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; 6784ad6884SPeter Tyser ulong fref = 24000000; 6884ad6884SPeter Tyser 6984ad6884SPeter Tyser return imx_decode_pll(readl(&ccm->mpctl), fref); 7084ad6884SPeter Tyser } 7184ad6884SPeter Tyser 7284ad6884SPeter Tyser ulong imx_get_armclk(void) 7384ad6884SPeter Tyser { 7484ad6884SPeter Tyser struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; 7584ad6884SPeter Tyser ulong cctl = readl(&ccm->cctl); 7684ad6884SPeter Tyser ulong fref = imx_get_mpllclk(); 7784ad6884SPeter Tyser ulong div; 7884ad6884SPeter Tyser 7984ad6884SPeter Tyser if (cctl & CCM_CCTL_ARM_SRC) 8084ad6884SPeter Tyser fref = lldiv((fref * 3), 4); 8184ad6884SPeter Tyser 8284ad6884SPeter Tyser div = ((cctl >> CCM_CCTL_ARM_DIV_SHIFT) 8384ad6884SPeter Tyser & CCM_CCTL_ARM_DIV_MASK) + 1; 8484ad6884SPeter Tyser 8584ad6884SPeter Tyser return lldiv(fref, div); 8684ad6884SPeter Tyser } 8784ad6884SPeter Tyser 8884ad6884SPeter Tyser ulong imx_get_ahbclk(void) 8984ad6884SPeter Tyser { 9084ad6884SPeter Tyser struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; 9184ad6884SPeter Tyser ulong cctl = readl(&ccm->cctl); 9284ad6884SPeter Tyser ulong fref = imx_get_armclk(); 9384ad6884SPeter Tyser ulong div; 9484ad6884SPeter Tyser 9584ad6884SPeter Tyser div = ((cctl >> CCM_CCTL_AHB_DIV_SHIFT) 9684ad6884SPeter Tyser & CCM_CCTL_AHB_DIV_MASK) + 1; 9784ad6884SPeter Tyser 9884ad6884SPeter Tyser return lldiv(fref, div); 9984ad6884SPeter Tyser } 10084ad6884SPeter Tyser 10184ad6884SPeter Tyser ulong imx_get_perclk(int clk) 10284ad6884SPeter Tyser { 10384ad6884SPeter Tyser struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; 10484ad6884SPeter Tyser ulong fref = imx_get_ahbclk(); 10584ad6884SPeter Tyser ulong div; 10684ad6884SPeter Tyser 10784ad6884SPeter Tyser div = readl(&ccm->pcdr[CCM_PERCLK_REG(clk)]); 10884ad6884SPeter Tyser div = ((div >> CCM_PERCLK_SHIFT(clk)) & CCM_PERCLK_MASK) + 1; 10984ad6884SPeter Tyser 11084ad6884SPeter Tyser return lldiv(fref, div); 11184ad6884SPeter Tyser } 11284ad6884SPeter Tyser 11342d25327STimo Ketola unsigned int mxc_get_clock(enum mxc_clock clk) 11442d25327STimo Ketola { 11542d25327STimo Ketola if (clk >= MXC_CLK_NUM) 11642d25327STimo Ketola return -1; 11742d25327STimo Ketola switch (clk) { 11842d25327STimo Ketola case MXC_ARM_CLK: 11942d25327STimo Ketola return imx_get_armclk(); 12042d25327STimo Ketola case MXC_FEC_CLK: 12142d25327STimo Ketola return imx_get_ahbclk(); 12242d25327STimo Ketola default: 12342d25327STimo Ketola return imx_get_perclk(clk); 12442d25327STimo Ketola } 12542d25327STimo Ketola } 12642d25327STimo Ketola 127986d0d1bSFabio Estevam u32 get_cpu_rev(void) 128986d0d1bSFabio Estevam { 129986d0d1bSFabio Estevam u32 srev; 130986d0d1bSFabio Estevam u32 system_rev = 0x25000; 131986d0d1bSFabio Estevam 132986d0d1bSFabio Estevam /* read SREV register from IIM module */ 133986d0d1bSFabio Estevam struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; 134986d0d1bSFabio Estevam srev = readl(&iim->iim_srev); 135986d0d1bSFabio Estevam 136986d0d1bSFabio Estevam switch (srev) { 137986d0d1bSFabio Estevam case 0x00: 138986d0d1bSFabio Estevam system_rev |= CHIP_REV_1_0; 139986d0d1bSFabio Estevam break; 140986d0d1bSFabio Estevam case 0x01: 141986d0d1bSFabio Estevam system_rev |= CHIP_REV_1_1; 142986d0d1bSFabio Estevam break; 143986d0d1bSFabio Estevam default: 144986d0d1bSFabio Estevam system_rev |= 0x8000; 145986d0d1bSFabio Estevam break; 146986d0d1bSFabio Estevam } 147986d0d1bSFabio Estevam 148986d0d1bSFabio Estevam return system_rev; 149986d0d1bSFabio Estevam } 150986d0d1bSFabio Estevam 15184ad6884SPeter Tyser #if defined(CONFIG_DISPLAY_CPUINFO) 152e6ec1761SFabio Estevam static char *get_reset_cause(void) 153e6ec1761SFabio Estevam { 154e6ec1761SFabio Estevam /* read RCSR register from CCM module */ 155e6ec1761SFabio Estevam struct ccm_regs *ccm = 156e6ec1761SFabio Estevam (struct ccm_regs *)IMX_CCM_BASE; 157e6ec1761SFabio Estevam 158e6ec1761SFabio Estevam u32 cause = readl(&ccm->rcsr) & 0x0f; 159e6ec1761SFabio Estevam 160e6ec1761SFabio Estevam if (cause == 0) 161e6ec1761SFabio Estevam return "POR"; 162e6ec1761SFabio Estevam else if (cause == 1) 163e6ec1761SFabio Estevam return "RST"; 164e6ec1761SFabio Estevam else if ((cause & 2) == 2) 165e6ec1761SFabio Estevam return "WDOG"; 166e6ec1761SFabio Estevam else if ((cause & 4) == 4) 167e6ec1761SFabio Estevam return "SW RESET"; 168e6ec1761SFabio Estevam else if ((cause & 8) == 8) 169e6ec1761SFabio Estevam return "JTAG"; 170e6ec1761SFabio Estevam else 171e6ec1761SFabio Estevam return "unknown reset"; 172e6ec1761SFabio Estevam 173e6ec1761SFabio Estevam } 174e6ec1761SFabio Estevam 17584ad6884SPeter Tyser int print_cpuinfo(void) 17684ad6884SPeter Tyser { 17784ad6884SPeter Tyser char buf[32]; 178986d0d1bSFabio Estevam u32 cpurev = get_cpu_rev(); 17984ad6884SPeter Tyser 180957dc024SFabio Estevam printf("CPU: Freescale i.MX25 rev%d.%d%s at %s MHz\n", 181986d0d1bSFabio Estevam (cpurev & 0xF0) >> 4, (cpurev & 0x0F), 182986d0d1bSFabio Estevam ((cpurev & 0x8000) ? " unknown" : ""), 18334196b0aSJohn Rigby strmhz(buf, imx_get_armclk())); 184957dc024SFabio Estevam printf("Reset cause: %s\n\n", get_reset_cause()); 18584ad6884SPeter Tyser return 0; 18684ad6884SPeter Tyser } 18784ad6884SPeter Tyser #endif 18884ad6884SPeter Tyser 189*e107c7e9SBenoît Thébaudeau void enable_caches(void) 190*e107c7e9SBenoît Thébaudeau { 191*e107c7e9SBenoît Thébaudeau #ifndef CONFIG_SYS_DCACHE_OFF 192*e107c7e9SBenoît Thébaudeau /* Enable D-cache. I-cache is already enabled in start.S */ 193*e107c7e9SBenoît Thébaudeau dcache_enable(); 194*e107c7e9SBenoît Thébaudeau #endif 195*e107c7e9SBenoît Thébaudeau } 196*e107c7e9SBenoît Thébaudeau 19784ad6884SPeter Tyser int cpu_eth_init(bd_t *bis) 19884ad6884SPeter Tyser { 19984ad6884SPeter Tyser #if defined(CONFIG_FEC_MXC) 20084ad6884SPeter Tyser struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; 20184ad6884SPeter Tyser ulong val; 20284ad6884SPeter Tyser 20384ad6884SPeter Tyser val = readl(&ccm->cgr0); 20484ad6884SPeter Tyser val |= (1 << 23); 20584ad6884SPeter Tyser writel(val, &ccm->cgr0); 20684ad6884SPeter Tyser return fecmxc_initialize(bis); 20784ad6884SPeter Tyser #else 20884ad6884SPeter Tyser return 0; 20984ad6884SPeter Tyser #endif 21084ad6884SPeter Tyser } 21184ad6884SPeter Tyser 21242d25327STimo Ketola int get_clocks(void) 21342d25327STimo Ketola { 21442d25327STimo Ketola #ifdef CONFIG_FSL_ESDHC 21542d25327STimo Ketola gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); 21642d25327STimo Ketola #endif 21742d25327STimo Ketola return 0; 21842d25327STimo Ketola } 21942d25327STimo Ketola 22084ad6884SPeter Tyser /* 22184ad6884SPeter Tyser * Initializes on-chip MMC controllers. 22284ad6884SPeter Tyser * to override, implement board_mmc_init() 22384ad6884SPeter Tyser */ 22484ad6884SPeter Tyser int cpu_mmc_init(bd_t *bis) 22584ad6884SPeter Tyser { 22684ad6884SPeter Tyser #ifdef CONFIG_MXC_MMC 22784ad6884SPeter Tyser return mxc_mmc_init(bis); 22884ad6884SPeter Tyser #else 22984ad6884SPeter Tyser return 0; 23084ad6884SPeter Tyser #endif 23184ad6884SPeter Tyser } 23284ad6884SPeter Tyser 23384ad6884SPeter Tyser #ifdef CONFIG_MXC_UART 2349aa720b1SFabio Estevam void mx25_uart1_init_pins(void) 23584ad6884SPeter Tyser { 23684ad6884SPeter Tyser struct iomuxc_mux_ctl *muxctl; 23784ad6884SPeter Tyser struct iomuxc_pad_ctl *padctl; 23884ad6884SPeter Tyser u32 inpadctl; 23984ad6884SPeter Tyser u32 outpadctl; 24084ad6884SPeter Tyser u32 muxmode0; 24184ad6884SPeter Tyser 24284ad6884SPeter Tyser muxctl = (struct iomuxc_mux_ctl *)IMX_IOPADMUX_BASE; 24384ad6884SPeter Tyser padctl = (struct iomuxc_pad_ctl *)IMX_IOPADCTL_BASE; 24484ad6884SPeter Tyser muxmode0 = MX25_PIN_MUX_MODE(0); 24584ad6884SPeter Tyser /* 24684ad6884SPeter Tyser * set up input pins with hysteresis and 100K pull-ups 24784ad6884SPeter Tyser */ 24884ad6884SPeter Tyser inpadctl = MX25_PIN_PAD_CTL_HYS 24984ad6884SPeter Tyser | MX25_PIN_PAD_CTL_PKE 25084ad6884SPeter Tyser | MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PU; 25184ad6884SPeter Tyser 25284ad6884SPeter Tyser /* 25384ad6884SPeter Tyser * set up output pins with 100K pull-downs 25484ad6884SPeter Tyser * FIXME: need to revisit this 25584ad6884SPeter Tyser * PUE is ignored if PKE is not set 25684ad6884SPeter Tyser * so the right value here is likely 25784ad6884SPeter Tyser * 0x0 for no pull up/down 25884ad6884SPeter Tyser * or 25984ad6884SPeter Tyser * 0xc0 for 100k pull down 26084ad6884SPeter Tyser */ 26184ad6884SPeter Tyser outpadctl = MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PD; 26284ad6884SPeter Tyser 26384ad6884SPeter Tyser /* UART1 */ 26484ad6884SPeter Tyser /* rxd */ 26584ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_uart1_rxd); 26684ad6884SPeter Tyser writel(inpadctl, &padctl->pad_uart1_rxd); 26784ad6884SPeter Tyser 26884ad6884SPeter Tyser /* txd */ 26984ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_uart1_txd); 27084ad6884SPeter Tyser writel(outpadctl, &padctl->pad_uart1_txd); 27184ad6884SPeter Tyser 27284ad6884SPeter Tyser /* rts */ 27384ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_uart1_rts); 27484ad6884SPeter Tyser writel(outpadctl, &padctl->pad_uart1_rts); 27584ad6884SPeter Tyser 27684ad6884SPeter Tyser /* cts */ 27784ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_uart1_cts); 27884ad6884SPeter Tyser writel(inpadctl, &padctl->pad_uart1_cts); 27984ad6884SPeter Tyser } 28084ad6884SPeter Tyser #endif /* CONFIG_MXC_UART */ 28184ad6884SPeter Tyser 28284ad6884SPeter Tyser #ifdef CONFIG_FEC_MXC 28384ad6884SPeter Tyser void mx25_fec_init_pins(void) 28484ad6884SPeter Tyser { 28584ad6884SPeter Tyser struct iomuxc_mux_ctl *muxctl; 28684ad6884SPeter Tyser struct iomuxc_pad_ctl *padctl; 28784ad6884SPeter Tyser u32 inpadctl_100kpd; 28884ad6884SPeter Tyser u32 inpadctl_22kpu; 28984ad6884SPeter Tyser u32 outpadctl; 29084ad6884SPeter Tyser u32 muxmode0; 29184ad6884SPeter Tyser 29284ad6884SPeter Tyser muxctl = (struct iomuxc_mux_ctl *)IMX_IOPADMUX_BASE; 29384ad6884SPeter Tyser padctl = (struct iomuxc_pad_ctl *)IMX_IOPADCTL_BASE; 29484ad6884SPeter Tyser muxmode0 = MX25_PIN_MUX_MODE(0); 29584ad6884SPeter Tyser inpadctl_100kpd = MX25_PIN_PAD_CTL_HYS 29684ad6884SPeter Tyser | MX25_PIN_PAD_CTL_PKE 29784ad6884SPeter Tyser | MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PD; 29884ad6884SPeter Tyser inpadctl_22kpu = MX25_PIN_PAD_CTL_HYS 29984ad6884SPeter Tyser | MX25_PIN_PAD_CTL_PKE 30084ad6884SPeter Tyser | MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_22K_PU; 30184ad6884SPeter Tyser /* 30284ad6884SPeter Tyser * set up output pins with 100K pull-downs 30384ad6884SPeter Tyser * FIXME: need to revisit this 30484ad6884SPeter Tyser * PUE is ignored if PKE is not set 30584ad6884SPeter Tyser * so the right value here is likely 30684ad6884SPeter Tyser * 0x0 for no pull 30784ad6884SPeter Tyser * or 30884ad6884SPeter Tyser * 0xc0 for 100k pull down 30984ad6884SPeter Tyser */ 31084ad6884SPeter Tyser outpadctl = MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PD; 31184ad6884SPeter Tyser 31284ad6884SPeter Tyser /* FEC_TX_CLK */ 31384ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_tx_clk); 31484ad6884SPeter Tyser writel(inpadctl_100kpd, &padctl->pad_fec_tx_clk); 31584ad6884SPeter Tyser 31684ad6884SPeter Tyser /* FEC_RX_DV */ 31784ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_rx_dv); 31884ad6884SPeter Tyser writel(inpadctl_100kpd, &padctl->pad_fec_rx_dv); 31984ad6884SPeter Tyser 32084ad6884SPeter Tyser /* FEC_RDATA0 */ 32184ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_rdata0); 32284ad6884SPeter Tyser writel(inpadctl_100kpd, &padctl->pad_fec_rdata0); 32384ad6884SPeter Tyser 32484ad6884SPeter Tyser /* FEC_TDATA0 */ 32584ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_tdata0); 32684ad6884SPeter Tyser writel(outpadctl, &padctl->pad_fec_tdata0); 32784ad6884SPeter Tyser 32884ad6884SPeter Tyser /* FEC_TX_EN */ 32984ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_tx_en); 33084ad6884SPeter Tyser writel(outpadctl, &padctl->pad_fec_tx_en); 33184ad6884SPeter Tyser 33284ad6884SPeter Tyser /* FEC_MDC */ 33384ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_mdc); 33484ad6884SPeter Tyser writel(outpadctl, &padctl->pad_fec_mdc); 33584ad6884SPeter Tyser 33684ad6884SPeter Tyser /* FEC_MDIO */ 33784ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_mdio); 33884ad6884SPeter Tyser writel(inpadctl_22kpu, &padctl->pad_fec_mdio); 33984ad6884SPeter Tyser 34084ad6884SPeter Tyser /* FEC_RDATA1 */ 34184ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_rdata1); 34284ad6884SPeter Tyser writel(inpadctl_100kpd, &padctl->pad_fec_rdata1); 34384ad6884SPeter Tyser 34484ad6884SPeter Tyser /* FEC_TDATA1 */ 34584ad6884SPeter Tyser writel(muxmode0, &muxctl->pad_fec_tdata1); 34684ad6884SPeter Tyser writel(outpadctl, &padctl->pad_fec_tdata1); 34784ad6884SPeter Tyser 34884ad6884SPeter Tyser } 349565e39c5SLiu Hui-R64343 350be252b65SFabio Estevam void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 351565e39c5SLiu Hui-R64343 { 352565e39c5SLiu Hui-R64343 int i; 353565e39c5SLiu Hui-R64343 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; 354565e39c5SLiu Hui-R64343 struct fuse_bank *bank = &iim->bank[0]; 355565e39c5SLiu Hui-R64343 struct fuse_bank0_regs *fuse = 356565e39c5SLiu Hui-R64343 (struct fuse_bank0_regs *)bank->fuse_regs; 357565e39c5SLiu Hui-R64343 358565e39c5SLiu Hui-R64343 for (i = 0; i < 6; i++) 359565e39c5SLiu Hui-R64343 mac[i] = readl(&fuse->mac_addr[i]) & 0xff; 360565e39c5SLiu Hui-R64343 } 36184ad6884SPeter Tyser #endif /* CONFIG_FEC_MXC */ 362