diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c
index 0fc7db2..ece45d6 100644
--- a/board/gdsys/405ep/iocon.c
+++ b/board/gdsys/405ep/iocon.c
@@ -23,6 +23,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <errno.h>
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/ppc4xx-gpio.h>
@@ -31,6 +32,13 @@
 #include <gdsys_fpga.h>
 
 #include "../common/osd.h"
+#include "../common/mclink.h"
+
+#include <i2c.h>
+#include <pca953x.h>
+#include <pca9698.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 #define LATCH0_BASE (CONFIG_SYS_LATCH_BASE)
 #define LATCH1_BASE (CONFIG_SYS_LATCH_BASE + 0x100)
@@ -47,11 +55,20 @@ enum {
 	HWVER_100 = 0,
 	HWVER_104 = 1,
 	HWVER_110 = 2,
+	HWVER_120 = 3,
+	HWVER_200 = 4,
+	HWVER_210 = 5,
+};
+
+enum {
+	FPGA_HWVER_200 = 0,
+	FPGA_HWVER_210 = 1,
 };
 
 enum {
 	COMPRESSION_NONE = 0,
-	COMPRESSION_TYPE1_DELTA,
+	COMPRESSION_TYPE1_DELTA = 1,
+	COMPRESSION_TYPE1_TYPE2_DELTA = 3,
 };
 
 enum {
@@ -67,8 +84,56 @@ enum {
 
 enum {
 	RAM_DDR2_32 = 0,
+	RAM_DDR3_32 = 1,
+};
+
+enum {
+	MCFPGA_DONE = 1 << 0,
+	MCFPGA_INIT_N = 1 << 1,
+	MCFPGA_PROGRAM_N = 1 << 2,
+	MCFPGA_UPDATE_ENABLE_N = 1 << 3,
+	MCFPGA_RESET_N = 1 << 4,
 };
 
+unsigned int mclink_fpgacount;
+
+void fpga_set_reg(unsigned int fpga, u16 reg, u16 data)
+{
+	int res;
+	struct ihs_fpga *fpga_0 = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(0);
+
+	switch (fpga) {
+	case 0:
+		out_le16((u16 *)fpga_0 + reg / sizeof(u16), data);
+		break;
+	default:
+		res = mclink_send(fpga - 1, reg, data);
+		if (res < 0)
+			printf("mclink_send reg %02x data %04x returned %d\n",
+			       reg, data, res);
+		break;
+	}
+}
+
+u16 fpga_get_reg(unsigned int fpga, u16 reg)
+{
+	int res;
+	u16 data;
+	struct ihs_fpga *fpga_0 = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(0);
+
+	switch (fpga) {
+	case 0:
+		return in_le16((u16 *)fpga_0 + reg / sizeof(u16));
+	default:
+		if (fpga > mclink_fpgacount)
+			return -EINVAL;
+		res = mclink_receive(fpga - 1, reg, &data);
+		if (res < 0)
+			printf("mclink_receive returned %d\n", res);
+		return data;
+	}
+}
+
 /*
  * Check Board Identity:
  */
@@ -90,12 +155,11 @@ int checkboard(void)
 	return 0;
 }
 
-static void print_fpga_info(void)
+static void print_fpga_info(unsigned int fpga)
 {
-	struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0);
-	u16 versions = in_le16(&fpga->versions);
-	u16 fpga_version = in_le16(&fpga->fpga_version);
-	u16 fpga_features = in_le16(&fpga->fpga_features);
+	u16 versions = fpga_get_reg(fpga, REG(versions));
+	u16 fpga_version = fpga_get_reg(fpga, REG(fpga_version));
+	u16 fpga_features = fpga_get_reg(fpga, REG(fpga_features));
 	unsigned unit_type;
 	unsigned hardware_version;
 	unsigned feature_compression;
@@ -105,9 +169,9 @@ static void print_fpga_info(void)
 	unsigned feature_ramconfig;
 	unsigned feature_carriers;
 	unsigned feature_video_channels;
+	int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
 
 	unit_type = (versions & 0xf000) >> 12;
-	hardware_version = versions & 0x000f;
 	feature_compression = (fpga_features & 0xe000) >> 13;
 	feature_osd = fpga_features & (1<<11);
 	feature_audio = (fpga_features & 0x0600) >> 9;
@@ -116,6 +180,9 @@ static void print_fpga_info(void)
 	feature_carriers = (fpga_features & 0x000c) >> 2;
 	feature_video_channels = fpga_features & 0x0003;
 
+	if (legacy)
+		printf("legacy ");
+
 	switch (unit_type) {
 	case UNITTYPE_MAIN_USER:
 		printf("Mainchannel");
@@ -130,27 +197,68 @@ static void print_fpga_info(void)
 		break;
 	}
 
-	switch (hardware_version) {
-	case HWVER_100:
-		printf(" HW-Ver 1.00\n");
-		break;
-
-	case HWVER_104:
-		printf(" HW-Ver 1.04\n");
-		break;
-
-	case HWVER_110:
-		printf(" HW-Ver 1.10\n");
-		break;
+	if (unit_type == UNITTYPE_MAIN_USER) {
+		if (legacy)
+			hardware_version =
+				(in_le16((void *)LATCH2_BASE)>>8) & 0x0f;
+		else
+			hardware_version =
+				  (!!pca9698_get_value(0x20, 24) << 0)
+				| (!!pca9698_get_value(0x20, 25) << 1)
+				| (!!pca9698_get_value(0x20, 26) << 2)
+				| (!!pca9698_get_value(0x20, 27) << 3);
+		switch (hardware_version) {
+		case HWVER_100:
+			printf(" HW-Ver 1.00,");
+			break;
+
+		case HWVER_104:
+			printf(" HW-Ver 1.04,");
+			break;
+
+		case HWVER_110:
+			printf(" HW-Ver 1.10,");
+			break;
+
+		case HWVER_120:
+			printf(" HW-Ver 1.20-1.21,");
+			break;
+
+		case HWVER_200:
+			printf(" HW-Ver 2.00,");
+			break;
+
+		case HWVER_210:
+			printf(" HW-Ver 2.10,");
+			break;
+
+		default:
+			printf(" HW-Ver %d(not supported),",
+			       hardware_version);
+			break;
+		}
+	}
 
-	default:
-		printf(" HW-Ver %d(not supported)\n",
-		       hardware_version);
-		break;
+	if (unit_type == UNITTYPE_VIDEO_USER) {
+		hardware_version = versions & 0x000f;
+		switch (hardware_version) {
+		case FPGA_HWVER_200:
+			printf(" HW-Ver 2.00,");
+			break;
+
+		case FPGA_HWVER_210:
+			printf(" HW-Ver 2.10,");
+			break;
+
+		default:
+			printf(" HW-Ver %d(not supported),",
+			       hardware_version);
+			break;
+		}
 	}
 
-	printf("       FPGA V %d.%02d, features:",
-		fpga_version / 100, fpga_version % 100);
+	printf(" FPGA V %d.%02d\n       features:",
+	       fpga_version / 100, fpga_version % 100);
 
 
 	switch (feature_compression) {
@@ -162,6 +270,10 @@ static void print_fpga_info(void)
 		printf(" type1-deltacompression");
 		break;
 
+	case COMPRESSION_TYPE1_TYPE2_DELTA:
+		printf(" type1-deltacompression, type2-inlinecompression");
+		break;
+
 	default:
 		printf(" compression %d(not supported)", feature_compression);
 		break;
@@ -208,6 +320,10 @@ static void print_fpga_info(void)
 		printf(", RAM 32 bit DDR2");
 		break;
 
+	case RAM_DDR3_32:
+		printf(", RAM 32 bit DDR3");
+		break;
+
 	default:
 		printf(", RAM %d(not supported)", feature_ramconfig);
 		break;
@@ -220,41 +336,94 @@ static void print_fpga_info(void)
 
 int last_stage_init(void)
 {
-	print_fpga_info();
+	int slaves;
+	unsigned int k;
+	unsigned char mclink_controllers[] = { 0x24, 0x25, 0x26 };
+
+	print_fpga_info(0);
+	osd_probe(0);
+
+	/* wait for FPGA done */
+	for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
+		unsigned int ctr = 0;
+
+		if (i2c_probe(mclink_controllers[k]))
+			continue;
+
+		while (!(pca953x_get_val(mclink_controllers[k])
+		       & MCFPGA_DONE)) {
+			udelay(100000);
+			if (ctr++ > 5) {
+				printf("no done for mclink_controller %d\n", k);
+				break;
+			}
+		}
+	}
+
+	/* wait for slave-PLLs to be up and running */
+	udelay(500000);
+
+	mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
+	slaves = mclink_probe();
+	mclink_fpgacount = 0;
+
+	if (slaves <= 0)
+		return 0;
+
+	mclink_fpgacount = slaves;
+
+	for (k = 1; k <= slaves; ++k) {
+		print_fpga_info(k);
+		osd_probe(k);
+	}
 
-	return osd_probe(0);
+	return 0;
 }
 
 /*
  * provide access to fpga gpios (for I2C bitbang)
  */
-void fpga_gpio_set(int pin)
+void fpga_gpio_set(unsigned int bus, int pin)
 {
-	out_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x18), pin);
+	fpga_set_reg(bus, REG(gpio.set), pin);
 }
 
-void fpga_gpio_clear(int pin)
+void fpga_gpio_clear(unsigned int bus, int pin)
 {
-	out_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x16), pin);
+	fpga_set_reg(bus, REG(gpio.clear), pin);
 }
 
-int fpga_gpio_get(int pin)
+int fpga_gpio_get(unsigned int bus, int pin)
 {
-	return in_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x14)) & pin;
+	return fpga_get_reg(bus, REG(gpio.read)) & pin;
 }
 
 void gd405ep_init(void)
 {
+	unsigned int k;
+
+	if (i2c_probe(0x20)) { /* i2c_probe returns 0 on success */
+		for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k)
+			gd->fpga_state[k] |= FPGA_STATE_PLATFORM;
+	} else {
+		pca9698_direction_output(0x20, 4, 1);
+	}
 }
 
 void gd405ep_set_fpga_reset(unsigned state)
 {
-	if (state) {
-		out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET);
-		out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET);
+	int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
+
+	if (legacy) {
+		if (state) {
+			out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET);
+			out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET);
+		} else {
+			out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT);
+			out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT);
+		}
 	} else {
-		out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT);
-		out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT);
+		pca9698_set_value(0x20, 4, state ? 0 : 1);
 	}
 }
 
@@ -269,5 +438,11 @@ void gd405ep_setup_hw(void)
 
 int gd405ep_get_fpga_done(unsigned fpga)
 {
-	return in_le16((void *)LATCH2_BASE) & CONFIG_SYS_FPGA_DONE(fpga);
+	int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
+
+	if (legacy)
+		return in_le16((void *)LATCH2_BASE)
+		       & CONFIG_SYS_FPGA_DONE(fpga);
+	else
+		return pca9698_get_value(0x20, 20);
 }
diff --git a/include/configs/iocon.h b/include/configs/iocon.h
index 7f8825b..e99efa6 100644
--- a/include/configs/iocon.h
+++ b/include/configs/iocon.h
@@ -112,28 +112,31 @@
  */
 #define CONFIG_SYS_I2C_SPEED		400000
 
-/* enable I2C and select the hardware/software driver */
-#undef  CONFIG_HARD_I2C			/* I2C with hardware support	*/
-#define CONFIG_SOFT_I2C		1	/* I2C bit-banged		*/
-
+#define CONFIG_PCA953X			/* NXP PCA9554 */
+#define CONFIG_PCA9698			/* NXP PCA9698 */
 /*
  * Software (bit-bang) I2C driver configuration
  */
 
 #ifndef __ASSEMBLY__
-void fpga_gpio_set(int pin);
-void fpga_gpio_clear(int pin);
-int fpga_gpio_get(int pin);
+void fpga_gpio_set(unsigned int bus, int pin);
+void fpga_gpio_clear(unsigned int bus, int pin);
+int fpga_gpio_get(unsigned int bus, int pin);
 #endif
 
-#define I2C_ACTIVE	{ }
-#define I2C_TRISTATE	{ }
-#define I2C_READ	fpga_gpio_get(0x0040) ? 1 : 0
-#define I2C_SDA(bit)	if (bit) fpga_gpio_set(0x0040); \
-			else fpga_gpio_clear(0x0040)
-#define I2C_SCL(bit)	if (bit) fpga_gpio_set(0x0020); \
-			else fpga_gpio_clear(0x0020)
-#define I2C_DELAY	udelay(25)	/* 1/4 I2C clock duration */
+#define BB_I2C_SOFT_DECLARATIONS(bus)
+#define BB_I2C_ACTIVE(bus)	{ }
+#define BB_I2C_TRISTATE(bus)	{ }
+#define BB_I2C_READ(bus)	fpga_gpio_get(bus, 0x0040) ? 1 : 0
+#define BB_I2C_SDA(bus, bit)	if (bit) \
+					fpga_gpio_set(bus, 0x0040); \
+				else \
+					fpga_gpio_clear(bus, 0x0040)
+#define BB_I2C_SCL(bus, bit)	if (bit) \
+					 fpga_gpio_set(bus, 0x0020); \
+				else \
+					fpga_gpio_clear(bus, 0x0020)
+#define BB_I2C_DELAY(bus)	udelay(25)	/* 1/4 I2C clock duration */
 
 /*
  * OSD hardware
@@ -252,6 +255,8 @@ int fpga_gpio_get(int pin);
 
 #define CONFIG_SYS_FPGA_COUNT		1
 
+#define CONFIG_SYS_MCLINK_MAX		3
+
 /* Memory Bank 3 (Latches) initialization */
 #define CONFIG_SYS_LATCH_BASE		0x7f200000
 #define CONFIG_SYS_EBC_PB3AP		0x02025080
@@ -267,6 +272,6 @@ int fpga_gpio_get(int pin);
  */
 #define CONFIG_SYS_MPC92469AC
 #define CONFIG_SYS_CH7301
-#define CONFIG_SYS_OSD_SCREENS		CONFIG_SYS_FPGA_COUNT
+#define CONFIG_SYS_OSD_SCREENS		1
 
 #endif	/* __CONFIG_H */
diff --git a/include/gdsys_fpga.h b/include/gdsys_fpga.h
index c12a31d..b246f2f 100644
--- a/include/gdsys_fpga.h
+++ b/include/gdsys_fpga.h
@@ -117,10 +117,21 @@ struct ihs_fpga {
 	u16 mpc3w_control;	/* 0x001a */
 	u16 reserved_1[19];	/* 0x001c */
 	u16 videocontrol;	/* 0x0042 */
-	u16 reserved_2[93];	/* 0x0044 */
+	u16 reserved_2[14];	/* 0x0044 */
+	u16 mc_int;		/* 0x0060 */
+	u16 mc_int_en;		/* 0x0062 */
+	u16 mc_status;		/* 0x0064 */
+	u16 mc_control;		/* 0x0066 */
+	u16 mc_tx_data;		/* 0x0068 */
+	u16 mc_tx_address;	/* 0x006a */
+	u16 mc_tx_cmd;		/* 0x006c */
+	u16 mc_res;		/* 0x006e */
+	u16 mc_rx_cmd_status;	/* 0x0070 */
+	u16 mc_rx_data;		/* 0x0072 */
+	u16 reserved_3[69];	/* 0x0074 */
 	u16 reflection_high;	/* 0x00fe */
 	struct ihs_osd osd;	/* 0x0100 */
-	u16 reserved_3[889];	/* 0x010e */
+	u16 reserved_4[889];	/* 0x010e */
 	u16 videomem;		/* 0x0800 */
 };
 #endif
