* Patch by David Müller, 13 Sep 2003:
  various changes to VCMA9 board specific files

* Add I2C support for MGT5100 / MPC5200
diff --git a/CHANGELOG b/CHANGELOG
index b034331..c058cc4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,11 @@
 Changes for U-Boot 1.0.0:
 ======================================================================
 
+* Patch by David Müller, 13 Sep 2003:
+  various changes to VCMA9 board specific files
+
+* Add I2C support for MGT5100 / MPC5200
+
 * Patch by Rune Torgersen, 11 Sep 2003:
   Changed default memory option on MPC8266ADS to NOT be Page Based
   Interleave, since this doesn't work very well with the standard
diff --git a/README b/README
index 0503ccb..e431c29 100644
--- a/README
+++ b/README
@@ -203,6 +203,7 @@
 - board/mpl/common	Common files for MPL boards
 - board/mpl/pip405	Files specific to PIP405     boards
 - board/mpl/mip405	Files specific to MIP405     boards
+- board/mpl/vcma9	Files specific to VCMA9      boards
 - board/musenki	Files specific to MUSEKNI    boards
 - board/mvs1	Files specific to MVS1       boards
 - board/nx823   Files specific to NX823      boards
@@ -363,7 +364,7 @@
 		CONFIG_IMPA7,       CONFIG_LART,       CONFIG_LUBBOCK,
 		CONFIG_INNOVATOROMAP1510,	CONFIG_INNOVATOROMAP1610
 		CONFIG_SHANNON,     CONFIG_SMDK2400,   CONFIG_SMDK2410,
-		CONFIG_TRAB,	    CONFIG_AT91RM9200DK
+		CONFIG_TRAB,	    CONFIG_VCMA9,      CONFIG_AT91RM9200DK
 
 
 - CPU Module Type: (if CONFIG_COGENT is defined)
diff --git a/board/mpl/vcma9/cmd_vcma9.c b/board/mpl/vcma9/cmd_vcma9.c
index 32fa334..3b04535 100644
--- a/board/mpl/vcma9/cmd_vcma9.c
+++ b/board/mpl/vcma9/cmd_vcma9.c
@@ -41,9 +41,12 @@
 #endif
 
 extern void print_vcma9_info(void);
-extern int vcma9_cantest(void);
+extern int vcma9_cantest(int);
 extern int vcma9_nandtest(void);
-extern int vcma9_dactest(void);
+extern int vcma9_nanderase(void);
+extern int vcma9_nandread(ulong);
+extern int vcma9_nandwrite(ulong);
+extern int vcma9_dactest(int);
 extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 
 /* ------------------------------------------------------------------------- */
@@ -126,18 +129,53 @@
 #endif
 #if 0
 	if (strcmp(argv[1], "cantest") == 0) {
-		vcma9_cantest();
+		if (argc >= 3)
+			vcma9_cantest(strcmp(argv[2], "s") ? 0 : 1);
+		else
+			vcma9_cantest(0);
 		return 0;
 	}
 	if (strcmp(argv[1], "nandtest") == 0) {
 		vcma9_nandtest();
 		return 0;
 	}
+	if (strcmp(argv[1], "nanderase") == 0) {
+		vcma9_nanderase();
+		return 0;
+	}
+	if (strcmp(argv[1], "nandread") == 0) {
+		ulong offset = 0;
+
+		if (argc >= 3)
+			offset = simple_strtoul(argv[2], NULL, 16);
+
+		vcma9_nandread(offset);
+		return 0;
+	}
+	if (strcmp(argv[1], "nandwrite") == 0) {
+		ulong offset = 0;
+
+		if (argc >= 3)
+			offset = simple_strtoul(argv[2], NULL, 16);
+
+		vcma9_nandwrite(offset);
+		return 0;
+	}
 	if (strcmp(argv[1], "dactest") == 0) {
-		vcma9_dactest();
+		if (argc >= 3)
+			vcma9_dactest(strcmp(argv[2], "s") ? 0 : 1);
+		else
+		vcma9_dactest(0);
 		return 0;
 	}
 #endif
 
 	return (do_mplcommon(cmdtp, flag, argc, argv));
 }
+
+U_BOOT_CMD(
+	vcma9, 6, 1, do_vcma9,
+	"vcma9   - VCMA9 specific commands\n",
+	"flash mem [SrcAddr]\n    - updates U-Boot with image in memory\n"
+);
+
diff --git a/board/mpl/vcma9/config.mk b/board/mpl/vcma9/config.mk
index 95d69cc..942d42e 100644
--- a/board/mpl/vcma9/config.mk
+++ b/board/mpl/vcma9/config.mk
@@ -1,5 +1,5 @@
 #
-# (C) Copyright 2002
+# (C) Copyright 2002, 2003
 # David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
 #
 # MPL VCMA9 board with S3C2410X (ARM920T) cpu
@@ -8,17 +8,17 @@
 #
 
 #
-# MPL VCMA9 has 1 bank of 64 MB DRAM
-#
-# 3000'0000 to 3400'0000
+# MPL VCMA9 has 1 bank of minimal 16 MB DRAM
+# from 0x30000000
 #
 # Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
-# optionally with a ramdisk at 3080'0000
+# optionally with a ramdisk at 3040'0000
 #
-# we load ourself to 33F8'0000
+# we load ourself to 30F8'0000
 #
-# download area is 3300'0000
+# download area is 3080'0000
 #
 
 
+#TEXT_BASE = 0x30F80000
 TEXT_BASE = 0x33F80000
diff --git a/board/mpl/vcma9/memsetup.S b/board/mpl/vcma9/memsetup.S
index 7b4193d..ab65901 100644
--- a/board/mpl/vcma9/memsetup.S
+++ b/board/mpl/vcma9/memsetup.S
@@ -34,7 +34,9 @@
 
 /* some parameters for the board */
 
-#define BWSCON	0x48000000
+#define BWSCON		0x48000000
+#define PLD_BASE	0x2C000000
+#define SDRAM_REG	0x2C000106
 
 /* BWSCON */
 #define DW8		 	(0x0)
@@ -43,6 +45,9 @@
 #define WAIT		 	(0x1<<2)
 #define UBLB		 	(0x1<<3)
 
+/* BANKSIZE */
+#define BURST_EN		(0x1<<7)
+
 #define B1_BWSCON	  	(DW16)
 #define B2_BWSCON	  	(DW32)
 #define B3_BWSCON	  	(DW32)
@@ -130,24 +135,39 @@
 	/* memory control configuration */
 	/* make r0 relative the current location so that it */
 	/* reads SMRDATA out of FLASH rather than memory ! */
-	ldr     r0, =SMRDATA
+	ldr     r0, =CSDATA
 	ldr	r1, _TEXT_BASE
 	sub	r0, r0, r1
 	ldr	r1, =BWSCON	/* Bus Width Status Controller */
-	add     r2, r0, #13*4
+	add     r2, r0, #CSDATA_END-CSDATA
 0:
 	ldr     r3, [r0], #4
 	str     r3, [r1], #4
 	cmp     r2, r0
 	bne     0b
 
+	/* PLD access is now possible */
+	/* r0 == SDRAMDATA */
+	/* r1 == SDRAM controller regs */
+	ldr	r2, =PLD_BASE
+	ldrb	r3, [r2, #SDRAM_REG-PLD_BASE]
+	mov	r4, #SDRAMDATA1_END-SDRAMDATA
+	/* calculate start and end point */
+	mla	r0, r3, r4, r0 
+	add     r2, r0, r4
+0:
+	ldr     r3, [r0], #4
+	str     r3, [r1], #4
+	cmp     r2, r0
+	bne     0b
+	
 	/* everything is fine now */
 	mov	pc, lr
 
 	.ltorg
 /* the literal pools origin */
 
-SMRDATA:
+CSDATA:
     .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
     .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
     .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
@@ -155,9 +175,38 @@
     .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
     .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
     .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
+CSDATA_END:
+
+SDRAMDATA:
+/* 4Mx8x4 */
     .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
     .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
     .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
-    .word 0x32
+    .word 0x32 + BURST_EN
+    .word 0x30
+    .word 0x30
+SDRAMDATA1_END:
+
+/* 8Mx8x4 (not implemented yet) */
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0x32 + BURST_EN
+    .word 0x30
+    .word 0x30
+    
+/* 2Mx8x4 (not implemented yet) */
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0x32 + BURST_EN
+    .word 0x30
+    .word 0x30
+    
+/* 4Mx8x2 (not implemented yet) */
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0x32 + BURST_EN
     .word 0x30
     .word 0x30
diff --git a/board/mpl/vcma9/vcma9.c b/board/mpl/vcma9/vcma9.c
index 359e565..33cec02 100644
--- a/board/mpl/vcma9/vcma9.c
+++ b/board/mpl/vcma9/vcma9.c
@@ -130,16 +130,6 @@
 	return 0;
 }
 
-int dram_init(void)
-{
-	DECLARE_GLOBAL_DATA_PTR;
-
-	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
-
-	return 0;
-}
-
 /*
  * NAND flash initialization.
  */
@@ -162,9 +152,16 @@
 
 static inline void NF_Init(void)
 {
+#if 0 /* a little bit too optimistic */
 #define TACLS   0
 #define TWRPH0  3
 #define TWRPH1  0
+#else
+#define TACLS   0
+#define TWRPH0  4
+#define TWRPH1  2
+#endif
+
     NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
     /*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
     /* 1  1    1     1,   1      xxx,  r xxx,   r xxx */
@@ -177,15 +174,12 @@
 nand_init(void)
 {
 	S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
-	unsigned totlen;
 
 	NF_Init();
 #ifdef DEBUG
 	printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
 #endif
-	totlen = nand_probe((ulong)nand) >> 20;
-
-	printf ("%4lu MB\n", totlen >> 20);
+	printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
 }
 #endif
 
@@ -193,29 +187,40 @@
  * Get some Board/PLD Info
  */
 
-static uchar Get_PLD_ID(void)
+static u8 Get_PLD_ID(void)
 {
-	return(*(volatile uchar *)PLD_ID_REG);
+	VCMA9_PLD * const pld = VCMA9_GetBase_PLD();
+	
+	return(pld->ID);
 }
 
-static uchar Get_PLD_BOARD(void)
+static u8 Get_PLD_BOARD(void)
 {
-	return(*(volatile uchar *)PLD_BOARD_REG);
+	VCMA9_PLD * const pld = VCMA9_GetBase_PLD();
+	
+	return(pld->BOARD);
 }
 
-static uchar Get_PLD_Version(void)
+static u8 Get_PLD_SDRAM(void)
+{
+	VCMA9_PLD * const pld = VCMA9_GetBase_PLD();
+	
+	return(pld->SDRAM);
+}
+
+static u8 Get_PLD_Version(void)
 {
 	return((Get_PLD_ID() >> 4) & 0x0F);
 }
 
-static uchar Get_PLD_Revision(void)
+static u8 Get_PLD_Revision(void)
 {
 	return(Get_PLD_ID() & 0x0F);
 }
 
 static int Get_Board_Config(void)
 {
-	uchar config = Get_PLD_BOARD() & 0x03;
+	u8 config = Get_PLD_BOARD() & 0x03;
 
 	if (config == 3)
 	    return 1;
@@ -228,6 +233,54 @@
 	return(((Get_PLD_BOARD() >> 4) & 0x03) + 'A');
 }
 
+static u8 Get_SDRAM_ChipNr(void)
+{
+	switch ((Get_PLD_SDRAM() >> 4) & 0x0F) {
+		case 0: return 4;
+		case 1: return 1;
+		case 2: return 2;
+		default: return 0;
+	}
+}
+
+static ulong Get_SDRAM_ChipSize(void)
+{
+	switch (Get_PLD_SDRAM() & 0x0F) {
+		case 0: return 16 * (1024*1024);
+		case 1: return 32 * (1024*1024);
+		case 2: return  8 * (1024*1024);
+		case 3: return  8 * (1024*1024);
+		default: return 0;
+	}	
+}
+static const char * Get_SDRAM_ChipGeom(void)
+{
+	switch (Get_PLD_SDRAM() & 0x0F) {
+		case 0: return "4Mx8x4";
+		case 1: return "8Mx8x4";
+		case 2: return "2Mx8x4";
+		case 3: return "4Mx8x2";
+		default: return "unknown";
+	}
+}
+
+static void Show_VCMA9_Info(char *board_name, char *serial)
+{
+	printf("Board: %s SN: %s  PCB Rev: %c PLD(%d,%d)\n",
+		board_name, serial, Get_Board_PCB(), Get_PLD_Version(), Get_PLD_Revision());
+	printf("SDRAM: %d chips %s\n", Get_SDRAM_ChipNr(), Get_SDRAM_ChipGeom());
+}
+
+int dram_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = Get_SDRAM_ChipSize() * Get_SDRAM_ChipNr();
+
+	return 0;
+}
+
 /* ------------------------------------------------------------------------- */
 
 /*
@@ -240,8 +293,6 @@
 	int i;
 	backup_t *b = (backup_t *) s;
 
-	puts("Board: ");
-
 	i = getenv_r("serial#", s, 32);
 	if ((i < 0) || strncmp (s, "VCMA9", 5)) {
 		get_backup_values (b);
@@ -249,32 +300,23 @@
 			puts ("### No HW ID - assuming VCMA9");
 		} else {
 			b->serial_name[5] = 0;
-			printf ("%s-%d PCB Rev %c SN: %s", b->serial_name, Get_Board_Config(),
-					Get_Board_PCB(), &b->serial_name[6]);
+			Show_VCMA9_Info(b->serial_name, &b->serial_name[6]);
 		}
 	} else {
 		s[5] = 0;
-		printf ("%s-%d PCB Rev %c SN: %s", s, Get_Board_Config(), Get_Board_PCB(),
-				&s[6]);
+		Show_VCMA9_Info(s, &s[6]);
 	}
-	printf("\n");
+	/*printf("\n");*/
 	return(0);
 }
 
 
-void print_vcma9_rev(void)
-{
-	printf("Board: VCMA9-%d PCB Rev: %c (PLD Ver: %d, Rev: %d)\n",
-		Get_Board_Config(), Get_Board_PCB(),
-		Get_PLD_Version(), Get_PLD_Revision());
-}
-
 extern void mem_test_reloc(void);
 
 int last_stage_init(void)
 {
 	mem_test_reloc();
-	print_vcma9_rev();
+	checkboard();
 	show_stdio_dev();
 	check_env();
 	return 0;
@@ -295,6 +337,15 @@
 * Print VCMA9 Info
 ************************************************************************/
 void print_vcma9_info(void)
-{
-    print_vcma9_rev();
+{	
+	unsigned char s[50];
+	int i;
+	
+	if ((i = getenv_r("serial#", s, 32)) < 0) {
+		puts ("### No HW ID - assuming VCMA9");
+		printf("i %d", i*24);
+	} else {
+		s[5] = 0;
+		Show_VCMA9_Info(s, &s[6]);
+	}
 }
diff --git a/board/mpl/vcma9/vcma9.h b/board/mpl/vcma9/vcma9.h
index 068eb21..c0167d5 100644
--- a/board/mpl/vcma9/vcma9.h
+++ b/board/mpl/vcma9/vcma9.h
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2002
+ * (C) Copyright 2002, 2003
  * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
  *
  * See file CREDITS for list of people who contributed to this
@@ -116,11 +116,19 @@
 
 #endif
 
+/* VCMA9 PLD regsiters */
+typedef struct {
+	S3C24X0_REG8	ID;
+	S3C24X0_REG8	NIC;
+	S3C24X0_REG8	CAN;
+	S3C24X0_REG8	MISC;
+	S3C24X0_REG8	GPCD;
+	S3C24X0_REG8	BOARD;
+	S3C24X0_REG8	SDRAM;
+} /*__attribute__((__packed__))*/ VCMA9_PLD;
 
-#define PLD_BASE_ADDRESS		0x2C000100
-#define PLD_ID_REG			(PLD_BASE_ADDRESS + 0)
-#define PLD_NIC_REG			(PLD_BASE_ADDRESS + 1)
-#define PLD_CAN_REG			(PLD_BASE_ADDRESS + 2)
-#define PLD_MISC_REG			(PLD_BASE_ADDRESS + 3)
-#define PLD_GPCD_REG			(PLD_BASE_ADDRESS + 4)
-#define PLD_BOARD_REG			(PLD_BASE_ADDRESS + 5)
+#define VCMA9_PLD_BASE	0x2C000100
+static inline VCMA9_PLD * const VCMA9_GetBase_PLD(void)
+{
+	return (VCMA9_PLD * const)VCMA9_PLD_BASE;
+}
diff --git a/cpu/mpc5xxx/Makefile b/cpu/mpc5xxx/Makefile
index 74ec64c..a65bc22 100644
--- a/cpu/mpc5xxx/Makefile
+++ b/cpu/mpc5xxx/Makefile
@@ -27,7 +27,7 @@
 
 START	= start.o
 ASOBJS	= io.o firmware_sc_task_bestcomm.impl.o firmware_sc_task.impl.o
-OBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o \
+OBJS	= i2c.o traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o \
 	  loadtask.o fec.o pci_mpc5200.o
 
 all:	.depend $(START) $(ASOBJS) $(LIB)
diff --git a/cpu/mpc5xxx/i2c.c b/cpu/mpc5xxx/i2c.c
new file mode 100644
index 0000000..640d140
--- /dev/null
+++ b/cpu/mpc5xxx/i2c.c
@@ -0,0 +1,338 @@
+/*
+ * (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 <common.h>
+
+#ifdef CONFIG_HARD_I2C
+
+#include <mpc5xxx.h>
+#include <i2c.h>
+
+#ifdef CFG_I2C_MODULE
+#define I2C_BASE	MPC5XXX_I2C2
+#else
+#define I2C_BASE	MPC5XXX_I2C1
+#endif
+
+#define I2C_TIMEOUT	100
+#define I2C_RETRIES	3
+
+static int  mpc_reg_in    (volatile u32 *reg);
+static void mpc_reg_out   (volatile u32 *reg, int val, int mask);
+static int  wait_for_bb   (void);
+static int  wait_for_pin  (int *status);
+static int  do_address    (uchar chip, char rdwr_flag);
+static int  send_bytes    (uchar chip, char *buf, int len);
+static int  receive_bytes (uchar chip, char *buf, int len);
+
+static int mpc_reg_in(volatile u32 *reg)
+{
+	return *reg >> 24;
+	__asm__ __volatile__ ("eieio");
+}
+
+static void mpc_reg_out(volatile u32 *reg, int val, int mask)
+{
+	int tmp;
+
+	if (!mask) {
+		*reg = val << 24;
+	} else {
+		tmp = mpc_reg_in(reg);
+		*reg = ((tmp & ~mask) | (val & mask)) << 24;
+	}
+	__asm__ __volatile__ ("eieio");
+
+	return;
+}
+
+static int wait_for_bb(void)
+{
+	struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 timeout = I2C_TIMEOUT;
+	int                 status;
+
+	status = mpc_reg_in(&regs->msr);
+
+	while (timeout-- && (status & I2C_BB)) {
+#if 1
+		volatile int temp;
+		mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+		temp = mpc_reg_in(&regs->mdr);
+		mpc_reg_out(&regs->mcr, 0, I2C_STA);
+		mpc_reg_out(&regs->mcr, 0, 0);
+		mpc_reg_out(&regs->mcr, I2C_EN, 0);
+#endif
+		udelay(1000);
+		status = mpc_reg_in(&regs->msr);
+	}
+
+	return (status & I2C_BB);
+}
+
+static int wait_for_pin(int *status)
+{
+	struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 timeout = I2C_TIMEOUT;
+
+	*status = mpc_reg_in(&regs->msr);
+
+	while (timeout-- && !(*status & I2C_IF)) {
+		udelay(1000);
+		*status = mpc_reg_in(&regs->msr);
+	}
+
+	if (!(*status & I2C_IF)) {
+		return -1;
+	}
+
+	mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+	return 0;
+}
+
+static int do_address(uchar chip, char rdwr_flag)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 status;
+
+	chip <<= 1;
+
+	if (rdwr_flag) {
+		chip |= 1;
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_TX, I2C_TX);
+	mpc_reg_out(&regs->mdr, chip, 0);
+
+        if (wait_for_pin(&status)) {
+                return -2;
+        }
+
+        if (status & I2C_RXAK) {
+                return -3;
+        }
+
+	return 0;
+}
+
+static int send_bytes(uchar chip, char *buf, int len)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 wrcount;
+	int                 status;
+
+	for (wrcount = 0; wrcount < len; ++wrcount) {
+
+		mpc_reg_out(&regs->mdr, buf[wrcount], 0);
+
+		if (wait_for_pin(&status)) {
+			break;
+		}
+
+		if (status & I2C_RXAK) {
+			break;
+		}
+
+	}
+
+	return !(wrcount == len);
+}
+
+static int receive_bytes(uchar chip, char *buf, int len)
+{
+	struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 dummy   = 1;
+	int                 rdcount = 0;
+	int                 status;
+	int                 i;
+
+	mpc_reg_out(&regs->mcr, 0, I2C_TX);
+
+	for (i = 0; i < len; ++i) {
+		buf[rdcount] = mpc_reg_in(&regs->mdr);
+
+		if (dummy) {
+			dummy = 0;
+		} else {
+			rdcount++;
+		}
+
+
+		if (wait_for_pin(&status)) {
+			return -4;
+		}
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_TXAK, I2C_TXAK);
+	buf[rdcount++] = mpc_reg_in(&regs->mdr);
+
+	if (wait_for_pin(&status)) {
+		return -5;
+	}
+
+	mpc_reg_out(&regs->mcr, 0, I2C_TXAK);
+
+	return 0;
+}
+
+/**************** I2C API ****************/
+
+void i2c_init(int speed, int saddr)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+
+	mpc_reg_out(&regs->mcr, 0, 0);
+	mpc_reg_out(&regs->madr, saddr << 1, 0);
+
+	/* Set clock
+	 */
+	mpc_reg_out(&regs->mfdr, speed, 0);
+
+	/* Enable module
+	 */
+	mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
+	mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+	return;
+}
+
+int i2c_probe(uchar chip)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 i;
+
+	for (i = 0; i < I2C_RETRIES; i++) {
+		mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+
+		if (! do_address(chip, 0)) {
+			mpc_reg_out(&regs->mcr, 0, I2C_STA);
+			break;
+		}
+
+		mpc_reg_out(&regs->mcr, 0, I2C_STA);
+		udelay(500);
+	}
+
+	return (i == I2C_RETRIES);
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	uchar                xaddr[4];
+	struct mpc5xxx_i2c * regs        = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                  ret         = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr	& 0xFF;
+
+	if (wait_for_bb()) {
+		printf("i2c_read: bus is busy\n");
+		goto Done;
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+	if (do_address(chip, 0)) {
+		printf("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes(chip, &xaddr[4-alen], alen)) {
+		printf("i2c_read: send_bytes failed\n");
+		goto Done;
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_RSTA, I2C_RSTA);
+	if (do_address(chip, 1)) {
+		printf("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (receive_bytes(chip, buf, len)) {
+		printf("i2c_read: receive_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+Done:
+	mpc_reg_out(&regs->mcr, 0, I2C_STA);
+	return ret;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	uchar               xaddr[4];
+	struct mpc5xxx_i2c *regs        = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 ret         = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr	& 0xFF;
+
+        if (wait_for_bb()) {
+		printf("i2c_write: bus is busy\n");
+		goto Done;
+	}
+
+        mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+        if (do_address(chip, 0)) {
+		printf("i2c_write: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes(chip, &xaddr[4-alen], alen)) {
+		printf("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	if (send_bytes(chip, buf, len)) {
+		printf("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+Done:
+	mpc_reg_out(&regs->mcr, 0, I2C_STA);
+	return ret;
+}
+
+uchar i2c_reg_read(uchar chip, uchar reg)
+{
+	char buf;
+
+	i2c_read(chip, reg, 1, &buf, 1);
+
+	return buf;
+}
+
+void i2c_reg_write(uchar chip, uchar reg, uchar val)
+{
+	i2c_write(chip, reg, 1, &val, 1);
+
+	return;
+}
+
+#endif	/* CONFIG_HARD_I2C */
diff --git a/include/configs/IceCube.h b/include/configs/IceCube.h
index 9d914a6..c2c398c 100644
--- a/include/configs/IceCube.h
+++ b/include/configs/IceCube.h
@@ -83,7 +83,8 @@
 /*
  * Supported commands
  */
-#define CONFIG_COMMANDS		(CONFIG_CMD_DFL | ADD_PCI_CMD)
+#define CONFIG_COMMANDS		(CONFIG_CMD_DFL | ADD_PCI_CMD | \
+				 CFG_CMD_I2C | CFG_CMD_EEPROM)
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
@@ -98,6 +99,23 @@
 /*
  * I2C configuration
  */
+#define CONFIG_HARD_I2C		1	/* I2C with hardware support */
+#define CFG_I2C_MODULE		1	/* If defined then I2C module #2 is used
+					 * otherwise I2C module #1 is used */
+#ifdef CONFIG_MPC5200
+#define CFG_I2C_SPEED		0x3D	/* 86KHz given 133MHz IPBI */
+#else
+#define CFG_I2C_SPEED		0x35	/* 86KHz given 33MHz IPBI */
+#endif
+#define CFG_I2C_SLAVE		0x7F
+
+/*
+ * EEPROM configuration
+ */
+#define CFG_I2C_EEPROM_ADDR		0x50	/* 1010000x */
+#define CFG_I2C_EEPROM_ADDR_LEN		1
+#define CFG_EEPROM_PAGE_WRITE_BITS	3
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS	35
 
 /*
  * Flash configuration
diff --git a/include/configs/VCMA9.h b/include/configs/VCMA9.h
index c0103fc..9f868f8 100644
--- a/include/configs/VCMA9.h
+++ b/include/configs/VCMA9.h
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2002
+ * (C) Copyright 2002, 2003
  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  * Marius Groeger <mgroeger@sysgo.de>
  * Gary Jennejohn <gj@denx.de>
@@ -160,9 +160,10 @@
 #define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/
 
 #define CFG_MEMTEST_START	0x30000000	/* memtest works on	*/
-#define CFG_MEMTEST_END		0x33F80000	/* 63.5 MB in DRAM	*/
+#define CFG_MEMTEST_END		0x30F80000	/* 15.5 MB in DRAM	*/
+
 #define CFG_ALT_MEMTEST
-#define	CFG_LOAD_ADDR		0x33000000	/* default load address	*/
+#define	CFG_LOAD_ADDR		0x30800000	/* default load address	*/
 
 
 #undef  CFG_CLKS_IN_HZ		/* everything, incl board info, in Hz */
@@ -197,8 +198,6 @@
  */
 #define CONFIG_NR_DRAM_BANKS	1	   /* we have 1 bank of DRAM */
 #define PHYS_SDRAM_1		0x30000000 /* SDRAM Bank #1 */
-#define PHYS_SDRAM_1_SIZE	0x04000000 /* 64 MB */
-
 #define PHYS_FLASH_1		0x00000000 /* Flash Bank #1 */
 
 #define CFG_FLASH_BASE		PHYS_FLASH_1
diff --git a/include/mpc5xxx.h b/include/mpc5xxx.h
index 02683e3..b38d7d4 100644
--- a/include/mpc5xxx.h
+++ b/include/mpc5xxx.h
@@ -108,6 +108,9 @@
 
 #define	MPC5XXX_FEC		(CFG_MBAR + 0x3000)
 
+#define MPC5XXX_I2C1		(CFG_MBAR + 0x3D00)
+#define MPC5XXX_I2C2		(CFG_MBAR + 0x3D40)
+
 #if defined(CONFIG_MGT5100)
 #define MPC5XXX_SRAM		(CFG_MBAR + 0x4000)
 #define MPC5XXX_SRAM_SIZE	(8*1024)
@@ -197,6 +200,24 @@
 #define MPC5XXX_GPT0_ENABLE		(MPC5XXX_GPT + 0x0)
 #define MPC5XXX_GPT0_COUNTER		(MPC5XXX_GPT + 0x4)
 
+/* I2Cn control register bits */
+#define I2C_EN		0x80
+#define I2C_IEN		0x40
+#define I2C_STA		0x20
+#define I2C_TX		0x10
+#define I2C_TXAK	0x08
+#define I2C_RSTA	0x04
+#define I2C_INIT_MASK	(I2C_EN | I2C_STA | I2C_TX | I2C_RSTA)
+
+/* I2Cn status register bits */
+#define I2C_CF		0x80
+#define I2C_AAS		0x40
+#define I2C_BB		0x20
+#define I2C_AL		0x10
+#define I2C_SRW		0x04
+#define I2C_IF		0x02
+#define I2C_RXAK	0x01
+
 /* Programmable Serial Controller (PSC) status register bits */
 #define PSC_SR_CDE		0x0080
 #define PSC_SR_RXRDY		0x0100
@@ -505,6 +526,14 @@
 	volatile u32 EU37;		/* SDMA + 0xfc */
 };
 
+struct mpc5xxx_i2c {
+	volatile u32 madr;		/* I2Cn + 0x00 */
+	volatile u32 mfdr;		/* I2Cn + 0x04 */
+	volatile u32 mcr;		/* I2Cn + 0x08 */
+	volatile u32 msr;		/* I2Cn + 0x0C */
+	volatile u32 mdr;		/* I2Cn + 0x10 */
+};
+
 /* function prototypes */
 void loadtask(int basetask, int tasks);
 
diff --git a/rtc/s3c24x0_rtc.c b/rtc/s3c24x0_rtc.c
index bf8008d..9e2191e 100644
--- a/rtc/s3c24x0_rtc.c
+++ b/rtc/s3c24x0_rtc.c
@@ -80,13 +80,15 @@
 	SetRTC_Access(RTC_ENABLE);
 
 	/* read RTC registers */
-	sec	= rtc->BCDSEC;
-	min	= rtc->BCDMIN;
-	hour	= rtc->BCDHOUR;
-	mday	= rtc->BCDDATE;
-	wday	= rtc->BCDDAY;
-	mon	= rtc->BCDMON;
-	year	= rtc->BCDYEAR;
+	do {
+		sec	= rtc->BCDSEC;
+		min	= rtc->BCDMIN;
+		hour	= rtc->BCDHOUR;
+		mday	= rtc->BCDDATE;
+		wday	= rtc->BCDDAY;
+		mon	= rtc->BCDMON;
+		year	= rtc->BCDYEAR;
+	} while (sec != rtc->BCDSEC);
 
 	/* read ALARM registers */
 	a_sec	= rtc->ALMSEC;
@@ -170,7 +172,7 @@
 	S3C24X0_RTC * const rtc = S3C24X0_GetBase_RTC();
 
 	rtc->RTCCON = (rtc->RTCCON & ~0x06) | 0x08;
-	rtc->RTCCON &= ~0x08;
+	rtc->RTCCON &= ~(0x08|0x01);
 }
 
 /* ------------------------------------------------------------------------- */