Browse Source

* LWMON extensions:
- Splashscreen support
- modem support
- sysmon support
- temperature dependend enabling of LCD

* Allow booting from old "PPCBoot" disk partitions

* Add support for TQM8255 Board / MPC8255 CPU

wdenk 21 years ago
parent
commit
4532cb696e

+ 14 - 0
CHANGELOG

@@ -1,3 +1,17 @@
+======================================================================
+Changes since U-Boot 0.3.1:
+======================================================================
+
+* LWMON extensions:
+  - Splashscreen support
+  - modem support
+  - sysmon support
+  - temperature dependend enabling of LCD
+
+* Allow booting from old "PPCBoot" disk partitions
+
+* Add support for TQM8255 Board / MPC8255 CPU
+
 ======================================================================
 Changes for U-Boot 0.3.1:
 ======================================================================

+ 4 - 1
Makefile

@@ -577,6 +577,7 @@ SCM_config:		unconfig
 
 TQM8260_config	\
 TQM8260_L2_config	\
+TQM8255_266MHz_config	\
 TQM8260_266MHz_config	\
 TQM8260_L2_266MHz_config \
 TQM8260_300MHz_config:	unconfig
@@ -596,7 +597,9 @@ TQM8260_300MHz_config:	unconfig
 		{ echo "#define CONFIG_300MHz"	>>include/config.h ; \
 		  echo "... with 300MHz system clock" ; \
 		}
-	@./mkconfig -a $(call xtract_82xx,$@) ppc mpc8260 tqm8260
+	@[ -z "$(findstring TQM8255_,$@)" ] || \
+		{ echo "#define CONFIG_MPC8255"	>>include/config.h ; }
+	@./mkconfig -a TQM8260 ppc mpc8260 tqm8260
 
 #########################################################################
 ## 74xx/7xx Systems

+ 171 - 86
board/lwmon/lwmon.c

@@ -47,11 +47,18 @@ V* Verification:  dzu@denx.de
 
 /*------------------------ Local prototypes ---------------------------*/
 static long int dram_size (long int, long int *, long int);
+static void kbd_init (void);
+static int compare_magic (uchar *kbd_data, uchar *str);
 
 
 /*--------------------- Local macros and constants --------------------*/
 #define	_NOT_USED_	0xFFFFFFFF
 
+#ifdef CONFIG_MODEM_SUPPORT
+static int key_pressed(void);
+extern void disable_putc(void);
+#endif /* CONFIG_MODEM_SUPPORT */
+
 /*
  * 66 MHz SDRAM access using UPM A
  */
@@ -396,6 +403,7 @@ int board_pre_init (void)
 	immr->im_cpm.cp_pbodr &= ~PB_ENET_TENA;
 	immr->im_cpm.cp_pbdat &= ~PB_ENET_TENA;	/* set to 0 = disabled */
 	immr->im_cpm.cp_pbdir |= PB_ENET_TENA;
+
 	return (0);
 }
 
@@ -466,38 +474,45 @@ static uchar *key_match (uchar *);
 #define	KEYBD_SET_DEBUGMODE	'#'	/* Magic key to enable debug output */
 
 /***********************************************************************
-F* Function:     int misc_init_r (void) P*A*Z*
+F* Function:     int board_postclk_init (void) P*A*Z*
  *
 P* Parameters:   none
 P*
 P* Returnvalue:  int
-P*                - 0 is always returned, even in the case of a keyboard
-P*                    error.
+P*                - 0 is always returned.
  *
-Z* Intention:    This function is the misc_init_r() method implementation
+Z* Intention:    This function is the board_postclk_init() method implementation
 Z*               for the lwmon board.
-Z*               The keyboard controller is initialized and the result
-Z*               of a read copied to the environment variable "keybd".
-Z*               If KEYBD_SET_DEBUGMODE is defined, a check is made for
-Z*               this key, and if found display to the LCD will be enabled.
-Z*               The keys in "keybd" are checked against the magic
-Z*               keycommands defined in the environment.
-Z*               See also key_match().
  *
-D* Design:       wd@denx.de
-C* Coding:       wd@denx.de
-V* Verification: dzu@denx.de
  ***********************************************************************/
-int misc_init_r (void)
+int board_postclk_init (void)
 {
+	DECLARE_GLOBAL_DATA_PTR;
+
+	kbd_init();
+
+#ifdef CONFIG_MODEM_SUPPORT
+	if (key_pressed()) {
+		disable_putc();	/* modem doesn't understand banner etc */
+		gd->do_mdm_init = 1;
+	}
+#endif
+
+	return (0);
+}
+
+static void kbd_init (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
 	uchar kbd_data[KEYBD_DATALEN];
 	uchar tmp_data[KEYBD_DATALEN];
-	uchar keybd_env[2 * KEYBD_DATALEN + 1];
 	uchar val, errcd;
-	uchar *str;
 	int i;
 
 	i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+	
+	gd->kbd_status = 0;
 
 	/* Read initial keyboard error code */
 	val = KEYBD_CMD_READ_STATUS;
@@ -508,7 +523,7 @@ int misc_init_r (void)
 	/* clear "irrelevant" bits. Recommended by Martin Rajek, LWN */
 	errcd &= ~(KEYBD_STATUS_H_RESET|KEYBD_STATUS_BROWNOUT);
 	if (errcd) {
-		printf ("KEYBD: Error %02X\n", errcd);
+		gd->kbd_status |= errcd << 8;
 	}
 	/* Reset error code and verify */
 	val = KEYBD_CMD_RESET_ERRORS;
@@ -521,28 +536,10 @@ int misc_init_r (void)
 
 	val &= KEYBD_STATUS_MASK;	/* clear unused bits */
 	if (val) {			/* permanent error, report it */
-		printf ("*** Keyboard error code %02X ***\n", val);
-		sprintf (keybd_env, "%02X", val);
-		setenv ("keybd", keybd_env);
-		return 0;
-	}
-
-	/*
-	 * Now we know that we have a working  keyboard,  so  disable
-	 * all output to the LCD except when a key press is detected.
-	 */
-
-	if ((console_assign (stdout, "serial") < 0) ||
-		(console_assign (stderr, "serial") < 0)) {
-		printf ("Can't assign serial port as output device\n");
+		gd->kbd_status |= val;
+		return;
 	}
 
-	/* Read Version */
-	val = KEYBD_CMD_READ_VERSION;
-	i2c_write (kbd_addr, 0, 0, &val, 1);
-	i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_VERSIONLEN);
-	printf ("KEYBD: Version %d.%d\n", kbd_data[0], kbd_data[1]);
-
 	/*
 	 * Read current keyboard state.
 	 *
@@ -569,6 +566,73 @@ int misc_init_r (void)
 		memcpy (tmp_data, kbd_data, KEYBD_DATALEN);
 		udelay (5000);
 	}
+}
+
+/***********************************************************************
+F* Function:     int misc_init_r (void) P*A*Z*
+ *
+P* Parameters:   none
+P*
+P* Returnvalue:  int
+P*                - 0 is always returned, even in the case of a keyboard
+P*                    error.
+ *
+Z* Intention:    This function is the misc_init_r() method implementation
+Z*               for the lwmon board.
+Z*               The keyboard controller is initialized and the result
+Z*               of a read copied to the environment variable "keybd".
+Z*               If KEYBD_SET_DEBUGMODE is defined, a check is made for
+Z*               this key, and if found display to the LCD will be enabled.
+Z*               The keys in "keybd" are checked against the magic
+Z*               keycommands defined in the environment.
+Z*               See also key_match().
+ *
+D* Design:       wd@denx.de
+C* Coding:       wd@denx.de
+V* Verification: dzu@denx.de
+ ***********************************************************************/
+int misc_init_r (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	uchar kbd_data[KEYBD_DATALEN];
+	uchar keybd_env[2 * KEYBD_DATALEN + 1];
+	uchar kbd_init_status = gd->kbd_status >> 8;
+	uchar kbd_status = gd->kbd_status;
+	uchar val;
+	uchar *str;
+	int i;
+
+	if (kbd_init_status) {
+		printf ("KEYBD: Error %02X\n", kbd_init_status);
+	}
+	if (kbd_status) {		/* permanent error, report it */
+		printf ("*** Keyboard error code %02X ***\n", kbd_status);
+		sprintf (keybd_env, "%02X", kbd_status);
+		setenv ("keybd", keybd_env);
+		return 0;
+	}
+
+	/*
+	 * Now we know that we have a working  keyboard,  so  disable
+	 * all output to the LCD except when a key press is detected.
+	 */
+
+	if ((console_assign (stdout, "serial") < 0) ||
+		(console_assign (stderr, "serial") < 0)) {
+		printf ("Can't assign serial port as output device\n");
+	}
+
+	/* Read Version */
+	val = KEYBD_CMD_READ_VERSION;
+	i2c_write (kbd_addr, 0, 0, &val, 1);
+	i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_VERSIONLEN);
+	printf ("KEYBD: Version %d.%d\n", kbd_data[0], kbd_data[1]);
+
+	/* Read current keyboard state */
+	val = KEYBD_CMD_READ_KEYS;
+	i2c_write (kbd_addr, 0, 0, &val, 1);
+	i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
 
 	for (i = 0; i < KEYBD_DATALEN; ++i) {
 		sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
@@ -598,6 +662,56 @@ int misc_init_r (void)
 static uchar kbd_magic_prefix[] = "key_magic";
 static uchar kbd_command_prefix[] = "key_cmd";
 
+static int compare_magic (uchar *kbd_data, uchar *str)
+{
+	uchar compare[KEYBD_DATALEN-1];
+	uchar *nxt;
+	int i;
+
+	/* Don't include modifier byte */
+	memcpy (compare, kbd_data+1, KEYBD_DATALEN-1);
+
+	for (; str != NULL; str = (*nxt) ? nxt+1 : nxt) {
+		uchar c;
+		int k;
+
+		c = (uchar) simple_strtoul (str, (char **) (&nxt), 16);
+
+		if (str == nxt) {	/* invalid character */
+			break;
+		}
+
+		/*
+		 * Check if this key matches the input.
+		 * Set matches to zero, so they match only once
+		 * and we can find duplicates or extra keys
+		 */
+		for (k = 0; k < sizeof(compare); ++k) {
+			if (compare[k] == '\0')	/* only non-zero entries */
+				continue;
+			if (c == compare[k]) {	/* found matching key */
+				compare[k] = '\0';
+				break;
+			}
+		}
+		if (k == sizeof(compare)) {
+			return -1;		/* unmatched key */
+		}
+	}
+
+	/*
+	 * A full match leaves no keys in the `compare' array,
+	 */
+	for (i = 0; i < sizeof(compare); ++i) {
+		if (compare[i])
+		{
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 /***********************************************************************
 F* Function:     static uchar *key_match (uchar *kbd_data) P*A*Z*
  *
@@ -627,12 +741,9 @@ V* Verification: dzu@denx.de
  ***********************************************************************/
 static uchar *key_match (uchar *kbd_data)
 {
-	uchar compare[KEYBD_DATALEN-1];
 	uchar magic[sizeof (kbd_magic_prefix) + 1];
-	uchar extra;
-	uchar *str, *nxt, *suffix;
+	uchar *suffix;
 	uchar *kbd_magic_keys;
-	int i;
 
 	/*
 	 * The following string defines the characters that can pe appended
@@ -653,50 +764,7 @@ static uchar *key_match (uchar *kbd_data)
 #if 0
 		printf ("### Check magic \"%s\"\n", magic);
 #endif
-		/* Don't include modifier byte */
-		memcpy (compare, kbd_data+1, KEYBD_DATALEN-1);
-
-		extra = 0;
-
-		for (str= getenv(magic); str != NULL; str = (*nxt) ? nxt+1 : nxt) {
-			uchar c;
-			int k;
-
-			c = (uchar) simple_strtoul (str, (char **) (&nxt), 16);
-
-			if (str == nxt) {	/* invalid character */
-				break;
-			}
-
-			/*
-			 * Check if this key matches the input.
-			 * Set matches to zero, so they match only once
-			 * and we can find duplicates or extra keys
-			 */
-			for (k = 0; k < sizeof(compare); ++k) {
-				if (compare[k] == '\0')	/* only non-zero entries */
-					continue;
-				if (c == compare[k]) {	/* found matching key */
-					compare[k] = '\0';
-					break;
-				}
-			}
-			if (k == sizeof(compare)) {
-				extra = 1;		/* unmatched key */
-			}
-		}
-
-		/*
-		 * A full match leaves no keys in the `compare' array,
-		 * and has no extra keys
-		 */
-
-		for (i = 0; i < sizeof(compare); ++i) {
-			if (compare[i])
-				break;
-		}
-
-		if ((i == sizeof(compare)) && (extra == 0)) {
+		if (compare_magic(kbd_data, getenv(magic)) == 0) {
 			uchar cmd_name[sizeof (kbd_command_prefix) + 1];
 			char *cmd;
 
@@ -815,7 +883,9 @@ int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 	uchar val;
 	int i;
 
+#if 0 /* Done in kbd_init */
 	i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+#endif
 
 	/* Read keys */
 	val = KEYBD_CMD_READ_KEYS;
@@ -964,3 +1034,18 @@ void board_poweroff (void)
 
     while (1);
 }
+
+#ifdef CONFIG_MODEM_SUPPORT
+static int key_pressed(void)
+{
+	uchar kbd_data[KEYBD_DATALEN];
+	uchar val;
+
+	/* Read keys */
+	val = KEYBD_CMD_READ_KEYS;
+	i2c_write (kbd_addr, 0, 0, &val, 1);
+	i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
+
+	return (compare_magic(kbd_data, CONFIG_MODEM_KEY_MAGIC) == 0);
+}
+#endif	/* CONFIG_MODEM_SUPPORT */

+ 1 - 1
board/tqm8260/tqm8260.c

@@ -200,7 +200,7 @@ int checkboard (void)
 
 	puts ("Board: ");
 
-	if (!i || strncmp (str, "TQM8260", 7)) {
+	if (!i || strncmp (str, "TQM82", 5)) {
 		puts ("### No HW ID - assuming TQM8260\n");
 		return (0);
 	}

+ 2 - 1
common/cmd_ide.c

@@ -404,7 +404,8 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		SHOW_BOOT_PROGRESS (-1);
 		return 1;
 	}
-	if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
+	if ((strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) &&
+	    (strncmp(info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)) {
 		printf ("\n** Invalid partition type \"%.32s\""
 			" (expect \"" BOOT_PART_TYPE "\")\n",
 			info.type);

+ 2 - 1
common/cmd_scsi.c

@@ -262,7 +262,8 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		printf("error reading partinfo\n");
 		return 1;
 	}
-	if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
+	if ((strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) &&
+	    (strncmp(info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)) {
 		printf ("\n** Invalid partition type \"%.32s\""
 			" (expect \"" BOOT_PART_TYPE "\")\n",
 			info.type);

+ 2 - 1
common/cmd_usb.c

@@ -376,7 +376,8 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		info.size=2880;
 		printf("error reading partinfo...try to boot raw\n");
 	}
-	if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
+	if ((strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) &&
+	    (strncmp(info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)) {
 		printf ("\n** Invalid partition type \"%.32s\""
 			" (expect \"" BOOT_PART_TYPE "\")\n",
 			info.type);

+ 7 - 4
cpu/mpc8260/cpu.c

@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000
+ * (C) Copyright 2000-2003
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * See file CREDITS for list of people who contributed to this
@@ -22,12 +22,12 @@
  */
 
 /*
- * CPU specific code for the MPC8260
+ * CPU specific code for the MPC8255 / MPC8260 CPUs
  *
  * written or collected and sometimes rewritten by
  * Magnus Damm <damm@bitsmart.com>
  *
- * minor modifications by
+ * modified by
  * Wolfgang Denk <wd@denx.de>
  *
  * modified for 8260 by
@@ -64,7 +64,7 @@ int checkcpu (void)
 	if ((immr & IMMR_ISB_MSK) != CFG_IMMR)
 		return -1;	/* whoops! someone moved the IMMR */
 
-	printf ("MPC8260 (Rev %02x, Mask ", rev);
+	printf (CPU_ID_STR " (Rev %02x, Mask ", rev);
 
 	/*
 	 * the bottom 16 bits of the immr are the Part Number and Mask Number
@@ -101,6 +101,9 @@ int checkcpu (void)
 	case 0x0060:
 		printf ("A.0(A) 2K25A");
 		break;
+	case 0x0062:
+		printf ("B.1 4K25A");
+		break;
 	default:
 		printf ("unknown [immr=0x%04x,k=0x%04x]", m, k);
 		break;

+ 1 - 1
cpu/mpc8260/cpu_init.c

@@ -250,7 +250,7 @@ int prt_8260_rsr (void)
 	int i;
 	char *sep;
 
-	puts ("MPC8260 Reset Status:");
+	puts (CPU_ID_STR " Reset Status:");
 
 	sep = " ";
 	for (i = 0; i < n; i++)

+ 1 - 1
cpu/mpc8260/speed.c

@@ -171,7 +171,7 @@ int prt_8260_clks (void)
 
 	cp = &corecnf_tab[corecnf];
 
-	printf ("MPC8260 Clock Configuration\n - Bus-to-Core Mult ");
+	printf (CPU_ID_STR " Clock Configuration\n - Bus-to-Core Mult ");
 
 	switch (cp->b2c_mult) {
 	case _byp:

+ 7 - 0
cpu/mpc8xx/lcd.c

@@ -32,6 +32,9 @@
 #include <lcdvideo.h>
 #include <linux/types.h>
 #include <devices.h>
+#if defined(CONFIG_POST)
+#include <post.h>
+#endif
 
 
 #ifdef CONFIG_LCD
@@ -982,7 +985,11 @@ static void lcd_enable (void)
 
 #if defined(CONFIG_LWMON)
     {	uchar c = pic_read (0x60);
+#if defined(CONFIG_LCD) && defined(CONFIG_LWMON) && (CONFIG_POST & CFG_POST_SYSMON)
+    	c |= 0x04;	/* Chip Enable LCD */
+#else
     	c |= 0x07;	/* Power on CCFL, Enable CCFL, Chip Enable LCD */
+#endif
 	pic_write (0x60, c);
     }
 #endif /* CONFIG_LWMON */

+ 21 - 0
cpu/mpc8xx/serial.c

@@ -246,6 +246,20 @@ serial_setbrg (void)
 		(((gd->cpu_clk / 16 / gd->baudrate)-1) << 1) | CPM_BRG_EN;
 }
 
+#ifdef CONFIG_MODEM_SUPPORT
+void disable_putc(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	gd->be_quiet = 1;
+}
+
+void enable_putc(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	gd->be_quiet = 0;
+}
+#endif
+
 void
 serial_putc(const char c)
 {
@@ -255,6 +269,13 @@ serial_putc(const char c)
         volatile immap_t	*im = (immap_t *)CFG_IMMR;
 	volatile cpm8xx_t	*cpmp = &(im->im_cpm);
 
+#ifdef CONFIG_MODEM_SUPPORT
+	DECLARE_GLOBAL_DATA_PTR;
+
+	if (gd->be_quiet)
+		return;
+#endif
+
 	if (c == '\n')
 		serial_putc ('\r');
 

+ 8 - 0
include/asm-ppc/global_data.h

@@ -70,10 +70,18 @@ typedef	struct	global_data {
 #endif
 #ifdef CONFIG_POST
 	unsigned long	post_log_word;  /* Record POST activities */
+	unsigned long	post_init_f_time;  /* When post_init_f started */
 #endif
 #ifdef CONFIG_BOARD_TYPES
 	unsigned long	board_type;
 #endif
+#ifdef CONFIG_MODEM_SUPPORT
+	unsigned long do_mdm_init;
+	unsigned long be_quiet;
+#endif
+#ifdef CONFIG_LWMON
+	unsigned long kbd_status;
+#endif	
 } gd_t;
 
 /*

+ 1 - 1
include/cmd_bmp.h

@@ -32,7 +32,7 @@
 #define CMD_TBL_BMP	MK_CMD_TBL_ENTRY(				\
 	"bmp", 3,	3,	1,	do_bmp,				\
 	"bmp     - manipulate BMP image data\n",			\
-	"\nbmp info <imageAddr>    - display image info\n"		\
+	"info <imageAddr>    - display image info\n"			\
 	"bmp display <imageAddr> - display image\n"			\
 ),
 int do_bmp (cmd_tbl_t *cmdtp,  int flag, int argc, char *argv[]);

+ 3 - 2
include/cmd_disk.h

@@ -31,9 +31,10 @@
 #include <command.h>
 
 /*
- * Type string for PPC bootable partitions
+ * Type string for U-Boot bootable partitions
  */
-#define BOOT_PART_TYPE	"U-Boot"
+#define BOOT_PART_TYPE	"U-Boot"	/* primary boot partition type	*/
+#define BOOT_PART_COMP	"PPCBoot"	/* PPCBoot compatibility type	*/
 
 #if 0
 

+ 3 - 2
include/configs/TQM8260.h

@@ -33,6 +33,7 @@
  *	CONFIG_L2_CACHE
  *	CONFIG_266MHz
  *	CONFIG_300MHz
+ *	CONFIG_MPC8255
  */
 
 /*
@@ -312,10 +313,10 @@
  */
 #if defined(CONFIG_266MHz)
 #define CFG_HRCW_MASTER		(HRCW_CIP | HRCW_ISB111 | HRCW_BMS | \
-				                              HRCW_MODCK_H0111)
+				 HRCW_MODCK_H0111)
 #elif defined(CONFIG_300MHz)
 #define CFG_HRCW_MASTER		(HRCW_CIP | HRCW_ISB111 | HRCW_BMS | \
-				                              HRCW_MODCK_H0110)
+				 HRCW_MODCK_H0110)
 #else
 #define CFG_HRCW_MASTER		(HRCW_CIP | HRCW_ISB111 | HRCW_BMS)
 #endif

+ 12 - 3
include/configs/lwmon.h

@@ -40,10 +40,13 @@
 #define CONFIG_LWMON		1	/* ...on a LWMON board		*/
 
 #define CONFIG_BOARD_PRE_INIT	1	/* Call board_pre_init		*/
+#define CONFIG_BOARD_POSTCLK_INIT 1	/* Call board_postclk_init	*/
 
 #define CONFIG_LCD		1	/* use LCD controller ...	*/
 #define CONFIG_HLD1045		1	/* ... with a HLD1045 display	*/
 
+#define	CONFIG_SPLASH_SCREEN		/* ... with splashscreen support*/
+
 #if 1
 #define CONFIG_8xx_CONS_SMC2	1	/* Console is on SMC2		*/
 #else
@@ -72,7 +75,8 @@
 				 CFG_POST_I2C	   | \
 				 CFG_POST_SPI	   | \
 				 CFG_POST_USB	   | \
-				 CFG_POST_SPR)
+				 CFG_POST_SPR	   | \
+				 CFG_POST_SYSMON)
 
 #define CONFIG_BOOTCOMMAND	"run flash_self"
 
@@ -134,7 +138,7 @@
 			else    immr->im_cpm.cp_pbdat &= ~PB_SDA
 #define I2C_SCL(bit)	if(bit) immr->im_cpm.cp_pbdat |=  PB_SCL; \
 			else    immr->im_cpm.cp_pbdat &= ~PB_SCL
-#define I2C_DELAY	udelay(1)	/* 1/4 I2C clock duration */
+#define I2C_DELAY	udelay(2)	/* 1/4 I2C clock duration */
 #endif	/* CONFIG_SOFT_I2C */
 
 
@@ -229,7 +233,7 @@
  */
 #define CFG_INIT_RAM_ADDR	CFG_IMMR
 #define CFG_INIT_RAM_END	0x2F00	/* End of used area in DPRAM	*/
-#define CFG_GBL_DATA_SIZE	64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_SIZE	68  /* size in bytes reserved for initial data */
 #define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
 #define CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET
 
@@ -571,4 +575,9 @@
 #define BOOTFLAG_COLD	0x01		/* Normal Power-On: Boot from FLASH	*/
 #define BOOTFLAG_WARM	0x02		/* Software reboot			*/
 
+#define CONFIG_MODEM_SUPPORT	1	/* enable modem initialization stuff */
+#undef CONFIG_MODEM_SUPPORT_DEBUG
+
+#define	CONFIG_MODEM_KEY_MAGIC	"3C+3F"	/* hold down these keys to enable modem */
+
 #endif	/* __CONFIG_H */

+ 8 - 1
include/mpc8260.h

@@ -24,12 +24,19 @@
 /*
  * mpc8260.h
  *
- * MPC8260 specific definitions
+ * MPC8255 / MPC8260 specific definitions
  */
 
 #ifndef __MPC8260_H__
 #define __MPC8260_H__
 
+#ifdef CONFIG_MPC8255
+#define CPU_ID_STR	"MPC8255"
+#endif
+#ifndef CPU_ID_STR
+#define CPU_ID_STR	"MPC8260"
+#endif
+
 /*-----------------------------------------------------------------------
  * Exception offsets (PowerPC standard)
  */

+ 5 - 0
include/post.h

@@ -54,8 +54,11 @@ struct post_test {
 	char *desc;
 	int flags;
 	int (*test) (int flags);
+	int (*init_f) (void);
+	void (*reloc) (void);
 	unsigned long testid;
 };
+int post_init_f (void);
 void post_bootmode_init (void);
 int post_bootmode_get (unsigned int * last_test);
 void post_bootmode_clear (void);
@@ -64,6 +67,7 @@ int post_run (char *name, int flags);
 int post_info (char *name);
 int post_log (char *format, ...);
 void post_reloc (void);
+unsigned long post_time_ms (unsigned long base);
 
 extern struct post_test post_list[];
 extern unsigned int post_list_size;
@@ -81,6 +85,7 @@ extern unsigned int post_list_size;
 #define CFG_POST_SPI		0x00000100
 #define CFG_POST_USB		0x00000200
 #define CFG_POST_SPR		0x00000400
+#define CFG_POST_SYSMON		0x00000800
 
 #endif /* CONFIG_POST */
 

+ 1 - 1
include/version.h

@@ -24,6 +24,6 @@
 #ifndef	__VERSION_H__
 #define	__VERSION_H__
 
-#define	U_BOOT_VERSION	"U-Boot 0.3.1"
+#define	U_BOOT_VERSION	"U-Boot 0.3.2"
 
 #endif	/* __VERSION_H__ */

+ 108 - 0
lib_ppc/board.c

@@ -307,6 +307,9 @@ init_fnc_t *init_sequence[] = {
 #endif
 #if defined(CONFIG_DTT)		/* Digital Thermometers and Thermostats */
 	dtt_init,
+#endif
+#ifdef CONFIG_POST
+	post_init_f,
 #endif
 	INIT_FUNC_WATCHDOG_RESET
 	init_func_ram,
@@ -976,6 +979,13 @@ void board_init_r (gd_t *id, ulong dest_addr)
 	}
 #endif
 
+#ifdef CONFIG_MODEM_SUPPORT
+ {
+	 extern int do_mdm_init;
+	 do_mdm_init = gd->do_mdm_init;
+ }
+#endif
+
 	/* Initialization complete - start the monitor */
 
 	/* main_loop() can return to retry autoboot, if so just run it again. */
@@ -993,6 +1003,104 @@ void hang (void)
 	for (;;);
 }
 
+#ifdef CONFIG_MODEM_SUPPORT
+/* called from main loop (common/main.c) */
+extern void  dbg(const char *fmt, ...);
+int mdm_init (void)
+{
+	char env_str[16];
+	char *init_str;
+	int i;
+	extern char console_buffer[];
+	static inline void mdm_readline(char *buf, int bufsiz);
+	extern void enable_putc(void);
+	extern int hwflow_onoff(int);
+
+	enable_putc(); /* enable serial_putc() */
+
+#ifdef CONFIG_HWFLOW
+	init_str = getenv("mdm_flow_control");
+	if (init_str && (strcmp(init_str, "rts/cts") == 0))
+		hwflow_onoff (1);
+	else
+		hwflow_onoff(-1);
+#endif
+
+	for (i = 1;;i++) {
+		sprintf(env_str, "mdm_init%d", i);
+		if ((init_str = getenv(env_str)) != NULL) {
+			serial_puts(init_str);
+			serial_puts("\n");
+			for(;;) {
+				mdm_readline(console_buffer, CFG_CBSIZE);
+				dbg("ini%d: [%s]", i, console_buffer);
+
+				if ((strcmp(console_buffer, "OK") == 0) ||
+					(strcmp(console_buffer, "ERROR") == 0)) {
+					dbg("ini%d: cmd done", i);
+					break;
+				} else /* in case we are originating call ... */
+					if (strncmp(console_buffer, "CONNECT", 7) == 0) {
+						dbg("ini%d: connect", i);
+						return 0;
+					}
+			}
+		} else
+			break; /* no init string - stop modem init */
+
+		udelay(100000);
+	}
+
+	udelay(100000);
+
+	/* final stage - wait for connect */
+	for(;i > 1;) { /* if 'i' > 1 - wait for connection
+				  message from modem */
+		mdm_readline(console_buffer, CFG_CBSIZE);
+		dbg("ini_f: [%s]", console_buffer);
+		if (strncmp(console_buffer, "CONNECT", 7) == 0) {
+			dbg("ini_f: connected");
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+/* 'inline' - We have to do it fast */
+static inline void mdm_readline(char *buf, int bufsiz)
+{
+	char c;
+	char *p;
+	int n;
+
+	n = 0;
+	p = buf;
+	for(;;) {
+		c = serial_getc();
+
+		/*		dbg("(%c)", c); */
+
+		switch(c) {
+		case '\r':
+			break;
+		case '\n':
+			*p = '\0';
+			return;
+
+		default:
+			if(n++ > bufsiz) {
+				*p = '\0';
+				return; /* sanity check */
+			}
+			*p = c;
+			p++;
+			break;
+		}
+	}
+}
+#endif
+
 #if 0 /* We could use plain global data, but the resulting code is bigger */
 /*
  * Pointer to initial global data area

+ 1 - 1
post/Makefile

@@ -27,7 +27,7 @@ SUBDIRS = cpu
 LIB	= libpost.a
 
 AOBJS	= cache_8xx.o
-COBJS	= post.o tests.o cpu.o rtc.o watchdog.o memory.o i2c.o cache.o
+COBJS	= post.o tests.o cpu.o rtc.o watchdog.o memory.o i2c.o cache.o sysmon.o
 COBJS	+= uart.o ether.o usb.o spr.o
 
 include $(TOPDIR)/post/rules.mk

+ 52 - 0
post/post.c

@@ -36,6 +36,30 @@
 
 #define BOOTMODE_MAGIC	0xDEAD0000
 
+int post_init_f (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	int res = 0;
+	unsigned int i;
+
+	for (i = 0; i < post_list_size; i++) {
+		struct post_test *test = post_list + i;
+
+		if (test->init_f && test->init_f()) {
+			res = -1;
+		}
+	}
+	
+	gd->post_init_f_time = post_time_ms(0);
+	if (!gd->post_init_f_time)
+	{
+		printf("post/post.c: post_time_ms seems not to be implemented\n");
+	}
+
+	return res;
+}
+
 void post_bootmode_init (void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
@@ -365,7 +389,35 @@ void post_reloc (void)
 			addr = (ulong) (test->test) + gd->reloc_off;
 			test->test = (int (*)(int flags)) addr;
 		}
+
+		if (test->init_f) {
+			addr = (ulong) (test->init_f) + gd->reloc_off;
+			test->init_f = (int (*)(void)) addr;
+		}
+
+		if (test->reloc) {
+			addr = (ulong) (test->reloc) + gd->reloc_off;
+			test->reloc = (void (*)(void)) addr;
+			
+			test->reloc();
+		}
 	}
 }
 
+
+/*
+ * Some tests (e.g. SYSMON) need the time when post_init_f started,
+ * but we cannot use get_timer() at this point.
+ *
+ * On PowerPC we implement it using the timebase register.
+ */
+unsigned long post_time_ms (unsigned long base)
+{
+#ifdef CONFIG_PPC
+	return (unsigned long)get_ticks () / (get_tbclk () / CFG_HZ) - base;
+#else
+	return 0; /* Not implemented yet */
+#endif
+}
+
 #endif /* CONFIG_POST */

+ 330 - 0
post/sysmon.c

@@ -0,0 +1,330 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <post.h>
+#include <common.h>
+
+#ifdef CONFIG_POST
+
+/*
+ * SYSMON test
+ *
+ * This test performs the system hardware monitoring.
+ * The test passes when all the following voltages and temperatures
+ * are within allowed ranges:
+ * 
+ * Board temperature
+ * Front temperature
+ * +3.3V CPU logic
+ * +5V logic
+ * +12V PCMCIA
+ * +12V CCFL
+ * +5V standby
+ * 
+ * CCFL is not enabled if temperature values are not within allowed ranges
+ *
+ * See the list off all parameters in the sysmon_table below
+ */
+
+#include <post.h>
+#include <watchdog.h>
+#include <i2c.h>
+
+static int sysmon_temp_invalid = 0;
+
+#if CONFIG_POST & CFG_POST_SYSMON
+
+/* #define DEBUG */
+
+#define	RELOC(x) if (x != NULL) x = (void *) ((ulong) (x) + gd->reloc_off)
+
+typedef struct sysmon_s sysmon_t;
+typedef struct sysmon_table_s sysmon_table_t;
+
+static void sysmon_lm87_init (sysmon_t * this);
+static void sysmon_pic_init (sysmon_t * this);
+static uint sysmon_i2c_read (sysmon_t * this, uint addr);
+static uint sysmon_i2c_read_sgn (sysmon_t * this, uint addr);
+static void sysmon_ccfl_disable (sysmon_table_t * this);
+static void sysmon_ccfl_enable (sysmon_table_t * this);
+
+struct sysmon_s
+{
+	uchar	chip;
+	void	(*init)(sysmon_t *);
+	uint	(*read)(sysmon_t *, uint);
+};
+
+static sysmon_t sysmon_lm87 =
+	{CFG_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read};
+static sysmon_t sysmon_lm87_sgn =
+	{CFG_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read_sgn};
+static sysmon_t sysmon_pic =
+	{CFG_I2C_PICIO_ADDR, sysmon_pic_init, sysmon_i2c_read};
+
+static sysmon_t * sysmon_list[] =
+{
+	&sysmon_lm87,
+	&sysmon_lm87_sgn,
+	&sysmon_pic,
+	NULL
+};
+
+struct sysmon_table_s
+{
+	char *		name;
+	char *		unit_name;
+	sysmon_t *	sysmon;
+	void		(*exec_before)(sysmon_table_t *);
+	void		(*exec_after)(sysmon_table_t *);
+
+	int		unit_div;
+	int		unit_min;
+	int		unit_max;
+	uint		val_mask;
+	uint		val_min;
+	uint		val_max;
+	int		val_valid;
+	uint		addr;
+};
+
+static sysmon_table_t sysmon_table[] =
+{
+    {"Board temperature", " C", &sysmon_lm87_sgn, NULL, sysmon_ccfl_disable,
+     1, -128, 127, 0xFF, 0x58, 0xD5, 0, 0x27},
+
+    {"Front temperature", " C", &sysmon_lm87, NULL, sysmon_ccfl_disable,
+     100, -27316, 8984, 0xFF, 0xA4, 0xFC, 0, 0x29},
+
+    {"+3.3V CPU logic", "V", &sysmon_lm87, NULL, NULL,
+     1000, 0, 4386, 0xFF, 0xB6, 0xC9, 0, 0x22},
+
+    {"+5V logic", "V", &sysmon_lm87, NULL, NULL,
+     1000, 0, 6630, 0xFF, 0xB6, 0xCA, 0, 0x23},
+
+    {"+12V PCMCIA", "V", &sysmon_lm87, NULL, NULL,
+     1000, 0, 15460, 0xFF, 0xBC, 0xD0, 0, 0x21},
+
+    {"+12V CCFL", "V", &sysmon_lm87, NULL, sysmon_ccfl_enable,
+     1000, 0, 15900, 0xFF, 0xB6, 0xCA, 0, 0x24},
+
+    {"+5V standby", "V", &sysmon_pic, NULL, NULL,
+     1000, 0, 6040, 0xFF, 0xC8, 0xDE, 0, 0x7C},
+};
+static int sysmon_table_size = sizeof(sysmon_table) / sizeof(sysmon_table[0]);
+
+static int conversion_done = 0;
+
+
+int sysmon_init_f (void)
+{
+	sysmon_t ** l;
+	ulong reg;
+
+	/* Power on CCFL, PCMCIA */
+	reg = pic_read  (0x60);
+	reg |= 0x09;
+	pic_write (0x60, reg);
+
+	for (l = sysmon_list; *l; l++)
+	{
+		(*l)->init(*l);
+	}
+	
+	return 0;
+}
+
+void sysmon_reloc (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	sysmon_t ** l;
+	sysmon_table_t * t;
+
+	for (l = sysmon_list; *l; l++)
+	{
+		RELOC(*l);
+		RELOC((*l)->init);
+		RELOC((*l)->read);
+	}
+
+	for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++)
+	{
+		RELOC(t->exec_before);
+		RELOC(t->exec_after);
+		RELOC(t->sysmon);
+	}
+}
+
+static char * sysmon_unit_value (sysmon_table_t * s, uint val)
+{
+	static char buf[32];
+	int unit_val =
+	    s->unit_min + (s->unit_max - s->unit_min) * val / s->val_mask;
+	char * p;
+	int dec, frac;
+
+	sprintf(buf, "%+d", unit_val / s->unit_div);
+	
+	frac = (unit_val > 0 ? unit_val : -unit_val) % s->unit_div;
+	p = buf + strlen(buf);
+	
+	dec = s->unit_div;
+	
+	if (dec != 1)
+	{
+		*p++ = '.';
+	}
+	
+	for (dec /= 10; dec != 0; dec /= 10)
+	{
+		*p++ = '0' + frac / dec % 10;
+	}
+	
+	strcpy(p, s->unit_name);
+	
+	return buf;
+}
+
+static void sysmon_lm87_init (sysmon_t * this)
+{
+	uchar val;
+
+	/* Detect LM87 chip */
+	if (i2c_read(this->chip, 0x40, 1, &val, 1) || (val & 0x80) != 0 ||
+	    i2c_read(this->chip, 0x3E, 1, &val, 1) || val != 0x02)
+	{
+		printf("Error: LM87 not found at 0x%02X\n", this->chip);
+		return;
+	}
+	
+	/* Configure pins 5,6 as AIN */
+	val = 0x03;
+	if (i2c_write(this->chip, 0x16, 1, &val, 1))
+	{
+		printf("Error: can't write LM87 config register\n");
+		return;
+	}
+
+	/* Start monitoring */
+	val = 0x01;
+	if (i2c_write(this->chip, 0x40, 1, &val, 1))
+	{
+		printf("Error: can't write LM87 config register\n");
+		return;
+	}
+}
+
+static void sysmon_pic_init (sysmon_t * this)
+{
+}
+
+static uint sysmon_i2c_read (sysmon_t * this, uint addr)
+{
+	uchar val;
+	uint res = i2c_read(this->chip, addr, 1, &val, 1);
+
+	return res == 0 ? val : -1;
+}
+
+static uint sysmon_i2c_read_sgn (sysmon_t * this, uint addr)
+{
+	uchar val;
+	return i2c_read(this->chip, addr, 1, &val, 1) == 0 ?
+		128 + (signed char)val : -1;
+}
+
+static void sysmon_ccfl_disable (sysmon_table_t * this)
+{
+	if (!this->val_valid)
+	{
+		sysmon_temp_invalid = 1;
+	}
+}
+
+static void sysmon_ccfl_enable (sysmon_table_t * this)
+{
+	ulong reg;
+
+	if (!sysmon_temp_invalid)
+	{
+		reg = pic_read  (0x60);
+		reg |= 0x02;
+		pic_write (0x60, reg);
+	}
+}
+
+int sysmon_post_test (int flags)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	int res = 0;
+	sysmon_table_t * t;
+	uint val;
+
+	/*
+	 * The A/D conversion on the LM87 sensor takes 300 ms.
+	 */
+	if (! conversion_done)
+	{
+		while (post_time_ms(gd->post_init_f_time) < 300) WATCHDOG_RESET ();
+		conversion_done = 1;
+	}
+
+	for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++)
+	{
+		if (t->exec_before)
+		{
+			t->exec_before(t);
+		}
+
+		val = t->sysmon->read(t->sysmon, t->addr);
+		t->val_valid = val >= t->val_min && val <= t->val_max;
+
+		if (t->exec_after)
+		{
+			t->exec_after(t);
+		}
+
+#ifndef DEBUG
+		if (!t->val_valid)
+#endif
+		{
+			printf("%-17s = %-10s ", t->name, sysmon_unit_value(t, val));
+			printf("allowed range");
+			printf(" %-8s ..", sysmon_unit_value(t, t->val_min));
+			printf(" %-8s", sysmon_unit_value(t, t->val_max));
+			printf("     %s\n", t->val_valid ? "OK" : "FAIL");
+		}
+
+		if (!t->val_valid)
+		{
+			res = -1;
+		}
+	}
+
+	return res;
+}
+
+#endif /* CONFIG_POST & CFG_POST_SYSMON */
+#endif /* CONFIG_POST */

+ 40 - 0
post/tests.c

@@ -42,6 +42,12 @@ extern int ether_post_test (int flags);
 extern int spi_post_test (int flags);
 extern int usb_post_test (int flags);
 extern int spr_post_test (int flags);
+extern int sysmon_post_test (int flags);
+
+extern int sysmon_init_f (void);
+
+extern void sysmon_reloc (void);
+
 
 struct post_test post_list[] =
 {
@@ -52,6 +58,8 @@ struct post_test post_list[] =
         "This test verifies the CPU cache operation.",
         POST_RAM | POST_ALWAYS,
         &cache_post_test,
+        NULL,
+        NULL,
 	CFG_POST_CACHE
     },
 #endif
@@ -62,6 +70,8 @@ struct post_test post_list[] =
         "This test checks the watchdog timer.",
         POST_RAM | POST_POWERON | POST_POWERFAIL | POST_MANUAL | POST_REBOOT,
         &watchdog_post_test,
+        NULL,
+        NULL,
 	CFG_POST_WATCHDOG
     },
 #endif
@@ -72,6 +82,8 @@ struct post_test post_list[] =
         "This test verifies the I2C operation.",
         POST_RAM | POST_ALWAYS,
         &i2c_post_test,
+        NULL,
+        NULL,
 	CFG_POST_I2C
     },
 #endif
@@ -82,6 +94,8 @@ struct post_test post_list[] =
         "This test verifies the RTC operation.",
         POST_RAM | POST_POWERFAIL | POST_MANUAL,
         &rtc_post_test,
+        NULL,
+        NULL,
 	CFG_POST_RTC
     },
 #endif
@@ -92,6 +106,8 @@ struct post_test post_list[] =
         "This test checks RAM.",
         POST_ROM | POST_POWERON | POST_POWERFAIL | POST_PREREL,
         &memory_post_test,
+        NULL,
+        NULL,
 	CFG_POST_MEMORY
     },
 #endif
@@ -103,6 +119,8 @@ struct post_test post_list[] =
         " CPU.",
         POST_RAM | POST_ALWAYS,
         &cpu_post_test,
+        NULL,
+        NULL,
 	CFG_POST_CPU
     },
 #endif
@@ -113,6 +131,8 @@ struct post_test post_list[] =
         "This test verifies the UART operation.",
         POST_RAM | POST_POWERFAIL | POST_MANUAL,
         &uart_post_test,
+        NULL,
+        NULL,
 	CFG_POST_UART
     },
 #endif
@@ -123,6 +143,8 @@ struct post_test post_list[] =
         "This test verifies the ETHERNET operation.",
         POST_RAM | POST_ALWAYS | POST_MANUAL,
         &ether_post_test,
+        NULL,
+        NULL,
 	CFG_POST_ETHER
     },
 #endif
@@ -133,6 +155,8 @@ struct post_test post_list[] =
         "This test verifies the SPI operation.",
         POST_RAM | POST_ALWAYS | POST_MANUAL,
         &spi_post_test,
+        NULL,
+        NULL,
 	CFG_POST_SPI
     },
 #endif
@@ -143,6 +167,8 @@ struct post_test post_list[] =
         "This test verifies the USB operation.",
         POST_RAM | POST_ALWAYS | POST_MANUAL,
         &usb_post_test,
+        NULL,
+        NULL,
 	CFG_POST_USB
     },
 #endif
@@ -153,9 +179,23 @@ struct post_test post_list[] =
         "This test checks SPR contents.",
         POST_ROM | POST_ALWAYS | POST_PREREL,
         &spr_post_test,
+        NULL,
+        NULL,
 	CFG_POST_SPR
     },
 #endif
+#if CONFIG_POST & CFG_POST_SYSMON
+    {
+        "SYSMON test",
+        "sysmon",
+        "This test monitors system hardware.",
+        POST_RAM | POST_ALWAYS,
+        &sysmon_post_test,
+        &sysmon_init_f,
+        &sysmon_reloc,
+	CFG_POST_SYSMON
+    },
+#endif
 };
 
 unsigned int post_list_size = sizeof (post_list) / sizeof (struct post_test);