* [U-Boot] [PATCH] [v3] p1022ds: use weak CFI flash accessors when DIU is enabled
@ 2010-09-16 21:35 Timur Tabi
2010-09-17 2:27 ` [U-Boot] [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen " Jaggi Manish-B10520
2010-09-25 12:51 ` [U-Boot] [PATCH v4] p1022ds: use weak CFI flash accessors when " Anatolij Gustschin
0 siblings, 2 replies; 6+ messages in thread
From: Timur Tabi @ 2010-09-16 21:35 UTC (permalink / raw)
To: u-boot
On the Freescale P1022, the DIU and the LBC share address 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 function 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.
This change allows the 'saveenv' command to work when the video display is
enabled. Erasing flash and writing to flash (with the 'cp' command) works,
but reading from flash (with the 'md' and 'cp' commands) does not. Also, while
flash is being written, the video display will be blank.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
v3: changes as requested
board/freescale/p1022ds/diu.c | 208 +++++++++++++++++++++++++++++++++++++++--
include/configs/P1022DS.h | 6 +
2 files changed, 205 insertions(+), 9 deletions(-)
diff --git a/board/freescale/p1022ds/diu.c b/board/freescale/p1022ds/diu.c
index be6e9a8..c8bfdf0 100644
--- a/board/freescale/p1022ds/diu.c
+++ b/board/freescale/p1022ds/diu.c
@@ -14,8 +14,6 @@
#include <command.h>
#include <asm/io.h>
-#ifdef CONFIG_FSL_DIU_FB
-
#include "../common/ngpixis.h"
#include "../common/fsl_diu_fb.h"
@@ -24,13 +22,22 @@
#include <video_fb.h>
#endif
-#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 PX_BRDCFG1_DDCEN 0x10
+#define PMUXCR_ELBCDIU_MASK 0xc0000000
+#define PMUXCR_ELBCDIU_NOR16 0x80000000
+
/*
* DIU Area Descriptor
*
@@ -63,6 +70,16 @@
#define AD_DEFAULT
static int xres, yres;
+/*
+ * 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);
@@ -88,6 +105,10 @@ int p1022ds_diu_init(void)
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) |
@@ -114,17 +135,24 @@ int p1022ds_diu_init(void)
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);
}
@@ -169,4 +197,166 @@ void *video_hw_init(void)
#endif
+#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 d518c69..a4910a6 100644
--- a/include/configs/P1022DS.h
+++ b/include/configs/P1022DS.h
@@ -190,6 +190,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
/*
--
1.7.2.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [U-Boot] [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen DIU is enabled
2010-09-16 21:35 [U-Boot] [PATCH] [v3] p1022ds: use weak CFI flash accessors when DIU is enabled Timur Tabi
@ 2010-09-17 2:27 ` Jaggi Manish-B10520
2010-09-17 2:51 ` Tabi Timur-B04825
2010-09-25 12:51 ` [U-Boot] [PATCH v4] p1022ds: use weak CFI flash accessors when " Anatolij Gustschin
1 sibling, 1 reply; 6+ messages in thread
From: Jaggi Manish-B10520 @ 2010-09-17 2:27 UTC (permalink / raw)
To: u-boot
Hi,
A trivial question
Most of the read/write functions do this way
0:+ int sw = set_mux_to_lbc();
1:+
2:+ ret = __raw_readl(addr);
3:+ if (sw)
4:+ set_mux_to_diu();
compiler might reorder 2 before 3 and 0, read / write wont have any issue , right ?
-manish
-----Original Message-----
From: u-boot-release-bounces@linux.freescale.net on behalf of Tabi Timur-B04825
Sent: Fri 9/17/2010 3:05 AM
To: u-boot at lists.denx.de; Gala Kumar-B11780
Subject: [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen DIU is enabled
On the Freescale P1022, the DIU and the LBC share address 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 function 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.
This change allows the 'saveenv' command to work when the video display is
enabled. Erasing flash and writing to flash (with the 'cp' command) works,
but reading from flash (with the 'md' and 'cp' commands) does not. Also, while
flash is being written, the video display will be blank.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
v3: changes as requested
board/freescale/p1022ds/diu.c | 208 +++++++++++++++++++++++++++++++++++++++--
include/configs/P1022DS.h | 6 +
2 files changed, 205 insertions(+), 9 deletions(-)
diff --git a/board/freescale/p1022ds/diu.c b/board/freescale/p1022ds/diu.c
index be6e9a8..c8bfdf0 100644
--- a/board/freescale/p1022ds/diu.c
+++ b/board/freescale/p1022ds/diu.c
@@ -14,8 +14,6 @@
#include <command.h>
#include <asm/io.h>
-#ifdef CONFIG_FSL_DIU_FB
-
#include "../common/ngpixis.h"
#include "../common/fsl_diu_fb.h"
@@ -24,13 +22,22 @@
#include <video_fb.h>
#endif
-#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 PX_BRDCFG1_DDCEN 0x10
+#define PMUXCR_ELBCDIU_MASK 0xc0000000
+#define PMUXCR_ELBCDIU_NOR16 0x80000000
+
/*
* DIU Area Descriptor
*
@@ -63,6 +70,16 @@
#define AD_DEFAULT
static int xres, yres;
+/*
+ * 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);
@@ -88,6 +105,10 @@ int p1022ds_diu_init(void)
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) |
@@ -114,17 +135,24 @@ int p1022ds_diu_init(void)
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);
}
@@ -169,4 +197,166 @@ void *video_hw_init(void)
#endif
+#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 d518c69..a4910a6 100644
--- a/include/configs/P1022DS.h
+++ b/include/configs/P1022DS.h
@@ -190,6 +190,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
/*
--
1.7.2.3
_______________________________________________
u-boot-release mailing list
u-boot-release at linux.freescale.net
http://linux.freescale.net/mailman/listinfo/u-boot-release
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [U-Boot] [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen DIU is enabled
2010-09-17 2:27 ` [U-Boot] [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen " Jaggi Manish-B10520
@ 2010-09-17 2:51 ` Tabi Timur-B04825
2010-09-17 19:10 ` Scott Wood
0 siblings, 1 reply; 6+ messages in thread
From: Tabi Timur-B04825 @ 2010-09-17 2:51 UTC (permalink / raw)
To: u-boot
Jaggi Manish-B10520 wrote:
> Most of the read/write functions do this way
> 0:+ int sw = set_mux_to_lbc();
> 1:+
> 2:+ ret = __raw_readl(addr);
> 3:+ if (sw)
> 4:+ set_mux_to_diu();
>
> compiler might reorder 2 before 3 and 0, read / write wont have any
> issue , right ?
Really? I don't see why the compiler would do that. That would be a bug, IMHO.
Can you explain why you think it will make such a reordering? My
understanding is that the compiler reorders things that don't have any side
effects. Only function calls marked as "const" have no side effects, and
none of these functions are const functions.
--
Timur Tabi
Linux kernel developer
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot] [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen DIU is enabled
2010-09-17 2:51 ` Tabi Timur-B04825
@ 2010-09-17 19:10 ` Scott Wood
0 siblings, 0 replies; 6+ messages in thread
From: Scott Wood @ 2010-09-17 19:10 UTC (permalink / raw)
To: u-boot
On Thu, 16 Sep 2010 19:51:33 -0700
Tabi Timur-B04825 <B04825@freescale.com> wrote:
> Jaggi Manish-B10520 wrote:
> > Most of the read/write functions do this way
> > 0:+ int sw = set_mux_to_lbc();
> > 1:+
> > 2:+ ret = __raw_readl(addr);
> > 3:+ if (sw)
> > 4:+ set_mux_to_diu();
> >
> > compiler might reorder 2 before 3 and 0, read / write wont have any
> > issue , right ?
>
> Really? I don't see why the compiler would do that. That would be a bug, IMHO.
Only if set_mux_to_lbc() is non-inline, and the compiler has no
visibility into what it does.
But even then, the hardware is free to reorder. That's why we have
non-raw I/O accessors.
> Can you explain why you think it will make such a reordering? My
> understanding is that the compiler reorders things that don't have any side
> effects.
The compiler can reorder anything where the reordering won't affect the
results of single-threaded execution with no interrupts,
well-behaved memory (no device registers, bank switches, etc), no
violations of aliasing rules, etc.
-Scott
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot] [PATCH v4] p1022ds: use weak CFI flash accessors when DIU is enabled
2010-09-16 21:35 [U-Boot] [PATCH] [v3] p1022ds: use weak CFI flash accessors when DIU is enabled Timur Tabi
2010-09-17 2:27 ` [U-Boot] [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen " Jaggi Manish-B10520
@ 2010-09-25 12:51 ` Anatolij Gustschin
2010-09-25 12:54 ` Anatolij Gustschin
1 sibling, 1 reply; 6+ messages in thread
From: Anatolij Gustschin @ 2010-09-25 12:51 UTC (permalink / raw)
To: u-boot
From: Timur Tabi <timur@freescale.com>
On the Freescale P1022, the DIU and the LBC share address 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 function 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.
This change allows the 'saveenv' command to work when the video display is
enabled. Erasing flash and writing to flash (with the 'cp' command) works,
but reading from flash (with the 'md' and 'cp' commands) does not. Also, while
flash is being written, the video display will be blank.
Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
v4:
- rebased on current u-boot-video/next
board/freescale/p1022ds/diu.c | 208 +++++++++++++++++++++++++++++++++++++++--
include/configs/P1022DS.h | 6 +
2 files changed, 207 insertions(+), 7 deletions(-)
diff --git a/board/freescale/p1022ds/diu.c b/board/freescale/p1022ds/diu.c
index 5ca84df..12b40a0 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) |
@@ -94,17 +117,188 @@ 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 8e0117f..2306e7f 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
/*
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [U-Boot] [PATCH v4] p1022ds: use weak CFI flash accessors when DIU is enabled
2010-09-25 12:51 ` [U-Boot] [PATCH v4] p1022ds: use weak CFI flash accessors when " Anatolij Gustschin
@ 2010-09-25 12:54 ` Anatolij Gustschin
0 siblings, 0 replies; 6+ messages in thread
From: Anatolij Gustschin @ 2010-09-25 12:54 UTC (permalink / raw)
To: u-boot
On Sat, 25 Sep 2010 14:51:22 +0200
Anatolij Gustschin <agust@denx.de> wrote:
> From: Timur Tabi <timur@freescale.com>
>
> On the Freescale P1022, the DIU and the LBC share address 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 function 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.
>
> This change allows the 'saveenv' command to work when the video display is
> enabled. Erasing flash and writing to flash (with the 'cp' command) works,
> but reading from flash (with the 'md' and 'cp' commands) does not. Also, while
> flash is being written, the video display will be blank.
>
> Signed-off-by: Timur Tabi <timur@freescale.com>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> ---
> v4:
> - rebased on current u-boot-video/next
>
> board/freescale/p1022ds/diu.c | 208 +++++++++++++++++++++++++++++++++++++++--
> include/configs/P1022DS.h | 6 +
> 2 files changed, 207 insertions(+), 7 deletions(-)
Applied to u-boot-video/next.
Anatolij
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-09-25 12:54 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-16 21:35 [U-Boot] [PATCH] [v3] p1022ds: use weak CFI flash accessors when DIU is enabled Timur Tabi
2010-09-17 2:27 ` [U-Boot] [u-boot-release] [PATCH] [v3] p1022ds: use weak CFI flash accessorswhen " Jaggi Manish-B10520
2010-09-17 2:51 ` Tabi Timur-B04825
2010-09-17 19:10 ` Scott Wood
2010-09-25 12:51 ` [U-Boot] [PATCH v4] p1022ds: use weak CFI flash accessors when " Anatolij Gustschin
2010-09-25 12:54 ` Anatolij Gustschin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox