+======================================================================
+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:
======================================================================
TQM8260_config \
TQM8260_L2_config \
+TQM8255_266MHz_config \
TQM8260_266MHz_config \
TQM8260_L2_266MHz_config \
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
/*------------------------ 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
*/
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);
}
#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;
/* 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;
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.
*
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]);
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*
*
***********************************************************************/
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
#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;
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;
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 */
puts ("Board: ");
- if (!i || strncmp (str, "TQM8260", 7)) {
+ if (!i || strncmp (str, "TQM82", 5)) {
puts ("### No HW ID - assuming TQM8260\n");
return (0);
}
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);
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);
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);
/*
- * (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
*/
/*
- * 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
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
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;
int i;
char *sep;
- puts ("MPC8260 Reset Status:");
+ puts (CPU_ID_STR " Reset Status:");
sep = " ";
for (i = 0; i < n; i++)
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:
#include <lcdvideo.h>
#include <linux/types.h>
#include <devices.h>
+#if defined(CONFIG_POST)
+#include <post.h>
+#endif
#ifdef CONFIG_LCD
#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 */
(((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)
{
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');
#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;
/*
#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[]);
#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
* CONFIG_L2_CACHE
* CONFIG_266MHz
* CONFIG_300MHz
+ * CONFIG_MPC8255
*/
/*
*/
#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
#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
CFG_POST_I2C | \
CFG_POST_SPI | \
CFG_POST_USB | \
- CFG_POST_SPR)
+ CFG_POST_SPR | \
+ CFG_POST_SYSMON)
#define CONFIG_BOOTCOMMAND "run flash_self"
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 */
*/
#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
#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 */
/*
* 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)
*/
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);
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;
#define CFG_POST_SPI 0x00000100
#define CFG_POST_USB 0x00000200
#define CFG_POST_SPR 0x00000400
+#define CFG_POST_SYSMON 0x00000800
#endif /* CONFIG_POST */
#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__ */
#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,
}
#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. */
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
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
#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;
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 */
--- /dev/null
+/*
+ * (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 */
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[] =
{
"This test verifies the CPU cache operation.",
POST_RAM | POST_ALWAYS,
&cache_post_test,
+ NULL,
+ NULL,
CFG_POST_CACHE
},
#endif
"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
"This test verifies the I2C operation.",
POST_RAM | POST_ALWAYS,
&i2c_post_test,
+ NULL,
+ NULL,
CFG_POST_I2C
},
#endif
"This test verifies the RTC operation.",
POST_RAM | POST_POWERFAIL | POST_MANUAL,
&rtc_post_test,
+ NULL,
+ NULL,
CFG_POST_RTC
},
#endif
"This test checks RAM.",
POST_ROM | POST_POWERON | POST_POWERFAIL | POST_PREREL,
&memory_post_test,
+ NULL,
+ NULL,
CFG_POST_MEMORY
},
#endif
" CPU.",
POST_RAM | POST_ALWAYS,
&cpu_post_test,
+ NULL,
+ NULL,
CFG_POST_CPU
},
#endif
"This test verifies the UART operation.",
POST_RAM | POST_POWERFAIL | POST_MANUAL,
&uart_post_test,
+ NULL,
+ NULL,
CFG_POST_UART
},
#endif
"This test verifies the ETHERNET operation.",
POST_RAM | POST_ALWAYS | POST_MANUAL,
ðer_post_test,
+ NULL,
+ NULL,
CFG_POST_ETHER
},
#endif
"This test verifies the SPI operation.",
POST_RAM | POST_ALWAYS | POST_MANUAL,
&spi_post_test,
+ NULL,
+ NULL,
CFG_POST_SPI
},
#endif
"This test verifies the USB operation.",
POST_RAM | POST_ALWAYS | POST_MANUAL,
&usb_post_test,
+ NULL,
+ NULL,
CFG_POST_USB
},
#endif
"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);