public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* Supporting high-level NAND controllers like FTNANDC024
@ 2016-05-26  5:45 Mychaela Falconia
  2016-05-26  7:15 ` Boris Brezillon
  0 siblings, 1 reply; 4+ messages in thread
From: Mychaela Falconia @ 2016-05-26  5:45 UTC (permalink / raw)
  To: linux-mtd

I am working with a very high-level NAND flash controller, too high-
level to fit comfortably into the abstraction model provided by the
current "generic" NAND code layer in Linux.  This generic NAND layer
assumes that the controller provides a more or less raw access to the
NAND chip, such that the generic NAND code can send arbitrary command
opcodes, do individual read_byte's and request buffer reads and writes.

But the controller I'm working with (Faraday FTNANDC024) provides a
much higher level of abstraction.  The level of abstraction provided
by this controller is more like the MTD interface in Linux than the
current "nand" interface.  This controller does not allow the user to
issue arbitrary opcodes to the NAND or to read/write bytes directly on
the NAND interface under CPU sequencing - instead it has high-level
read and write commands that are essentially like MTD's read and write
methods.  One can command the controller to read or write between 1
and 65535 "sectors" (their term for ECC unit) of 512 or 1024 bytes,
i.e., one can transfer almost 64 MiB of data in one operation.  One
"operation" means that you program the NAND and DMA controllers, give
it the command, and then wait for an interrupt - the controller will
automatically issue as many Read Page or Write Page commands to the
physical NAND as needed, transfer all data by DMA and do all ECC work.

I am currently working in the vendor's tree based on linux-3.3, but I
don't see any substantial changes in the current linux-mtd or l2-mtd
trees in this department.  Faraday made a heroic attempt at hammering
a square peg into a round hole by implementing a driver for their
controller that attaches to the generic NAND layer, but the code is
horrible.  So horrible that I am reimplementing my own FTNANDC024
driver from scratch.  Because the level of abstraction provided by
this controller is so at odds with the assumptions of the current
Linux "generic" NAND layer, I decided to forego this generic NAND
layer altogether and implement my driver as a self-contained MTD
device instead, attaching directly to the MTD layer.

The reason I am posting on this list is to see if any others have run
into similar issues, and to exchange ideas as to how such high-level
NAND flash controllers should be handled.  I have a difficult time
imagining that I am the only one with this problem: sure, Faraday's
SoCs and peripheral cores aren't nearly as popular as the bigger
vendors, so I may be the only one having to deal with FTNANDC024, but
surely this core from Faraday is not the only high-level NAND controller
in the world.  Instead my common sense suggests that as time marches
forward, controllers get smarter and smarter, and I have every reason
to suspect that super-high-level controllers like FTNANDC024 may very
well be the new norm.

Looking in the current code, I see that every currently supported NAND
controller is supported with a driver that attaches to the "generic"
NAND layer - I don't see anyone doing what I am doing, foregoing this
generic NAND layer and attaching directly to MTD instead.  Obviously I
am not familiar with the detailed workings of all those controllers,
but I reason that there must be some high-level ones in there, perhaps
as high-level as FTNANDC024.  If there are such high-level controllers
currently supported by drivers that attach to the generic NAND layer,
are they the result of heroic square peg in round hole hammering?  Or
am I just unlucky to be the first one trying to support a *really*
high-level NAND controller, more high-level than any of the currently
mainlined ones?

Of course foregoing the generic NAND layer entirely is not a perfect
solution either.  While most of it is inapplicable to high-level NAND
controllers, there are two useful functions in it which become very
painful to reimplement when foregoing it and attaching to MTD directly:
NAND chip type and geometry autodetection, and the on-flash bad block
table.

Autodetection: a high-level NAND controller still needs to be told via
register settings what the page and block sizes are, and of course the
upper layers need this info too.  Autodetection by way of NAND ID
bytes or the ONFI parameter page would still be quite useful, but the
way it is currently implemented in the generic NAND layer (at least in
linux-3.3) is too tied to the assumption of a low-level pass-through
controller, and cannot be made to work with FTNANDC024.  Faraday's
official driver (which does attach to the generic NAND layer) requires
hacking nand_ids.c so that the ONFI code will never execute, as it is
broken in the generic NAND layer + FTNANDC024 combo.

Bad block handling: FTNANDC024 rigidly imposes its own data format in
the physical flash, and the factory bad block mark location is smack
in the middle of a user data sector in this format.  The only workable
solution with such controllers is to scan the "virgin" blank flash on
the very first boot, find all factory marked bad blocks, then write an
on-flash BBT (letting the controller write it as it likes) and use
this BBT afterward.  There is perfectly good BBT code in the generic
NAND layer, but if I have to forego this generic NAND layer because of
mismatching abstraction levels, then I have to duplicate all this BBT
code in my "self-contained" driver that attaches directly to MTD.

So, what have other people's experiences been?  Is anyone already
working or planning to work on a generic framework for supporting
high-level NAND controllers, or will I have to be the first one?

TIA for reading my rant...

M~

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Supporting high-level NAND controllers like FTNANDC024
  2016-05-26  5:45 Supporting high-level NAND controllers like FTNANDC024 Mychaela Falconia
@ 2016-05-26  7:15 ` Boris Brezillon
  2016-05-26  9:45   ` Artem Bityutskiy
  0 siblings, 1 reply; 4+ messages in thread
From: Boris Brezillon @ 2016-05-26  7:15 UTC (permalink / raw)
  To: Mychaela Falconia; +Cc: linux-mtd, Peter Pan

Hi Mychaela,

On Thu, 26 May 2016 05:45:21 GMT
falcon@ivan.Harhan.ORG (Mychaela Falconia) wrote:

> I am working with a very high-level NAND flash controller, too high-
> level to fit comfortably into the abstraction model provided by the
> current "generic" NAND code layer in Linux.  This generic NAND layer
> assumes that the controller provides a more or less raw access to the
> NAND chip, such that the generic NAND code can send arbitrary command
> opcodes, do individual read_byte's and request buffer reads and writes.
> 
> But the controller I'm working with (Faraday FTNANDC024) provides a
> much higher level of abstraction.  The level of abstraction provided
> by this controller is more like the MTD interface in Linux than the
> current "nand" interface.  This controller does not allow the user to
> issue arbitrary opcodes to the NAND or to read/write bytes directly on
> the NAND interface under CPU sequencing - instead it has high-level
> read and write commands that are essentially like MTD's read and write
> methods.  One can command the controller to read or write between 1
> and 65535 "sectors" (their term for ECC unit) of 512 or 1024 bytes,
> i.e., one can transfer almost 64 MiB of data in one operation.  One
> "operation" means that you program the NAND and DMA controllers, give
> it the command, and then wait for an interrupt - the controller will
> automatically issue as many Read Page or Write Page commands to the
> physical NAND as needed, transfer all data by DMA and do all ECC work.
> 
> I am currently working in the vendor's tree based on linux-3.3, but I
> don't see any substantial changes in the current linux-mtd or l2-mtd
> trees in this department.  Faraday made a heroic attempt at hammering
> a square peg into a round hole by implementing a driver for their
> controller that attaches to the generic NAND layer, but the code is
> horrible.  So horrible that I am reimplementing my own FTNANDC024
> driver from scratch.  Because the level of abstraction provided by
> this controller is so at odds with the assumptions of the current
> Linux "generic" NAND layer, I decided to forego this generic NAND
> layer altogether and implement my driver as a self-contained MTD
> device instead, attaching directly to the MTD layer

Actually that's a good approach IMO.

> 
> The reason I am posting on this list is to see if any others have run
> into similar issues, and to exchange ideas as to how such high-level
> NAND flash controllers should be handled.  I have a difficult time
> imagining that I am the only one with this problem: sure, Faraday's
> SoCs and peripheral cores aren't nearly as popular as the bigger
> vendors, so I may be the only one having to deal with FTNANDC024, but
> surely this core from Faraday is not the only high-level NAND controller
> in the world.  Instead my common sense suggests that as time marches
> forward, controllers get smarter and smarter, and I have every reason
> to suspect that super-high-level controllers like FTNANDC024 may very
> well be the new norm.

Actually, even quite recent controllers provides 'raw modes' allowing
one to send raw commands if needed, but they usually do optimize
specific operations like 'read-full page with pipelined ECC correction"
or "sequential page accesses" (and probably other optimizations I'm not
aware of).

As you mentioned, this kind of optimizations are not really supported in
the current design, but I'm working on improving things in this regard.

Now your problem is a bit different, since what I'm working on is a
generic solution, but it would still involve knowledge of how to
interact with a raw NAND chip (chip detection cmds, read/write cmds,
cached access cmds, ...).

> 
> Looking in the current code, I see that every currently supported NAND
> controller is supported with a driver that attaches to the "generic"
> NAND layer - I don't see anyone doing what I am doing, foregoing this
> generic NAND layer and attaching directly to MTD instead.  Obviously I
> am not familiar with the detailed workings of all those controllers,
> but I reason that there must be some high-level ones in there, perhaps
> as high-level as FTNANDC024.  If there are such high-level controllers
> currently supported by drivers that attach to the generic NAND layer,
> are they the result of heroic square peg in round hole hammering?  Or
> am I just unlucky to be the first one trying to support a *really*
> high-level NAND controller, more high-level than any of the currently
> mainlined ones?

Don't know if you're the first one ever trying to support this kind of
NAND controller, but there's definitely a need for that, and I'd prefer
to see them supported through a proper interface than adding more hacks
to the current NAND core code.

> 
> Of course foregoing the generic NAND layer entirely is not a perfect
> solution either.  While most of it is inapplicable to high-level NAND
> controllers, there are two useful functions in it which become very
> painful to reimplement when foregoing it and attaching to MTD directly:
> NAND chip type and geometry autodetection, and the on-flash bad block
> table.

Cool, that's exactly the kind of things I was going to ask. Actually
I'm working with Peter to add an intermediate abstraction layer hiding
the interface type to avoid duplicating common code. As you may know we
already 3 kinds of NAND based devices out there:
- raw NANDs (the one using the 'standard' NAND interface)
- OneNAND NANDs
- SPI NANDs

So far we've only shared 'memory organization' information and BBT code
(the changes are available here if you want to have a look [1]).

What else would you need that is already implemented by the NAND
framework?

> 
> Autodetection: a high-level NAND controller still needs to be told via
> register settings what the page and block sizes are, and of course the
> upper layers need this info too.  Autodetection by way of NAND ID
> bytes or the ONFI parameter page would still be quite useful, but the
> way it is currently implemented in the generic NAND layer (at least in
> linux-3.3) is too tied to the assumption of a low-level pass-through
> controller, and cannot be made to work with FTNANDC024.  Faraday's
> official driver (which does attach to the generic NAND layer) requires
> hacking nand_ids.c so that the ONFI code will never execute, as it is
> broken in the generic NAND layer + FTNANDC024 combo.

Could you detail a bit more how your controller is retrieving NAND ID,
ONFI or JEDEC parameter pages, and why the generic layer + FTNANDC024
combo is broken?

> 
> Bad block handling: FTNANDC024 rigidly imposes its own data format in
> the physical flash, and the factory bad block mark location is smack
> in the middle of a user data sector in this format.  The only workable
> solution with such controllers is to scan the "virgin" blank flash on
> the very first boot, find all factory marked bad blocks, then write an
> on-flash BBT (letting the controller write it as it likes) and use
> this BBT afterward.

Well, that is a real problem in my opinion: what happens if the
on-flash BBT is corrupted? You have no way to recover from that since
you've screwed all the BBM on the blocks you've programmed.
NAND/ECC controllers usually provide a way to swap the data and BBM
bytes before/after actually transferring data to/from the NAND.
When that's not the case, drivers manually swap those bytes if that's
possible. Other implementation are just broken in my opinion, but I
guess that's your problem not mine ;-).

> There is perfectly good BBT code in the generic
> NAND layer, but if I have to forego this generic NAND layer because of
> mismatching abstraction levels, then I have to duplicate all this BBT
> code in my "self-contained" driver that attaches directly to MTD.

Yep, as I said, this should be addressed soon.

> 
> So, what have other people's experiences been?  Is anyone already
> working or planning to work on a generic framework for supporting
> high-level NAND controllers, or will I have to be the first one?

I guess for the generic framework it's a bit to early to even consider
that. Let's first finish the "interface-agnostic NAND layer", and then
we'll see what we can do for your "high-level NAND controller".

I'll finish with a side note regarding the approach taken by Faraday
for its NAND controller: it's risky. I've seen a lot of NAND devices
and modern ones are so tricky to interface with that providing an high
level interface is just not enough, you need to tweak a lot of things
(using private vendor commands) to be able to recover from corner cases.
Are you sure Farady don't provide an hidden feature allowing one to send
raw commands when needed?

BTW, can you share the code you have (both the existing version and
your rework) so I can have a look.

Best Regards,

Boris

[1]https://github.com/bbrezillon/linux-0day/commits/nand/generic


-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Supporting high-level NAND controllers like FTNANDC024
  2016-05-26  7:15 ` Boris Brezillon
@ 2016-05-26  9:45   ` Artem Bityutskiy
  2016-05-26 11:08     ` Boris Brezillon
  0 siblings, 1 reply; 4+ messages in thread
From: Artem Bityutskiy @ 2016-05-26  9:45 UTC (permalink / raw)
  To: Boris Brezillon, Mychaela Falconia; +Cc: Peter Pan, linux-mtd

On Thu, 2016-05-26 at 09:15 +0200, Boris Brezillon wrote:
> - OneNAND NANDs

While this should not stop you, you may have troubles finding a device
with this kind of NAND where you could test your changes, though.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Supporting high-level NAND controllers like FTNANDC024
  2016-05-26  9:45   ` Artem Bityutskiy
@ 2016-05-26 11:08     ` Boris Brezillon
  0 siblings, 0 replies; 4+ messages in thread
From: Boris Brezillon @ 2016-05-26 11:08 UTC (permalink / raw)
  To: Artem Bityutskiy; +Cc: Mychaela Falconia, Peter Pan, linux-mtd

On Thu, 26 May 2016 12:45:50 +0300
Artem Bityutskiy <dedekind1@gmail.com> wrote:

> On Thu, 2016-05-26 at 09:15 +0200, Boris Brezillon wrote:
> > - OneNAND NANDs  
> 
> While this should not stop you, you may have troubles finding a device
> with this kind of NAND where you could test your changes, though.

Brian already warned me that :). Let's focus on the rawNAND and SPINAND
cases for now, we'll see if someone wants to port the OneNAND code to
this new framework ;).

-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-05-26 11:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-26  5:45 Supporting high-level NAND controllers like FTNANDC024 Mychaela Falconia
2016-05-26  7:15 ` Boris Brezillon
2016-05-26  9:45   ` Artem Bityutskiy
2016-05-26 11:08     ` Boris Brezillon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox