summaryrefslogtreecommitdiff
path: root/cpu/arm1136/mx35
diff options
context:
space:
mode:
authorTerry Lv <r65388@freescale.com>2009-10-29 19:19:00 +0800
committerTerry Lv <r65388@freescale.com>2009-11-03 18:22:03 +0800
commitba816f983f5dac44d9f4461906b9bc0101237ac8 (patch)
tree52d3b83aa1cc146b88933f75b0a65c2dc813ea28 /cpu/arm1136/mx35
parent3227c278048e6b13397d9d0793e77e703649d7de (diff)
downloadu-boot-imx-ba816f983f5dac44d9f4461906b9bc0101237ac8.zip
u-boot-imx-ba816f983f5dac44d9f4461906b9bc0101237ac8.tar.gz
u-boot-imx-ba816f983f5dac44d9f4461906b9bc0101237ac8.tar.bz2
u-boot v2009.08 sd/mmc support.
Signed-off-by: Terry Lv <r65388@freescale.com>
Diffstat (limited to 'cpu/arm1136/mx35')
-rw-r--r--cpu/arm1136/mx35/Makefile2
-rw-r--r--cpu/arm1136/mx35/generic.c159
-rw-r--r--cpu/arm1136/mx35/timer.c (renamed from cpu/arm1136/mx35/interrupts.c)22
3 files changed, 175 insertions, 8 deletions
diff --git a/cpu/arm1136/mx35/Makefile b/cpu/arm1136/mx35/Makefile
index afcf771..996360f 100644
--- a/cpu/arm1136/mx35/Makefile
+++ b/cpu/arm1136/mx35/Makefile
@@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
-COBJS = interrupts.o serial.o generic.o iomux.o
+COBJS = timer.o serial.o generic.o iomux.o
SOBJS = mxc_nand_load.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
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;
}
diff --git a/cpu/arm1136/mx35/interrupts.c b/cpu/arm1136/mx35/timer.c
index 40b9d4c..d6f65cf 100644
--- a/cpu/arm1136/mx35/interrupts.c
+++ b/cpu/arm1136/mx35/timer.c
@@ -38,18 +38,28 @@
#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */
#define GPTCR_TEN (1) /* Timer enable */
-/* nothing really to do with interrupts, just starts up a counter. */
-int interrupt_init(void)
+static inline void setup_gpt()
{
int i;
+ static int init_done;
+
+ if (init_done)
+ return;
+
+ init_done = 1;
/* setup GP Timer 1 */
GPTCR = GPTCR_SWR;
for (i = 0; i < 100; i++)
- GPTCR = 0; /* We have no udelay by now */
- GPTPR = 0; /* 32Khz */
+ GPTCR = 0; /* We have no udelay by now */
+ GPTPR = 0; /* 32Khz */
/* Freerun Mode, PERCLK1 input */
GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN;
+}
+
+int timer_init(void)
+{
+ setup_gpt();
return 0;
}
@@ -86,7 +96,9 @@ void udelay(unsigned long usec)
{
ulong tmo, tmp;
- /* if "big" number, spread normalization to seconds */
+ setup_gpt();
+
+ /* if "big" number, spread normalization to seconds */
if (usec >= 1000) {
/* start to normalize for usec to ticks per sec */
tmo = usec / 1000;