Merge branch 'master' of git://git.denx.de/u-boot-blackfin
diff --git a/board/ads5121/ads5121.c b/board/ads5121/ads5121.c
index 0610928..6c40e94 100644
--- a/board/ads5121/ads5121.c
+++ b/board/ads5121/ads5121.c
@@ -31,6 +31,8 @@
 #include <i2c.h>
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Clocks in use */
 #define SCCR1_CLOCKS_EN	(CLOCK_SCCR1_CFG_EN |				\
 			 CLOCK_SCCR1_LPC_EN |				\
@@ -38,6 +40,7 @@
 			 CLOCK_SCCR1_PSCFIFO_EN |			\
 			 CLOCK_SCCR1_DDR_EN |				\
 			 CLOCK_SCCR1_FEC_EN |				\
+			 CLOCK_SCCR1_PATA_EN |				\
 			 CLOCK_SCCR1_PCI_EN |				\
 			 CLOCK_SCCR1_TPR_EN)
 
@@ -101,6 +104,9 @@
 	 */
 	im->clk.sccr[0] = SCCR1_CLOCKS_EN;
 	im->clk.sccr[1] = SCCR2_CLOCKS_EN;
+#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE)
+	im->clk.sccr[1] |= CLOCK_SCCR2_IIM_EN;
+#endif
 
 	return 0;
 }
@@ -290,17 +296,28 @@
 	}
 };
 
+static  iopin_t rev2_silicon_pci_ioregs_init[] = {
+	/* FUNC0=PCI Sets next 54 to PCI pads */
+	{
+		IOCTL_PCI_AD31, 54, 0,
+		IO_PIN_FMUX(0) | IO_PIN_HOLD(0) | IO_PIN_DS(0)
+	}
+};
+
 int checkboard (void)
 {
 	ushort brd_rev = *(vu_short *) (CONFIG_SYS_CPLD_BASE + 0x00);
 	uchar cpld_rev = *(vu_char *) (CONFIG_SYS_CPLD_BASE + 0x02);
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 
 	printf ("Board: ADS5121 rev. 0x%04x (CPLD rev. 0x%02x)\n",
 		brd_rev, cpld_rev);
 	/* initialize function mux & slew rate IO inter alia on IO Pins  */
 
-
 	iopin_initialize(ioregs_init, sizeof(ioregs_init) / sizeof(ioregs_init[0]));
+	if (SVR_MJREV (im->sysconf.spridr) >= 2) {
+		iopin_initialize(rev2_silicon_pci_ioregs_init, 1);
+	}
 
 	return 0;
 }
@@ -312,3 +329,104 @@
 	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
 }
 #endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
+
+#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_RESET)
+
+void init_ide_reset (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	debug ("init_ide_reset\n");
+
+	/*
+	 * Clear the reset bit to reset the interface
+	 * cf. RefMan MPC5121EE: 28.4.1 Resetting the ATA Bus
+	 */
+	immr->pata.pata_ata_control = 0;
+	udelay(100);
+	/* Assert the reset bit to enable the interface */
+	immr->pata.pata_ata_control = FSL_ATA_CTRL_ATA_RST_B;
+	udelay(100);
+
+}
+
+void ide_set_reset (int idereset)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	debug ("ide_set_reset(%d)\n", idereset);
+
+	if (idereset) {
+		immr->pata.pata_ata_control = 0;
+		udelay(100);
+	} else {
+		immr->pata.pata_ata_control = FSL_ATA_CTRL_ATA_RST_B;
+		udelay(100);
+	}
+}
+
+#define CALC_TIMING(t) (t + period - 1) / period
+
+int ide_preinit (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	long t;
+	const struct {
+		short t0;
+		short t1;
+		short t2_8;
+		short t2_16;
+		short t2i;
+		short t4;
+		short t9;
+		short tA;
+	} pio_specs = {
+		.t0    = 600,
+		.t1    =  70,
+		.t2_8  = 290,
+		.t2_16 = 165,
+		.t2i   =   0,
+		.t4    =  30,
+		.t9    =  20,
+		.tA    =  50,
+	};
+	union {
+		u32 config;
+		struct {
+			u8 field1;
+			u8 field2;
+			u8 field3;
+			u8 field4;
+		}bytes;
+	}cfg;
+
+	debug ("IDE preinit using PATA peripheral at IMMR-ADDR %08x\n",
+		(u32)&immr->pata);
+
+	/* Set the reset bit to 1 to enable the interface */
+	immr->pata.pata_ata_control = FSL_ATA_CTRL_ATA_RST_B;
+
+	/* Init timings : we use PIO mode 0 timings */
+	t = 1000000000 / gd->ips_clk;	/* period in ns */
+	cfg.bytes.field1 = 3;
+	cfg.bytes.field2 = 3;
+	cfg.bytes.field3 = (pio_specs.t1 + t) / t;
+	cfg.bytes.field4 = (pio_specs.t2_8 + t) / t;
+
+	immr->pata.pata_time1 = cfg.config;
+
+	cfg.bytes.field1 = (pio_specs.t2_8 + t) / t;
+	cfg.bytes.field2 = (pio_specs.tA + t) / t + 2;
+	cfg.bytes.field3 = 1;
+	cfg.bytes.field4 = (pio_specs.t4 + t) / t;
+
+	immr->pata.pata_time2 = cfg.config;
+
+	cfg.config = immr->pata.pata_time3;
+	cfg.bytes.field1 = (pio_specs.t9 + t) / t;
+
+	immr->pata.pata_time3 = cfg.config;
+	debug ("PATA preinit complete.\n");
+
+	return 0;
+}
+
+#endif /* defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_RESET) */
diff --git a/board/ads5121/ads5121_diu.c b/board/ads5121/ads5121_diu.c
index 4f7dda0..41a1353 100644
--- a/board/ads5121/ads5121_diu.c
+++ b/board/ads5121/ads5121_diu.c
@@ -37,7 +37,11 @@
 #include <video_fb.h>
 #endif
 
+#ifdef CONFIG_FSL_DIU_LOGO_BMP
 extern unsigned int FSL_Logo_BMP[];
+#else
+#define FSL_Logo_BMP NULL
+#endif
 
 static int xres, yres;
 
@@ -61,16 +65,40 @@
 	debug("DIU: Modified value of CLKDVDR = 0x%08x\n", *clkdvdr);
 }
 
+char *valid_bmp(char *addr)
+{
+	unsigned long h_addr;
+
+	h_addr = simple_strtoul(addr, NULL, 16);
+	if (h_addr < CONFIG_SYS_FLASH_BASE ||
+			h_addr >= (CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_SIZE - 1)) {
+		printf("bmp addr %lx is not a valid flash address\n", h_addr);
+		return 0;
+	} else if ((*(char *)(h_addr) != 'B') || (*(char *)(h_addr+1) != 'M')) {
+		printf("bmp addr is not a bmp\n");
+		return 0;
+	} else
+		return (char *)h_addr;
+}
+
 int ads5121_diu_init(void)
 {
 	unsigned int pixel_format;
+	char *bmp = NULL;
+	char *bmp_env;
 
 	xres = 1024;
 	yres = 768;
 	pixel_format = 0x88883316;
 
-	return fsl_diu_init(xres, pixel_format, 0,
-		     (unsigned char *)FSL_Logo_BMP);
+	debug("ads5121_diu_init\n");
+	bmp_env = getenv("diu_bmp_addr");
+	if (bmp_env) {
+		bmp = valid_bmp(bmp_env);
+	}
+	if (!bmp)
+		bmp = FSL_Logo_BMP;
+	return fsl_diu_init(xres, pixel_format, 0, (unsigned char *)bmp);
 }
 
 int ads5121diu_init_show_bmp(cmd_tbl_t *cmdtp,
diff --git a/common/cmd_ide.c b/common/cmd_ide.c
index c9b9a47..8c6ed35 100644
--- a/common/cmd_ide.c
+++ b/common/cmd_ide.c
@@ -45,6 +45,10 @@
 #include <mpc5xxx.h>
 #endif
 
+#ifdef CONFIG_MPC512X
+#include <mpc512x.h>
+#endif
+
 #include <ide.h>
 #include <ata.h>
 
diff --git a/cpu/mpc512x/Makefile b/cpu/mpc512x/Makefile
index e8f1060..297d135 100644
--- a/cpu/mpc512x/Makefile
+++ b/cpu/mpc512x/Makefile
@@ -26,6 +26,9 @@
 
 START	= start.o
 COBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o i2c.o iopin.o
+ifdef CONFIG_IIM
+COBJS	+= iim.o
+endif
 
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/mpc512x/iim.c b/cpu/mpc512x/iim.c
new file mode 100644
index 0000000..6cdc422
--- /dev/null
+++ b/cpu/mpc512x/iim.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2008 Silicon Turnkey Express, Inc.
+ * Martha Marx <mmarx@silicontkx.com>
+ *
+ * ADS5121 IIM (Fusebox) Interface
+ *
+ * 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>
+#include <command.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CMD_FUSE
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char cur_bank = '1';
+
+char *iim_err_msg(u32 err)
+{
+	static char *IIM_errs[] = {
+		"Parity Error in cache",
+		"Explicit Sense Cycle Error",
+		"Write to Locked Register Error",
+		"Read Protect Error",
+		"Override Protect Error",
+		"Write Protect Error"};
+
+	int i;
+
+	if (!err)
+		return "";
+	for (i = 1; i < 8; i++)
+		if (err & (1 << i))
+			printf("IIM - %s\n", IIM_errs[i-1]);
+	return "";
+}
+
+int in_range(int n, int min, int max, char *err, char *usg)
+{
+	if (n > max || n < min) {
+		printf(err);
+		printf("Usage:\n%s\n", usg);
+		return 0;
+	}
+	return 1;
+}
+
+int ads5121_fuse_read(int bank, int fstart, int num)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 *iim_fb, dummy;
+	int f, ctr;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fb = (u32 *)&(iim->fbac0);
+	else
+		iim_fb = (u32 *)&(iim->fbac1);
+/* try a read to see if Read Protect is set */
+	dummy = in_be32(&iim_fb[0]);
+	if (in_be32(&iim->err) & IIM_ERR_RPE) {
+		printf("\tRead protect fuse is set\n");
+		out_be32(&iim->err, IIM_ERR_RPE);
+		return 0;
+	}
+	printf("Reading Bank %d cache\n", bank);
+	for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
+		if (ctr % 4 == 0)
+			printf("F%2d:", f);
+		printf("\t%#04x", (u8)(iim_fb[f]));
+		if (ctr % 4 == 3)
+			printf("\n");
+	}
+	if (ctr % 4 != 0)
+		printf("\n");
+}
+
+int ads5121_fuse_override(int bank, int f, u8 val)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 *iim_fb;
+	u32 iim_stat;
+	int i;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fb = (u32 *)&(iim->fbac0);
+	else
+		iim_fb = (u32 *)&(iim->fbac1);
+/* try a read to see if Read Protect is set */
+	iim_stat = in_be32(&iim_fb[0]);
+	if (in_be32(&iim->err) & IIM_ERR_RPE) {
+		printf("Read protect fuse is set on bank %d;"
+			"Override protect may also be set\n", bank);
+		printf("An attempt will be made to override\n");
+		out_be32(&iim->err, IIM_ERR_RPE);
+	}
+	if (iim_stat & IIM_FBAC_FBOP) {
+		printf("Override protect fuse is set on bank %d\n", bank);
+		return 1;
+	}
+	if (f > IIM_FMAX) /* reset the entire bank */
+		for (i = 0; i < IIM_FMAX + 1; i++)
+			out_be32(&iim_fb[i],  0);
+	else
+		out_be32(&iim_fb[f], val);
+	return 0;
+}
+
+int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	int f, i, bitno;
+	u32 stat, err;
+
+	f = simple_strtol(fuseno_bitno, NULL, 10);
+	if (f == 0 && fuseno_bitno[0] != '0')
+		f = -1;
+	if (!in_range(f, 0, IIM_FMAX,
+		"<frow> must be between 0-31\n\n", cmdtp->usage))
+		return 1;
+	bitno = -1;
+	for (i = 0; i < 6; i++) {
+		if (fuseno_bitno[i] == '_') {
+			bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
+			if (bitno == 0 && fuseno_bitno[i+1] != '0')
+				bitno = -1;
+			break;
+		}
+	}
+	if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
+		"Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
+		cmdtp->usage))
+		return 1;
+	out_be32(&iim->err, in_be32(&iim->err));
+	out_be32(&iim->prg_p, IIM_PRG_P_SET);
+	out_be32(&iim->ua, IIM_SET_UA(bank, f));
+	out_be32(&iim->la, IIM_SET_LA(f, bitno));
+#ifdef DEBUG
+	printf("Programming disabled with DEBUG defined \n");
+	printf(""Set up to pro
+	printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
+#else
+	out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
+	do
+		udelay(20);
+	while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
+	out_be32(&iim->prg_p, 0);
+	err = in_be32(&iim->err);
+	if (stat & IIM_STAT_PRGD) {
+		if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
+			printf("Fuse is successfully set");
+			if (err)
+				printf(" - however there are other errors");
+			printf("\n");
+		}
+		iim->stat = 0;
+	}
+	if (err) {
+		iim_err_msg(err);
+		out_be32(&iim->err, in_be32(&iim->err));
+	}
+#endif
+}
+
+int ads5121_fuse_sense(int bank, int fstart, int num)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 iim_fbac;
+	u32 stat, err, err_hold = 0;
+	int f, ctr;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fbac = in_be32(&iim->fbac0);
+	else
+		iim_fbac = in_be32(&iim->fbac1);
+	if (iim_fbac & IIM_FBAC_FBESP) {
+		printf("\tSense Protect disallows this operation\n");
+		out_be32(&iim->err, IIM_FBAC_FBESP);
+		return 1;
+	}
+	err = in_be32(&iim->err);
+	if (err) {
+		iim_err_msg(err);
+		err_hold |= err;
+	}
+	if (err & IIM_ERR_RPE)
+		printf("\tRead protect fuse is set; "
+			"Sense Protect may be set but will be attempted\n");
+	if (err)
+		out_be32(&iim->err, err);
+	printf("Sensing fuse(s) on Bank %d\n", bank);
+	for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
+		out_be32(&iim->ua, IIM_SET_UA(bank, f));
+		out_be32(&iim->la, IIM_SET_LA(f, 0));
+		out_be32(&iim->fctl,  IIM_FCTL_ESNS_N);
+		do
+			udelay(20);
+		while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
+		err = in_be32(&iim->err);
+		if (err & IIM_ERR_SNSE) {
+			iim_err_msg(err);
+			out_be32(&iim->err, IIM_ERR_SNSE);
+			return 1;
+		}
+		if (stat & IIM_STAT_SNSD) {
+			out_be32(&iim->stat, 0);
+			if (ctr % 4 == 0)
+				printf("F%2d:", f);
+			printf("\t%#04x", (u8)iim->sdat);
+			if (ctr % 4 == 3)
+				printf("\n");
+		}
+		if (err) {
+			err_hold |= err;
+			out_be32(&iim->err, err);
+		}
+	}
+	if (ctr % 4 != 0)
+		printf("\n");
+	if (err_hold)
+		iim_err_msg(err_hold);
+
+	return 0;
+}
+
+int ads5121_fuse_stat(int bank)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 iim_fbac;
+	u32 err;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fbac = in_be32(&iim->fbac0);
+	else
+		iim_fbac = in_be32(&iim->fbac1);
+	err = in_be32(&iim->err);
+	if (err)
+		iim_err_msg(err);
+	if (err & IIM_ERR_RPE  || iim_fbac & IIM_FBAC_FBRP) {
+		if (iim_fbac == 0)
+			printf("Since protection settings can't be read - "
+				"try sensing fuse row 0;\n");
+		return 0;
+	}
+	if (iim_fbac & IIM_PROTECTION)
+		printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
+	else if (!(err & IIM_ERR_RPE))
+		printf("No Protection fuses are set\n");
+	if (iim_fbac & IIM_FBAC_FBWP)
+		printf("\tWrite Protect fuse is set\n");
+	if (iim_fbac & IIM_FBAC_FBOP)
+		printf("\tOverride Protect fuse is set\n");
+	if (iim_fbac & IIM_FBAC_FBESP)
+		printf("\tSense Protect Fuse is set\n");
+	out_be32(&iim->err, in_be32(&iim->err));
+
+	return 0;
+}
+
+int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int frow, n, v, bank;
+
+	if (cur_bank == '0')
+		bank = 0;
+	else
+		bank = 1;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	case 2:
+		if (strncmp(argv[1], "stat", 4) == 0)
+			return ads5121_fuse_stat(bank);
+		if (strncmp(argv[1], "read", 4) == 0)
+			return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
+		if (strncmp(argv[1], "sense", 5) == 0)
+			return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
+		if (strncmp(argv[1], "ovride", 6) == 0)
+			return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
+		if (strncmp(argv[1], "bank", 4) == 0) {
+			printf("Active Fuse Bank is %c\n", cur_bank);
+			return 0;
+		}
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	case 3:
+		if (strncmp(argv[1], "bank", 4) == 0) {
+			if (argv[2][0] == '0')
+				cur_bank = '0';
+			else if (argv[2][0] == '1')
+				cur_bank = '1';
+			else {
+				printf("Usage:\n%s\n", cmdtp->usage);
+				return 1;
+			}
+
+			printf("Setting Active Fuse Bank to %c\n", cur_bank);
+			return 0;
+		}
+		if (strncmp(argv[1], "prog", 4) == 0)
+			return ads5121_fuse_prog(cmdtp, bank, argv[2]);
+
+		frow = (int)simple_strtol(argv[2], NULL, 10);
+		if (frow == 0 && argv[2][0] != '0')
+			frow = -1;
+		if (!in_range(frow, 0, IIM_FMAX,
+			"<frow> must be between 0-31\n\n", cmdtp->usage))
+			return 1;
+		if (strncmp(argv[1], "read", 4) == 0)
+			return ads5121_fuse_read(bank, frow, 1);
+		if (strncmp(argv[1], "ovride", 6) == 0)
+			return ads5121_fuse_override(bank, frow, 0);
+		if (strncmp(argv[1], "sense", 5) == 0)
+			return ads5121_fuse_sense(bank, frow, 1);
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	case 4:
+		frow = (int)simple_strtol(argv[2], NULL, 10);
+		if (frow == 0 && argv[2][0] != '0')
+			frow = -1;
+		if (!in_range(frow, 0, IIM_FMAX,
+			"<frow> must be between 0-31\n\n", cmdtp->usage))
+			return 1;
+		if (strncmp(argv[1], "read", 4) == 0) {
+			n = (int)simple_strtol(argv[3], NULL, 10);
+			if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
+				"<frow>+<n> must be between 1-32\n\n",
+				cmdtp->usage))
+				return 1;
+			return ads5121_fuse_read(bank, frow, n);
+		}
+		if (strncmp(argv[1], "ovride", 6) == 0) {
+			v = (int)simple_strtol(argv[3], NULL, 10);
+			return ads5121_fuse_override(bank, frow, v);
+		}
+		if (strncmp(argv[1], "sense", 5) == 0) {
+			n = (int)simple_strtol(argv[3], NULL, 10);
+			if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
+				"<frow>+<n> must be between 1-32\n\n",
+				cmdtp->usage))
+				return 1;
+			return ads5121_fuse_sense(bank, frow, n);
+		}
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	default: /* at least 5 args */
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+}
+
+U_BOOT_CMD(
+	fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
+	"   - Read, Sense, Override or Program Fuses\n",
+	"bank <n>		- sets active Fuse Bank to 0 or 1\n"
+	"			    no args shows current active bank\n"
+	"fuse stat		- print active fuse bank's protection status\n"
+	"fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n"
+	"			    no args to print entire bank's fuses\n"
+	"fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
+	"			    no <v> defaults to 0 for the row\n"
+	"			    no args resets entire bank to 0\n"
+	"			  NOTE - settings persist until hard reset\n"
+	"fuse sense [<frow>]	- senses current fuse at <frow>\n"
+	"			    no args for entire bank\n"
+	"fuse prog <frow_bit> 	- program fuse at row <frow>, bit <_bit>\n"
+	"			    <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
+	"			  WARNING - this is permanent\n"
+	);
+#endif /* CONFIG_CMD_FUSE */
diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c
index e8871fc..2e75886 100644
--- a/cpu/ppc4xx/4xx_pci.c
+++ b/cpu/ppc4xx/4xx_pci.c
@@ -588,8 +588,9 @@
 	int busno;
 
 	busno = pci_440_init (&ppc440_hose);
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if (defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
+    !defined(CONFIG_PCI_DISABLE_PCIE)
 	pcie_setup_hoses(busno + 1);
 #endif
 }
diff --git a/cpu/ppc4xx/4xx_pcie.c b/cpu/ppc4xx/4xx_pcie.c
index fd40d8a..58d96bb 100644
--- a/cpu/ppc4xx/4xx_pcie.c
+++ b/cpu/ppc4xx/4xx_pcie.c
@@ -33,7 +33,7 @@
 
 #if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) ||	\
     defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
-    defined(CONFIG_PCI)
+    defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_PCIE)
 
 #include <asm/4xx_pcie.h>
 
diff --git a/cpu/ppc4xx/fdt.c b/cpu/ppc4xx/fdt.c
index c55e1cf..ba5c120 100644
--- a/cpu/ppc4xx/fdt.c
+++ b/cpu/ppc4xx/fdt.c
@@ -113,6 +113,7 @@
 void ft_cpu_setup(void *blob, bd_t *bd)
 {
 	sys_info_t sys_info;
+	int off, ndepth = 0;
 
 	get_sys_info(&sys_info);
 
@@ -133,9 +134,28 @@
 	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
 
 	/*
-	 * Setup all baudrates for the UARTs
+	 * Fixup all UART clocks for CPU internal UARTs
+	 * (only these UARTs are definitely clocked by gd->uart_clk)
+	 *
+	 * These UARTs are direct childs of /plb/opb. This code
+	 * does not touch any UARTs that are connected to the ebc.
 	 */
-	do_fixup_by_compat_u32(blob, "ns16550", "clock-frequency", gd->uart_clk, 1);
+	off = fdt_path_offset(blob, "/plb/opb");
+	while ((off = fdt_next_node(blob, off, &ndepth)) >= 0) {
+		/*
+		 * process all sub nodes and stop when we are back
+		 * at the starting depth
+		 */
+		if (ndepth <= 0)
+			break;
+
+		/* only update direct childs */
+		if ((ndepth == 1) &&
+		    (fdt_node_check_compatible(blob, off, "ns16550") == 0))
+			fdt_setprop(blob, off,
+				    "clock-frequency",
+				    (void*)&(gd->uart_clk), 4);
+	}
 
 	/*
 	 * Fixup all ethernet nodes
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 84ff7e8..bdfad98 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -305,17 +305,12 @@
 {
 	unsigned int byte_offset = offset * info->portwidth;
 
-	return map_physmem(info->start[sect] + byte_offset,
-			flash_sector_size(info, sect) - byte_offset,
-			MAP_NOCACHE);
+	return (void *)(info->start[sect] + byte_offset);
 }
 
 static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
 		unsigned int offset, void *addr)
 {
-	unsigned int byte_offset = offset * info->portwidth;
-
-	unmap_physmem(addr, flash_sector_size(info, sect) - byte_offset);
 }
 
 /*-----------------------------------------------------------------------
@@ -802,13 +797,11 @@
 static int flash_write_cfiword (flash_info_t * info, ulong dest,
 				cfiword_t cword)
 {
-	void *dstaddr;
+	void *dstaddr = (void *)dest;
 	int flag;
 	flash_sect_t sect = 0;
 	char sect_found = 0;
 
-	dstaddr = map_physmem(dest, info->portwidth, MAP_NOCACHE);
-
 	/* Check if Flash is (sufficiently) erased */
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
@@ -827,10 +820,8 @@
 		flag = 0;
 		break;
 	}
-	if (!flag) {
-		unmap_physmem(dstaddr, info->portwidth);
+	if (!flag)
 		return ERR_NOT_ERASED;
-	}
 
 	/* Disable interrupts which might cause a timeout here */
 	flag = disable_interrupts ();
@@ -873,8 +864,6 @@
 	if (flag)
 		enable_interrupts ();
 
-	unmap_physmem(dstaddr, info->portwidth);
-
 	if (!sect_found)
 		sect = find_sector (info, dest);
 
@@ -890,7 +879,7 @@
 	int cnt;
 	int retcode;
 	void *src = cp;
-	void *dst = map_physmem(dest, len, MAP_NOCACHE);
+	void *dst = (void *)dest;
 	void *dst2 = dst;
 	int flag = 0;
 	uint offset = 0;
@@ -1052,7 +1041,6 @@
 	}
 
 out_unmap:
-	unmap_physmem(dst, len);
 	return retcode;
 }
 #endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
@@ -1301,7 +1289,7 @@
 	/* handle unaligned start */
 	if ((aln = addr - wp) != 0) {
 		cword.l = 0;
-		p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
+		p = (uchar *)wp;
 		for (i = 0; i < aln; ++i)
 			flash_add_byte (info, &cword, flash_read8(p + i));
 
@@ -1313,7 +1301,6 @@
 			flash_add_byte (info, &cword, flash_read8(p + i));
 
 		rc = flash_write_cfiword (info, wp, cword);
-		unmap_physmem(p, info->portwidth);
 		if (rc != 0)
 			return rc;
 
@@ -1372,14 +1359,13 @@
 	 * handle unaligned tail bytes
 	 */
 	cword.l = 0;
-	p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
+	p = (uchar *)wp;
 	for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
 		flash_add_byte (info, &cword, *src++);
 		--cnt;
 	}
 	for (; i < info->portwidth; ++i)
 		flash_add_byte (info, &cword, flash_read8(p + i));
-	unmap_physmem(p, info->portwidth);
 
 	return flash_write_cfiword (info, wp, cword);
 }
@@ -1618,7 +1604,7 @@
  * board_flash_get_legacy needs to fill in at least:
  * info->portwidth, info->chipwidth and info->interface for Jedec probing.
  */
-static int flash_detect_legacy(ulong base, int banknum)
+static int flash_detect_legacy(phys_addr_t base, int banknum)
 {
 	flash_info_t *info = &flash_info[banknum];
 
@@ -1634,7 +1620,10 @@
 
 			for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
 				info->vendor = modes[i];
-				info->start[0] = base;
+				info->start[0] =
+					(ulong)map_physmem(base,
+							   info->portwidth,
+							   MAP_NOCACHE);
 				if (info->portwidth == FLASH_CFI_8BIT
 					&& info->interface == FLASH_CFI_X8X16) {
 					info->addr_unlock1 = 0x2AAA;
@@ -1648,8 +1637,11 @@
 						info->manufacturer_id,
 						info->device_id,
 						info->device_id2);
-				if (jedec_flash_match(info, base))
+				if (jedec_flash_match(info, info->start[0]))
 					break;
+				else
+					unmap_physmem((void *)info->start[0],
+						      MAP_NOCACHE);
 			}
 		}
 
@@ -1671,7 +1663,7 @@
 	return 0; /* use CFI */
 }
 #else
-static inline int flash_detect_legacy(ulong base, int banknum)
+static inline int flash_detect_legacy(phys_addr_t base, int banknum)
 {
 	return 0; /* use CFI */
 }
@@ -1826,12 +1818,12 @@
  * The following code cannot be run from FLASH!
  *
  */
-ulong flash_get_size (ulong base, int banknum)
+ulong flash_get_size (phys_addr_t base, int banknum)
 {
 	flash_info_t *info = &flash_info[banknum];
 	int i, j;
 	flash_sect_t sect_cnt;
-	unsigned long sector;
+	phys_addr_t sector;
 	unsigned long tmp;
 	int size_ratio;
 	uchar num_erase_regions;
@@ -1847,7 +1839,7 @@
 	info->legacy_unlock = 0;
 #endif
 
-	info->start[0] = base;
+	info->start[0] = (ulong)map_physmem(base, info->portwidth, MAP_NOCACHE);
 
 	if (flash_detect_cfi (info, &qry)) {
 		info->vendor = le16_to_cpu(qry.p_id);
@@ -1939,7 +1931,10 @@
 					printf("ERROR: too many flash sectors\n");
 					break;
 				}
-				info->start[sect_cnt] = sector;
+				info->start[sect_cnt] =
+					(ulong)map_physmem(sector,
+							   info->portwidth,
+							   MAP_NOCACHE);
 				sector += (erase_region_size * size_ratio);
 
 				/*
@@ -2016,7 +2011,7 @@
 	char *s = getenv("unlock");
 #endif
 
-#define BANK_BASE(i)	(((unsigned long [CFI_MAX_FLASH_BANKS])CONFIG_SYS_FLASH_BANKS_LIST)[i])
+#define BANK_BASE(i)	(((phys_addr_t [CFI_MAX_FLASH_BANKS])CONFIG_SYS_FLASH_BANKS_LIST)[i])
 
 	/* Init: no FLASHes known */
 	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
diff --git a/drivers/mtd/jedec_flash.c b/drivers/mtd/jedec_flash.c
index 2d99d4d..e48acec 100644
--- a/drivers/mtd/jedec_flash.c
+++ b/drivers/mtd/jedec_flash.c
@@ -37,10 +37,6 @@
 
 #define P_ID_AMD_STD CFI_CMDSET_AMD_LEGACY
 
-/* Manufacturers */
-#define MANUFACTURER_AMD	0x0001
-#define MANUFACTURER_SST	0x00BF
-
 /* AMD */
 #define AM29DL800BB	0x22CB
 #define AM29DL800BT	0x224A
@@ -172,7 +168,7 @@
 static const struct amd_flash_info jedec_table[] = {
 #ifdef CONFIG_SYS_FLASH_LEGACY_256Kx8
 	{
-		.mfr_id		= MANUFACTURER_SST,
+		.mfr_id		= (u16)SST_MANUFACT,
 		.dev_id		= SST39LF020,
 		.name		= "SST 39LF020",
 		.uaddr		= {
@@ -188,7 +184,7 @@
 #endif
 #ifdef CONFIG_SYS_FLASH_LEGACY_512Kx8
 	{
-		.mfr_id		= MANUFACTURER_AMD,
+		.mfr_id		= (u16)AMD_MANUFACT,
 		.dev_id		= AM29LV040B,
 		.name		= "AMD AM29LV040B",
 		.uaddr		= {
@@ -202,7 +198,7 @@
 		}
 	},
 	{
-		.mfr_id		= MANUFACTURER_SST,
+		.mfr_id		= (u16)SST_MANUFACT,
 		.dev_id		= SST39LF040,
 		.name		= "SST 39LF040",
 		.uaddr		= {
@@ -216,7 +212,7 @@
 		}
 	},
 	{
-		.mfr_id		= STM_MANUFACT,
+		.mfr_id		= (u16)STM_MANUFACT,
 		.dev_id		= STM_ID_M29W040B,
 		.name		= "ST Micro M29W040B",
 		.uaddr		= {
@@ -232,7 +228,7 @@
 #endif
 #ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
 	{
-		.mfr_id		= MANUFACTURER_AMD,
+		.mfr_id		= (u16)AMD_MANUFACT,
 		.dev_id		= AM29LV400BB,
 		.name		= "AMD AM29LV400BB",
 		.uaddr		= {
@@ -249,7 +245,7 @@
 		}
 	},
 	{
-		.mfr_id		= MANUFACTURER_AMD,
+		.mfr_id		= (u16)AMD_MANUFACT,
 		.dev_id		= AM29LV800BB,
 		.name		= "AMD AM29LV800BB",
 		.uaddr		= {
diff --git a/include/asm-ppc/immap_512x.h b/include/asm-ppc/immap_512x.h
index cd90945..8087869 100644
--- a/include/asm-ppc/immap_512x.h
+++ b/include/asm-ppc/immap_512x.h
@@ -415,7 +415,25 @@
  * IIM
  */
 typedef struct iim512x {
-	u8 fixme[0x1000];
+	u32 stat;		/* IIM status register */
+	u32 statm;		/* IIM status IRQ mask */
+	u32 err;		/* IIM errors register */
+	u32 emask;		/* IIM error IRQ mask  */
+	u32 fctl;		/* IIM fuse control register */
+	u32 ua;			/* IIM upper address register */
+	u32 la;			/* IIM lower address register */
+	u32 sdat;		/* IIM explicit sense data */
+	u8 res0[0x08];
+	u32 prg_p;		/* IIM program protection register */
+	u8 res1[0x10];
+	u32 divide;		/* IIM divide factor register */
+	u8 res2[0x7c0];
+	u32 fbac0;		/* IIM fuse bank 0 prot (for Freescale use) */
+	u32 fb0w0[0x1f];	/* IIM fuse bank 0 data (for Freescale use) */
+	u8 res3[0x380];
+	u32 fbac1;		/* IIM fuse bank 1 protection */
+	u32 fb1w1[0x01f];	/* IIM fuse bank 1 data */
+	u8 res4[0x380];
 } iim512x_t;
 
 /*
@@ -451,7 +469,34 @@
  * PATA
  */
 typedef struct pata512x {
-	u8 fixme[0x100];
+	/* LOCAL Registers */
+	u32 pata_time1;		/* Time register 1: PIO and tx timing parameter */
+	u32 pata_time2;		/* Time register 2: PIO timing parameter */
+	u32 pata_time3;		/* Time register 3: PIO and MDMA timing parameter */
+	u32 pata_time4;		/* Time register 4: MDMA and UDMA timing parameter */
+	u32 pata_time5;		/* Time register 5: UDMA timing parameter */
+	u32 pata_time6;		/* Time register 6: UDMA timing parameter */
+	u32 pata_fifo_data32;   /* 32bit wide dataport to/from FIFO */
+	u32 pata_fifo_data16;   /* 16bit wide dataport to/from FIFO */
+	u32 pata_fifo_fill;	/* FIFO filling in halfwords (READONLY)*/
+	u32 pata_ata_control;   /* ATA Interface control register */
+	u32 pata_irq_pending;   /* Interrupt pending register (READONLY) */
+	u32 pata_irq_enable;	/* Interrupt enable register */
+	u32 pata_irq_clear;	/* Interrupt clear register (WRITEONLY)*/
+	u32 pata_fifo_alarm;	/* fifo alarm threshold */
+	u32 res1[0x1A];
+	/* DRIVE Registers */
+	u32 pata_drive_data;	/* drive data register*/
+	u32 pata_drive_features;/* drive features register */
+	u32 pata_drive_sectcnt; /* drive sector count register */
+	u32 pata_drive_sectnum; /* drive sector number register */
+	u32 pata_drive_cyllow;  /* drive cylinder low register */
+	u32 pata_drive_cylhigh; /* drive cylinder high register */
+	u32 pata_drive_dev_head;/* drive device head register */
+	u32 pata_drive_command; /* write = drive command, read = drive status reg */
+	u32 res2[0x06];
+	u32 pata_drive_alt_stat;/* write = drive control, read = drive alt status reg */
+	u32 res3[0x09];
 } pata512x_t;
 
 /*
diff --git a/include/configs/ads5121.h b/include/configs/ads5121.h
index bb3525f..8fda3f2 100644
--- a/include/configs/ads5121.h
+++ b/include/configs/ads5121.h
@@ -47,6 +47,7 @@
 #define CONFIG_E300		1	/* E300 Family */
 #define CONFIG_MPC512X		1	/* MPC512X family */
 #define CONFIG_FSL_DIU_FB	1	/* FSL DIU */
+#undef CONFIG_FSL_DIU_LOGO_BMP		/* Don't include FSL DIU binary bmp */
 
 /* video */
 #undef CONFIG_VIDEO
@@ -294,6 +295,11 @@
 #endif
 
 /*
+ * IIM - IC Identification Module
+ */
+#undef CONFIG_IIM
+
+/*
  * EEPROM configuration
  */
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN		2	/* 16-bit EEPROM address */
@@ -348,11 +354,20 @@
 #define CONFIG_CMD_REGINFO
 #define CONFIG_CMD_EEPROM
 #define CONFIG_CMD_DATE
+#undef CONFIG_CMD_FUSE
+#define CONFIG_CMD_IDE
+#define CONFIG_CMD_EXT2
 
 #if defined(CONFIG_PCI)
 #define CONFIG_CMD_PCI
 #endif
 
+#if defined(CONFIG_CMD_IDE)
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION
+#endif /* defined(CONFIG_CMD_IDE) */
+
 /*
  * Watchdog timeout = CONFIG_SYS_WATCHDOG_VALUE * 65536 / IPS clock.
  * For example, when IPS is set to 66MHz and CONFIG_SYS_WATCHDOG_VALUE is set
@@ -489,4 +504,48 @@
 #define OF_TBCLK		(bd->bi_busfreq / 4)
 #define OF_STDOUT_PATH		"/soc@80000000/serial@11300"
 
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff
+ *-----------------------------------------------------------------------
+ */
+
+#undef  CONFIG_IDE_8xx_PCCARD		/* Use IDE with PC Card	Adapter	*/
+#undef	CONFIG_IDE_8xx_DIRECT		/* Direct IDE    not supported	*/
+#undef	CONFIG_IDE_LED			/* LED   for IDE not supported	*/
+
+#define CONFIG_IDE_RESET		/* reset for IDE supported	*/
+#define CONFIG_IDE_PREINIT
+
+#define CONFIG_SYS_IDE_MAXBUS		1	/* max. 1 IDE bus		*/
+#define CONFIG_SYS_IDE_MAXDEVICE	2	/* max. 1 drive per IDE bus	*/
+
+#define CONFIG_SYS_ATA_IDE0_OFFSET	0x0000
+#define CONFIG_SYS_ATA_BASE_ADDR	MPC512X_PATA
+
+/* Offset for data I/O			RefMan MPC5121EE Table 28-10	*/
+#define CONFIG_SYS_ATA_DATA_OFFSET	(0x00A0)
+
+/* Offset for normal register accesses	*/
+#define CONFIG_SYS_ATA_REG_OFFSET	(CONFIG_SYS_ATA_DATA_OFFSET)
+
+/* Offset for alternate registers	RefMan MPC5121EE Table 28-23	*/
+#define CONFIG_SYS_ATA_ALT_OFFSET	(0x00D8)
+
+/* Interval between registers	*/
+#define CONFIG_SYS_ATA_STRIDE		4
+
+#define ATA_BASE_ADDR		MPC512X_PATA
+
+/*
+ * Control register bit definitions
+ */
+#define FSL_ATA_CTRL_FIFO_RST_B		0x80000000
+#define FSL_ATA_CTRL_ATA_RST_B		0x40000000
+#define FSL_ATA_CTRL_FIFO_TX_EN		0x20000000
+#define FSL_ATA_CTRL_FIFO_RCV_EN	0x10000000
+#define FSL_ATA_CTRL_DMA_PENDING	0x08000000
+#define FSL_ATA_CTRL_DMA_ULTRA		0x04000000
+#define FSL_ATA_CTRL_DMA_WRITE		0x02000000
+#define FSL_ATA_CTRL_IORDY_EN		0x01000000
+
 #endif	/* __CONFIG_H */
diff --git a/include/flash.h b/include/flash.h
index 6e2981c..02c6a04 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -33,7 +33,7 @@
 	ulong	size;			/* total bank size in bytes		*/
 	ushort	sector_count;		/* number of erase units		*/
 	ulong	flash_id;		/* combined device & manufacturer code	*/
-	ulong	start[CONFIG_SYS_MAX_FLASH_SECT];   /* physical sector start addresses */
+	ulong	start[CONFIG_SYS_MAX_FLASH_SECT];   /* virtual sector start address */
 	uchar	protect[CONFIG_SYS_MAX_FLASH_SECT]; /* sector protection status	*/
 #ifdef CONFIG_SYS_FLASH_CFI
 	uchar	portwidth;		/* the width of the port		*/
diff --git a/include/mpc512x.h b/include/mpc512x.h
index 05a2063..0f02293 100644
--- a/include/mpc512x.h
+++ b/include/mpc512x.h
@@ -573,6 +573,31 @@
 
  /* Register Offset Base */
 #define MPC512X_FEC		(CONFIG_SYS_IMMR + 0x02800)
+#define MPC512X_PATA		(CONFIG_SYS_IMMR + 0x10200)
+
+/* IIM control */
+#define IIM_SET_UA(bk, f)	((bk << 3) | (f >> 5))
+#define IIM_SET_LA(f, bit)	(((f & 0x0000001f) << 3) | bit)
+#define IIM_STAT_BUSY		0x00000080
+#define IIM_STAT_PRGD		0x00000002
+#define IIM_STAT_SNSD		0x00000001
+#define IIM_ERR_WPE		0x00000040
+#define IIM_ERR_OPE		0x00000020
+#define IIM_ERR_RPE		0x00000010
+#define IIM_ERR_WLRE		0x00000008
+#define IIM_ERR_SNSE		0x00000004
+#define IIM_ERR_PARITYE		0x00000002
+#define IIM_PRG_P_SET		0x000000aa
+#define IIM_PRG_P_UNSET		0
+#define IIM_FCTL_PROG_PULSE	0x00000020
+#define IIM_FCTL_PROG		0x00000001
+#define IIM_FCTL_ESNS_N		0x00000008
+#define	IIM_FBAC_FBWP		0x00000080
+#define IIM_FBAC_FBOP		0x00000040
+#define IIM_FBAC_FBRP		0x00000020
+#define	IIM_FBAC_FBESP		0x00000008
+#define IIM_PROTECTION		0x000000e8
+#define IIM_FMAX			31
 
 /* Number of I2C buses */
 #define I2C_BUS_CNT	3