diff --git a/board/freescale/p1022ds/diu.c b/board/freescale/p1022ds/diu.c
index 5ca84dfafc436c106c15ad6411de8ac7277cef8b..12b40a01ed00f071f12c905bfc6f17973bade791 100644
--- a/board/freescale/p1022ds/diu.c
+++ b/board/freescale/p1022ds/diu.c
@@ -18,12 +18,21 @@
 #include "../common/ngpixis.h"
 #include <fsl_diu_fb.h>
 
-#define PX_BRDCFG0_ELBC_DIU	0x02
+/* The CTL register is called 'csr' in the ngpixis_t structure */
+#define PX_CTL_ALTACC		0x80
+
+#define PX_BRDCFG0_ELBC_SPI_MASK	0xc0
+#define PX_BRDCFG0_ELBC_SPI_ELBC	0x00
+#define PX_BRDCFG0_ELBC_SPI_NULL	0xc0
+#define PX_BRDCFG0_ELBC_DIU		0x02
 
 #define PX_BRDCFG1_DVIEN	0x80
 #define PX_BRDCFG1_DFPEN	0x40
 #define PX_BRDCFG1_BACKLIGHT	0x20
 
+#define PMUXCR_ELBCDIU_MASK	0xc0000000
+#define PMUXCR_ELBCDIU_NOR16	0x80000000
+
 /*
  * DIU Area Descriptor
  *
@@ -43,6 +52,16 @@
 #define AD_COMP_1_SHIFT		4
 #define AD_COMP_0_SHIFT		0
 
+/*
+ * Variables used by the DIU/LBC switching code.  It's safe to makes these
+ * global, because the DIU requires DDR, so we'll only run this code after
+ * relocation.
+ */
+static u8 px_brdcfg0;
+static u32 pmuxcr;
+static void *lbc_lcs0_ba;
+static void *lbc_lcs1_ba;
+
 void diu_set_pixel_clock(unsigned int pixclock)
 {
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
@@ -68,6 +87,10 @@ int platform_diu_init(unsigned int *xres, unsigned int *yres)
 	u32 pixel_format;
 	u8 temp;
 
+	/* Save the LBC LCS0 and LCS1 addresses for the DIU mux functions */
+	lbc_lcs0_ba = (void *)(get_lbc_br(0) & get_lbc_or(0) & 0xFFFF8000);
+	lbc_lcs1_ba = (void *)(get_lbc_br(1) & get_lbc_or(1) & 0xFFFF8000);
+
 	pixel_format = cpu_to_le32(AD_BYTE_F | (3 << AD_ALPHA_C_SHIFT) |
 		(0 << AD_BLUE_C_SHIFT) | (1 << AD_GREEN_C_SHIFT) |
 		(2 << AD_RED_C_SHIFT) | (8 << AD_COMP_3_SHIFT) |
@@ -93,18 +116,189 @@ int platform_diu_init(unsigned int *xres, unsigned int *yres)
 
 	out_8(&pixis->brdcfg1, temp);
 
+	/*
+	 * Enable PIXIS indirect access mode.  This is a hack that allows us to
+	 * access PIXIS registers even when the LBC pins have been muxed to the
+	 * DIU.
+	 */
+	setbits_8(&pixis->csr, PX_CTL_ALTACC);
+
 	/*
 	 * Route the LAD pins to the DIU.  This will disable access to the eLBC,
 	 * which means we won't be able to read/write any NOR flash addresses!
 	 */
-	out_8(&pixis->brdcfg0, in_8(&pixis->brdcfg0) | PX_BRDCFG0_ELBC_DIU);
-	/* we must do the dummy read from eLBC to sync the write as above */
-	in_8(&pixis->brdcfg0);
+	out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0));
+	px_brdcfg0 = in_8(lbc_lcs1_ba);
+	out_8(lbc_lcs1_ba, px_brdcfg0 | PX_BRDCFG0_ELBC_DIU);
 
 	/* Setting PMUXCR to switch to DVI from ELBC */
-	/* Set pmuxcr to allow both i2c1 and i2c2 */
-	clrsetbits_be32(&gur->pmuxcr, 0xc0000000, 0x40000000);
-	in_be32(&gur->pmuxcr);
+	clrsetbits_be32(&gur->pmuxcr,
+		PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_NOR16);
+	pmuxcr = in_be32(&gur->pmuxcr);
 
 	return fsl_diu_init(*xres, pixel_format, 0);
 }
+
+#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
+
+/*
+ * set_mux_to_lbc - disable the DIU so that we can read/write to elbc
+ *
+ * On the Freescale P1022, the DIU video signal and the LBC address/data lines
+ * share the same pins, which means that when the DIU is active (e.g. the
+ * console is on the DVI display), NOR flash cannot be accessed.  So we use the
+ * weak accessor feature of the CFI flash code to temporarily switch the pin
+ * mux from DIU to LBC whenever we want to read or write flash.  This has a
+ * significant performance penalty, but it's the only way to make it work.
+ *
+ * There are two muxes: one on the chip, and one on the board. The chip mux
+ * controls whether the pins are used for the DIU or the LBC, and it is
+ * set via PMUXCR.  The board mux controls whether those signals go to
+ * the video connector or the NOR flash chips, and it is set via the ngPIXIS.
+ */
+static int set_mux_to_lbc(void)
+{
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	/* Switch the muxes only if they're currently set to DIU mode */
+	if ((in_be32(&gur->pmuxcr) & PMUXCR_ELBCDIU_MASK) ==
+	    PMUXCR_ELBCDIU_NOR16) {
+		/*
+		 * In DIU mode, the PIXIS can only be accessed indirectly
+		 * since we can't read/write the LBC directly.
+		 */
+
+		/* Set the board mux to LBC.  This will disable the display. */
+		out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0));
+		px_brdcfg0 = in_8(lbc_lcs1_ba);
+		out_8(lbc_lcs1_ba, (px_brdcfg0 & ~(PX_BRDCFG0_ELBC_SPI_MASK
+			| PX_BRDCFG0_ELBC_DIU)) | PX_BRDCFG0_ELBC_SPI_ELBC);
+
+		/* Disable indirect PIXIS mode */
+		out_8(lbc_lcs0_ba, offsetof(ngpixis_t, csr));
+		clrbits_8(lbc_lcs1_ba, PX_CTL_ALTACC);
+
+		/* Set the chip mux to LBC mode, so that writes go to flash. */
+		out_be32(&gur->pmuxcr, (pmuxcr & ~PMUXCR_ELBCDIU_MASK) |
+			 PMUXCR_ELBCDIU_NOR16);
+		in_be32(&gur->pmuxcr);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * set_mux_to_diu - re-enable the DIU muxing
+ *
+ * This function restores the chip and board muxing to point to the DIU.
+ */
+static void set_mux_to_diu(void)
+{
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	/* Enable indirect PIXIS mode */
+	setbits_8(&pixis->csr, PX_CTL_ALTACC);
+
+	/* Set the board mux to DIU.  This will enable the display. */
+	out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0));
+	out_8(lbc_lcs1_ba, px_brdcfg0);
+	in_8(lbc_lcs1_ba);
+
+	/* Set the chip mux to DIU mode. */
+	out_be32(&gur->pmuxcr, pmuxcr);
+	in_be32(&gur->pmuxcr);
+}
+
+void flash_write8(u8 value, void *addr)
+{
+	int sw = set_mux_to_lbc();
+
+	__raw_writeb(value, addr);
+	if (sw)
+		set_mux_to_diu();
+}
+
+void flash_write16(u16 value, void *addr)
+{
+	int sw = set_mux_to_lbc();
+
+	__raw_writew(value, addr);
+	if (sw)
+		set_mux_to_diu();
+}
+
+void flash_write32(u32 value, void *addr)
+{
+	int sw = set_mux_to_lbc();
+
+	__raw_writel(value, addr);
+	if (sw)
+		set_mux_to_diu();
+}
+
+void flash_write64(u64 value, void *addr)
+{
+	int sw = set_mux_to_lbc();
+
+	/* There is no __raw_writeq(), so do the write manually */
+	*(volatile u64 *)addr = value;
+	if (sw)
+		set_mux_to_diu();
+}
+
+u8 flash_read8(void *addr)
+{
+	u8 ret;
+
+	int sw = set_mux_to_lbc();
+
+	ret = __raw_readb(addr);
+	if (sw)
+		set_mux_to_diu();
+
+	return ret;
+}
+
+u16 flash_read16(void *addr)
+{
+	u16 ret;
+
+	int sw = set_mux_to_lbc();
+
+	ret = __raw_readw(addr);
+	if (sw)
+		set_mux_to_diu();
+
+	return ret;
+}
+
+u32 flash_read32(void *addr)
+{
+	u32 ret;
+
+	int sw = set_mux_to_lbc();
+
+	ret = __raw_readl(addr);
+	if (sw)
+		set_mux_to_diu();
+
+	return ret;
+}
+
+u64 flash_read64(void *addr)
+{
+	u64 ret;
+
+	int sw = set_mux_to_lbc();
+
+	/* There is no __raw_readq(), so do the read manually */
+	ret = *(volatile u64 *)addr;
+	if (sw)
+		set_mux_to_diu();
+
+	return ret;
+}
+
+#endif
diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h
index 8e0117f6a1b732bd3912571a78589360048abc0f..2306e7f90c961c30aa25c8ed3f051e557ef24cce 100644
--- a/include/configs/P1022DS.h
+++ b/include/configs/P1022DS.h
@@ -188,6 +188,12 @@
 #define CONFIG_VGA_AS_SINGLE_DEVICE
 #define CONFIG_VIDEO_LOGO
 #define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
+/*
+ * With CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS, flash I/O is really slow, so
+ * disable empty flash sector detection, which is I/O-intensive.
+ */
+#undef CONFIG_SYS_FLASH_EMPTY_INFO
 #endif
 
 /*