APM821xx: Add CPU support

APM821XX is a new line of SoCs which are derivatives of
PPC44X family of processors. This patch adds support of CPU, cache,
tlb, 32k ocm, bootstraps, PLB and AHB bus.

Signed-off-by: Tirumala R Marri <tmarri@apm.com>
Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/arch/powerpc/cpu/ppc4xx/cpu.c b/arch/powerpc/cpu/ppc4xx/cpu.c
index 6009b0c..67f1fff 100644
--- a/arch/powerpc/cpu/ppc4xx/cpu.c
+++ b/arch/powerpc/cpu/ppc4xx/cpu.c
@@ -250,6 +250,20 @@
 };
 static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
 #endif
+#if defined(CONFIG_APM821XX)
+#define SDR0_PINSTP_SHIFT       29
+static char *bootstrap_str[] = {
+	"RESERVED",
+	"RESERVED",
+	"RESERVED",
+	"NAND (8 bits)",
+	"NOR  (8 bits)",
+	"NOR  (8 bits) w/PLL Bypassed",
+	"I2C (Addr 0x54)",
+	"I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
+#endif
 
 #if defined(SDR0_PINSTP_SHIFT)
 static int bootstrap_option(void)
@@ -590,6 +604,11 @@
 		strcpy(addstr, "No Security support");
 		break;
 
+	case PVR_APM821XX_RA:
+		puts("APM821XX Rev. A");
+		strcpy(addstr, "Security support");
+		break;
+
 	case PVR_VIRTEX5:
 		puts("440x5 VIRTEX5");
 		break;
diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c
index d54b30e..2a727b1 100644
--- a/arch/powerpc/cpu/ppc4xx/cpu_init.c
+++ b/arch/powerpc/cpu/ppc4xx/cpu_init.c
@@ -237,7 +237,8 @@
 
 	reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
 
-#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CONFIG_SYS_4xx_GPIO_TABLE)
+#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && \
+    !defined(CONFIG_APM821XX) &&!defined(CONFIG_SYS_4xx_GPIO_TABLE)
 	/*
 	 * GPIO0 setup (select GPIO or alternate function)
 	 */
@@ -393,7 +394,7 @@
 #if defined(CONFIG_405EX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
     defined(CONFIG_460EX) || defined(CONFIG_460GT)  || \
-    defined(CONFIG_460SX)
+    defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
 	/*
 	 * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
 	 */
diff --git a/arch/powerpc/cpu/ppc4xx/speed.c b/arch/powerpc/cpu/ppc4xx/speed.c
index abd4e91..09d6671 100644
--- a/arch/powerpc/cpu/ppc4xx/speed.c
+++ b/arch/powerpc/cpu/ppc4xx/speed.c
@@ -189,7 +189,7 @@
 #elif defined(CONFIG_440)
 
 #if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
-    defined(CONFIG_460SX)
+    defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
 static u8 pll_fwdv_multi_bits[] = {
 	/* values for:  1 - 16 */
 	0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c,
@@ -250,6 +250,78 @@
 	return 0;
 }
 
+#if defined(CONFIG_APM821XX)
+
+void get_sys_info(sys_info_t *sysInfo)
+{
+	unsigned long plld;
+	unsigned long temp;
+	unsigned long mul;
+	unsigned long cpudv;
+	unsigned long plb2dv;
+	unsigned long ddr2dv;
+
+	/* Calculate Forward divisor A and Feeback divisor */
+	mfcpr(CPR0_PLLD, plld);
+
+	temp = CPR0_PLLD_FWDVA(plld);
+	sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
+
+	temp = CPR0_PLLD_FDV(plld);
+	sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
+
+	/* Calculate OPB clock divisor */
+	mfcpr(CPR0_OPBD, temp);
+	temp = CPR0_OPBD_OPBDV(temp);
+	sysInfo->pllOpbDiv = temp ? temp : 4;
+
+	/* Calculate Peripheral clock divisor */
+	mfcpr(CPR0_PERD, temp);
+	temp = CPR0_PERD_PERDV(temp);
+	sysInfo->pllExtBusDiv = temp ? temp : 4;
+
+	/* Calculate CPU clock divisor */
+	mfcpr(CPR0_CPUD, temp);
+	temp = CPR0_CPUD_CPUDV(temp);
+	cpudv = temp ? temp : 8;
+
+	/* Calculate PLB2 clock divisor */
+	mfcpr(CPR0_PLB2D, temp);
+	temp = CPR0_PLB2D_PLB2DV(temp);
+	plb2dv = temp ? temp : 4;
+
+	/* Calculate DDR2 clock divisor */
+	mfcpr(CPR0_DDR2D, temp);
+	temp = CPR0_DDR2D_DDR2DV(temp);
+	ddr2dv = temp ? temp : 4;
+
+	/* Calculate 'M' based on feedback source */
+	mfcpr(CPR0_PLLC, temp);
+	temp = CPR0_PLLC_SEL(temp);
+	if (temp == 0) {
+		/* PLL internal feedback */
+		mul = sysInfo->pllFbkDiv;
+	} else {
+		/* PLL PerClk feedback */
+		mul = sysInfo->pllFwdDivA * sysInfo->pllFbkDiv * cpudv
+			* plb2dv * 2 * sysInfo->pllOpbDiv *
+			  sysInfo->pllExtBusDiv;
+	}
+
+	/* Now calculate the individual clocks */
+	sysInfo->freqVCOMhz = (mul * CONFIG_SYS_CLK_FREQ) + (mul >> 1);
+	sysInfo->freqProcessor = sysInfo->freqVCOMhz /
+		sysInfo->pllFwdDivA / cpudv;
+	sysInfo->freqPLB = sysInfo->freqVCOMhz /
+		sysInfo->pllFwdDivA / cpudv / plb2dv / 2;
+	sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+	sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
+	sysInfo->freqDDR = sysInfo->freqVCOMhz /
+		sysInfo->pllFwdDivA / cpudv / ddr2dv / 2;
+	sysInfo->freqUART = sysInfo->freqPLB;
+}
+
+#else
 /*
  * AMCC_TODO: verify this routine against latest EAS, cause stuff changed
  *            with latest EAS
@@ -307,6 +379,7 @@
 
 	return;
 }
+#endif
 
 #elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S
index 7a65d9f..c2d52bf 100644
--- a/arch/powerpc/cpu/ppc4xx/start.S
+++ b/arch/powerpc/cpu/ppc4xx/start.S
@@ -703,7 +703,8 @@
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
     defined(CONFIG_460SX)
 	mtdcr	L2_CACHE_CFG,r0		/* Ensure L2 Cache is off */
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+      defined(CONFIG_APM821XX)
 	lis	r1, 0x0000
 	ori	r1,r1,0x0008		/* Set L2_CACHE_CFG[RDBW]=1 */
 	mtdcr	L2_CACHE_CFG,r1
@@ -731,7 +732,8 @@
 	lis	r1, 0x8003
 	ori	r1,r1, 0x0980		/* fourth 64k */
 	mtdcr	ISRAM0_SB3CR,r1
-#elif defined(CONFIG_440SPE) || defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#elif defined(CONFIG_440SPE) || defined(CONFIG_460EX) || \
+      defined(CONFIG_460GT) || defined(CONFIG_APM821XX)
 	lis	r1,0x0000		/* BAS = X_0000_0000 */
 	ori	r1,r1,0x0984		/* first 64k */
 	mtdcr	ISRAM0_SB0CR,r1
@@ -744,7 +746,8 @@
 	lis	r1, 0x0003
 	ori	r1,r1, 0x0984		/* fourth 64k */
 	mtdcr	ISRAM0_SB3CR,r1
-#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_APM821XX)
 	lis	r2,0x7fff
 	ori	r2,r2,0xffff
 	mfdcr	r1,ISRAM1_DPC
@@ -755,7 +758,7 @@
 	mtdcr	ISRAM1_PMEG,r1
 
 	lis	r1,0x0004		/* BAS = 4_0004_0000 */
-	ori	r1,r1,0x0984		/* 64k */
+	ori     r1,r1,ISRAM1_SIZE       /* ocm size */
 	mtdcr	ISRAM1_SB0CR,r1
 #endif
 #elif defined(CONFIG_460SX)