* Add support for 16 MB flash configuration of TRAB board

* Patch by Erwin Rol, 27 Feb 2003:
  Add support for RTEMS

* Add image information to README

* Fix dual PCMCIA slot support (when running with just one
  slot populated)

* Add VFD type detection to trab board

* extend drivers/cs8900.c driver to synchronize  ethaddr  environment
  variable with value in the EEPROM

* Start adding MIPS support files
diff --git a/board/sc520_cdp/sc520_cdp.c b/board/sc520_cdp/sc520_cdp.c
index ba6255f..2809ff7 100644
--- a/board/sc520_cdp/sc520_cdp.c
+++ b/board/sc520_cdp/sc520_cdp.c
@@ -31,35 +31,35 @@
 
 static void irq_init(void)
 {
-
+	
 	/* disable global interrupt mode */
-	write_mmcr_byte(SC520_PICICR, 0x40);
-
+	write_mmcr_byte(SC520_PICICR, 0x40); 
+	
 	/* set irq0-7 to edge */
 	write_mmcr_byte(SC520_MPICMODE, 0x00);
-
+	
 	/* set irq9-12 to level, all the other (8, 13-15) are edge */
 	write_mmcr_byte(SC520_SL1PICMODE, 0x1e);
-
+	
 	/* set irq16-24 (unused slave pic2) to level */
 	write_mmcr_byte(SC520_SL2PICMODE, 0xff);
-
-	/* active low polarity on PIC interrupt pins,
+	
+	/* active low polarity on PIC interrupt pins, 
 	   active high polarity on all other irq pins */
 	write_mmcr_word(SC520_INTPINPOL, 0);
 
 	/* set irq number mapping */
-	write_mmcr_byte(SC520_GPTMR0MAP,0);            /* disable GP timer 0 INT */
+	write_mmcr_byte(SC520_GPTMR0MAP,0);            /* disable GP timer 0 INT */       
 	write_mmcr_byte(SC520_GPTMR1MAP,0);            /* disable GP timer 1 INT */
 	write_mmcr_byte(SC520_GPTMR2MAP,0);            /* disable GP timer 2 INT */
-	write_mmcr_byte(SC520_PIT0MAP,0x1);            /* Set PIT timer 0 INT to IRQ0 */
+	write_mmcr_byte(SC520_PIT0MAP,0x1);            /* Set PIT timer 0 INT to IRQ0 */ 
 	write_mmcr_byte(SC520_PIT1MAP,0);              /* diable PIT timer 1 INT */
 	write_mmcr_byte(SC520_PIT2MAP,0);              /* diable PIT timer 2 INT */
 	write_mmcr_byte(SC520_PCIINTAMAP,0x4);         /* Set PCI INT A to IRQ9 */
 	write_mmcr_byte(SC520_PCIINTBMAP,0x5);         /* Set PCI INT B to IRQ10 */
 	write_mmcr_byte(SC520_PCIINTCMAP,0x6);         /* Set PCI INT C to IRQ11 */
 	write_mmcr_byte(SC520_PCIINTDMAP,0x7);         /* Set PCI INT D to IRQ12 */
-	write_mmcr_byte(SC520_DMABCINTMAP,0);          /* disable DMA INT */
+	write_mmcr_byte(SC520_DMABCINTMAP,0);          /* disable DMA INT */ 
 	write_mmcr_byte(SC520_SSIMAP,0);               /* disable Synchronius serial INT */
 	write_mmcr_byte(SC520_WDTMAP,0);               /* disable Watchdor INT */
 	write_mmcr_byte(SC520_RTCMAP,0x3);             /* Set RTC int to 8 */
@@ -69,28 +69,28 @@
 	write_mmcr_byte(SC520_GP0IMAP,6);              /* Set GPIRQ0 (ISA IRQ2) to IRQ9 */
 	write_mmcr_byte(SC520_GP1IMAP,2);              /* Set GPIRQ1 (SIO IRQ1) to IRQ1 */
 	write_mmcr_byte(SC520_GP2IMAP,7);              /* Set GPIRQ2 (ISA IRQ12) to IRQ12 */
-
+	
 	if (CFG_USE_SIO_UART) {
 		write_mmcr_byte(SC520_UART1MAP,0);     /* disable internal UART1 INT */
 		write_mmcr_byte(SC520_UART2MAP,0);     /* disable internal UART2 INT */
-		write_mmcr_byte(SC520_GP3IMAP,11);     /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */
+		write_mmcr_byte(SC520_GP3IMAP,11);     /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */ 
 		write_mmcr_byte(SC520_GP4IMAP,12);     /* Set GPIRQ4 (ISA IRQ4) to IRQ4 */
 	} else {
 		write_mmcr_byte(SC520_UART1MAP,12);    /* Set internal UART2 INT to IRQ4 */
 		write_mmcr_byte(SC520_UART2MAP,11);    /* Set internal UART2 INT to IRQ3 */
-		write_mmcr_byte(SC520_GP3IMAP,0);      /* disable GPIRQ3 (ISA IRQ3) */
+		write_mmcr_byte(SC520_GP3IMAP,0);      /* disable GPIRQ3 (ISA IRQ3) */ 
 		write_mmcr_byte(SC520_GP4IMAP,0);      /* disable GPIRQ4 (ISA IRQ4) */
 	}
-
+	
 	write_mmcr_byte(SC520_GP5IMAP,13);             /* Set GPIRQ5 (ISA IRQ5) to IRQ5 */
 	write_mmcr_byte(SC520_GP6IMAP,21);             /* Set GPIRQ6 (ISA IRQ6) to IRQ6 */
 	write_mmcr_byte(SC520_GP7IMAP,22);             /* Set GPIRQ7 (ISA IRQ7) to IRQ7 */
 	write_mmcr_byte(SC520_GP8IMAP,3);              /* Set GPIRQ8 (SIO IRQ8) to IRQ8 */
 	write_mmcr_byte(SC520_GP9IMAP,4);              /* Set GPIRQ9 (ISA IRQ9) to IRQ9 */
-	write_mmcr_byte(SC520_GP10IMAP,9);             /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */
+	write_mmcr_byte(SC520_GP10IMAP,9);             /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */          
 	write_mmcr_word(SC520_PCIHOSTMAP,0x11f);       /* Map PCI hostbridge INT to NMI */
 	write_mmcr_word(SC520_ECCMAP,0x100);           /* Map SDRAM ECC failure INT to NMI */
-
+ 
 }
 
 /* PCI stuff */
@@ -98,11 +98,11 @@
 {
 	char pin;
 	int irq;
-
-
+	
+	
 	pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
 	irq = pin-1;
-
+	
 	switch (PCI_DEV(dev)) {
 	case 20:
 		break;
@@ -115,20 +115,20 @@
 	case 17:
 		irq+=3;
 		break;
-	default:
+	default: 
 		return;
 	}
-
+	
 	irq&=3; /* wrap around */
 	irq+=9; /* lowest IRQ is 9 */
-
+	
 	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, irq);
-#if 0
-	printf("fixup_irq: device %d pin %c irq %d\n",
+#if 0	
+	printf("fixup_irq: device %d pin %c irq %d\n", 
 	       PCI_DEV(dev), 'A' + pin -1, irq);
 #endif
 }
-
+ 
 static struct pci_controller sc520_cdp_hose = {
 	fixup_irq: pci_sc520_cdp_fixup_irq,
 };
@@ -147,7 +147,7 @@
 void setup_ali_sio(int uart_primary)
 {
 	ali512x_init();
-
+	
 	ali512x_set_fdc(ALI_ENABLED, 0x3f2, 6, 0);
 	ali512x_set_pp(ALI_ENABLED, 0x278, 7, 3);
 	ali512x_set_uart(ALI_ENABLED, ALI_UART1, uart_primary?0x3f8:0x3e8, 4);
@@ -155,21 +155,21 @@
 	ali512x_set_rtc(ALI_DISABLED, 0, 0);
 	ali512x_set_kbc(ALI_ENABLED, 1, 12);
 	ali512x_set_cio(ALI_ENABLED);
-
+	
 	/* IrDa pins */
 	ali512x_cio_function(12, 1, 0, 0);
 	ali512x_cio_function(13, 1, 0, 0);
-
+	
 	/* SSI chip select pins */
 	ali512x_cio_function(14, 0, 0, 0);  /* SSI_CS */
-	ali512x_cio_function(15, 0, 0, 0);  /* SSI_MV */
+	ali512x_cio_function(15, 0, 0, 0);  /* SSI_MV */					     
 	ali512x_cio_function(16, 0, 1, 0);  /* SSI_SPI# (inverted) */
 
 	/* Board REV pins */
 	ali512x_cio_function(20, 0, 0, 1);
 	ali512x_cio_function(21, 0, 0, 1);
 	ali512x_cio_function(22, 0, 0, 1);
-	ali512x_cio_function(23, 0, 0, 1);
+	ali512x_cio_function(23, 0, 0, 1);      
 }
 
 
@@ -178,13 +178,13 @@
 {
 
 	/* set up the GP IO pins */
-	write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); 	/* set the GPIO pin function 31-16 reg */
+	write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); 	/* set the GPIO pin function 31-16 reg */		   
 	write_mmcr_word(SC520_PIOPFS15_0, 0xffff);  	/* set the GPIO pin function 15-0 reg */
-	write_mmcr_byte(SC520_CSPFS, 0xf8);  		/* set the CS pin function  reg */
+	write_mmcr_byte(SC520_CSPFS, 0xf8);  		/* set the CS pin function  reg */	
 	write_mmcr_byte(SC520_CLKSEL, 0x70);
 
-
-	write_mmcr_byte(SC520_GPCSRT, 1);   /* set the GP CS offset */
+	
+	write_mmcr_byte(SC520_GPCSRT, 1);   /* set the GP CS offset */    	
 	write_mmcr_byte(SC520_GPCSPW, 3);   /* set the GP CS pulse width */
 	write_mmcr_byte(SC520_GPCSOFF, 1);  /* set the GP CS offset */
 	write_mmcr_byte(SC520_GPRDW, 3);    /* set the RD pulse width */
@@ -192,40 +192,40 @@
         write_mmcr_byte(SC520_GPWRW, 3);    /* set the GP WR pulse width */
 	write_mmcr_byte(SC520_GPWROFF, 1);  /* set the GP WR offset */
 
-	write_mmcr_word(SC520_BOOTCSCTL, 0x1823);		/* set up timing of BOOTCS */
+	write_mmcr_word(SC520_BOOTCSCTL, 0x1823);		/* set up timing of BOOTCS */ 
 	write_mmcr_word(SC520_ROMCS1CTL, 0x1823);		/* set up timing of ROMCS1 */
-	write_mmcr_word(SC520_ROMCS2CTL, 0x1823);		/* set up timing of ROMCS2 */
-
+	write_mmcr_word(SC520_ROMCS2CTL, 0x1823);		/* set up timing of ROMCS2 */ 
+	
 	/* adjust the memory map:
 	 * by default the first 256MB (0x00000000 - 0x0fffffff) is mapped to SDRAM
 	 * and 256MB to 1G-128k  (0x1000000 - 0x37ffffff) is mapped to PCI mmio
-	 * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */
-
-
+	 * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */ 
+	
+		
 	/* SRAM = GPCS3 128k @ d0000-effff*/
-	write_mmcr_long(SC520_PAR2,  0x4e00400d);
-
+	write_mmcr_long(SC520_PAR2,  0x4e00400d);		
+	
 	/* IDE0 = GPCS6 1f0-1f7 */
-	write_mmcr_long(SC520_PAR3,  0x380801f0);
+	write_mmcr_long(SC520_PAR3,  0x380801f0);		
 
 	/* IDE1 = GPCS7 3f6 */
-	write_mmcr_long(SC520_PAR4,  0x3c0003f6);
+	write_mmcr_long(SC520_PAR4,  0x3c0003f6);		
 	/* bootcs */
-	write_mmcr_long(SC520_PAR12, 0x8bffe800);
+	write_mmcr_long(SC520_PAR12, 0x8bffe800);		
 	/* romcs2 */
-	write_mmcr_long(SC520_PAR13, 0xcbfff000);
+	write_mmcr_long(SC520_PAR13, 0xcbfff000);		
 	/* romcs1 */
-	write_mmcr_long(SC520_PAR14, 0xabfff800);
+	write_mmcr_long(SC520_PAR14, 0xabfff800);		
 	/* 680 LEDS */
-	write_mmcr_long(SC520_PAR15, 0x30000640);
-
-	asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */
+	write_mmcr_long(SC520_PAR15, 0x30000640);		
+	
+	asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */	
 
 	if (CFG_USE_SIO_UART) {
-		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS);
+		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS);	
 		setup_ali_sio(1);
 	} else {
-		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));
+		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));	
 		setup_ali_sio(0);
 		silence_uart(0x3e8);
 		silence_uart(0x2e8);
@@ -242,21 +242,21 @@
 int board_init(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
-
-	init_sc520();
+	
+	init_sc520();	
 	bus_init();
 	irq_init();
-
+		
 	/* max drive current on SDRAM */
 	write_mmcr_word(SC520_DSCTL, 0x0100);
-
+		
 	/* enter debug mode after next reset (only if jumper is also set) */
 	write_mmcr_byte(SC520_RESCFG, 0x08);
-
+	
 	/* configure the software timer to 33.333MHz */
 	write_mmcr_byte(SC520_SWTMRCFG, 0);
 	gd->bus_clk = 33333000;
-
+	
 	return 0;
 }
 
@@ -277,14 +277,14 @@
 {
 	int minor;
 	int major;
-
+	
 	major = minor = 0;
 	major |= ali512x_cio_in(23)?2:0;
 	major |= ali512x_cio_in(22)?1:0;
 	minor |= ali512x_cio_in(21)?2:0;
 	minor |= ali512x_cio_in(20)?1:0;
-
+	
 	printf("AMD SC520 CDP revision %d.%d\n", major, minor);
-
+	
 	return 0;
 }
diff --git a/board/smdk2400/flash.c b/board/smdk2400/flash.c
index c4d6bae..6882b88 100644
--- a/board/smdk2400/flash.c
+++ b/board/smdk2400/flash.c
@@ -76,7 +76,7 @@
 		flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
 		memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
 		if (i == 0)
-			flashbase = PHYS_FLASH_1;
+			flashbase = CFG_FLASH_BASE;
 		else
 			panic ("configured too many flash banks!\n");
 		for (j = 0; j < flash_info[i].sector_count; j++) {
diff --git a/board/trab/flash.c b/board/trab/flash.c
index 2443777..a4f164b 100644
--- a/board/trab/flash.c
+++ b/board/trab/flash.c
@@ -26,12 +26,7 @@
 #include <common.h>
 #include <environment.h>
 
-ulong myflush (void);
-
-
-#define FLASH_BANK_SIZE	0x800000	/* 8 MB */
-/* this varies depending on the sector */
-#define MAIN_SECT_SIZE  0x20000		/* 2 x 64 kB */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
 
 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
 
@@ -43,6 +38,7 @@
 #define CMD_ERASE_CONFIRM	0x00300030
 #define CMD_PROGRAM		0x00A000A0
 #define CMD_UNLOCK_BYPASS	0x00200020
+#define CMD_READ_MANF_ID	0x00900090
 
 #define MEM_FLASH_ADDR1		(*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2)))
 #define MEM_FLASH_ADDR2		(*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2)))
@@ -64,27 +60,38 @@
 	int i, j;
 	ulong size = 0;
 
-	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
 		ulong flashbase = 0;
+		flash_info_t *info = &flash_info[i];
 
-		flash_info[i].flash_id =
-			(AMD_MANUFACT  & FLASH_VENDMASK) |
-			(AMD_ID_LV320B & FLASH_TYPEMASK);
-		flash_info[i].size = FLASH_BANK_SIZE;
-		flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
-		memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
+		/* Init: no FLASHes known */
+		info->flash_id = FLASH_UNKNOWN;
+
+		size += flash_get_size (CFG_FLASH_BASE, info);
+
 		if (i == 0)
-			flashbase = PHYS_FLASH_1;
+			flashbase = CFG_FLASH_BASE;
 		else
 			panic ("configured too many flash banks!\n");
-		for (j = 0; j < flash_info[i].sector_count; j++) {
+		for (j = 0; j < info->sector_count; j++) {
 
-			flash_info[i].start[j] = flashbase;
+			info->protect[j] = 0;
+			info->start[j] = flashbase;
 
-			/* the first 8 sectors are 8 kB */
-			flashbase += (j < 8) ? 0x4000 : MAIN_SECT_SIZE;
+			switch (info->flash_id & FLASH_TYPEMASK) {
+			case (FLASH_AM320B & FLASH_TYPEMASK):
+				/* Boot sector type: 8 x 8 + N x 128 kB */
+				flashbase += (j < 8) ? 0x4000 : 0x20000;
+				break;
+			case (FLASH_AM640U & FLASH_TYPEMASK):
+				/* Uniform sector type: 128 kB */
+				flashbase += 0x20000;
+				break;
+			default:
+				printf ("## Bad flash chip type 0x%04lX\n",
+					info->flash_id & FLASH_TYPEMASK);
+			}
 		}
-		size += flash_info[i].size;
 	}
 
 	/*
@@ -116,7 +123,7 @@
 	int i;
 
 	switch (info->flash_id & FLASH_VENDMASK) {
-	case (AMD_MANUFACT & FLASH_VENDMASK):
+	case (FLASH_MAN_AMD & FLASH_VENDMASK):
 		printf ("AMD: ");
 		break;
 	default:
@@ -125,9 +132,12 @@
 	}
 
 	switch (info->flash_id & FLASH_TYPEMASK) {
-	case (AMD_ID_LV320B & FLASH_TYPEMASK):
+	case (FLASH_AM320B & FLASH_TYPEMASK):
 		printf ("2x Am29LV320DB (32Mbit)\n");
 		break;
+	case (FLASH_AM640U & FLASH_TYPEMASK):
+		printf ("2x Am29LV640D (64Mbit)\n");
+		break;
 	default:
 		printf ("Unknown Chip Type\n");
 		goto Done;
@@ -177,7 +187,7 @@
 	}
 
 	if ((info->flash_id & FLASH_VENDMASK) !=
-		(AMD_MANUFACT & FLASH_VENDMASK)) {
+		(FLASH_MAN_AMD & FLASH_VENDMASK)) {
 		return ERR_UNKNOWN_FLASH_VENDOR;
 	}
 
@@ -265,13 +275,6 @@
 				rc = ERR_TIMOUT;
 				goto outahere;
 			}
-
-#if 0
-			printf ("ok.\n");
-		} else {		/* it was protected */
-
-			printf ("protected!\n");
-#endif
 		}
 	}
 
@@ -453,3 +456,71 @@
 
 	return write_word (info, wp, data);
 }
+
+/*-----------------------------------------------------------------------
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	ulong value;
+
+	/* Write auto select command sequence and read Manufacturer ID */
+	addr[0x0555] = CMD_UNLOCK1;
+	addr[0x02AA] = CMD_UNLOCK2;
+	addr[0x0555] = CMD_READ_MANF_ID;
+
+	value = addr[0];
+
+	debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value);
+
+	switch (value) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		addr[0] = 0x00FF00FF;		/* restore read mode */
+		debug ("## flash_init: unknown manufacturer\n");
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
+
+	switch (value) {
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 71;
+		info->size = 0x00800000;
+
+		addr[0] = 0x00FF00FF;		/* restore read mode */
+		break;				/* =>  8 MB		*/
+
+	case AMD_ID_LV640U:
+		info->flash_id += FLASH_AM640U;
+		info->sector_count = 128;
+		info->size = 0x01000000;
+
+		addr[0] = 0x00F000F0;		/* restore read mode */
+		break;				/* => 16 MB		*/
+
+	default:
+		debug ("## flash_init: unknown flash chip\n");
+		info->flash_id = FLASH_UNKNOWN;
+		addr[0] = 0x00FF00FF;		/* restore read mode */
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	return (info->size);
+}
diff --git a/board/trab/trab.c b/board/trab/trab.c
index 32f27ef..111c861 100644
--- a/board/trab/trab.c
+++ b/board/trab/trab.c
@@ -60,11 +60,8 @@
 
 int board_init ()
 {
-#if defined(CONFIG_MODEM_SUPPORT) && defined(CONFIG_VFD)
-	ulong size;
-	unsigned long addr;
-	extern void mem_malloc_init (ulong);
-	extern int drv_vfd_init(void);
+#if defined(CONFIG_VFD)
+	extern int vfd_init_clocks(void);
 #endif
 	DECLARE_GLOBAL_DATA_PTR;
 
@@ -107,26 +104,11 @@
 	/* adress of boot parameters */
 	gd->bd->bi_boot_params = 0x0c000100;
 
-#ifdef CONFIG_MODEM_SUPPORT
 #ifdef CONFIG_VFD
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096
-#endif
-	/*
-	 * reserve memory for VFD display (always full pages)
-	 */
-	/* armboot_real_end is defined in the board-specific linker script */
-	addr = (_armboot_real_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-	size = vfd_setmem (addr);
-	gd->fb_base = addr;
-	/* round to the next page boundary */
-	addr += size;
-	addr = (addr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-	mem_malloc_init (addr);
-	/* must do this after the framebuffer is allocated */
-	drv_vfd_init();
+	vfd_init_clocks();
 #endif /* CONFIG_VFD */
 
+#ifdef CONFIG_MODEM_SUPPORT
 	udelay_no_timer (KBD_MDELAY);
 
 	if (key_pressed()) {
diff --git a/board/trab/vfd.c b/board/trab/vfd.c
index 234a9d4..fa1194c 100644
--- a/board/trab/vfd.c
+++ b/board/trab/vfd.c
@@ -55,12 +55,16 @@
 #define BLAU	0x0C
 #define VIOLETT	0X0D
 
-ulong vfdbase;
-ulong frame_buf_size;
+ulong	vfdbase;
+ulong	frame_buf_size;
 #define frame_buf_offs 4
 
+/* Supported VFD Types */
+#define	VFD_TYPE_T119C		1	/* Noritake T119C VFD */
+#define	VFD_TYPE_MN11236	2
+
 /* taken from armboot/common/vfd.c */
-ulong         adr_vfd_table[112][18][2][4][2];
+unsigned long adr_vfd_table[112][18][2][4][2];
 unsigned char bit_vfd_table[112][18][2][4][2];
 
 /*
@@ -68,26 +72,42 @@
  */
 void init_grid_ctrl(void)
 {
+	DECLARE_GLOBAL_DATA_PTR;
 	ulong adr, grid_cycle;
 	unsigned int bit, display;
 	unsigned char temp, bit_nr;
+	ulong val;
 
-	for (adr=vfdbase; adr<=(vfdbase+7168); adr+=4) /*clear frame buffer */
-		(*(volatile ulong*)(adr))=0;
+	/*
+	 * clear frame buffer (logical clear => set to "black")
+	 */
+	if (gd->vfd_inv_data == 0)
+		val = 0;
+	else
+		val = ~0;
 
-	for(display=0;display<=3;display++)
-	{
-		for(grid_cycle=0;grid_cycle<=55;grid_cycle++)
-		{
-			bit = grid_cycle*256*4+(grid_cycle+200)*4+frame_buf_offs+display;
+	for (adr = vfdbase; adr <= (vfdbase+7168); adr += 4) {
+		(*(volatile ulong*)(adr)) = val;
+	}
+
+	switch (gd->vfd_type) {
+	case VFD_TYPE_T119C:
+	    for (display=0; display<4; display++) {
+		for(grid_cycle=0; grid_cycle<56; grid_cycle++) {
+			bit = grid_cycle * 256  * 4 +
+			     (grid_cycle + 200) * 4 +
+			     frame_buf_offs + display;
  			/* wrap arround if offset (see manual S3C2400) */
 			if (bit>=frame_buf_size*8)
-				bit = bit-(frame_buf_size*8);
-			adr = vfdbase+(bit/32)*4+(3-(bit%32)/8);
-			bit_nr = bit%8;
-			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+				bit = bit - (frame_buf_size * 8);
+			adr = vfdbase + (bit/32) * 4 + (3 - (bit%32) / 8);
+			bit_nr = bit % 8;
+			bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
 			temp=(*(volatile unsigned char*)(adr));
-			temp|=(1<<bit_nr);
+			if (gd->vfd_inv_data)
+				temp &= ~(1<<bit_nr);
+			else
+				temp |=  (1<<bit_nr);
 			(*(volatile unsigned char*)(adr))=temp;
 
 			if(grid_cycle<55)
@@ -101,9 +121,54 @@
 			bit_nr = bit%8;
 			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
 			temp=(*(volatile unsigned char*)(adr));
-			temp|=(1<<bit_nr);
+			if (gd->vfd_inv_data)
+				temp &= ~(1<<bit_nr);
+			else
+				temp |=  (1<<bit_nr);
 			(*(volatile unsigned char*)(adr))=temp;
 		}
+	    }
+	    break;
+	case VFD_TYPE_MN11236:
+	    for (display=0; display<4; display++) {
+		for (grid_cycle=0; grid_cycle<38; grid_cycle++) {
+			bit = grid_cycle * 256  * 4 +
+			     (253 - grid_cycle) * 4 +
+			     frame_buf_offs + display;
+			/* wrap arround if offset (see manual S3C2400) */
+			if (bit>=frame_buf_size*8)
+				bit = bit - (frame_buf_size * 8);
+			adr = vfdbase + (bit/32) * 4 + (3 - (bit%32) / 8);
+			bit_nr = bit % 8;
+			bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
+			temp=(*(volatile unsigned char*)(adr));
+			if (gd->vfd_inv_data)
+				temp &= ~(1<<bit_nr);
+			else
+				temp |=  (1<<bit_nr);
+			(*(volatile unsigned char*)(adr))=temp;
+
+			if(grid_cycle<37)
+				bit = grid_cycle*256*4+(252-grid_cycle)*4+frame_buf_offs+display;
+
+			/* wrap arround if offset (see manual S3C2400) */
+			if (bit>=frame_buf_size*8)
+				bit = bit-(frame_buf_size*8);
+			adr = vfdbase+(bit/32)*4+(3-(bit%32)/8);
+			bit_nr = bit%8;
+			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+			temp=(*(volatile unsigned char*)(adr));
+			if (gd->vfd_inv_data)
+				temp &= ~(1<<bit_nr);
+			else
+				temp |=  (1<<bit_nr);
+			(*(volatile unsigned char*)(adr))=temp;
+		}
+	    }
+	    break;
+	default:
+	    printf ("Warning: unknown display type\n");
+	    break;
 	}
 }
 
@@ -113,175 +178,142 @@
  */
 void create_vfd_table(void)
 {
-	unsigned int vfd_table[112][18][2][4][2];
-	ulong adr;
-	unsigned int x, y, color, display, entry, pixel, bit_nr;
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned long vfd_table[112][18][2][4][2];
+	unsigned int x, y, color, display, entry, pixel;
+	unsigned int x_abcdef = 0;
 
-	/*
-	 * Create translation table for Noritake-T119C-VFD-specific
-	 * organized frame-buffer.
-	 * Created is the number of the bit in the framebuffer (the
-	 * first transferred pixel of each frame is bit 0).
-	 */
-	for(y=0;y<=17;y++)   /* Zeile */
-	{
-		for(x=0;x<=111;x++)  /* Spalten */
-		{
-			/*Display 0 blaue Pixel Eintrag 1 */
-			vfd_table[x][y][0][0][0]=((x%4)*4+y*16+(x/4)*2048);
-			/*Display 0 rote Pixel Eintrag 1 */
-			vfd_table[x][y][1][0][0]=((x%4)*4+y*16+(x/4)*2048+512);
-			if(x<=1)
-			{
-				/*Display 0 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1024);
-				/*Display 0 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1024);
-			}
-			else
-			{
-				/*Display 0 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+1024);
-				/*Display 0 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1024);
-			}
-			/*Display 1 blaue Pixel Eintrag 1 */
-			vfd_table[x][y][0][1][0]=((x%4)*4+y*16+(x/4)*2048+1);
-			/*Display 1 rote Pixel Eintrag 1 */
-			vfd_table[x][y][1][1][0]=((x%4)*4+y*16+(x/4)*2048+512+1);
-			if(x<=1)
-			{
-				/*Display 1 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1+1024);
-				/*Display 1 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1+1024);
-			}
-			else
-			{
-				/*Display 1 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+1+1024);
-				/*Display 1 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1+1024);
-			}
-			/*Display 2 blaue Pixel Eintrag 1 */
-			vfd_table[x][y][0][2][0]=((x%4)*4+y*16+(x/4)*2048+2);
-			/*Display 2 rote Pixel Eintrag 1 */
-			vfd_table[x][y][1][2][0]=((x%4)*4+y*16+(x/4)*2048+512+2);
-			if(x<=1)
-			{
-				/*Display 2 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+2+1024);
-				/*Display 2 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+2+1024);
-			}
-			else
-			{
-				/*Display 2 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+2+1024);
-				/*Display 2 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+2+1024);
-			}
-			/*Display 3 blaue Pixel Eintrag 1 */
-			vfd_table[x][y][0][3][0]=((x%4)*4+y*16+(x/4)*2048+3);
-			/*Display 3 rote Pixel Eintrag 1 */
-			vfd_table[x][y][1][3][0]=((x%4)*4+y*16+(x/4)*2048+512+3);
-			if(x<=1)
-			{
-				/*Display 3 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+3+1024);
-				/*Display 3 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+3+1024);
-			}
-			else
-			{
-				/*Display 3 blaue Pixel Eintrag 2 */
-				vfd_table[x][y][0][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+3+1024);
-				/*Display 3 rote Pixel Eintrag 2 */
-				vfd_table[x][y][1][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+3+1024);
-			}
+	switch (gd->vfd_type) {
+	case VFD_TYPE_T119C:
+	    for(y=0; y<=17; y++) {	/* Line */
+		for(x=0; x<=111; x++) {	/* Column */
+		    for(display=0; display <=3; display++) {
+
+			    /* Display 0 blue pixels */
+			    vfd_table[x][y][0][display][0] =
+				(x==0) ? y*16+display
+				       : (x%4)*4+y*16+((x-1)/2)*1024+display;
+			    /* Display 0 red pixels */
+			    vfd_table[x][y][1][display][0] =
+				(x==0) ? y*16+512+display
+			    	       : (x%4)*4+y*16+((x-1)/2)*1024+512+display;
+		    }
 		}
+	    }
+	    break;
+	case VFD_TYPE_MN11236:
+	    for(y=0; y<=17; y++) {	/* Line */
+		for(x=0; x<=111; x++) {	/* Column */
+		    for(display=0; display <=3; display++) {
+
+			    vfd_table[x][y][0][display][0]=0;
+			    vfd_table[x][y][0][display][1]=0;
+			    vfd_table[x][y][1][display][0]=0;
+			    vfd_table[x][y][1][display][1]=0;
+
+			    switch (x%6) {
+			    case 0: x_abcdef=0; break; /* a -> a */
+			    case 1: x_abcdef=2; break; /* b -> c */
+			    case 2: x_abcdef=4; break; /* c -> e */
+			    case 3: x_abcdef=5; break; /* d -> f */
+			    case 4: x_abcdef=3; break; /* e -> d */
+			    case 5: x_abcdef=1; break; /* f -> b */
+			    }
+
+			    /* blue pixels */
+			    vfd_table[x][y][0][display][0] =
+				(x>1) ? x_abcdef*4+((x-1)/3)*1024+y*48+display
+				      : x_abcdef*4+             0+y*48+display;
+			    /* blue pixels */
+			    if (x>1 && (x-1)%3)
+				    vfd_table[x][y][0][display][1] = x_abcdef*4+((x-1)/3+1)*1024+y*48+display;
+
+			    /* red pixels */
+			    vfd_table[x][y][1][display][0] =
+				(x>1) ? x_abcdef*4+24+((x-1)/3)*1024+y*48+display
+				      : x_abcdef*4+24+             0+y*48+display;
+			    /* red pixels */
+			    if (x>1 && (x-1)%3)
+				    vfd_table[x][y][1][display][1] = x_abcdef*4+24+((x-1)/3+1)*1024+y*48+display;
+		    }
+		}
+	    }
+	    break;
+	default:
+	    /* do nothing */
+	    return;
 	}
 
 	/*
-	 * Create translation table for Noritake-T119C-VFD-specific
-	 * organized frame-buffer
 	 * Create table with entries for physical byte adresses and
 	 * bit-number within the byte
 	 * from table with bit-numbers within the total framebuffer
 	 */
-	for(y=0;y<=17;y++)
-	{
-		for(x=0;x<=111;x++)
-		{
-			for(color=0;color<=1;color++)
-			{
-				for(display=0;display<=3;display++)
-				{
-					for(entry=0;entry<=1;entry++)
-					{
-						pixel  = vfd_table[x][y][color][display][entry] + frame_buf_offs;
-						 /*
-						  * wrap arround if offset
-						  * (see manual S3C2400)
-						  */
-						if (pixel>=frame_buf_size*8)
-							pixel = pixel-(frame_buf_size*8);
-						adr    = vfdbase+(pixel/32)*4+(3-(pixel%32)/8);
-						bit_nr = pixel%8;
-						bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
-						adr_vfd_table[x][y][color][display][entry] = adr;
-						bit_vfd_table[x][y][color][display][entry] = bit_nr;
-					}
-				}
+	for(y=0;y<18;y++) {
+	    for(x=0;x<112;x++) {
+		for(color=0;color<2;color++) {
+		    for(display=0;display<4;display++) {
+			for(entry=0;entry<2;entry++) {
+			    unsigned long adr  = vfdbase;
+			    unsigned int bit_nr = 0;
+			    
+			    if (vfd_table[x][y][color][display][entry]) {
+
+				pixel  = vfd_table[x][y][color][display][entry] + frame_buf_offs;
+				 /*
+				  * wrap arround if offset
+				  * (see manual S3C2400)
+				  */
+				if (pixel>=frame_buf_size*8)
+					pixel = pixel-(frame_buf_size*8);
+				adr    = vfdbase+(pixel/32)*4+(3-(pixel%32)/8);
+				bit_nr = pixel%8;
+				bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+			    }
+			    adr_vfd_table[x][y][color][display][entry] = adr;
+			    bit_vfd_table[x][y][color][display][entry] = bit_nr;
 			}
+		    }
 		}
+	    }
 	}
 }
 
 /*
  * Set/clear pixel of the VFDs
  */
-void set_vfd_pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char display, unsigned char value)
+void set_vfd_pixel(unsigned char x, unsigned char y,
+		   unsigned char color, unsigned char display,
+		   unsigned char value)
 {
+	DECLARE_GLOBAL_DATA_PTR;
 	ulong adr;
 	unsigned char bit_nr, temp;
 
-	if (value!=0)
-	{
-		/* Pixel-Eintrag Nr. 1 */
-		adr = adr_vfd_table[x][y][color][display][0];
-		/* Pixel-Eintrag Nr. 1 */
-		bit_nr = bit_vfd_table[x][y][color][display][0];
-		temp=(*(volatile unsigned char*)(adr));
-		temp|=1<<bit_nr;
-		(*(volatile unsigned char*)(adr))=temp;
-
-		/* Pixel-Eintrag Nr. 2 */
-		adr = adr_vfd_table[x][y][color][display][1];
-		/* Pixel-Eintrag Nr. 2 */
-		bit_nr = bit_vfd_table[x][y][color][display][1];
-		temp=(*(volatile unsigned char*)(adr));
-		temp|=1<<bit_nr;
-		(*(volatile unsigned char*)(adr))=temp;
+	if (! gd->vfd_type) {
+		/* Unknown type. */
+		return;
 	}
-	else
-	{
-		/* Pixel-Eintrag Nr. 1 */
-		adr = adr_vfd_table[x][y][color][display][0];
-		/* Pixel-Eintrag Nr. 1 */
-		bit_nr = bit_vfd_table[x][y][color][display][0];
-		temp=(*(volatile unsigned char*)(adr));
-		temp&=~(1<<bit_nr);
-		(*(volatile unsigned char*)(adr))=temp;
 
-		/* Pixel-Eintrag Nr. 2 */
-		adr = adr_vfd_table[x][y][color][display][1];
-		/* Pixel-Eintrag Nr. 2 */
-		bit_nr = bit_vfd_table[x][y][color][display][1];
-		temp=(*(volatile unsigned char*)(adr));
-		temp&=~(1<<bit_nr);
-		(*(volatile unsigned char*)(adr))=temp;
+	/* Pixel-Eintrag Nr. 1 */
+	adr = adr_vfd_table[x][y][color][display][0];
+	/* Pixel-Eintrag Nr. 1 */
+	bit_nr = bit_vfd_table[x][y][color][display][0];
+	temp=(*(volatile unsigned char*)(adr));
+
+	if (gd->vfd_inv_data) {
+		if (value)
+			temp &= ~(1<<bit_nr);
+		else
+			temp |=  (1<<bit_nr);
+	} else {
+		if (value)
+			temp |=  (1<<bit_nr);
+		else
+			temp &= ~(1<<bit_nr);
 	}
+	
+	(*(volatile unsigned char*)(adr))=temp;
 }
 
 /*
@@ -334,36 +366,11 @@
 }
 
 /*
- * initialize LCD-Controller of the S3C2400 for using VFDs
+ * This function initializes VFD clock that is needed for the CPLD that
+ * manages the keyboard.
  */
-int drv_vfd_init(void)
+int vfd_init_clocks(void)
 {
-	ulong palette;
-	static int vfd_init_done = 0;
-
-	DECLARE_GLOBAL_DATA_PTR;
-
-	if (vfd_init_done != 0)
-		return (0);
-	vfd_init_done = 1;
-
-	vfdbase = gd->fb_base;
-	create_vfd_table();
-	init_grid_ctrl();
-
-	/*
-	 * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben
-	 * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt
-	 * das letzte angezeigte Pixel wird aus dem ersten Nibble geholt
-	 * (wrap around)
-	 * see manual S3C2400
-	 */
-	/* frame buffer startadr */
-	rLCDSADDR1 = vfdbase >> 1;
- 	/* frame buffer endadr */
-	rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1;
-	rLCDSADDR3 = ((256/4));
-
 	/* Port-Pins als LCD-Ausgang */
 	rPCCON =   (rPCCON & 0xFFFFFF00)| 0x000000AA;
 	/* Port-Pins als LCD-Ausgang */
@@ -378,16 +385,93 @@
 	rLCDCON4 = 0x00000001;
 	rLCDCON5 = 0x00000440;
 	rLCDCON1 = 0x00000B75;
+}
+
+/*
+ * initialize LCD-Controller of the S3C2400 for using VFDs
+ */
+int drv_vfd_init(void)
+{
+	char *tmp;
+	ulong palette;
+	static int vfd_init_done = 0;
+	int vfd_id;
+
+	DECLARE_GLOBAL_DATA_PTR;
+
+	if (vfd_init_done != 0)
+		return (0);
+	vfd_init_done = 1;
+
+	/* try to determine display type from the value
+	 * defined by pull-ups
+	 */
+	rPCUP  = (rPCUP | 0x000F);	/* activate  GPC0...GPC3 pullups */
+	rPCCON = (rPCCON & 0xFFFFFF00);	/* configure GPC0...GPC3 as inputs */
+
+	vfd_id = (~rPCDAT) & 0x000F;	/* read GPC0...GPC3 port pins */
+	debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_id);
+
+	switch (vfd_id) {
+	case 0:				/* board revision <= Rev.100 */
+/*-----*/
+		gd->vfd_inv_data = 0;
+		if (0)
+			gd->vfd_type = VFD_TYPE_MN11236;
+		else
+			gd->vfd_type = VFD_TYPE_T119C;
+/*-----*/
+		if ((tmp = getenv ("vfd_type")) == NULL) {
+			break;
+		}
+		if (strcmp(tmp, "T119C") == 0) {
+			gd->vfd_type = VFD_TYPE_T119C;
+		} else if (strcmp(tmp, "MN11236") == 0) {
+			gd->vfd_type = VFD_TYPE_MN11236;
+		} else {
+			/* cannot use printf for a warning here */
+			gd->vfd_type = 0;	/* unknown */
+		}
+		gd->vfd_inv_data = 0;
+
+		break;
+	default:			/* default to MN11236, data inverted */
+		gd->vfd_type = VFD_TYPE_MN11236;
+		gd->vfd_inv_data = 1;
+		setenv ("vfd_type", "MN11236");
+	}
+	debug ("VFD type: %s%s\n",
+		(gd->vfd_type == VFD_TYPE_T119C)   ? "T119C" :
+		(gd->vfd_type == VFD_TYPE_MN11236) ? "MN11236" :
+		"unknown",
+		gd->vfd_inv_data ? ", inverted data" : "");
+
+	vfdbase = gd->fb_base;
+	create_vfd_table();
+	init_grid_ctrl();
+
+	for (palette=0; palette < 16; palette++)
+		(*(volatile unsigned int*)(PALETTE+(palette*4)))=palette;
+	for (palette=16; palette < 256; palette++)
+		(*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00;
+
+	/*
+	 * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben
+	 * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt
+	 * das letzte angezeigte Pixel wird aus dem ersten Nibble geholt
+	 * (wrap around)
+	 * see manual S3C2400
+	 */
+	/* frame buffer startadr */
+	rLCDSADDR1 = vfdbase >> 1;
+ 	/* frame buffer endadr */
+	rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1;
+	rLCDSADDR3 = ((256/4));
 
 	debug ("LCDSADDR1: %lX\n", rLCDSADDR1);
 	debug ("LCDSADDR2: %lX\n", rLCDSADDR2);
 	debug ("LCDSADDR3: %lX\n", rLCDSADDR3);
 
-	for(palette=0;palette<=15;palette++)
-		(*(volatile unsigned int*)(PALETTE+(palette*4)))=palette;
-	for(palette=16;palette<=255;palette++)
-		(*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00;
-
 	return 0;
 }