ppc4xx: Big lwmon5 board support rework/update

This patch brings the lwmon5 board support up-to-date. Here a
summary of the changes:

lwmon5 board port related:
- GPIO's changed to control the LSB transmitter
- Reset USB PHY's upon power-up
- Enable CAN upon power-up
- USB init error workaround (errata CHIP_6)
- EBC: Enable burstmode and modify the timings for the GDC memory
- EBC: Speed up NOR flash timings

lwmon5 board POST related:
- Add FPGA memory test
- Add GDC memory test
- DSP POST reworked
- SYSMON POST: Fix handling of negative temperatures
- Add output for sysmon1 POST
- HW-watchdog min. time test reworked

Additionally some coding-style changes were done.

Signed-off-by: Sascha Laue <sascha.laue@liebherr.com>
Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/board/lwmon5/kbd.c b/board/lwmon5/kbd.c
index 0e26b89..5231c7a 100644
--- a/board/lwmon5/kbd.c
+++ b/board/lwmon5/kbd.c
@@ -45,6 +45,10 @@
 /*--------------------- Local macros and constants --------------------*/
 #define	_NOT_USED_	0xFFFFFFFF
 
+/*------------------------- dspic io expander -----------------------*/
+#define DSPIC_PON_STATUS_REG	0x80A
+#define DSPIC_PON_INV_STATUS_REG 0x80C
+#define DSPIC_PON_KEY_REG	0x810
 /*------------------------- Keyboard controller -----------------------*/
 /* command codes */
 #define	KEYBD_CMD_READ_KEYS	0x01
@@ -75,6 +79,7 @@
 /* maximum number of "magic" key codes that can be assigned */
 
 static uchar kbd_addr = CONFIG_SYS_I2C_KEYBD_ADDR;
+static uchar dspic_addr = CONFIG_SYS_I2C_DSPIC_IO_ADDR;
 
 static uchar *key_match (uchar *);
 
@@ -167,6 +172,23 @@
 	}
 }
 
+
+/* Read a register from the dsPIC. */
+int _dspic_read(ushort reg, ushort *data)
+{
+	uchar buf[sizeof(*data)];
+	int rval;
+
+	if (i2c_read(dspic_addr, reg, 2, buf, 2))
+		return -1;
+
+	rval = i2c_read(dspic_addr, reg, sizeof(reg), buf, sizeof(*data));
+	*data = (buf[0] << 8) | buf[1];
+
+	return rval;
+}
+
+
 /***********************************************************************
 F* Function:     int misc_init_r (void) P*A*Z*
  *
@@ -197,6 +219,7 @@
 	uchar kbd_init_status = gd->kbd_status >> 8;
 	uchar kbd_status = gd->kbd_status;
 	uchar val;
+	ushort data, inv_data;
 	char *str;
 	int i;
 
@@ -231,9 +254,31 @@
 	i2c_write (kbd_addr, 0, 0, &val, 1);
 	i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
 
+	/* read out start key from bse01 received via can */
+	_dspic_read(DSPIC_PON_STATUS_REG, &data);
+	/* check highbyte from status register */
+	if (data > 0xFF) {
+		_dspic_read(DSPIC_PON_INV_STATUS_REG, &inv_data);
+
+		/* check inverse data */
+		if ((data+inv_data) == 0xFFFF) {
+			/* don't overwrite local key */
+			if (kbd_data[1] == 0) {
+				/* read key value */
+				_dspic_read(DSPIC_PON_KEY_REG, &data);
+				str = (char *)&data;
+				/* swap bytes */
+				kbd_data[1] = str[1];
+				kbd_data[2] = str[0];
+				printf("CAN received startkey: 0x%X\n", data);
+			}
+		}
+	}
+
 	for (i = 0; i < KEYBD_DATALEN; ++i) {
 		sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
 	}
+
 	setenv ("keybd", keybd_env);
 
 	str = strdup ((char *)key_match (kbd_data));	/* decode keys */
diff --git a/board/lwmon5/lwmon5.c b/board/lwmon5/lwmon5.c
index 9622b70..dd275bf 100644
--- a/board/lwmon5/lwmon5.c
+++ b/board/lwmon5/lwmon5.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2007
+ * (C) Copyright 2007-2010
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
  * This program is free software; you can redistribute it and/or
@@ -24,10 +24,13 @@
 #include <asm/processor.h>
 #include <asm/ppc4xx-gpio.h>
 #include <asm/io.h>
+#include <post.h>
+#include <flash.h>
+#include <mtd/cfi_flash.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-extern flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+static phys_addr_t lwmon5_cfi_flash_bank_addr[2] = CONFIG_SYS_FLASH_BANKS_LIST;
 
 ulong flash_get_size(ulong base, int banknum);
 int misc_init_r_kbd(void);
@@ -97,16 +100,18 @@
 	gpio_write_bit(CONFIG_SYS_GPIO_FLASH_WP, 1);
 
 #if CONFIG_POST & CONFIG_SYS_POST_BSPEC1
-	gpio_write_bit(CONFIG_SYS_GPIO_HIGHSIDE, 1);
+	/* enable the LSB transmitter */
+	gpio_write_bit(CONFIG_SYS_GPIO_LSB_ENABLE, 1);
+	/* enable the CAN transmitter */
+	gpio_write_bit(CONFIG_SYS_GPIO_CAN_ENABLE, 1);
 
 	reg = 0; /* reuse as counter */
 	out_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR,
 		in_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR)
 			& ~CONFIG_SYS_DSPIC_TEST_MASK);
-	while (!gpio_read_in_bit(CONFIG_SYS_GPIO_DSPIC_READY) && reg++ < 1000) {
+	while (gpio_read_in_bit(CONFIG_SYS_GPIO_DSPIC_READY) && reg++ < 1000) {
 		udelay(1000);
 	}
-	gpio_write_bit(CONFIG_SYS_GPIO_HIGHSIDE, 0);
 	if (gpio_read_in_bit(CONFIG_SYS_GPIO_DSPIC_READY)) {
 		/* set "boot error" flag */
 		out_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR,
@@ -135,9 +140,61 @@
 	return 0;
 }
 
-/*---------------------------------------------------------------------------+
-  | misc_init_r.
-  +---------------------------------------------------------------------------*/
+/*
+ * Override weak default with board specific version
+ */
+phys_addr_t cfi_flash_bank_addr(int bank)
+{
+	return lwmon5_cfi_flash_bank_addr[bank];
+}
+
+/*
+ * Override the weak default mapping function with a board specific one
+ */
+u32 flash_get_bank_size(int cs, int idx)
+{
+	return flash_info[idx].size;
+}
+
+int board_early_init_r(void)
+{
+	u32 val0, val1;
+
+	/*
+	 * lwmon5 is manufactured in 2 different board versions:
+	 * The lwmon5a board has 64MiB NOR flash instead of the
+	 * 128MiB of the original lwmon5. Unfortunately the CFI driver
+	 * will report 2 banks of 64MiB even for the smaller flash
+	 * chip, since the bank is mirrored. To fix this, we bring
+	 * one bank into CFI query mode and read its response. This
+	 * enables us to detect the real number of flash devices/
+	 * banks which will be used later on by the common CFI driver.
+	 */
+
+	/* Put bank 0 into CFI command mode and read */
+	out_be32((void *)CONFIG_SYS_FLASH0, 0x00980098);
+	val0 = in_be32((void *)CONFIG_SYS_FLASH0 + FLASH_OFFSET_CFI_RESP);
+	val1 = in_be32((void *)CONFIG_SYS_FLASH1 + FLASH_OFFSET_CFI_RESP);
+
+	/* Reset flash again out of query mode */
+	out_be32((void *)CONFIG_SYS_FLASH0, 0x00f000f0);
+
+	/* When not identical, we have 2 different flash devices/banks */
+	if (val0 != val1)
+		return 0;
+
+	/*
+	 * Now we're sure that we're running on a LWMON5a board with
+	 * only 64MiB NOR flash in one bank:
+	 *
+	 * Set flash base address and bank count for CFI driver probing.
+	 */
+	cfi_flash_num_flash_banks = 1;
+	lwmon5_cfi_flash_bank_addr[0] = CONFIG_SYS_FLASH0;
+
+	return 0;
+}
+
 int misc_init_r(void)
 {
 	u32 pbcr;
@@ -145,7 +202,7 @@
 	u32 reg;
 	unsigned long usb2d0cr = 0;
 	unsigned long usb2phy0cr, usb2h0cr = 0;
-	unsigned long sdr0_pfc1;
+	unsigned long sdr0_pfc1, sdr0_srst;
 
 	/*
 	 * FLASH stuff...
@@ -158,32 +215,7 @@
 	gd->bd->bi_flashoffset = 0;
 
 	mfebc(PB0CR, pbcr);
-	switch (gd->bd->bi_flashsize) {
-	case 1 << 20:
-		size_val = 0;
-		break;
-	case 2 << 20:
-		size_val = 1;
-		break;
-	case 4 << 20:
-		size_val = 2;
-		break;
-	case 8 << 20:
-		size_val = 3;
-		break;
-	case 16 << 20:
-		size_val = 4;
-		break;
-	case 32 << 20:
-		size_val = 5;
-		break;
-	case 64 << 20:
-		size_val = 6;
-		break;
-	case 128 << 20:
-		size_val = 7;
-		break;
-	}
+	size_val = ffs(gd->bd->bi_flashsize) - 21;
 	pbcr = (pbcr & 0x0001ffff) | gd->bd->bi_flashstart | (size_val << 17);
 	mtebc(PB0CR, pbcr);
 
@@ -193,53 +225,92 @@
 	flash_get_size(gd->bd->bi_flashstart, 0);
 
 	/* Monitor protection ON by default */
-	(void)flash_protect(FLAG_PROTECT_SET,
-			    -CONFIG_SYS_MONITOR_LEN,
-			    0xffffffff,
-			    &flash_info[1]);
+	flash_protect(FLAG_PROTECT_SET, -CONFIG_SYS_MONITOR_LEN, 0xffffffff,
+		      &flash_info[cfi_flash_num_flash_banks - 1]);
 
 	/* Env protection ON by default */
-	(void)flash_protect(FLAG_PROTECT_SET,
-			    CONFIG_ENV_ADDR_REDUND,
-			    CONFIG_ENV_ADDR_REDUND + 2*CONFIG_ENV_SECT_SIZE - 1,
-			    &flash_info[1]);
+	flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
+		      CONFIG_ENV_ADDR_REDUND + 2 * CONFIG_ENV_SECT_SIZE - 1,
+		      &flash_info[cfi_flash_num_flash_banks - 1]);
 
 	/*
 	 * USB suff...
 	 */
+
+	/* Reset USB */
+	/* Reset of USB2PHY0 must be active at least 10 us  */
+	mtsdr(SDR0_SRST0, SDR0_SRST0_USB2H | SDR0_SRST0_USB2D);
+	udelay(2000);
+
+	mtsdr(SDR0_SRST1, SDR0_SRST1_USB20PHY | SDR0_SRST1_USB2HUTMI |
+	      SDR0_SRST1_USB2HPHY | SDR0_SRST1_OPBA2 |
+	      SDR0_SRST1_PLB42OPB1 | SDR0_SRST1_OPB2PLB40);
+	udelay(2000);
+
+	/* Errata CHIP_6 */
+
+	/* 1. Set internal PHY configuration */
 	/* SDR Setting */
 	mfsdr(SDR0_PFC1, sdr0_pfc1);
 	mfsdr(SDR0_USB0, usb2d0cr);
 	mfsdr(SDR0_USB2PHY0CR, usb2phy0cr);
 	mfsdr(SDR0_USB2H0CR, usb2h0cr);
 
-	usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_XOCLK_MASK;
-	usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_XOCLK_EXTERNAL;	/*0*/
-	usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_WDINT_MASK;
-	usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_WDINT_16BIT_30MHZ;	/*1*/
-	usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_DVBUS_MASK;
-	usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_DVBUS_PURDIS;		/*0*/
-	usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_DWNSTR_MASK;
-	usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_DWNSTR_HOST;		/*1*/
-	usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_UTMICN_MASK;
-	usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_UTMICN_HOST;		/*1*/
+	usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_XOCLK_MASK;
+	usb2phy0cr = usb2phy0cr |  SDR0_USB2PHY0CR_XOCLK_EXTERNAL;	/*0*/
+	usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_WDINT_MASK;
+	usb2phy0cr = usb2phy0cr |  SDR0_USB2PHY0CR_WDINT_16BIT_30MHZ;	/*1*/
+	usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_DVBUS_MASK;
+	usb2phy0cr = usb2phy0cr |  SDR0_USB2PHY0CR_DVBUS_PUREN;		/*1*/
+	usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_DWNSTR_MASK;
+	usb2phy0cr = usb2phy0cr |  SDR0_USB2PHY0CR_DWNSTR_HOST;		/*1*/
+	usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_UTMICN_MASK;
+	usb2phy0cr = usb2phy0cr |  SDR0_USB2PHY0CR_UTMICN_HOST;		/*1*/
 
-	/* An 8-bit/60MHz interface is the only possible alternative
-	   when connecting the Device to the PHY */
-	usb2h0cr   = usb2h0cr &~SDR0_USB2H0CR_WDINT_MASK;
-	usb2h0cr   = usb2h0cr | SDR0_USB2H0CR_WDINT_16BIT_30MHZ;	/*1*/
+	/*
+	 * An 8-bit/60MHz interface is the only possible alternative
+	 * when connecting the Device to the PHY
+	 */
+	usb2h0cr   = usb2h0cr & ~SDR0_USB2H0CR_WDINT_MASK;
+	usb2h0cr   = usb2h0cr |  SDR0_USB2H0CR_WDINT_16BIT_30MHZ;	/*1*/
 
 	mtsdr(SDR0_PFC1, sdr0_pfc1);
 	mtsdr(SDR0_USB0, usb2d0cr);
 	mtsdr(SDR0_USB2PHY0CR, usb2phy0cr);
 	mtsdr(SDR0_USB2H0CR, usb2h0cr);
 
+	/* 2. De-assert internal PHY reset */
+	mfsdr(SDR0_SRST1, sdr0_srst);
+	sdr0_srst = sdr0_srst & ~SDR0_SRST1_USB20PHY;
+	mtsdr(SDR0_SRST1, sdr0_srst);
+
+	/* 3. Wait for more than 1 ms */
+	udelay(2000);
+
+	/* 4. De-assert USB 2.0 Host main reset */
+	mfsdr(SDR0_SRST0, sdr0_srst);
+	sdr0_srst = sdr0_srst &~ SDR0_SRST0_USB2H;
+	mtsdr(SDR0_SRST0, sdr0_srst);
+	udelay(1000);
+
+	/* 5. De-assert reset of OPB2 cores */
+	mfsdr(SDR0_SRST1, sdr0_srst);
+	sdr0_srst = sdr0_srst &~ SDR0_SRST1_PLB42OPB1;
+	sdr0_srst = sdr0_srst &~ SDR0_SRST1_OPB2PLB40;
+	sdr0_srst = sdr0_srst &~ SDR0_SRST1_OPBA2;
+	mtsdr(SDR0_SRST1, sdr0_srst);
+	udelay(1000);
+
+	/* 6. Set EHCI Configure FLAG */
+
+	/* 7. Reassert internal PHY reset: */
+	mtsdr(SDR0_SRST1, SDR0_SRST1_USB20PHY);
+	udelay(1000);
+
 	/*
 	 * Clear resets
 	 */
-	udelay (1000);
 	mtsdr(SDR0_SRST1, 0x00000000);
-	udelay (1000);
 	mtsdr(SDR0_SRST0, 0x00000000);
 
 	printf("USB:   Host(int phy) Device(ext phy)\n");
@@ -264,7 +335,7 @@
 {
 	char *s = getenv("serial#");
 
-	printf("Board: lwmon5");
+	puts("Board: lwmon5");
 
 	if (s != NULL) {
 		puts(", serial# ");
@@ -331,34 +402,33 @@
 
 extern GraphicDevice mb862xx;
 
-static const gdc_regs init_regs [] =
-{
-	{0x0100, 0x00000f00},
-	{0x0020, 0x801401df},
-	{0x0024, 0x00000000},
-	{0x0028, 0x00000000},
-	{0x002c, 0x00000000},
-	{0x0110, 0x00000000},
-	{0x0114, 0x00000000},
-	{0x0118, 0x01df0280},
-	{0x0004, 0x031f0000},
-	{0x0008, 0x027f027f},
-	{0x000c, 0x015f028f},
-	{0x0010, 0x020c0000},
-	{0x0014, 0x01df01ea},
-	{0x0018, 0x00000000},
-	{0x001c, 0x01e00280},
-	{0x0100, 0x80010f00},
-	{0x0, 0x0}
+static const gdc_regs init_regs [] = {
+	{ 0x0100, 0x00000f00 },
+	{ 0x0020, 0x801401df },
+	{ 0x0024, 0x00000000 },
+	{ 0x0028, 0x00000000 },
+	{ 0x002c, 0x00000000 },
+	{ 0x0110, 0x00000000 },
+	{ 0x0114, 0x00000000 },
+	{ 0x0118, 0x01df0280 },
+	{ 0x0004, 0x031f0000 },
+	{ 0x0008, 0x027f027f },
+	{ 0x000c, 0x015f028f },
+	{ 0x0010, 0x020c0000 },
+	{ 0x0014, 0x01df01ea },
+	{ 0x0018, 0x00000000 },
+	{ 0x001c, 0x01e00280 },
+	{ 0x0100, 0x80010f00 },
+	{ 0x0, 0x0 }
 };
 
-const gdc_regs *board_get_regs (void)
+const gdc_regs *board_get_regs(void)
 {
 	return init_regs;
 }
 
 /* Returns Lime base address */
-unsigned int board_video_init (void)
+unsigned int board_video_init(void)
 {
 	/*
 	 * Reset Lime controller
@@ -375,7 +445,7 @@
 	return CONFIG_SYS_LIME_BASE_0;
 }
 
-#define DEFAULT_BRIGHTNESS 0x64
+#define DEFAULT_BRIGHTNESS	0x64
 
 static void board_backlight_brightness(int brightness)
 {
@@ -390,7 +460,7 @@
 	}
 }
 
-void board_backlight_switch (int flag)
+void board_backlight_switch(int flag)
 {
 	char * param;
 	int rc;
@@ -410,15 +480,14 @@
 /*
  * Return text to be printed besides the logo.
  */
-void video_get_info_str (int line_number, char *info)
+void video_get_info_str(int line_number, char *info)
 {
-	if (line_number == 1) {
-		strcpy (info, " Board: Lwmon5 (Liebherr Elektronik GmbH)");
-	} else {
+	if (line_number == 1)
+		strcpy(info, " Board: Lwmon5 (Liebherr Elektronik GmbH)");
+	else
 		info [0] = '\0';
-	}
 }
-#endif
+#endif /* CONFIG_CONSOLE_EXTRA_INFO */
 #endif /* CONFIG_VIDEO */
 
 void board_reset(void)