summaryrefslogtreecommitdiff
path: root/cpu/arm1136/mx35/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/arm1136/mx35/generic.c')
-rw-r--r--cpu/arm1136/mx35/generic.c159
1 files changed, 157 insertions, 2 deletions
diff --git a/cpu/arm1136/mx35/generic.c b/cpu/arm1136/mx35/generic.c
index b70c3ea..31bcbec 100644
--- a/cpu/arm1136/mx35/generic.c
+++ b/cpu/arm1136/mx35/generic.c
@@ -24,6 +24,7 @@
*/
#include <common.h>
+#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/mx35.h>
#include "crm_regs.h"
@@ -47,6 +48,12 @@ static int g_clk_mux_consumer[16] = {
-1, -1, CLK_CODE(4, 2, 0), -1,
};
+static int hsp_div_table[3][16] = {
+ {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1},
+ {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1},
+ {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1},
+};
+
static u32 __get_arm_div(u32 pdr0, u32 *fi, u32 *fd)
{
int *pclk_mux;
@@ -117,7 +124,7 @@ static u32 __get_mcu_main_clk(void)
u32 arm_div, fi, fd;
arm_div = __get_arm_div(__REG(CCM_BASE_ADDR + CLKCTL_PDR0), &fi, &fd);
fi *=
- __decode_pll(__REG(CCM_BASE_ADDR + CLKCTL_MPCTL),
+ __decode_pll(__REG(MCU_PLL),
CONFIG_MX35_HCLK_FREQ);
return fi / (arm_div * fd);
}
@@ -160,7 +167,7 @@ static u32 __get_uart_clk(void)
if (__REG(CCM_BASE_ADDR + CLKCTL_PDR3) & MXC_CCM_PDR3_UART_M_U)
freq = __get_mcu_main_clk();
else
- freq = __decode_pll(__REG(CCM_BASE_ADDR + CLKCTL_PPCTL),
+ freq = __decode_pll(__REG(PER_PLL),
CONFIG_MX35_HCLK_FREQ);
freq /= ((CCM_GET_DIVIDER(pdr4,
MXC_CCM_PDR4_UART_PRDF_MASK,
@@ -171,6 +178,150 @@ static u32 __get_uart_clk(void)
return freq;
}
+unsigned int mxc_get_main_clock(enum mxc_main_clocks clk)
+{
+ u32 nfc_pdf, hsp_podf;
+ u32 pll, ret_val = 0, usb_prdf, usb_podf;
+
+ u32 reg = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
+ u32 reg4 = readl(CCM_BASE_ADDR + CLKCTL_PDR4);
+
+ reg |= 0x1;
+
+ switch (clk) {
+ case CPU_CLK:
+ ret_val = __get_mcu_main_clk();
+ break;
+ case AHB_CLK:
+ ret_val = __get_mcu_main_clk();
+ break;
+ case HSP_CLK:
+ if (reg & CLKMODE_CONSUMER) {
+ hsp_podf = (reg >> 20) & 0x3;
+ pll = __get_mcu_main_clk();
+ hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF];
+ if(hsp_podf > 0 ) {
+ ret_val = pll / hsp_podf;
+ } else {
+ puts("mismatch HSP with ARM clock setting\n");
+ ret_val = 0;
+ }
+ } else {
+ ret_val = __get_mcu_main_clk();
+ }
+ break;
+ case IPG_CLK:
+ ret_val = __get_ipg_clk();;
+ break;
+ case IPG_PER_CLK:
+ ret_val = __get_ipg_per_clk();
+ break;
+ case NFC_CLK:
+ nfc_pdf = (reg4 >> 28) & 0xF;
+ pll = __get_mcu_main_clk();
+ /* AHB/nfc_pdf */
+ ret_val = pll / (nfc_pdf + 1);
+ break;
+ case USB_CLK:
+ usb_prdf = (reg4 >> 25) & 0x7;
+ usb_podf = (reg4 >> 22) & 0x7;
+ if (reg4 & 0x200)
+ pll = __get_mcu_main_clk();
+ else
+ pll = __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ);
+
+ ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
+ break;
+ default:
+ printf("Unknown clock: %d\n", clk);
+ break;
+ }
+
+ return ret_val;
+}
+unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk)
+{
+ u32 ret_val = 0, pdf, pre_pdf, clk_sel;
+ u32 mpdr2 = readl(CCM_BASE_ADDR + CLKCTL_PDR2);
+ u32 mpdr3 = readl(CCM_BASE_ADDR + CLKCTL_PDR3);
+ u32 mpdr4 = readl(CCM_BASE_ADDR + CLKCTL_PDR4);
+
+ switch (clk) {
+ case UART1_BAUD:
+ case UART2_BAUD:
+ case UART3_BAUD:
+ clk_sel = mpdr3 & (1 << 14);
+ pre_pdf = (mpdr4 >> 13) & 0x7;
+ pdf = (mpdr4 >> 10) & 0x7;
+ ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+ __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (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(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1));
+ break;
+ case SSI2_BAUD:
+ pre_pdf = (mpdr2 >> 27) & 0x7;
+ pdf = (mpdr2 >> 8)& 0x3F;
+ clk_sel = mpdr2 & ( 1 << 6);
+ ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+ __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1));
+ break;
+ case CSI_BAUD:
+ clk_sel = mpdr2 & (1 << 7);
+ pre_pdf = (mpdr2 >> 16) & 0x7;
+ pdf = (mpdr2 >> 19) & 0x7;
+ ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+ __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1));
+ break;
+ case MSHC_CLK:
+ pre_pdf = readl(CCM_BASE_ADDR + CLKCTL_PDR1);
+ clk_sel = (pre_pdf & 0x80);
+ pdf = (pre_pdf >> 22) & 0x3F;
+ pre_pdf = (pre_pdf >> 28) & 0x7;
+ ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) :
+ __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1));
+ break;
+ case ESDHC1_CLK:
+ clk_sel = mpdr3 & 0x40;
+ pre_pdf = mpdr3&0x7;
+ pdf = (mpdr3>>3)&0x7;
+ ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) :
+ __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1));
+ break;
+ case ESDHC2_CLK:
+ clk_sel = mpdr3 & 0x40;
+ pre_pdf = (mpdr3 >> 8)&0x7;
+ pdf = (mpdr3 >> 11)&0x7;
+ ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) :
+ __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1));
+ break;
+ case ESDHC3_CLK:
+ clk_sel = mpdr3 & 0x40;
+ pre_pdf = (mpdr3 >> 16)&0x7;
+ pdf = (mpdr3 >> 19)&0x7;
+ ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) :
+ __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (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(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1));
+ break;
+ default:
+ printf("%s(): This clock: %d not supported yet \n",
+ __FUNCTION__, clk);
+ break;
+ }
+
+ return ret_val;
+}
+
unsigned int mxc_get_clock(enum mxc_clock clk)
{
switch (clk) {
@@ -184,6 +335,10 @@ unsigned int mxc_get_clock(enum mxc_clock clk)
return __get_ipg_per_clk();
case MXC_UART_CLK:
return __get_uart_clk();
+ case MXC_ESDHC_CLK:
+ return mxc_get_peri_clock(ESDHC1_CLK);
+ case MXC_USB_CLK:
+ return mxc_get_main_clock(USB_CLK);
}
return -1;
}