[PATCH 00/21] Armada 370/XP NAND support

Brian Norris computersforpeace at gmail.com
Wed Oct 2 20:02:53 EDT 2013


On Mon, Sep 30, 2013 at 09:24:29AM -0300, Ezequiel Garcia wrote:
> On Thu, Sep 26, 2013 at 12:56:15PM -0700, Brian Norris wrote:
> > On Thu, Sep 19, 2013 at 01:01:24PM -0300, Ezequiel Garcia wrote:
> > > * Page layout
> > > 
> > > The controller has a 2176 bytes FIFO buffer. Therefore, in order to support
> > > larger pages, I/O operations on 4 KiB and 8 KiB pages is done with a set of
> > > chunked transfers.
> > > 
> > > For instance, if we choose a 2048 data chunk and BCH ECC we will have
> > > to use this layout in the pages:
> > > 
> > >   ------------------------------------------------------------------------------
> > >   | 2048B data | 32B spare | 30B ECC || 2048B data | 32B spare | 30B ECC | ... |
> > >   ------------------------------------------------------------------------------
> > > 
> > > The last remaining area is unusable (i.e. wasted).
> > 
> > Why is it wasted? With a 2176B buffer, you can fit more than 2048+32+30.
> > Are you simplifying things to support only NAND geometries like the
> > tradiditional large page 2KB+64? (If so, what happens with 4KB pages
> > that need higher level of ECC than can fit in 64 x 2 = 128B?) And in the
> > 2KB+64 case, why is the 64-32-30=2B wasted?
> > 
> 
> Hm... the wasted bytes are due to an 8-byte alignment controller requirement on the
> data buffer. However, you're right: in a flash with a page of 4KB+224B (e.g.) you
> should be able to access at least some of the remaining OOB area.

Alignment requirement for the start of the buffer, length of the buffer,
or both?

> Notice OOB handling is still a bit confusing in this driver.

Yes.

> > > To match this, my current (already working!) implementation acts like
> > > a layout "impedance matcher" to produce in an internal driver's buffer
> > 
> > Maybe I'm in the wrong field, but I'm not sure how an impedance matcher
> > applies here.
> > 
> > > this layout:
> > > 
> > >   ------------------------------------------
> > >   |     4096B data     |     64B spare     |
> > >   ------------------------------------------
> > 
> > What is this "internal buffer"? (I'll read through your patches in a bit
> > and find out, perhaps?) Just the raw data + spare that you are ready to
> > read/write? Are you dropping the ECC from this buffer? Doesn't it need
> > to be returned to the callee (when the 'oob_required' flag is true)?
> > 
> 
> Yes, the driver's internal buffer has the raw data + OOB that has
> been read from the controller after a read operation, or that's
> ready to be written to the flash before a program operation.
> 
> That said, if the command issued was READOOB then the OOB is read fully:
> spare and ECC code and the buffer is filled like this:
> 
>   ----------------------------------------------------------------------------------------------
>   |     4096B data     |  32B spare  |  30B ECC*  | 2x 0xff |  32B spare  |  30B ECC  | 2x 0xff |
>   ----------------------------------------------------------------------------------------------
> 
> (*) We need to add two bytes (0xff) to align the 30B ECC read.
> 
> I was expecting to handle the above layout properly using this nand_ecclayout
> structure:
> 
> static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
>         .eccbytes = 64,
>         .eccpos = {
>                 32,  33,  34,  35,  36,  37,  38,  39,
>                 40,  41,  42,  43,  44,  45,  46,  47,
>                 48,  49,  50,  51,  52,  53,  54,  55,
>                 56,  57,  58,  59,  60,  61,  62,  63,
>                 96,  97,  98,  99,  100, 101, 102, 103,
>                 104, 105, 106, 107, 108, 109, 110, 111,
>                 112, 113, 114, 115, 116, 117, 118, 119,
>                 120, 121, 122, 123, 124, 125, 126, 127},
>         /* Bootrom looks in bytes 0 & 5 for bad blocks */
>         .oobfree = { {1, 4}, {6, 26}, { 64, 32} }
> };
> 
> However, I must be doing something wrong since currently the mtd_oobtest fails
> at some point and I need to investigate the issue further.
> 
> > > In order to achieve reading (for instance), we issue several READ0 commands
> > > (with some additional controller-specific magic) and read two chunks of 2080B
> > > (2048 data + 64 spare) each.
> > 
> > The math is a little inconsistent here and elsewhere. Do you mean two
> > chunks of 2080B (2048 data + 32 spare)?
> > 
> 
> Yes. It should be: 2048B data + 32B spare.
> 
> > > The driver accomodates this data to expose the NAND base a contiguous 4160B buffer
> > > (4096 data + 64 spare).
> > 
> > This math matches up right, if it's double the 2KB+32 instead of double
> > 2KB+64.
> > 
> 
> Yup.
> 
> > > * ECC
> > > 
> > > The controller has built-in hardware ECC capabilities. In addition it is completely
> > > configurable, and we can choose between Hamming and BCH ECC. If we choose BCH ECC
> > > then the ECC code will be calculated for each transfered chunk and expected to be
> > > located (when reading/programming) at specific locations.
> > 
> > At "specific locations", but always within the 30B region that you've
> > been mapping out?
> > 
> 
> By 'specific location' I mean after the 32B spare area.
> 
> > > So, repeating the above scheme, a 2048B data chunk will be followed by 32B spare,
> > > and then the ECC controller will read/write the ECC code (30B in this case):
> > > 
> > >   ------------------------------------
> > >   | 2048B data | 32B spare | 30B ECC |
> > >   ------------------------------------
> > 
> > Is ECC always 30B? Or is this just the maximum size, so you always
> > reserve 30B?
> > 
> 
> In the BCH case, yes: it's always 30B.

So by "BCH" you actually are referring to BCH-4? Are there any other BCH
modes supported? Or do you expect any future revisions to expand on the
BCH options available?

> AFAIK, the ECC works like this. When programming a page, you can
> actually instruct the controller to transfer an arbitrary amount of bytes.
> 
> (Details: you do this by adding NDCB0_LEN_OVRD to the command buffer 0,
> and setting the i/o length at buffer 3).
> 
> The ECC code will be written after the transfered bytes. So, when
> programming a page we configure the length to be 2048B + 32B and get
> the ECC after it.
> 
> Equally, we can read an arbitrary length. and the ECC code is expected
> to be in the area immediate the read area.
> 
> Notice that this means you can control the ECC strength: since the ECC
> is always 30B, and it's calculated on the transfered chunk you can
> configure the controller to transfer the page in 1024B chunks and get a
> 30B ECC for each of this chunk, thus doubling the ECC strength.

This is a little odd. Your ECC HW is not parameterized by ECC strength,
but instead by ECC sector size? I think I have some comments for patch
5, relevant to this topic.

> This should be added to the driver, and I expect it to be fairly easy
> with the infrastructure already in place.

Brian



More information about the linux-mtd mailing list