]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/arm1136/mx35/generic.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / arm / cpu / arm1136 / mx35 / generic.c
index fcfaba55153770642125e73dd9b23cf721ad985c..ef65176eed2c55c6c479cf7be9f07de61fddf6ca 100644 (file)
  */
 
 #include <common.h>
+#include <div64.h>
 #include <asm/io.h>
 #include <asm/errno.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
 #include <netdev.h>
 
 #define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel))
@@ -126,15 +130,17 @@ static int get_ahb_div(u32 pdr0)
 static u32 decode_pll(u32 reg, u32 infreq)
 {
        u32 mfi = (reg >> 10) & 0xf;
-       u32 mfn = reg & 0x3f;
-       u32 mfd = (reg >> 16) & 0x3f;
+       s32 mfn = reg & 0x3ff;
+       u32 mfd = (reg >> 16) & 0x3ff;
        u32 pd = (reg >> 26) & 0xf;
 
        mfi = mfi <= 5 ? 5 : mfi;
+       mfn = mfn >= 512 ? mfn - 1024 : mfn;
        mfd += 1;
        pd += 1;
 
-       return ((2 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000;
+       return lldiv(2 * (u64)infreq * (mfi * mfd + mfn),
+               mfd * pd);
 }
 
 static u32 get_mcu_main_clk(void)
@@ -143,9 +149,7 @@ static u32 get_mcu_main_clk(void)
        struct ccm_regs *ccm =
                (struct ccm_regs *)IMX_CCM_BASE;
        arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd);
-       fi *=
-               decode_pll(readl(&ccm->mpctl),
-                       CONFIG_MX35_HCLK_FREQ);
+       fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK);
        return fi / (arm_div * fd);
 }
 
@@ -168,17 +172,14 @@ static u32 get_ipg_per_clk(void)
        u32 pdr4 = readl(&ccm->pdr4);
        u32 div;
        if (pdr0 & MXC_CCM_PDR0_PER_SEL) {
-               div = (CCM_GET_DIVIDER(pdr4,
-                       MXC_CCM_PDR4_PER0_PRDF_MASK,
-                       MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1) *
-                       (CCM_GET_DIVIDER(pdr4,
+               div = CCM_GET_DIVIDER(pdr4,
                        MXC_CCM_PDR4_PER0_PODF_MASK,
-                       MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1);
+                       MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1;
        } else {
                div = CCM_GET_DIVIDER(pdr0,
                        MXC_CCM_PDR0_PER_PODF_MASK,
                        MXC_CCM_PDR0_PER_PODF_OFFSET) + 1;
-               freq /= get_ahb_div(pdr0);
+               div *= get_ahb_div(pdr0);
        }
        return freq / div;
 }
@@ -190,25 +191,20 @@ u32 imx_get_uartclk(void)
                (struct ccm_regs *)IMX_CCM_BASE;
        u32 pdr4 = readl(&ccm->pdr4);
 
-       if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) {
+       if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U)
                freq = get_mcu_main_clk();
-       } else {
-               freq = decode_pll(readl(&ccm->ppctl),
-                       CONFIG_MX35_HCLK_FREQ);
-       }
-       freq /= ((CCM_GET_DIVIDER(pdr4,
-                       MXC_CCM_PDR4_UART_PRDF_MASK,
-                       MXC_CCM_PDR4_UART_PRDF_OFFSET) + 1) *
-               (CCM_GET_DIVIDER(pdr4,
+       else
+               freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK);
+       freq /= CCM_GET_DIVIDER(pdr4,
                        MXC_CCM_PDR4_UART_PODF_MASK,
-                       MXC_CCM_PDR4_UART_PODF_OFFSET) + 1));
+                       MXC_CCM_PDR4_UART_PODF_OFFSET) + 1;
        return freq;
 }
 
-unsigned int mxc_get_main_clock(enum mxc_main_clocks clk)
+unsigned int mxc_get_main_clock(enum mxc_main_clock clk)
 {
        u32 nfc_pdf, hsp_podf;
-       u32 pll, ret_val = 0, usb_prdf, usb_podf;
+       u32 pll, ret_val = 0, usb_podf;
        struct ccm_regs *ccm =
                (struct ccm_regs *)IMX_CCM_BASE;
 
@@ -240,7 +236,7 @@ unsigned int mxc_get_main_clock(enum mxc_main_clocks clk)
                }
                break;
        case IPG_CLK:
-               ret_val = get_ipg_clk();;
+               ret_val = get_ipg_clk();
                break;
        case IPG_PER_CLK:
                ret_val = get_ipg_per_clk();
@@ -252,16 +248,13 @@ unsigned int mxc_get_main_clock(enum mxc_main_clocks clk)
                ret_val = pll / (nfc_pdf + 1);
                break;
        case USB_CLK:
-               usb_prdf = (reg4 >> 25) & 0x7;
-               usb_podf = (reg4 >> 22) & 0x7;
-               if (reg4 & 0x200) {
+               usb_podf = (reg4 >> 22) & 0x3F;
+               if (reg4 & 0x200)
                        pll = get_mcu_main_clk();
-               } else {
-                       pll = decode_pll(readl(&ccm->ppctl),
-                               CONFIG_MX35_HCLK_FREQ);
-               }
+               else
+                       pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK);
 
-               ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
+               ret_val = pll / (usb_podf + 1);
                break;
        default:
                printf("Unknown clock: %d\n", clk);
@@ -270,7 +263,7 @@ unsigned int mxc_get_main_clock(enum mxc_main_clocks clk)
 
        return ret_val;
 }
-unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk)
+unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk)
 {
        u32 ret_val = 0, pdf, pre_pdf, clk_sel;
        struct ccm_regs *ccm =
@@ -284,18 +277,16 @@ unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk)
        case UART2_BAUD:
        case UART3_BAUD:
                clk_sel = mpdr3 & (1 << 14);
-               pre_pdf = (mpdr4 >> 13) & 0x7;
-               pdf = (mpdr4 >> 10) & 0x7;
+               pdf = (mpdr4 >> 10) & 0x3F;
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
-                               ((pre_pdf + 1) * (pdf + 1));
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
                break;
        case SSI1_BAUD:
                pre_pdf = (mpdr2 >> 24) & 0x7;
                pdf = mpdr2 & 0x3F;
                clk_sel = mpdr2 & (1 << 6);
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
                                ((pre_pdf + 1) * (pdf + 1));
                break;
        case SSI2_BAUD:
@@ -303,16 +294,14 @@ unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk)
                pdf = (mpdr2 >> 8) & 0x3F;
                clk_sel = mpdr2 & (1 << 6);
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
                                ((pre_pdf + 1) * (pdf + 1));
                break;
        case CSI_BAUD:
                clk_sel = mpdr2 & (1 << 7);
-               pre_pdf = (mpdr2 >> 16) & 0x7;
-               pdf = (mpdr2 >> 19) & 0x7;
+               pdf = (mpdr2 >> 16) & 0x3F;
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
-                               ((pre_pdf + 1) * (pdf + 1));
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
                break;
        case MSHC_CLK:
                pre_pdf = readl(&ccm->pdr1);
@@ -320,39 +309,33 @@ unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk)
                pdf = (pre_pdf >> 22) & 0x3F;
                pre_pdf = (pre_pdf >> 28) & 0x7;
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
                                ((pre_pdf + 1) * (pdf + 1));
                break;
        case ESDHC1_CLK:
                clk_sel = mpdr3 & 0x40;
-               pre_pdf = mpdr3 & 0x7;
-               pdf = (mpdr3>>3) & 0x7;
+               pdf = mpdr3 & 0x3F;
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
-                               ((pre_pdf + 1) * (pdf + 1));
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
                break;
        case ESDHC2_CLK:
                clk_sel = mpdr3 & 0x40;
-               pre_pdf = (mpdr3 >> 8) & 0x7;
-               pdf = (mpdr3 >> 11) & 0x7;
+               pdf = (mpdr3 >> 8) & 0x3F;
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
-                               ((pre_pdf + 1) * (pdf + 1));
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
                break;
        case ESDHC3_CLK:
                clk_sel = mpdr3 & 0x40;
-               pre_pdf = (mpdr3 >> 16) & 0x7;
-               pdf = (mpdr3 >> 19) & 0x7;
+               pdf = (mpdr3 >> 16) & 0x3F;
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
-                               ((pre_pdf + 1) * (pdf + 1));
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
                break;
        case SPDIF_CLK:
                clk_sel = mpdr3 & 0x400000;
                pre_pdf = (mpdr3 >> 29) & 0x7;
                pdf = (mpdr3 >> 23) & 0x3F;
                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
-                       decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
+                       decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
                                ((pre_pdf + 1) * (pdf + 1));
                break;
        default:
@@ -393,7 +376,7 @@ unsigned int mxc_get_clock(enum mxc_clock clk)
 /*
  * The MX35 has no fuse for MAC, return a NULL MAC
  */
-void imx_get_mac_from_fuse(unsigned char *mac)
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 {
        memset(mac, 0, 6);
 }
@@ -423,11 +406,38 @@ U_BOOT_CMD(
 );
 
 #if defined(CONFIG_DISPLAY_CPUINFO)
+static char *get_reset_cause(void)
+{
+       /* read RCSR register from CCM module */
+       struct ccm_regs *ccm =
+               (struct ccm_regs *)IMX_CCM_BASE;
+
+       u32 cause = readl(&ccm->rcsr) & 0x0F;
+
+       switch (cause) {
+       case 0x0000:
+               return "POR";
+       case 0x0002:
+               return "JTAG";
+       case 0x0004:
+               return "RST";
+       case 0x0008:
+               return "WDOG";
+       default:
+               return "unknown reset";
+       }
+}
+
 int print_cpuinfo(void)
 {
-       printf("CPU:   Freescale i.MX35 at %d MHz\n",
+       u32 srev = get_cpu_rev();
+
+       printf("CPU:   Freescale i.MX35 rev %d.%d at %d MHz.\n",
+               (srev & 0xF0) >> 4, (srev & 0x0F),
                get_mcu_main_clk() / 1000000);
-       /* mxc_dump_clocks(); */
+
+       printf("Reset cause: %s\n", get_reset_cause());
+
        return 0;
 }
 #endif
@@ -436,7 +446,6 @@ int print_cpuinfo(void)
  * Initializes on-chip ethernet controllers.
  * to override, implement board_eth_init()
  */
-
 int cpu_eth_init(bd_t *bis)
 {
        int rc = -ENODEV;
@@ -448,6 +457,17 @@ int cpu_eth_init(bd_t *bis)
        return rc;
 }
 
+#ifdef CONFIG_FSL_ESDHC
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+       return fsl_esdhc_mmc_init(bis);
+}
+#endif
+
 int get_clocks(void)
 {
 #ifdef CONFIG_FSL_ESDHC