* Add support for log buffer which can be passed to Linux kernel's
syslog mechanism; used especially for POST results.
* Patch by Klaus Heydeck, 31 Oct 2002:
Add initial support for kup4k board
diff --git a/common/Makefile b/common/Makefile
index f2c90c7..3f4ff01 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -33,7 +33,7 @@
cmd_dcr.o cmd_diag.o cmd_doc.o cmd_dtt.o \
cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_flash.o \
cmd_fpga.o cmd_i2c.o cmd_ide.o cmd_immap.o \
- cmd_jffs2.o cmd_mem.o cmd_mii.o cmd_misc.o \
+ cmd_jffs2.o cmd_log.o cmd_mem.o cmd_mii.o cmd_misc.o \
cmd_net.o cmd_nvedit.o env_common.o \
env_flash.o env_eeprom.o env_nvram.o env_nowhere.o \
cmd_pci.o cmd_pcmcia.o \
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index e8ce40d..70ca999 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -325,6 +325,17 @@
initrd_high = ~0;
}
+#ifdef CONFIG_LOGBUFFER
+ kbd=gd->bd;
+ if ((s = getenv ("logstart")) != NULL) {
+ kbd->bi_sramstart = simple_strtoul(s, NULL, 16);
+ /* Prevent initrd from overwriting logbuffer */
+ if (initrd_high < kbd->bi_sramstart)
+ initrd_high = kbd->bi_sramstart-1024;
+ }
+ debug ("## Logbuffer at 0x%08lX ", kbd->bi_sramstart);
+#endif
+
/*
* Booting a (Linux) kernel image
*
@@ -337,17 +348,15 @@
asm( "mr %0,1": "=r"(sp) : );
-#ifdef DEBUG
- printf ("## Current stack ends at 0x%08lX ", sp);
-#endif
+ debug ("## Current stack ends at 0x%08lX ", sp);
+
sp -= 2048; /* just to be sure */
if (sp > CFG_BOOTMAPSZ)
sp = CFG_BOOTMAPSZ;
sp &= ~0xF;
-#ifdef DEBUG
- printf ("=> set upper limit to 0x%08lX\n", sp);
-#endif
+ debug ("=> set upper limit to 0x%08lX\n", sp);
+
cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
@@ -492,11 +501,9 @@
len = data = 0;
}
-#ifdef DEBUG
if (!data) {
- printf ("No initrd\n");
+ debug ("No initrd\n");
}
-#endif
if (data) {
initrd_start = (ulong)kbd - len;
@@ -527,10 +534,10 @@
}
SHOW_BOOT_PROGRESS (12);
-#ifdef DEBUG
- printf ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
+
+ debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
data, data + len - 1, len, len);
-#endif
+
initrd_end = initrd_start + len;
printf (" Loading Ramdisk to %08lx, end %08lx ... ",
initrd_start, initrd_end);
@@ -558,10 +565,10 @@
initrd_end = 0;
}
-#ifdef DEBUG
- printf ("## Transferring control to Linux (at address %08lx) ...\n",
+
+ debug ("## Transferring control to Linux (at address %08lx) ...\n",
(ulong)kernel);
-#endif
+
SHOW_BOOT_PROGRESS (15);
#ifdef CFG_INIT_RAM_LOCK
diff --git a/common/cmd_log.c b/common/cmd_log.c
new file mode 100644
index 0000000..2e42f10
--- /dev/null
+++ b/common/cmd_log.c
@@ -0,0 +1,223 @@
+/*
+ * (C) Copyright 2002
+ * Detlev Zundel, DENX Software Engineering, dzu@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
+ */
+
+/*
+ * Logbuffer handling routines
+ */
+
+#include <common.h>
+#include <command.h>
+#include <devices.h>
+#include <logbuff.h>
+
+#if defined(CONFIG_LOGBUFFER)
+
+#define LOG_BUF_LEN (16384)
+#define LOG_BUF_MASK (LOG_BUF_LEN-1)
+
+/* Local prototypes */
+static void logbuff_putc (const char c);
+static void logbuff_puts (const char *s);
+static int logbuff_printk(const char *line);
+
+static char buf[1024];
+
+static unsigned console_loglevel = 3;
+static unsigned default_message_loglevel = 4;
+static unsigned long log_size;
+static unsigned char *log_buf=NULL;
+static unsigned long *ext_log_start, *ext_logged_chars;
+#define log_start (*ext_log_start)
+#define logged_chars (*ext_logged_chars)
+
+/* Forced by code, eh! */
+#define LOGBUFF_MAGIC 0xc0de4ced
+
+int drv_logbuff_init (void)
+{
+ device_t logdev;
+ int rc;
+
+ /* Device initialization */
+ memset (&logdev, 0, sizeof (logdev));
+
+ strcpy (logdev.name, "logbuff");
+ logdev.ext = 0; /* No extensions */
+ logdev.flags = DEV_FLAGS_OUTPUT; /* Output only */
+ logdev.putc = logbuff_putc; /* 'putc' function */
+ logdev.puts = logbuff_puts; /* 'puts' function */
+
+ rc = device_register (&logdev);
+
+ return (rc == 0) ? 1 : rc;
+}
+
+static void logbuff_putc (const char c)
+{
+ char buf[2];
+ buf[0]=c;
+ buf[1]='\0';
+ logbuff_printk(buf);
+}
+
+static void logbuff_puts (const char *s)
+{
+ char buf[512];
+
+ sprintf(buf, "%s\n", s);
+ logbuff_printk(buf);
+}
+
+void logbuff_log(char *msg)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ if (gd->flags & GD_FLG_RELOC) {
+ logbuff_printk(msg);
+ } else {
+ puts(msg);
+ }
+}
+
+void logbuff_reset (void)
+{
+ char *s;
+ unsigned long *ext_tag;
+
+ if ((s = getenv ("logstart")) != NULL) {
+ log_buf = (unsigned char *)simple_strtoul(s, NULL, 16);
+ ext_tag=(unsigned long *)(log_buf)-3;
+ ext_log_start=(unsigned long *)(log_buf)-2;
+ ext_logged_chars=(unsigned long *)(log_buf)-1;
+// if (*ext_tag!=LOGBUFF_MAGIC) {
+ logged_chars=log_start=0;
+ *ext_tag=LOGBUFF_MAGIC;
+// }
+ log_size=logged_chars;
+ }
+}
+
+/*
+ * Subroutine: do_log
+ *
+ * Description: Handler for 'log' command..
+ *
+ * Inputs: argv[1] contains the subcommand
+ *
+ * Return: None
+ *
+ */
+int do_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *s;
+ unsigned long i;
+
+ if (log_buf==NULL) {
+ printf ("No logbuffer defined! Set 'logstart' to use this feature.\n");
+ return 1;
+ }
+
+ switch (argc) {
+
+ case 2:
+ if (strcmp(argv[1],"show") == 0) {
+ for (i=0; i<logged_chars; i++) {
+ s=log_buf+((log_start+i)&LOG_BUF_MASK);
+ putc(*s);
+ }
+ return 0;
+ } else if (strcmp(argv[1],"reset") == 0) {
+ log_start=0;
+ logged_chars=0;
+ log_size=0;
+ return 0;
+ }
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+
+ case 3:
+ if (strcmp(argv[1],"append") == 0) {
+ logbuff_puts(argv[2]);
+ return 0;
+
+ }
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+
+ default:
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+}
+
+static int logbuff_printk(const char *line)
+{
+ int i;
+ char *msg, *p, *buf_end;
+ int line_feed;
+ static signed char msg_level = -1;
+
+ strcpy(buf + 3, line);
+ i = strlen(line);
+ buf_end = buf + 3 + i;
+ for (p = buf + 3; p < buf_end; p++) {
+ msg = p;
+ if (msg_level < 0) {
+ if (
+ p[0] != '<' ||
+ p[1] < '0' ||
+ p[1] > '7' ||
+ p[2] != '>'
+ ) {
+ p -= 3;
+ p[0] = '<';
+ p[1] = default_message_loglevel + '0';
+ p[2] = '>';
+ } else
+ msg += 3;
+ msg_level = p[1] - '0';
+ }
+ line_feed = 0;
+ for (; p < buf_end; p++) {
+ log_buf[(log_start+log_size) & LOG_BUF_MASK] = *p;
+ if (log_size < LOG_BUF_LEN)
+ log_size++;
+ else
+ log_start++;
+
+ logged_chars++;
+ if (*p == '\n') {
+ line_feed = 1;
+ break;
+ }
+ }
+ if (msg_level < console_loglevel) {
+ printf("%s", msg);
+ }
+ if (line_feed)
+ msg_level = -1;
+ }
+ return i;
+}
+
+#endif /* (CONFIG_LOGBUFFER) */
diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c
index ccf21a9..6d01e70 100644
--- a/common/cmd_pcmcia.c
+++ b/common/cmd_pcmcia.c
@@ -1975,6 +1975,224 @@
#endif /* R360MPI */
+/* ---------------------------------------------------------------------------- */
+/* KUP4K Board */
+/* ---------------------------------------------------------------------------- */
+#if defined(CONFIG_KUP4K)
+
+#define PCMCIA_BOARD_MSG "KUP4K"
+
+#define KUP4K_PCMCIA_B_3V3 (0x00020000)
+
+static int hardware_enable(int slot)
+{
+ volatile immap_t *immap;
+ volatile cpm8xx_t *cp;
+ volatile pcmconf8xx_t *pcmp;
+ volatile sysconf8xx_t *sysp;
+ uint reg, mask;
+
+ debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+ udelay(10000);
+
+ immap = (immap_t *)CFG_IMMR;
+ sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+ cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+ /*
+ * Configure SIUMCR to enable PCMCIA port B
+ * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
+ */
+ sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
+
+ /* clear interrupt state, and disable interrupts */
+ pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
+ pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+ /* disable interrupts & DMA */
+ PCMCIA_PGCRX(_slot_) = 0;
+
+ /*
+ * Disable PCMCIA buffers (isolate the interface)
+ * and assert RESET signal
+ */
+ debug ("Disable PCMCIA buffers and assert RESET\n");
+ reg = PCMCIA_PGCRX(_slot_);
+ reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
+ reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
+ PCMCIA_PGCRX(_slot_) = reg;
+ udelay(500);
+
+ /*
+ * Configure Port B pins for
+ * 3 Volts enable
+ */
+ cp->cp_pbdir |= KUP4K_PCMCIA_B_3V3;
+ cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
+ /* remove all power */
+ cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3; /* active low */
+
+ /*
+ * Make sure there is a card in the slot, then configure the interface.
+ */
+ udelay(10000);
+ debug ("[%d] %s: PIPR(%p)=0x%x\n",
+ __LINE__,__FUNCTION__,
+ &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
+ if (pcmp->pcmc_pipr & 0x00001800) {
+ printf (" No Card found\n");
+ return (1);
+ }
+
+ /*
+ * Power On.
+ */
+ mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
+ reg = pcmp->pcmc_pipr;
+ debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
+ reg,
+ (reg&PCMCIA_VS1(slot))?"n":"ff",
+ (reg&PCMCIA_VS2(slot))?"n":"ff");
+ if ((reg & mask) == mask) {
+ puts (" 5.0V card found: NOT SUPPORTED !!!\n");
+ } else {
+ cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
+ puts (" 3.3V card found: ");
+ }
+#if 0
+ /* VCC switch error flag, PCMCIA slot INPACK_ pin */
+ cp->cp_pbdir &= ~(0x0020 | 0x0010);
+ cp->cp_pbpar &= ~(0x0020 | 0x0010);
+ udelay(500000);
+#endif
+ debug ("Enable PCMCIA buffers and stop RESET\n");
+ reg = PCMCIA_PGCRX(_slot_);
+ reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
+ reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
+ PCMCIA_PGCRX(_slot_) = reg;
+
+ udelay(250000); /* some cards need >150 ms to come up :-( */
+
+ debug ("# hardware_enable done\n");
+
+ return (0);
+}
+
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+ volatile immap_t *immap;
+ volatile cpm8xx_t *cp;
+ volatile pcmconf8xx_t *pcmp;
+ u_long reg;
+
+ debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+ immap = (immap_t *)CFG_IMMR;
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+ cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+ /* remove all power */
+ cp->cp_pbdat |= DDC4000_PCMCIA_B_3V3;
+
+ /* Configure PCMCIA General Control Register */
+ PCMCIA_PGCRX(_slot_) = 0;
+
+ debug ("Disable PCMCIA buffers and assert RESET\n");
+ reg = PCMCIA_PGCRX(_slot_);
+ reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
+ reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
+ PCMCIA_PGCRX(_slot_) = reg;
+
+ udelay(10000);
+
+ return (0);
+}
+#endif /* CFG_CMD_PCMCIA */
+
+
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+ volatile immap_t *immap;
+ volatile cpm8xx_t *cp;
+ volatile pcmconf8xx_t *pcmp;
+ u_long reg;
+
+ debug ("voltage_set: " \
+ PCMCIA_BOARD_MSG \
+ " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
+ 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
+
+ immap = (immap_t *)CFG_IMMR;
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+ cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+ /*
+ * Disable PCMCIA buffers (isolate the interface)
+ * and assert RESET signal
+ */
+ debug ("Disable PCMCIA buffers and assert RESET\n");
+ reg = PCMCIA_PGCRX(_slot_);
+ reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
+ reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
+ PCMCIA_PGCRX(_slot_) = reg;
+ udelay(500);
+
+ debug ("PCMCIA power OFF\n");
+ /*
+ * Configure Port B pins for
+ * 3 Volts enable
+ */
+ cp->cp_pbdir |= KUP4K_PCMCIA_B_3V3;
+ cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
+ /* remove all power */
+ cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3; /* active low */
+
+ switch(vcc) {
+ case 0: break;
+ case 33:
+ cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
+ debug ("PCMCIA powered at 3.3V\n");
+ break;
+ case 50:
+ debug ("PCMCIA: 5Volt vcc not supported\n");
+ break;
+ default:
+ puts("PCMCIA: vcc not supported");
+ break;
+ }
+
+ /* Checking supported voltages */
+
+ debug ("PIPR: 0x%x --> %s\n",
+ pcmp->pcmc_pipr,
+ (pcmp->pcmc_pipr & 0x00008000)
+ ? "only 5 V --> NOT SUPPORTED"
+ : "can do 3.3V");
+
+
+ debug ("Enable PCMCIA buffers and stop RESET\n");
+ reg = PCMCIA_PGCRX(_slot_);
+ reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
+ reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
+ PCMCIA_PGCRX(_slot_) = reg;
+ udelay(500);
+
+ debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
+ slot+'A');
+ return (0);
+}
+
+#endif /* KUP4K */
+
+
+
+
/* ---------------------------------------------------------------------------- */
/* End of Board Specific Stuff */
diff --git a/common/command.c b/common/command.c
index 2f50e6d..db39b41 100644
--- a/common/command.c
+++ b/common/command.c
@@ -68,6 +68,7 @@
#include <cmd_dtt.h>
#include <cmd_vfd.h> /* load a bitmap to the VFDs on TRAB */
+#include <cmd_log.h>
/*
* HELP command
@@ -280,6 +281,7 @@
CMD_TBL_KGDB
CMD_TBL_LOADB
CMD_TBL_LOADS
+ CMD_TBL_LOG
CMD_TBL_LOOP
CMD_TBL_JFFS2_LS
CMD_TBL_MCCINFO
diff --git a/common/devices.c b/common/devices.c
index 2d0b046..8207f83 100644
--- a/common/devices.c
+++ b/common/devices.c
@@ -178,6 +178,9 @@
#ifdef CONFIG_WL_4PPM_KEYBOARD
drv_wlkbd_init ();
#endif
+#ifdef CONFIG_LOGBUFFER
+ drv_logbuff_init ();
+#endif
drv_system_init ();
gd-> flags |= GD_FLG_DEVINIT; /* device initialization done */