POST: Add ppc405 support to cache and UART POST

Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/post/cpu/ppc4xx/cache.c b/post/cpu/ppc4xx/cache.c
index e1f989e..109ca1f 100644
--- a/post/cpu/ppc4xx/cache.c
+++ b/post/cpu/ppc4xx/cache.c
@@ -53,14 +53,25 @@
 
 static int tlb = -1;		/* index to the victim TLB entry */
 
+#ifdef CONFIG_440
 static unsigned char testarea[CACHE_POST_SIZE]
 __attribute__((__aligned__(CACHE_POST_SIZE)));
+#endif
 
 int cache_post_test (int flags)
 {
 	void* virt = (void*)CFG_POST_CACHE_ADDR;
-	int ints, i, res = 0;
-	u32 word0;
+	int ints;
+	int res = 0;
+
+	/*
+	 * All 44x variants deal with cache management differently
+	 * because they have the address translation always enabled.
+	 * The 40x ppc's don't use address translation in U-Boot at all,
+	 * so we have to distinguish here between 40x and 44x.
+	 */
+#ifdef CONFIG_440
+	int word0, i;
 
 	if (tlb < 0) {
 		/*
@@ -83,6 +94,7 @@
 			}
 		}
 	}
+#endif
 	ints = disable_interrupts ();
 
 	WATCHDOG_RESET ();
diff --git a/post/cpu/ppc4xx/cache_4xx.S b/post/cpu/ppc4xx/cache_4xx.S
index dddd76b..d5cb075 100644
--- a/post/cpu/ppc4xx/cache_4xx.S
+++ b/post/cpu/ppc4xx/cache_4xx.S
@@ -37,6 +37,13 @@
 
 	.text
 
+	/*
+	 * All 44x variants deal with cache management differently
+	 * because they have the address translation always enabled.
+	 * The 40x ppc's don't use address translation in U-Boot at all,
+	 * so we have to distinguish here between 40x and 44x.
+	 */
+#ifdef CONFIG_440
 /* void cache_post_disable (int tlb)
  */
 cache_post_disable:
@@ -68,6 +75,43 @@
 	sync
 	isync
 	blr
+#else
+/* void cache_post_disable (int tlb)
+ */
+cache_post_disable:
+	lis	r0, 0x0000
+	ori	r0, r0, 0x0000
+	mtdccr	r0
+	sync
+	isync
+	blr
+
+/* void cache_post_wt (int tlb)
+ */
+cache_post_wt:
+	lis	r0, 0x8000
+	ori	r0, r0, 0x0000
+	mtdccr	r0
+	lis	r0, 0x8000
+	ori	r0, r0, 0x0000
+	mtdcwr	r0
+	sync
+	isync
+	blr
+
+/* void cache_post_wb (int tlb)
+ */
+cache_post_wb:
+	lis	r0, 0x8000
+	ori	r0, r0, 0x0000
+	mtdccr	r0
+	lis	r0, 0x0000
+	ori	r0, r0, 0x0000
+	mtdcwr	r0
+	sync
+	isync
+	blr
+#endif
 
 /* void cache_post_dinvalidate (void *p, int size)
  */
diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c
index b047d42..0cffda5 100644
--- a/post/cpu/ppc4xx/uart.c
+++ b/post/cpu/ppc4xx/uart.c
@@ -38,24 +38,77 @@
 
 #if CONFIG_POST & CFG_POST_UART
 
+/*
+ * This table defines the UART's that should be tested and can
+ * be overridden in the board config file
+ */
+#ifndef CFG_POST_UART_TABLE
+#define CFG_POST_UART_TABLE	{UART0_BASE, UART1_BASE, UART2_BASE, UART3_BASE}
+#endif
+
 #include <asm/processor.h>
 #include <serial.h>
 
+#if defined(CONFIG_440)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
 #define UART0_BASE  CFG_PERIPHERAL_BASE + 0x00000300
 #define UART1_BASE  CFG_PERIPHERAL_BASE + 0x00000400
 #define UART2_BASE  CFG_PERIPHERAL_BASE + 0x00000500
 #define UART3_BASE  CFG_PERIPHERAL_BASE + 0x00000600
+#else
+#define UART0_BASE  CFG_PERIPHERAL_BASE + 0x00000200
+#define UART1_BASE  CFG_PERIPHERAL_BASE + 0x00000300
+#endif
 
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+#define UART2_BASE  CFG_PERIPHERAL_BASE + 0x00000600
+#endif
+
+#if defined(CONFIG_440GP)
+#define CR0_MASK        0x3fff0000
+#define CR0_EXTCLK_ENA  0x00600000
+#define CR0_UDIV_POS    16
+#define UDIV_SUBTRACT	1
+#define UART0_SDR	cntrl0
+#define MFREG(a, d)	d = mfdcr(a)
+#define MTREG(a, d)	mtdcr(a, d)
+#else /* #if defined(CONFIG_440GP) */
+/* all other 440 PPC's access clock divider via sdr register */
 #define CR0_MASK        0xdfffffff
 #define CR0_EXTCLK_ENA  0x00800000
 #define CR0_UDIV_POS    0
 #define UDIV_SUBTRACT	0
 #define UART0_SDR	sdr_uart0
 #define UART1_SDR	sdr_uart1
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
+    defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPe)
 #define UART2_SDR	sdr_uart2
+#endif
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
+    defined(CONFIG_440GR) || defined(CONFIG_440GRx)
 #define UART3_SDR	sdr_uart3
+#endif
 #define MFREG(a, d)	mfsdr(a, d)
 #define MTREG(a, d)	mtsdr(a, d)
+#endif /* #if defined(CONFIG_440GP) */
+#elif defined(CONFIG_405EP) || defined(CONFIG_405EZ)
+#define UART0_BASE      0xef600300
+#define UART1_BASE      0xef600400
+#define UCR0_MASK       0x0000007f
+#define UCR1_MASK       0x00007f00
+#define UCR0_UDIV_POS   0
+#define UCR1_UDIV_POS   8
+#define UDIV_MAX        127
+#else /* CONFIG_405GP || CONFIG_405CR */
+#define UART0_BASE      0xef600300
+#define UART1_BASE      0xef600400
+#define CR0_MASK        0x00001fff
+#define CR0_EXTCLK_ENA  0x000000c0
+#define CR0_UDIV_POS    1
+#define UDIV_MAX        32
+#endif
 
 #define UART_RBR    0x00
 #define UART_THR    0x00
@@ -71,8 +124,8 @@
 #define UART_DLM    0x01
 
 /*
-  Line Status Register.
-*/
+ * Line Status Register.
+ */
 #define asyncLSRDataReady1            0x01
 #define asyncLSROverrunError1         0x02
 #define asyncLSRParityError1          0x04
@@ -84,6 +137,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if defined(CONFIG_440)
 static int uart_post_init (unsigned long dev_base)
 {
 	unsigned long reg;
@@ -147,6 +201,77 @@
 	return 0;
 }
 
+#else /* CONFIG_440 */
+
+static int uart_post_init (unsigned long dev_base)
+{
+	unsigned long reg;
+	unsigned long tmp;
+	unsigned long clk;
+	unsigned long udiv;
+	unsigned short bdiv;
+	volatile char val;
+	int i;
+
+	for (i = 0; i < 3500; i++) {
+		if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1)
+			break;
+		udelay (100);
+	}
+
+#if defined(CONFIG_405EZ)
+	serial_divs(gd->baudrate, &udiv, &bdiv);
+	clk = tmp = reg = 0;
+#else
+#ifdef CONFIG_405EP
+	reg = mfdcr(cpc0_ucr) & ~(UCR0_MASK | UCR1_MASK);
+	clk = gd->cpu_clk;
+	tmp = CFG_BASE_BAUD * 16;
+	udiv = (clk + tmp / 2) / tmp;
+	if (udiv > UDIV_MAX)                    /* max. n bits for udiv */
+		udiv = UDIV_MAX;
+	reg |= (udiv) << UCR0_UDIV_POS;	        /* set the UART divisor */
+	reg |= (udiv) << UCR1_UDIV_POS;	        /* set the UART divisor */
+	mtdcr (cpc0_ucr, reg);
+#else /* CONFIG_405EP */
+	reg = mfdcr(cntrl0) & ~CR0_MASK;
+#ifdef CFG_EXT_SERIAL_CLOCK
+	clk = CFG_EXT_SERIAL_CLOCK;
+	udiv = 1;
+	reg |= CR0_EXTCLK_ENA;
+#else
+	clk = gd->cpu_clk;
+#ifdef CFG_405_UART_ERRATA_59
+	udiv = 31;			/* Errata 59: stuck at 31 */
+#else
+	tmp = CFG_BASE_BAUD * 16;
+	udiv = (clk + tmp / 2) / tmp;
+	if (udiv > UDIV_MAX)                    /* max. n bits for udiv */
+		udiv = UDIV_MAX;
+#endif
+#endif
+	reg |= (udiv - 1) << CR0_UDIV_POS;	/* set the UART divisor */
+	mtdcr (cntrl0, reg);
+#endif /* CONFIG_405EP */
+	tmp = gd->baudrate * udiv * 16;
+	bdiv = (clk + tmp / 2) / tmp;
+#endif /* CONFIG_405EZ */
+
+	out8(dev_base + UART_LCR, 0x80);	/* set DLAB bit */
+	out8(dev_base + UART_DLL, bdiv);	/* set baudrate divisor */
+	out8(dev_base + UART_DLM, bdiv >> 8);	/* set baudrate divisor */
+	out8(dev_base + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */
+	out8(dev_base + UART_FCR, 0x00);	/* disable FIFO */
+	out8(dev_base + UART_MCR, 0x10);	/* enable loopback mode */
+	val = in8(dev_base + UART_LSR);	/* clear line status */
+	val = in8(dev_base + UART_RBR);	/* read receive buffer */
+	out8(dev_base + UART_SCR, 0x00);	/* set scratchpad */
+	out8(dev_base + UART_IER, 0x00);	/* set interrupt enable reg */
+
+	return (0);
+}
+#endif /* CONFIG_440 */
+
 static void uart_post_putc (unsigned long dev_base, char c)
 {
 	int i;
@@ -198,9 +323,7 @@
 int uart_post_test (int flags)
 {
 	int i, res = 0;
-	static unsigned long base[] = {
-		UART0_BASE, UART1_BASE, UART2_BASE, UART3_BASE
-	};
+	static unsigned long base[] = CFG_POST_UART_TABLE;
 
 	for (i = 0; i < sizeof (base) / sizeof (base[0]); i++) {
 		if (test_ctlr (base[i], i))