]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/armv7/mx5/clock.c
karo: merge with Ka-Ro specific tree for secure boot support
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / mx5 / clock.c
index 7dec2d1a2e46867a008cd2b185ac68431dff329e..443fb997826244080a4dd3d4ce7a1a979ee1e802 100644 (file)
@@ -46,6 +46,8 @@ struct mxc_pll_reg *mxc_plls[PLL_CLOCKS] = {
 #define EMI_DIV_MAX     8
 #define NFC_DIV_MAX     8
 
+#define MXC_IPG_PER_CLK        MXC_IPG_PERCLK
+
 struct fixed_pll_mfd {
        u32 ref_clk_hz;
        u32 mfd;
@@ -64,7 +66,7 @@ struct pll_param {
 
 #define PLL_FREQ_MAX(ref_clk)  (4 * (ref_clk) * PLL_MFI_MAX)
 #define PLL_FREQ_MIN(ref_clk) \
-               ((2 * (ref_clk) * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
+       ((4 * (ref_clk) * PLL_MFI_MIN) / PLL_PD_MAX)
 #define MAX_DDR_CLK     420000000
 #define NFC_CLK_MAX     34000000
 
@@ -172,7 +174,7 @@ void set_usboh3_clk(void)
                        MXC_CCM_CSCDR1_USBOH3_CLK_PODF(1));
 }
 
-void enable_usboh3_clk(unsigned char enable)
+void enable_usboh3_clk(bool enable)
 {
        unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
 
@@ -275,7 +277,7 @@ void ldb_clk_disable(int ldb)
 }
 #endif
 
-#ifdef CONFIG_I2C_MXC
+#ifdef CONFIG_SYS_I2C_MXC
 /* i2c_num can be from 0, to 1 for i.MX51 and 2 for i.MX53 */
 int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
 {
@@ -303,7 +305,7 @@ void set_usb_phy_clk(void)
 }
 
 #if defined(CONFIG_MX51)
-void enable_usb_phy1_clk(unsigned char enable)
+void enable_usb_phy1_clk(bool enable)
 {
        unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
 
@@ -312,12 +314,12 @@ void enable_usb_phy1_clk(unsigned char enable)
                        MXC_CCM_CCGR2_USB_PHY(cg));
 }
 
-void enable_usb_phy2_clk(unsigned char enable)
+void enable_usb_phy2_clk(bool enable)
 {
        /* i.MX51 has a single USB PHY clock, so do nothing here. */
 }
 #elif defined(CONFIG_MX53)
-void enable_usb_phy1_clk(unsigned char enable)
+void enable_usb_phy1_clk(bool enable)
 {
        unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
 
@@ -326,7 +328,7 @@ void enable_usb_phy1_clk(unsigned char enable)
                        MXC_CCM_CCGR4_USB_PHY1(cg));
 }
 
-void enable_usb_phy2_clk(unsigned char enable)
+void enable_usb_phy2_clk(bool enable)
 {
        unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
 
@@ -378,7 +380,6 @@ static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq)
        if (ctrl & MXC_DPLLC_CTL_DPDCK0_2_EN)
                refclk *= 2;
 
-       do_div(refclk, pdf + 1);
        temp = refclk * mfn_abs;
        do_div(temp, mfd + 1);
        ret = refclk * mfi;
@@ -388,6 +389,7 @@ static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq)
        else
                ret += temp;
 
+       ret /= pdf + 1;
        return ret;
 }
 
@@ -626,6 +628,17 @@ static u32 get_emi_slow_clk(void)
        return  get_periph_clk() / (pdf + 1);
 }
 
+static u32 get_nfc_clk(void)
+{
+       u32 parent_rate = get_emi_slow_clk();
+       u32 div = readl(&mxc_ccm->cbcdr);
+
+       div &= MXC_CCM_CBCDR_NFC_PODF_MASK;
+       div >>= MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+       div++;
+       return parent_rate / div;
+}
+
 static u32 get_ddr_clk(void)
 {
        u32 ret_val = 0;
@@ -695,6 +708,14 @@ unsigned int mxc_get_clock(enum mxc_clock clk)
                return get_ahb_clk();
        case MXC_DDR_CLK:
                return get_ddr_clk();
+       case MXC_AXI_A_CLK:
+               return get_axi_a_clk();
+       case MXC_AXI_B_CLK:
+               return get_axi_b_clk();
+       case MXC_EMI_SLOW_CLK:
+               return get_emi_slow_clk();
+       case MXC_NFC_CLK:
+               return get_nfc_clk();
        default:
                break;
        }
@@ -960,6 +981,18 @@ void enable_nfc_clk(unsigned char enable)
                MXC_CCM_CCGR5_EMI_ENFC(cg));
 }
 
+#ifdef CONFIG_FSL_IIM
+void enable_efuse_prog_supply(bool enable)
+{
+       if (enable)
+               setbits_le32(&mxc_ccm->cgpr,
+                            MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE);
+       else
+               clrbits_le32(&mxc_ccm->cgpr,
+                            MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE);
+}
+#endif
+
 /* Config main_bus_clock for periphs */
 static int config_periph_clk(u32 ref, u32 freq)
 {
@@ -1123,7 +1156,7 @@ void mxc_set_sata_internal_clock(void)
        pr_clk_val(c, __clk);                                   \
 }
 
-int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_mx5_showclocks(void)
 {
        unsigned long freq;
 
@@ -1140,19 +1173,91 @@ int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        printf("\n");
        pr_clk(AHB);
+       pr_clk(AXI_A);
+       pr_clk(AXI_B);
        pr_clk(IPG);
-       pr_clk(IPG);
+       pr_clk(IPG_PER);
        pr_clk(DDR);
+       pr_clk(EMI_SLOW);
+       pr_clk(NFC);
 #ifdef CONFIG_MXC_SPI
        pr_clk(CSPI);
 #endif
        return 0;
 }
 
+static struct clk_lookup {
+       const char *name;
+       unsigned int index;
+} mx5_clk_lookup[] = {
+       { "arm", MXC_ARM_CLK, },
+};
+
+int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       int i;
+       unsigned long freq;
+       unsigned long ref = ~0UL;
+
+       if (argc < 2) {
+               do_mx5_showclocks();
+               return CMD_RET_SUCCESS;
+       } else if (argc == 2 || argc > 4) {
+               return CMD_RET_USAGE;
+       }
+
+       freq = simple_strtoul(argv[2], NULL, 0);
+       if (freq == 0) {
+               printf("Invalid clock frequency %lu\n", freq);
+               return CMD_RET_FAILURE;
+       }
+       if (argc > 3) {
+               ref = simple_strtoul(argv[3], NULL, 0);
+       }
+       for (i = 0; i < ARRAY_SIZE(mx5_clk_lookup); i++) {
+               if (strcasecmp(argv[1], mx5_clk_lookup[i].name) == 0) {
+                       switch (mx5_clk_lookup[i].index) {
+                       case MXC_ARM_CLK:
+                               if (argc > 3)
+                                       return CMD_RET_USAGE;
+                               ref = CONFIG_SYS_MX5_HCLK;
+                               break;
+
+                       case MXC_NFC_CLK:
+                               if (argc > 3 && ref > 3) {
+                                       printf("Invalid clock selector value: %lu\n", ref);
+                                       return CMD_RET_FAILURE;
+                               }
+                               break;
+                       }
+                       printf("Setting %s clock to %lu MHz\n",
+                               mx5_clk_lookup[i].name, freq);
+                       if (mxc_set_clock(ref, freq, mx5_clk_lookup[i].index))
+                               break;
+                       freq = mxc_get_clock(mx5_clk_lookup[i].index);
+                       printf("%s clock set to %lu.%03lu MHz\n",
+                               mx5_clk_lookup[i].name,
+                               freq / 1000000, freq / 1000 % 1000);
+                       return CMD_RET_SUCCESS;
+               }
+       }
+       if (i == ARRAY_SIZE(mx5_clk_lookup)) {
+               printf("clock %s not found; supported clocks are:\n", argv[1]);
+               for (i = 0; i < ARRAY_SIZE(mx5_clk_lookup); i++) {
+                       printf("\t%s\n", mx5_clk_lookup[i].name);
+               }
+       } else {
+               printf("Failed to set clock %s to %s MHz\n",
+                       argv[1], argv[2]);
+       }
+       return CMD_RET_FAILURE;
+}
+
 /***************************************************/
 
 U_BOOT_CMD(
-       clocks, CONFIG_SYS_MAXARGS, 1, do_mx5_showclocks,
-       "display clocks",
-       ""
+       clocks, 4, 0, do_clocks,
+       "display/set clocks",
+       "                    - display clock settings\n"
+       "clocks <clkname> <freq>    - set clock <clkname> to <freq> MHz"
 );