ColdFire: Add MCF5441x CPU support

Add MCF5441x CPU support.

The MCF5441x devices are a family of highly-integrated 32-bit
microprocessors based on the Version 4m ColdFire microarchitecture,
comprising of the V4 integer core, memory management unit(MMU) and
enchanced multiply-accumulate unit(EMAC).

Signed-off-by: TsiChung Liew <tsicliew@gmail.com>
Signed-off-by: Jason Jin <Jason.jin@freescale.com>
Signed-off-by: Alison Wang <b18965@freescale.com>
diff --git a/arch/m68k/cpu/mcf5445x/config.mk b/arch/m68k/cpu/mcf5445x/config.mk
index 61a731e..0c48783 100644
--- a/arch/m68k/cpu/mcf5445x/config.mk
+++ b/arch/m68k/cpu/mcf5445x/config.mk
@@ -4,6 +4,8 @@
 # (C) Copyright 2000-2004
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
+# Copyright 2011-2012 Freescale Semiconductor, Inc.
+#
 # See file CREDITS for list of people who contributed to this
 # project.
 #
@@ -24,7 +26,15 @@
 #
 
 PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
+
+cfg=$(shell grep configs $(OBJTREE)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
+is5441x:=$(shell grep CONFIG_MCF5441x $(TOPDIR)/include/$(cfg))
+
+ifneq (,$(findstring CONFIG_MCF5441x,$(is5441x)))
+PLATFORM_CPPFLAGS += -mcpu=54418 -fPIC
+else
 PLATFORM_CPPFLAGS += -mcpu=54455 -fPIC
+endif
 
 ifneq (,$(findstring -linux-,$(shell $(CC) --version)))
 ifneq (,$(findstring GOT,$(shell $(LD) --help)))
diff --git a/arch/m68k/cpu/mcf5445x/cpu.c b/arch/m68k/cpu/mcf5445x/cpu.c
index adfc708..b612cda 100644
--- a/arch/m68k/cpu/mcf5445x/cpu.c
+++ b/arch/m68k/cpu/mcf5445x/cpu.c
@@ -39,6 +39,8 @@
 {
 	rcm_t *rcm = (rcm_t *) (MMAP_RCM);
 	udelay(1000);
+	out_8(&rcm->rcr, RCM_RCR_FRCRSTOUT);
+	udelay(10000);
 	setbits_8(&rcm->rcr, RCM_RCR_SOFTRST);
 
 	/* we don't return! */
@@ -74,6 +76,21 @@
 	case 0x4f:
 		id = 54450;
 		break;
+	case 0x9F:
+		id = 54410;
+		break;
+	case 0xA0:
+		id = 54415;
+		break;
+	case 0xA1:
+		id = 54416;
+		break;
+	case 0xA2:
+		id = 54417;
+		break;
+	case 0xA3:
+		id = 54418;
+		break;
 	}
 
 	if (id) {
diff --git a/arch/m68k/cpu/mcf5445x/cpu_init.c b/arch/m68k/cpu/mcf5445x/cpu_init.c
index b6ceac3..6e947d0 100644
--- a/arch/m68k/cpu/mcf5445x/cpu_init.c
+++ b/arch/m68k/cpu/mcf5445x/cpu_init.c
@@ -39,37 +39,11 @@
 #include <asm/fec.h>
 #endif
 
-/*
- * Breath some life into the CPU...
- *
- * Set up the memory map,
- * initialize a bunch of registers,
- * initialize the UPM's
- */
-void cpu_init_f(void)
+void init_fbcs(void)
 {
-	scm1_t *scm1 = (scm1_t *) MMAP_SCM1;
-	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
 	fbcs_t *fbcs __maybe_unused = (fbcs_t *) MMAP_FBCS;
 
-	out_be32(&scm1->mpr, 0x77777777);
-	out_be32(&scm1->pacra, 0);
-	out_be32(&scm1->pacrb, 0);
-	out_be32(&scm1->pacrc, 0);
-	out_be32(&scm1->pacrd, 0);
-	out_be32(&scm1->pacre, 0);
-	out_be32(&scm1->pacrf, 0);
-	out_be32(&scm1->pacrg, 0);
-
-	/* FlexBus */
-	out_8(&gpio->par_be,
-		GPIO_PAR_BE_BE3_BE3 | GPIO_PAR_BE_BE2_BE2 |
-		GPIO_PAR_BE_BE1_BE1 | GPIO_PAR_BE_BE0_BE0);
-	out_8(&gpio->par_fbctl,
-		GPIO_PAR_FBCTL_OE | GPIO_PAR_FBCTL_TA_TA |
-		GPIO_PAR_FBCTL_RW_RW | GPIO_PAR_FBCTL_TS_TS);
-
-#if !defined(CONFIG_CF_SBF)
+#if !defined(CONFIG_SERIAL_BOOT)
 #if (defined(CONFIG_SYS_CS0_BASE) && defined(CONFIG_SYS_CS0_MASK) && defined(CONFIG_SYS_CS0_CTRL))
 	out_be32(&fbcs->csar0, CONFIG_SYS_CS0_BASE);
 	out_be32(&fbcs->cscr0, CONFIG_SYS_CS0_CTRL);
@@ -107,6 +81,145 @@
 	out_be32(&fbcs->cscr5, CONFIG_SYS_CS5_CTRL);
 	out_be32(&fbcs->csmr5, CONFIG_SYS_CS5_MASK);
 #endif
+}
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f(void)
+{
+	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
+
+#ifdef CONFIG_MCF5441x
+	scm_t *scm = (scm_t *) MMAP_SCM;
+	pm_t *pm = (pm_t *) MMAP_PM;
+
+	/* Disable Switch */
+	*(unsigned long *)(MMAP_L2_SW0 + 0x00000024) = 0;
+
+	/* Disable core watchdog */
+	out_be16(&scm->cwcr, 0);
+	out_8(&gpio->par_fbctl,
+		GPIO_PAR_FBCTL_ALE_FB_ALE | GPIO_PAR_FBCTL_OE_FB_OE |
+		GPIO_PAR_FBCTL_FBCLK | GPIO_PAR_FBCTL_RW |
+		GPIO_PAR_FBCTL_TA_TA);
+	out_8(&gpio->par_be,
+		GPIO_PAR_BE_BE3_BE3 | GPIO_PAR_BE_BE2_BE2 |
+		GPIO_PAR_BE_BE1_BE1 | GPIO_PAR_BE_BE0_BE0);
+
+	/* eDMA */
+	out_8(&pm->pmcr0, 17);
+
+	/* INTR0 - INTR2 */
+	out_8(&pm->pmcr0, 18);
+	out_8(&pm->pmcr0, 19);
+	out_8(&pm->pmcr0, 20);
+
+	/* I2C */
+	out_8(&pm->pmcr0, 22);
+	out_8(&pm->pmcr1, 4);
+	out_8(&pm->pmcr1, 7);
+
+	/* DTMR0 - DTMR3*/
+	out_8(&pm->pmcr0, 28);
+	out_8(&pm->pmcr0, 29);
+	out_8(&pm->pmcr0, 30);
+	out_8(&pm->pmcr0, 31);
+
+	/* PIT0 - PIT3 */
+	out_8(&pm->pmcr0, 32);
+	out_8(&pm->pmcr0, 33);
+	out_8(&pm->pmcr0, 34);
+	out_8(&pm->pmcr0, 35);
+
+	/* Edge Port */
+	out_8(&pm->pmcr0, 36);
+	out_8(&pm->pmcr0, 37);
+
+	/* USB OTG */
+	out_8(&pm->pmcr0, 44);
+	/* USB Host */
+	out_8(&pm->pmcr0, 45);
+
+	/* ESDHC */
+	out_8(&pm->pmcr0, 51);
+
+	/* ENET0 - ENET1 */
+	out_8(&pm->pmcr0, 53);
+	out_8(&pm->pmcr0, 54);
+
+	/* NAND */
+	out_8(&pm->pmcr0, 63);
+
+#ifdef CONFIG_SYS_I2C_0
+	out_8(&gpio->par_cani2c, 0xF0);
+	/* I2C0 pull up */
+	out_be16(&gpio->pcr_b, 0x003C);
+	/* I2C0 max speed */
+	out_8(&gpio->srcr_cani2c, 0x03);
+#endif
+#ifdef CONFIG_SYS_I2C_2
+	/* I2C2 */
+	out_8(&gpio->par_ssi0h, 0xA0);
+	/* I2C2, UART7 */
+	out_8(&gpio->par_ssi0h, 0xA8);
+	/* UART7 */
+	out_8(&gpio->par_ssi0l, 0x2);
+	/* UART8, UART9 */
+	out_8(&gpio->par_cani2c, 0xAA);
+	/* UART4, UART0 */
+	out_8(&gpio->par_uart0, 0xAF);
+	/* UART5, UART1 */
+	out_8(&gpio->par_uart1, 0xAF);
+	/* UART6, UART2 */
+	out_8(&gpio->par_uart2, 0xAF);
+	/* I2C2 pull up */
+	out_be16(&gpio->pcr_h, 0xF000);
+#endif
+#ifdef CONFIG_SYS_I2C_5
+	/* I2C5 */
+	out_8(&gpio->par_uart1, 0x0A);
+	/* I2C5 pull up */
+	out_be16(&gpio->pcr_e, 0x0003);
+	out_be16(&gpio->pcr_f, 0xC000);
+#endif
+
+	/* Lowest slew rate for UART0,1,2 */
+	out_8(&gpio->srcr_uart, 0x00);
+#endif		/* CONFIG_MCF5441x */
+
+#ifdef CONFIG_MCF5445x
+	scm1_t *scm1 = (scm1_t *) MMAP_SCM1;
+
+	out_be32(&scm1->mpr, 0x77777777);
+	out_be32(&scm1->pacra, 0);
+	out_be32(&scm1->pacrb, 0);
+	out_be32(&scm1->pacrc, 0);
+	out_be32(&scm1->pacrd, 0);
+	out_be32(&scm1->pacre, 0);
+	out_be32(&scm1->pacrf, 0);
+	out_be32(&scm1->pacrg, 0);
+
+	/* FlexBus */
+	out_8(&gpio->par_be,
+		GPIO_PAR_BE_BE3_BE3 | GPIO_PAR_BE_BE2_BE2 |
+		GPIO_PAR_BE_BE1_BE1 | GPIO_PAR_BE_BE0_BE0);
+	out_8(&gpio->par_fbctl,
+		GPIO_PAR_FBCTL_OE | GPIO_PAR_FBCTL_TA_TA |
+		GPIO_PAR_FBCTL_RW_RW | GPIO_PAR_FBCTL_TS_TS);
+
+#ifdef CONFIG_FSL_I2C
+	out_be16(&gpio->par_feci2c,
+		GPIO_PAR_FECI2C_SCL_SCL | GPIO_PAR_FECI2C_SDA_SDA);
+#endif
+#endif		/* CONFIG_MCF5445x */
+
+	/* FlexBus Chipselect */
+	init_fbcs();
 
 	/*
 	 * now the flash base address is no longer at 0 (Newer ColdFire family
@@ -116,11 +229,6 @@
 	if (CONFIG_SYS_CS0_BASE != 0)
 		setvbr(CONFIG_SYS_CS0_BASE);
 
-#ifdef CONFIG_FSL_I2C
-	out_be16(&gpio->par_feci2c,
-		GPIO_PAR_FECI2C_SCL_SCL | GPIO_PAR_FECI2C_SDA_SDA);
-#endif
-
 	icache_enable();
 }
 
@@ -143,9 +251,95 @@
 void uart_port_conf(int port)
 {
 	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
+#ifdef CONFIG_MCF5441x
+	pm_t *pm = (pm_t *) MMAP_PM;
+#endif
 
 	/* Setup Ports: */
 	switch (port) {
+#ifdef CONFIG_MCF5441x
+	case 0:
+		/* UART0 */
+		out_8(&pm->pmcr0, 24);
+		clrbits_8(&gpio->par_uart0,
+			~(GPIO_PAR_UART0_U0RXD_MASK | GPIO_PAR_UART0_U0TXD_MASK));
+		setbits_8(&gpio->par_uart0,
+			GPIO_PAR_UART0_U0RXD_U0RXD | GPIO_PAR_UART0_U0TXD_U0TXD);
+		break;
+	case 1:
+		/* UART1 */
+		out_8(&pm->pmcr0, 25);
+		clrbits_8(&gpio->par_uart1,
+			~(GPIO_PAR_UART1_U1RXD_MASK | GPIO_PAR_UART1_U1TXD_MASK));
+		setbits_8(&gpio->par_uart1,
+			GPIO_PAR_UART1_U1RXD_U1RXD | GPIO_PAR_UART1_U1TXD_U1TXD);
+		break;
+	case 2:
+		/* UART2 */
+		out_8(&pm->pmcr0, 26);
+		clrbits_8(&gpio->par_uart2,
+			~(GPIO_PAR_UART2_U2RXD_MASK | GPIO_PAR_UART2_U2TXD_MASK));
+		setbits_8(&gpio->par_uart2,
+			GPIO_PAR_UART2_U2RXD_U2RXD | GPIO_PAR_UART2_U2TXD_U2TXD);
+		break;
+	case 3:
+		/* UART3 */
+		out_8(&pm->pmcr0, 27);
+		clrbits_8(&gpio->par_dspi0,
+			~(GPIO_PAR_DSPI0_SIN_MASK | GPIO_PAR_DSPI0_SOUT_MASK));
+		setbits_8(&gpio->par_dspi0,
+			GPIO_PAR_DSPI0_SIN_U3RXD | GPIO_PAR_DSPI0_SOUT_U3TXD);
+		break;
+	case 4:
+		/* UART4 */
+		out_8(&pm->pmcr1, 24);
+		clrbits_8(&gpio->par_uart0,
+			~(GPIO_PAR_UART0_U0CTS_MASK | GPIO_PAR_UART0_U0RTS_MASK));
+		setbits_8(&gpio->par_uart0,
+			GPIO_PAR_UART0_U0CTS_U4TXD | GPIO_PAR_UART0_U0RTS_U4RXD);
+		break;
+	case 5:
+		/* UART5 */
+		out_8(&pm->pmcr1, 25);
+		clrbits_8(&gpio->par_uart1,
+			~(GPIO_PAR_UART1_U1CTS_MASK | GPIO_PAR_UART1_U1RTS_MASK));
+		setbits_8(&gpio->par_uart1,
+			GPIO_PAR_UART1_U1CTS_U5TXD | GPIO_PAR_UART1_U1RTS_U5RXD);
+		break;
+	case 6:
+		/* UART6 */
+		out_8(&pm->pmcr1, 26);
+		clrbits_8(&gpio->par_uart2,
+			~(GPIO_PAR_UART2_U2CTS_MASK | GPIO_PAR_UART2_U2RTS_MASK));
+		setbits_8(&gpio->par_uart2,
+			GPIO_PAR_UART2_U2CTS_U6TXD | GPIO_PAR_UART2_U2RTS_U6RXD);
+		break;
+	case 7:
+		/* UART7 */
+		out_8(&pm->pmcr1, 27);
+		clrbits_8(&gpio->par_ssi0h, ~GPIO_PAR_SSI0H_RXD_MASK);
+		clrbits_8(&gpio->par_ssi0l, ~GPIO_PAR_SSI0L_BCLK_MASK);
+		setbits_8(&gpio->par_ssi0h, GPIO_PAR_SSI0H_FS_U7TXD);
+		setbits_8(&gpio->par_ssi0l, GPIO_PAR_SSI0L_BCLK_U7RXD);
+		break;
+	case 8:
+		/* UART8 */
+		out_8(&pm->pmcr0, 28);
+		clrbits_8(&gpio->par_cani2c,
+			~(GPIO_PAR_CANI2C_I2C0SCL_MASK | GPIO_PAR_CANI2C_I2C0SDA_MASK));
+		setbits_8(&gpio->par_cani2c,
+			GPIO_PAR_CANI2C_I2C0SCL_U8TXD | GPIO_PAR_CANI2C_I2C0SDA_U8RXD);
+		break;
+	case 9:
+		/* UART9 */
+		out_8(&pm->pmcr1, 29);
+		clrbits_8(&gpio->par_cani2c,
+			~(GPIO_PAR_CANI2C_CAN1TX_MASK | GPIO_PAR_CANI2C_CAN1RX_MASK));
+		setbits_8(&gpio->par_cani2c,
+			GPIO_PAR_CANI2C_CAN1TX_U9TXD | GPIO_PAR_CANI2C_CAN1RX_U9RXD);
+		break;
+#endif
+#ifdef CONFIG_MCF5445x
 	case 0:
 		clrbits_8(&gpio->par_uart,
 			GPIO_PAR_UART_U0TXD_U0TXD | GPIO_PAR_UART_U0RXD_U0RXD);
@@ -178,6 +372,7 @@
 			GPIO_PAR_FECI2C_SCL_U2TXD | GPIO_PAR_FECI2C_SDA_U2RXD);
 #endif
 		break;
+#endif	/* CONFIG_MCF5445x */
 	}
 }
 
@@ -187,6 +382,7 @@
 	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
 	struct fec_info_s *info = (struct fec_info_s *)dev->priv;
 
+#ifdef CONFIG_MCF5445x
 	if (setclear) {
 #ifdef CONFIG_SYS_FEC_NO_SHARED_PHY
 		if (info->iobase == CONFIG_SYS_FEC0_IOBASE)
@@ -224,6 +420,21 @@
 #endif
 		}
 	}
+#endif	/* CONFIG_MCF5445x */
+
+#ifdef CONFIG_MCF5441x
+	if (setclear) {
+		out_8(&gpio->par_fec, 0x03);
+		out_8(&gpio->srcr_fec, 0x0F);
+		clrsetbits_8(&gpio->par_simp0h, ~GPIO_PAR_SIMP0H_DAT_MASK,
+			GPIO_PAR_SIMP0H_DAT_GPIO);
+		clrsetbits_8(&gpio->pddr_g, ~GPIO_PDDR_G4_MASK,
+			GPIO_PDDR_G4_OUTPUT);
+		clrbits_8(&gpio->podr_g, ~GPIO_PODR_G4_MASK);
+
+	} else
+		clrbits_8(&gpio->par_fec, ~GPIO_PAR_FEC_FEC_MASK);
+#endif
 	return 0;
 }
 #endif
@@ -233,10 +444,24 @@
 {
 	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
 
+#ifdef CONFIG_MCF5445x
 	out_8(&gpio->par_dspi,
 		GPIO_PAR_DSPI_SIN_SIN |
 		GPIO_PAR_DSPI_SOUT_SOUT |
 		GPIO_PAR_DSPI_SCK_SCK);
+#endif
+
+#ifdef CONFIG_MCF5441x
+	pm_t *pm = (pm_t *) MMAP_PM;
+
+	out_8(&gpio->par_dspi0,
+		GPIO_PAR_DSPI0_SIN_DSPI0SIN | GPIO_PAR_DSPI0_SOUT_DSPI0SOUT |
+		GPIO_PAR_DSPI0_SCK_DSPI0SCK);
+	out_8(&gpio->srcr_dspiow, 3);
+
+	/* DSPI0 */
+	out_8(&pm->pmcr0, 23);
+#endif
 }
 
 int cfspi_claim_bus(uint bus, uint cs)
@@ -250,6 +475,7 @@
 	/* Clear FIFO and resume transfer */
 	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
 
+#ifdef CONFIG_MCF5445x
 	switch (cs) {
 	case 0:
 		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
@@ -272,6 +498,20 @@
 		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
 		break;
 	}
+#endif
+
+#ifdef CONFIG_MCF5441x
+	switch (cs) {
+	case 0:
+		clrbits_8(&gpio->par_dspi0, ~GPIO_PAR_DSPI0_PCS0_MASK);
+		setbits_8(&gpio->par_dspi0, GPIO_PAR_DSPI0_PCS0_DSPI0PCS0);
+		break;
+	case 1:
+		clrbits_8(&gpio->par_dspiow, GPIO_PAR_DSPIOW_DSPI0PSC1);
+		setbits_8(&gpio->par_dspiow, GPIO_PAR_DSPIOW_DSPI0PSC1);
+		break;
+	}
+#endif
 
 	return 0;
 }
@@ -284,6 +524,7 @@
 	/* Clear FIFO */
 	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
 
+#ifdef CONFIG_MCF5445x
 	switch (cs) {
 	case 0:
 		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
@@ -301,5 +542,11 @@
 		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
 		break;
 	}
+#endif
+
+#ifdef CONFIG_MCF5441x
+	if (cs == 1)
+		clrbits_8(&gpio->par_dspiow, GPIO_PAR_DSPIOW_DSPI0PSC1);
+#endif
 }
 #endif
diff --git a/arch/m68k/cpu/mcf5445x/speed.c b/arch/m68k/cpu/mcf5445x/speed.c
index d71b5fe..55d1c48 100644
--- a/arch/m68k/cpu/mcf5445x/speed.c
+++ b/arch/m68k/cpu/mcf5445x/speed.c
@@ -57,8 +57,10 @@
 	/* Round divider down to nearest power of two */
 	for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ;
 
+#ifdef CONFIG_MCF5445x
 	/* Apply the divider to the system clock */
 	clrsetbits_be16(&ccm->cdr, 0x0f00, CCM_CDR_LPDIV(i));
+#endif
 
 	/* Enable Limp Mode */
 	setbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
@@ -81,12 +83,66 @@
 		;
 }
 
-/*
- * get_clocks() fills in gd->cpu_clock and gd->bus_clk
- */
-int get_clocks(void)
+#ifdef CONFIG_MCF5441x
+void setup_5441x_clocks(void)
 {
+	ccm_t *ccm = (ccm_t *)MMAP_CCM;
+	pll_t *pll = (pll_t *)MMAP_PLL;
+	int temp, vco = 0, bootmod_ccr, pdr;
+
+	bootmod_ccr = (in_be16(&ccm->ccr) & CCM_CCR_BOOTMOD) >> 14;
+
+	switch (bootmod_ccr) {
+	case 0:
+		out_be32(&pll->pcr, 0x00000013);
+		out_be32(&pll->pdr, 0x00e70c61);
+		clock_exit_limp();
+		break;
+	case 2:
+		break;
+	case 3:
+		break;
+	}
+
+	/*Change frequency for Modelo SER1 USB host*/
+#ifdef CONFIG_LOW_MCFCLK
+	temp = in_be32(&pll->pcr);
+	temp &= ~0x3f;
+	temp |= 5;
+	out_be32(&pll->pcr, temp);
+
+	temp = in_be32(&pll->pdr);
+	temp &= ~0x001f0000;
+	temp |= 0x00040000;
+	out_be32(&pll->pdr, temp);
+	__asm__("tpf");
+#endif
+
+	setbits_be16(&ccm->misccr2, 0x02);
+
+	vco =  ((in_be32(&pll->pcr) & PLL_CR_FBKDIV_BITS) + 1) *
+		CONFIG_SYS_INPUT_CLKSRC;
+	gd->vco_clk = vco;
+
+	gd->inp_clk = CONFIG_SYS_INPUT_CLKSRC;	/* Input clock */
 
+	pdr = in_be32(&pll->pdr);
+	temp = (pdr & PLL_DR_OUTDIV1_BITS) + 1;
+	gd->cpu_clk = vco / temp;	/* cpu clock */
+	gd->flb_clk = vco / temp;	/* FlexBus clock */
+	gd->flb_clk >>= 1;
+	if (in_be16(ccm->misccr2) & 2)		/* fsys/4 */
+		gd->flb_clk >>= 1;
+
+	temp = ((pdr & PLL_DR_OUTDIV2_BITS) >> 5) + 1;
+	gd->bus_clk = vco / temp;	/* bus clock */
+
+}
+#endif
+
+#ifdef CONFIG_MCF5445x
+void setup_5445x_clocks(void)
+{
 	ccm_t *ccm = (ccm_t *)MMAP_CCM;
 	pll_t *pll = (pll_t *)MMAP_PLL;
 	int pllmult_nopci[] = { 20, 10, 24, 18, 12, 6, 16, 8 };
@@ -220,6 +276,22 @@
 #ifdef CONFIG_FSL_I2C
 	gd->i2c1_clk = gd->bus_clk;
 #endif
+}
+#endif
+
+/* get_clocks() fills in gd->cpu_clock and gd->bus_clk */
+int get_clocks(void)
+{
+#ifdef CONFIG_MCF5441x
+	setup_5441x_clocks();
+#endif
+#ifdef CONFIG_MCF5445x
+	setup_5445x_clocks();
+#endif
+
+#ifdef CONFIG_FSL_I2C
+	gd->i2c1_clk = gd->bus_clk;
+#endif
 
 	return (0);
 }
diff --git a/arch/m68k/cpu/mcf5445x/start.S b/arch/m68k/cpu/mcf5445x/start.S
index 9906014..5fc944d 100644
--- a/arch/m68k/cpu/mcf5445x/start.S
+++ b/arch/m68k/cpu/mcf5445x/start.S
@@ -2,6 +2,9 @@
  * Copyright (C) 2003	Josef Baumgartner <josef.baumgartner@telex.de>
  * Based on code from Bernhard Kuhn <bkuhn@metrowerks.com>
  *
+ * Copyright 2010-2012 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -21,8 +24,10 @@
  * MA 02111-1307 USA
  */
 
+#include <common.h>
 #include <asm-offsets.h>
 #include <config.h>
+#include <timestamp.h>
 #include "version.h"
 #include <asm/cache.h>
 
@@ -43,8 +48,9 @@
 	addl	#60,%sp;		/* space for 15 regs */ \
 	rte;
 
-#if defined(CONFIG_CF_SBF)
+#if defined(CONFIG_SERIAL_BOOT)
 #define ASM_DRAMINIT	(asm_dram_init - CONFIG_SYS_TEXT_BASE + CONFIG_SYS_INIT_RAM_ADDR)
+#define ASM_DRAMINIT_N	(asm_dram_init - TEXT_BASE)
 #define ASM_SBF_IMG_HDR	(asm_sbf_img_hdr - CONFIG_SYS_TEXT_BASE + CONFIG_SYS_INIT_RAM_ADDR)
 #endif
 
@@ -55,10 +61,15 @@
  *	These vectors are to catch any un-intended traps.
  */
 _vectors:
-#if defined(CONFIG_CF_SBF)
+#if defined(CONFIG_SERIAL_BOOT)
 
 INITSP:	.long	0		/* Initial SP	*/
+#ifdef CONFIG_CF_SBF
 INITPC:	.long	ASM_DRAMINIT	/* Initial PC 	*/
+#endif
+#ifdef CONFIG_SYS_NAND_BOOT
+INITPC:	.long	ASM_DRAMINIT_N	/* Initial PC 	*/
+#endif
 
 #else
 
@@ -95,7 +106,7 @@
 vector1E:	.long	_FAULT	/* Autovector Level 6	*/
 vector1F:	.long	_FAULT	/* Autovector Level 7	*/
 
-#if !defined(CONFIG_CF_SBF)
+#if !defined(CONFIG_SERIAL_BOOT)
 
 /* TRAP #0 - #15 */
 vector20_2F:
@@ -138,16 +149,26 @@
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 #endif
 
-#if defined(CONFIG_CF_SBF)
+#if defined(CONFIG_SERIAL_BOOT)
 	/* Image header: chksum 4 bytes, len 4 bytes, img dest 4 bytes */
 asm_sbf_img_hdr:
 	.long	0x00000000	/* checksum, not yet implemented */
-	.long	0x00030000	/* image length */
+	.long	0x00040000	/* image length */
 	.long	CONFIG_SYS_TEXT_BASE	/* image to be relocated at */
 
 asm_dram_init:
 	move.w #0x2700,%sr		/* Mask off Interrupt */
 
+#ifdef CONFIG_SYS_NAND_BOOT
+	/* for assembly stack */
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_CTRL), %d0
+	movec	%d0, %RAMBAR1
+
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
+	clr.l %sp@-
+#endif
+
+#ifdef CONFIG_CF_SBF
 	move.l	#CONFIG_SYS_INIT_RAM_ADDR, %d0
 	movec	%d0, %VBR
 
@@ -180,7 +201,90 @@
 	move.l	#(CONFIG_SYS_CS0_CTRL), (%a1)
 	move.l	#0xFC008004, %a1
 	move.l	#(CONFIG_SYS_CS0_MASK), (%a1)
+#endif			/* CONFIG_CF_SBF */
+
+#ifdef CONFIG_MCF5441x
+	/* TC: enable all peripherals,
+	in the future only enable certain peripherals */
+	move.l	#0xFC04002D, %a1
+
+#if defined(CONFIG_CF_SBF)
+	move.b	#23, (%a1)	/* dspi */
+#endif
+	move.b	#46, (%a1)	/* DDR */
+
+	/* slew settings */
+	move.l	#0xEC094060, %a1
+	move.b	#0, (%a1)
+
+	/* use vco instead of cpu*2 clock for ddr clock */
+	move.l	#0xEC09001A, %a1
+	move.w	#0xE01D, (%a1)
+
+	/* DDR settings */
+	move.l	#0xFC0B8180, %a1
+	move.l	#0x00000000, (%a1)
+	move.l	#0x40000000, (%a1)
+
+	move.l	#0xFC0B81AC, %a1
+	move.l	#0x01030203, (%a1)
 
+	move.l	#0xFC0B8000, %a1
+	move.l	#0x01010101, (%a1)+	/* 0x00 */
+	move.l	#0x00000101, (%a1)+	/* 0x04 */
+	move.l	#0x01010100, (%a1)+	/* 0x08 */
+	move.l	#0x01010000, (%a1)+	/* 0x0C */
+	move.l	#0x00010101, (%a1)+	/* 0x10 */
+	move.l	#0xFC0B8018, %a1
+	move.l	#0x00010100, (%a1)+	/* 0x18 */
+	move.l	#0x00000001, (%a1)+	/* 0x1C */
+	move.l	#0x01000001, (%a1)+	/* 0x20 */
+	move.l	#0x00000100, (%a1)+	/* 0x24 */
+	move.l	#0x00010001, (%a1)+	/* 0x28 */
+	move.l	#0x00000200, (%a1)+	/* 0x2C */
+	move.l	#0x01000002, (%a1)+	/* 0x30 */
+	move.l	#0x00000000, (%a1)+	/* 0x34 */
+	move.l	#0x00000100, (%a1)+	/* 0x38 */
+	move.l	#0x02000100, (%a1)+	/* 0x3C */
+	move.l	#0x02000407, (%a1)+	/* 0x40 */
+	move.l	#0x02030007, (%a1)+	/* 0x44 */
+	move.l	#0x02000100, (%a1)+	/* 0x48 */
+	move.l	#0x0A030203, (%a1)+	/* 0x4C */
+	move.l	#0x00020708, (%a1)+	/* 0x50 */
+	move.l	#0x00050008, (%a1)+	/* 0x54 */
+	move.l	#0x04030002, (%a1)+	/* 0x58 */
+	move.l	#0x00000004, (%a1)+	/* 0x5C */
+	move.l	#0x020A0000, (%a1)+	/* 0x60 */
+	move.l	#0x0C00000E, (%a1)+	/* 0x64 */
+	move.l	#0x00002004, (%a1)+	/* 0x68 */
+	move.l	#0x00000000, (%a1)+	/* 0x6C */
+	move.l	#0x00100010, (%a1)+	/* 0x70 */
+	move.l	#0x00100010, (%a1)+	/* 0x74 */
+	move.l	#0x00000000, (%a1)+	/* 0x78 */
+	move.l	#0x07990000, (%a1)+	/* 0x7C */
+	move.l	#0xFC0B80A0, %a1
+	move.l	#0x00000000, (%a1)+	/* 0xA0 */
+	move.l	#0x00C80064, (%a1)+	/* 0xA4 */
+	move.l	#0x44520002, (%a1)+	/* 0xA8 */
+	move.l	#0x00C80023, (%a1)+	/* 0xAC */
+	move.l	#0xFC0B80B4, %a1
+	move.l	#0x0000C350, (%a1)	/* 0xB4 */
+	move.l	#0xFC0B80E0, %a1
+	move.l	#0x04000000, (%a1)+	/* 0xE0 */
+	move.l	#0x03000304, (%a1)+	/* 0xE4 */
+	move.l	#0x40040000, (%a1)+	/* 0xE8 */
+	move.l	#0xC0004004, (%a1)+	/* 0xEC */
+	move.l	#0x0642C000, (%a1)+	/* 0xF0 */
+	move.l	#0x00000642, (%a1)+	/* 0xF4 */
+	move.l	#0xFC0B8024, %a1
+	tpf
+	move.l	#0x01000100, (%a1)	/* 0x24 */
+
+	move.l	#0x2000, %d1
+	jsr	asm_delay
+#endif		/* CONFIG_MCF5441x */
+
+#ifdef CONFIG_MCF5445x
 	/* Dram Initialization a1, a2, and d0 */
 	/* mscr sdram */
 	move.l	#0xFC0A4074, %a1
@@ -203,7 +307,9 @@
 	add.l	#1, %d1
 	cmp.l	#1, %d2
 	bne	dramsz_loop
-
+#ifdef CONFIG_SYS_NAND_BOOT
+	beq	asm_nand_chk_status
+#endif
 	/* SDRAM Chip 0 and 1 */
 	move.l	#(CONFIG_SYS_SDRAM_BASE), (%a1)
 	or.l	%d1, (%a1)
@@ -275,7 +381,9 @@
 
 	move.l	#2000, %d1
 	jsr	asm_delay
+#endif		/* CONFIG_MCF5445x */
 
+#ifdef CONFIG_CF_SBF
 	/*
 	 * DSPI Initialization
 	 * a0 - general, sram - 0x80008000 - 32, see M54455EVB.h
@@ -286,15 +394,28 @@
 	 */
 	/* Enable pins for DSPI mode - chip-selects are enabled later */
 asm_dspi_init:
+#ifdef CONFIG_MCF5441x
+	move.l	#0xEC09404E, %a1
+	move.l	#0xEC09404F, %a2
+	move.b	#0xFF, (%a1)
+	move.b	#0x80, (%a2)
+#endif
+
+#ifdef CONFIG_MCF5445x
 	move.l	#0xFC0A4063, %a0
 	move.b	#0x7F, (%a0)
-
+#endif
 	/* Configure DSPI module */
 	move.l	#0xFC05C000, %a0
 	move.l	#0x80FF0C00, (%a0)	/* Master, clear TX/RX FIFO */
 
 	move.l	#0xFC05C00C, %a0
+#ifdef CONFIG_MCF5441x
+	move.l	#0x3E000016, (%a0)
+#endif
+#ifdef CONFIG_MCF5445x
 	move.l	#0x3E000011, (%a0)
+#endif
 
 	move.l	#0xFC05C034, %a2	/* dtfr */
 	move.l	#0xFC05C03B, %a3	/* drfr */
@@ -379,19 +500,148 @@
 
 	move.b	(%a3), %d1
 	rts
+#endif			/* CONFIG_CF_SBF */
+
+#ifdef CONFIG_SYS_NAND_BOOT
+	/* copy 4 boot pages to dram as soon as possible */
+	/* each page is 996 bytes (1056 total with 60 ECC bytes */
+	move.l  #0x00000000, %a1	/* src */
+	move.l	#TEXT_BASE, %a2		/* dst */
+	move.l	#0x3E0, %d0		/* sz in long */
+
+asm_boot_nand_copy:
+	move.l	(%a1)+, (%a2)+
+	subq.l	#1, %d0
+	bne	asm_boot_nand_copy
+
+	/* jump to memory and execute */
+	move.l	#(asm_nand_init), %a0
+	jmp	(%a0)
+
+asm_nand_init:
+	/* exit nand boot-mode */
+	move.l	#0xFC0FFF30, %a1
+	or.l	#0x00000040, %d1
+	move.l	%d1, (%a1)
+
+	/* initialize general use internal ram */
+	move.l #0, %d0
+	move.l #(CACR_STATUS), %a1	/* CACR */
+	move.l #(ICACHE_STATUS), %a2	/* icache */
+	move.l #(DCACHE_STATUS), %a3	/* dcache */
+	move.l %d0, (%a1)
+	move.l %d0, (%a2)
+	move.l %d0, (%a3)
+
+	/* invalidate and disable cache */
+	move.l	#0x01004100, %d0	/* Invalidate cache cmd */
+	movec	%d0, %CACR		/* Invalidate cache */
+	move.l	#0, %d0
+	movec	%d0, %ACR0
+	movec	%d0, %ACR1
+	movec	%d0, %ACR2
+	movec	%d0, %ACR3
+
+	/* Must disable global address */
+	move.l	#0xFC008000, %a1
+	move.l	#(CONFIG_SYS_CS0_BASE), (%a1)
+	move.l	#0xFC008008, %a1
+	move.l	#(CONFIG_SYS_CS0_CTRL), (%a1)
+	move.l	#0xFC008004, %a1
+	move.l	#(CONFIG_SYS_CS0_MASK), (%a1)
+
+	/* NAND port configuration */
+	move.l	#0xEC094048, %a1
+	move.b	#0xFD, (%a1)+
+	move.b	#0x5F, (%a1)+
+	move.b	#0x04, (%a1)+
+
+	/* reset nand */
+	move.l  #0xFC0FFF38, %a1	/* isr */
+	move.l  #0x000e0000, (%a1)
+	move.l	#0xFC0FFF08, %a2
+	move.l	#0x00000000, (%a2)+	/* car */
+	move.l	#0x11000000, (%a2)+	/* rar */
+	move.l	#0x00000000, (%a2)+	/* rpt */
+	move.l	#0x00000000, (%a2)+	/* rai */
+	move.l  #0xFC0FFF2c, %a2	/* cfg */
+	move.l  #0x00000000, (%a2)+	/* secsz */
+	move.l  #0x000e0681, (%a2)+
+	move.l  #0xFC0FFF04, %a2	/* cmd2 */
+	move.l  #0xFF404001, (%a2)
+	move.l  #0x000e0000, (%a1)
+
+	move.l	#0x2000, %d1
+	jsr	asm_delay
+
+	/* setup nand */
+	move.l  #0xFC0FFF00, %a1
+	move.l  #0x30700000, (%a1)+	/* cmd1 */
+	move.l  #0x007EF000, (%a1)+	/* cmd2 */
+
+	move.l  #0xFC0FFF2C, %a1
+	move.l  #0x00000841, (%a1)+	/* secsz */
+	move.l  #0x000e0681, (%a1)+	/* cfg */
+
+	move.l	#100, %d4		/* 100 pages ~200KB */
+	move.l	#4, %d2			/* start at 4 */
+	move.l  #0xFC0FFF04, %a0	/* cmd2 */
+	move.l  #0xFC0FFF0C, %a1	/* rar */
+	move.l	#(TEXT_BASE + 0xF80), %a2	/* dst */
+
+asm_nand_read:
+	move.l	#0x11000000, %d0	/* rar */
+	or.l	%d2, %d0
+	move.l	%d0, (%a1)
+	add.l	#1, %d2
+
+	move.l	(%a0), %d0		/* cmd2 */
+	or.l	#1, %d0
+	move.l	%d0, (%a0)
+
+	move.l	#0x200, %d1
+	jsr	asm_delay
+
+asm_nand_chk_status:
+	move.l  #0xFC0FFF38, %a4	/* isr */
+	move.l	(%a4), %d0
+	and.l	#0x40000000, %d0
+	tst.l	%d0
+	beq	asm_nand_chk_status
+
+	move.l  #0xFC0FFF38, %a4	/* isr */
+	move.l	(%a4), %d0
+	or.l	#0x000E0000, %d0
+	move.l	%d0, (%a4)
+
+	move.l	#0x200, %d3
+	move.l	#0xFC0FC000, %a3	/* buf 1 */
+asm_nand_copy:
+	move.l	(%a3)+, (%a2)+
+	subq.l	#1, %d3
+	bgt	asm_nand_copy
+
+	subq.l	#1, %d4
+	bgt	asm_nand_read
+
+	/* jump to memory and execute */
+	move.l	#(TEXT_BASE + 0x400), %a0
+	jmp	(%a0)
+
+#endif			/* CONFIG_SYS_NAND_BOOT */
 
 asm_delay:
 	nop
 	subq.l	#1, %d1
 	bne	asm_delay
 	rts
-#endif			/* CONFIG_CF_SBF */
+#endif			/* CONFIG_CF_SBF || CONFIG_NAND_U_BOOT */
 
 	.text
 	. = 0x400
 	.globl	_start
 _start:
-#if !defined(CONFIG_CF_SBF)
+#if !defined(CONFIG_SERIAL_BOOT)
 	nop
 	nop
 	move.w #0x2700,%sr		/* Mask off Interrupt */
@@ -418,12 +668,15 @@
 	movec	%d0, %ACR1
 	movec	%d0, %ACR2
 	movec	%d0, %ACR3
+#else
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_CTRL), %d0
+	movec	%d0, %RAMBAR1
+#endif
 
 	/* set stackpointer to end of internal ram to get some stackspace for
 	   the first c-code */
 	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
 	clr.l %sp@-
-#endif
 
 	move.l #__got_start, %a5	/* put relocation table address to a5 */