[PATCH] mtd: brcmnand: Fix NAND_CMD_PARAM byte order

Brian Norris computersforpeace at gmail.com
Mon Oct 26 11:14:30 PDT 2015


On Sat, Oct 24, 2015 at 11:35:11AM -0700, Clay McClure wrote:
> On Friday, October 23, 2015, Brian Norris <computersforpeace at gmail.com> wrote:
> 
> > But to be clear: none of the systems in question are running with big
> > endian CPUs, correct? If not, then it's apparent we have to do something
> > different for iProc-based chips than for STB chips; we can't just fiddle
> > with the cpu_to_*() macros. Maybe this works?
> >
> > diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c
> > b/drivers/mtd/nand/brcmnand/brcmnand.c
> > index 9ü61a9ee4369c..073dbe4ce9bc 100644
> > --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> > +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> > @@ -1168,8 +1168,6 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd,
> > unsigned command,
> >                         native_cmd == CMD_PARAMETER_CHANGE_COL) {
> >                 int i;
> >
> > -               brcmnand_soc_data_bus_prepare(ctrl->soc);
> > -
> >                 /*
> >                  * Must cache the FLASH_CACHE now, since changes in
> >                  * SECTOR_SIZE_1K may invalidate it
> > @@ -1177,8 +1175,6 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd,
> > unsigned command,
> >                 for (i = 0; i < FC_WORDS; i++)
> >                         ctrl->flash_cache[i] = brcmnand_read_fc(ctrl, i);
> >
> > -               brcmnand_soc_data_bus_unprepare(ctrl->soc);
> > -
> >                 /* Cleanup from HW quirk: restore SECTOR_SIZE_1K */
> >                 if (host->hwcfg.sector_size_1k)
> >                         brcmnand_set_sector_size_1k(host,
> >
> 
> Yes, that does solve the problem I'm seeing. I actually tried
> this approach before submitting my previous patch, but opted not to submit
> this because it seemed that some thought and effort had gone into making
> little-endian APB transfers (it's one of the only things iproc_nand
> actually does), and I assumed it was being done for a reason.
> 
> If you're happy with this, would you mind if I submit this patch?

Feel free, though I suppose technically it'd have my authorship. So for
the above:

Signed-off-by: Brian Norris <computersforpeace at gmail.com>

I'd like an ack (or test) from Ray too, if possible. Perhaps a comment
is in order too, to explain why there is no bus swapping for that
instance of brcmnand_read_fc(). (AIUI, the reason is that the base STB
design pushes out this data in big endian, so we need to match this on
iProc.)

> Also, you mentioned that the original code could stand to be cleaned up a
> bit. Any specific clean ups you'd like to see?

I wrote up this patch, but it's untested. If you can test this in
addition with the above, that'd be great. I'd also like a test from the
STB folks, if possible.

Brian

----8<----
>From 8efc0791d4dbb4a326e2223b14aeae04933ee9af Mon Sep 17 00:00:00 2001
From: Brian Norris <computersforpeace at gmail.com>
Date: Fri, 23 Oct 2015 17:39:40 -0700
Subject: [PATCH] mtd: brcmnand: clean up flash cache for parameter pages

The read_byte() handling for accessing the flash cache has some awkward
swapping being done in the read_byte() function. Let's just make this a
byte array, and do the swapping with the word-level macros during the
initial buffer copy.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
Cc: Clay McClure <clay at daemons.net>
Cc: Ray Jui <rjui at broadcom.com>
Cc: Scott Branden <sbranden at broadcom.com>
---
 drivers/mtd/nand/brcmnand/brcmnand.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index d694d876631e..249b3728dc75 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -134,7 +134,7 @@ struct brcmnand_controller {
 	dma_addr_t		dma_pa;
 
 	/* in-memory cache of the FLASH_CACHE, used only for some commands */
-	u32			flash_cache[FC_WORDS];
+	u8			flash_cache[FC_BYTES];
 
 	/* Controller revision details */
 	const u16		*reg_offsets;
@@ -1166,6 +1166,8 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
 
 	if (native_cmd == CMD_PARAMETER_READ ||
 			native_cmd == CMD_PARAMETER_CHANGE_COL) {
+		/* Copy flash cache word-wise */
+		u32 *flash_cache = (u32 *)ctrl->flash_cache;
 		int i;
 
 		brcmnand_soc_data_bus_prepare(ctrl->soc);
@@ -1175,7 +1177,8 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
 		 * SECTOR_SIZE_1K may invalidate it
 		 */
 		for (i = 0; i < FC_WORDS; i++)
-			ctrl->flash_cache[i] = brcmnand_read_fc(ctrl, i);
+			/* cache is big endian for parameter pages? */
+			flash_cache[i] = be32_to_cpu(brcmnand_read_fc(ctrl, i));
 
 		brcmnand_soc_data_bus_unprepare(ctrl->soc);
 
@@ -1228,8 +1231,7 @@ static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
 		if (host->last_byte > 0 && offs == 0)
 			chip->cmdfunc(mtd, NAND_CMD_RNDOUT, addr, -1);
 
-		ret = ctrl->flash_cache[offs >> 2] >>
-					(24 - ((offs & 0x03) << 3));
+		ret = ctrl->flash_cache[offs];
 		break;
 	case NAND_CMD_GET_FEATURES:
 		if (host->last_byte >= ONFI_SUBFEATURE_PARAM_LEN) {
-- 
2.6.0.rc2.230.g3dd15c0




More information about the linux-mtd mailing list