[U-Boot] dm: Introduce SPI-NOR framework

Jagan Teki jteki at openedev.com
Wed Jan 6 15:32:55 CET 2016


Hi Simon,

On 6 January 2016 at 05:54, Simon Glass <sjg at chromium.org> wrote:
> Hi Jagan,
>
> On 17 December 2015 at 10:06, Jagan Teki <jteki at openedev.com> wrote:
>> Hi Simon,
>>
>> On 15 December 2015 at 03:44, Simon Glass <sjg at chromium.org> wrote:
>>> Hi Jagan,
>>>
>>> On 11 December 2015 at 09:57, Jagan Teki <jteki at openedev.com> wrote:
>>>> Hi Simon,
>>>>
>>>> On 11 December 2015 at 07:35, Simon Glass <sjg at chromium.org> wrote:
>>>>> Hi Jagan,
>>>>>
>>>>> On 8 December 2015 at 08:36, Jagan Teki <jteki at openedev.com> wrote:
>>>>>> Hi Simon,
>>>>>>
>>>>>> On 8 December 2015 at 08:22, Simon Glass <sjg at chromium.org> wrote:
>>>>>>> Hi Jagan,
>>>>>>>
>>>>>>> On 3 December 2015 at 03:10, Jagan Teki <jteki at openedev.com> wrote:
>>>>>>>> Hi Simon,
>>>>>>>>
>>>>>>>> I re-phrase all the question from previous thread and continue in this for
>>>>>>>> more discussion on spi-nor development.
>>>>>>>>
>>>>>>>>> Is it intended that SPI flash should be a driver for the MTD uclass?
>>>>>>>>> Others would be NAND and CFI. From what I can tell MTD has the same
>>>>>>>>> operations as SPI flash (erase, read, write) and adds a lot more.
>>>>>>>>>
>>>>>>>>> Or is SPI flash really a separate uclass from MTD, with SPI flash
>>>>>>>>> being at a higher level?
>>>>>>>>
>>>>>>>> Based on my "sf: MTD support" series SPI flash is a separate uclass from MTD
>>>>>>>> and it uses mtd_info operations.
>>>>>>>>
>>>>>>>>>> cmd_sf
>>>>>>>>>> =======
>>>>>>>>>> MTD
>>>>>>>>>> =======
>>>>>>>>>> spi-nor or spi-flash
>>>>>>>>>> ===============
>>>>>>>>>> "spi-nor to spi drivers" and spi-nor controller driver
>>>>>>>>>> =======================================
>>>>>>>>> Your diagram above suggests that MTD calls into SPI NOR or SPI flash,
>>>>>>>>> but when I look at (for exampe) spi_flash_erase(), it is calling
>>>>>>>>> mtd_erase(), suggesting that it is above MTD in the software stack,
>>>>>>>>> the opposite of your diagram above.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Will explain this clearly in below description.
>>>>>>>>
>>>>>>>>> Conceptually this seems problematic.
>>>>>>>>>
>>>>>>>>> SPI flash is a uclass and supports driver model. It has operations,
>>>>>>>>> etc. Your patches remove the operations in favour of calling MTD. But
>>>>>>>>> MTD does not support driver model. This is getting really messy.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Will explain this clearly in below description.
>>>>>>>>
>>>>>>>>
>>>>>>>> Introducing SPI-NOR:
>>>>>>>> ********************
>>>>>>>>
>>>>>>>> Some of the spi drivers or spi controllers at drivers/spi/*
>>>>>>>> not a real spi controllers, unlike normal spi controllers
>>>>>>>> those operates varienty of spi devices among spi-nor flash is
>>>>>>>> one of them but instead these were specially designed for
>>>>>>>> to operate spi-nor flash devices - these are spi-nor controllers.
>>>>>>>> example: drivers/spi/fsl_qspi.c
>>>>>>>>
>>>>>>>> The problem with these were sitting at drivers/spi is entire
>>>>>>>> spi layer becomes spi-nor flash oriented which is absolutely
>>>>>>>> wrong indication where spi layer gets effected more with
>>>>>>>> flash operations - So this SPI-NOR will resolve this issue
>>>>>>>> by separating all spi-nor flash operations from spi layer
>>>>>>>> and by creating a generic layer called SPI-NOR core where it
>>>>>>>> deals with all SPI-NOR flash activities. The basic idea is
>>>>>>>> taken from Linux spi-nor framework.
>>>>>>>>
>>>>>>>> SPI-NOR Block diagram:
>>>>>>>> *********************
>>>>>>>>
>>>>>>>> =========
>>>>>>>> cmd_sf.c
>>>>>>>> ===========
>>>>>>>> spi_flash.h
>>>>>>>> ===========
>>>>>>>> mtdcore.c
>>>>>>>> ===========
>>>>>>>> spi-nor.c
>>>>>>>> ========================
>>>>>>>> m25p80.c     fsl_qspi.c
>>>>>>>> ==========   ===========
>>>>>>>> spi-uclass   spi-nor hw
>>>>>>>> ==========   ===========
>>>>>>>> spi_drivers
>>>>>>>> ===========
>>>>>>>> spi-bus hw
>>>>>>>> ==========
>>>>>>>>
>>>>>>>> Note:
>>>>>>>> - spi-nor.c is a common core for m25p80.c which is a spi-nor to spi driver
>>>>>>>> interface layer and for fsl_qspi.c which is a typical spi-nor
>>>>>>>> controller driver.
>>>>>>>> - Challenging task is about probe.
>>>>>>>>
>>>>>>>> SPI-NOR Development plan:
>>>>>>>> *************************
>>>>>>>>
>>>>>>>> a) Adding MTD core support:
>>>>>>>>    From command point of view the spi-flash is like a mtd device having
>>>>>>>> erase/write/read ops with offset, addr and size, but from lower layers the
>>>>>>>> spi-flash becomes either spi-nor or spi-nand so they have their own specific
>>>>>>>> features like struct spi_nor {}.
>>>>>>>>
>>>>>>>>    This is the reason for calling MTD from command layer and the lower layer
>>>>>>>> as SPI_NOR uclass.
>>>>>>>>
>>>>>>>> b) Drop spi_flash uclass:
>>>>>>>>    Since spi_flash is a generic term for serial flash devices among
>>>>>>>>    these spi-nor and spi-nand are the real device categories so add
>>>>>>>>    driver model to these categories.
>>>>>>>>
>>>>>>>> I sent the series [1] for above a) and b)
>>>>>>>
>>>>>>> It doesn't look like that series drops the SPI flash uclass.
>>>>>>
>>>>>> Yes, I have not dropped SPI flash uclass fully on the series only ops.
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> c) Add spi-nor support (mean Adding SPI-NOR dm drivers) the next step.
>>>>>>>
>>>>>>> I think this is what I am missing. If you are moving to SPI NOR, what
>>>>>>> is the API? Is it the roughly the same as the current SPI flash API?
>>>>>>> (read, write, erase)
>>>>>>
>>>>>> For now SPI NOR api's are same as SPI flash in terms of structure
>>>>>> members but spi-nor hooks, definition and the calling context are
>>>>>> different. Usually SPI flash ops are getting called from cmd_sf ==>
>>>>>> spi_flash.h  ==> sf-uclass.c and then finally goes into sf_ops.c for
>>>>>> actual function definitions, but in case of SPI NOR spi-nor ops
>>>>>> (defined in spi-nor controller drivers - sf_probe.c, fsl_qspi.c) are
>>>>>> getting called from mtd_info ops definitions which are defined at
>>>>>> spi-nor core (which is sf_ops.c as of now), and from cmd_sf =>
>>>>>> spi_flash.h => mtdcore.c and the finally goes into spi-nor for actual
>>>>>> mtd ops definitions.
>>>>>>
>>>>>> Unlike SPI flash, SPI nor framework will separate the flow from
>>>>>> generic spi controller which one of the connected slave as spi nor
>>>>>> flash (through sf_probe.c) vs spi-nor controller drivers like
>>>>>> fsl_qspi.c
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> Detailed SPI-NOR with examples:
>>>>>>>> ******************************
>>>>>>>>
>>>>>>>> include/spi_flash.h
>>>>>>>> -------------------
>>>>>>>>
>>>>>>>> struct spi_flash {
>>>>>>>>    struct spi_nor  *nor;
>>>>>>>> };
>>>>>>>>
>>>>>>>> include/linux/mtd/spi-nor.h
>>>>>>>> ---------------------------
>>>>>>>>
>>>>>>>> struct spi_nor {
>>>>>>>>    struct udevice   *dev;
>>>>>>>>    struct mtd_info  *info;
>>>>>>>>
>>>>>>>>    // spi-nor hooks
>>>>>>>>    int (*read_reg)(struct udevice *dev, u8 cmd, u8 *val, int len);
>>>>>>>>    int (*write_reg)(struct udevice *dev, u8 cmd, u8 *data, int len);
>>>>>>>>
>>>>>>>>    int (*read_mmap)(struct udevice *dev, void *data, void *offset,
>>>>>>>>                 size_t len);
>>>>>>>>    int (*read)(struct udevice *dev, const u8 *opcode, size_t cmd_len,
>>>>>>>>                 void *data, size_t data_len);
>>>>>>>>    int (*write)(struct udevice *dev, const u8 *cmd, size_t cmd_len,
>>>>>>>>                 const void *data, size_t data_len);
>>>>>>>
>>>>>>> But here you show SPI nor with its own operations. So does SPI nor
>>>>>>> call into MTD? What is your plan to move MTD to driver model and
>>>>>>> create a MTD uclass? Also, does this mean that each SPI nor device
>>>>>>> will have an MTD sub-device?
>>>>>>
>>>>>> Yes, SPI NOR is different from MTD and MTD operations which are
>>>>>> defined at spi-nor will call the respective spi-nor controller driver
>>>>>> spi-nor operations. which I explained above.
>>>>>>
>>>>>> I think using MTD uclass is another approach where we can remove the
>>>>>> udevice from SPI NOR and making all spi-nor controller driver as
>>>>>> MTD_UCLASS - do you prefer this?
>>>>>
>>>>> I think so, so far as I understand it. My initial concern with your
>>>>> approach was that you had a driver model uclass making calls into an
>>>>> API that was not driver-model-compatible. So creating an MTD uclass
>>>>> definitely seems cleaner to me. Also I've found that driver model
>>>>> conversion is best done starting from the bottom of the stack.
>>>>
>>>> MTD uclass looks ok to me as well and with this I may drop spi_flash
>>>> {} and will use mtd_info since from cmd_sf and below is sample code
>>>> snippet, just written for understanding things will clear when patches
>>>> submitted. Let me know your inputs on this.
>>>>
>>>> cmd_sf.c
>>>> ---------
>>>>
>>>> spi_flash_t *flash;
>>>>
>>>> spi_flash.h
>>>> -----------
>>>>
>>>> typedef struct mtd_info spi_flash_t;
>>>>
>>>> static inline int spi_flash_read(spi_flash_t *flash, u32 offset,
>>>>                 size_t len, void *buf)
>>>> {
>>>>     // mtd_read
>>>
>>> Looks good, but you will need an MTD uclass before doing this.
>>
>> Yes.
>>
>>>
>>>> }
>>>>
>>>> static inline int spi_flash_write(spi_flash_t *flash, u32 offset,
>>>>                 size_t len, const void *buf)
>>>> {
>>>> // mtd_write
>>>> }
>>>>
>>>> static inline int spi_flash_erase(spi_flash_t *flash, u32 offset,
>>>>                 size_t len)
>>>> {
>>>> // mtd_erase
>>>> }
>>>>
>>>> static inline int spi_flash_protect(spi_flash_t *flash, u32 ofs, u32 len,
>>>>                                         bool prot)
>>>> {
>>>> // mtd_lock
>>>> // mtd_unlock
>>>> }
>>>>
>>>>
>>>> include/linux/mtd/spi-nor.h
>>>> ---------------------------
>>>>
>>>> struct spi_nor {
>>>>    struct mtd_info  *mtd;
>>>>
>>>>    // spi-nor hooks
>>>>    int (*read_reg)(struct spi_nor *nor, u8 cmd, u8 *val, int len);
>>>>    int (*write_reg)(struct spi_nor *nor, u8 cmd, u8 *data, int len);
>>>>
>>>>    int (*read_mmap)(struct spi_nor *nor, void *data, void *offset,
>>>>                 size_t len);
>>>>    int (*read)(struct spi_nor *nor, const u8 *opcode, size_t cmd_len,
>>>>         void *data, size_t data_len);
>>>>    int (*write)(struct spi_nor *nor, const u8 *cmd, size_t cmd_len,
>>>>                 const void *data, size_t data_len);
>>>
>>> Is this intended to me a new uclass that has a different API from MTD?
>>>
>>>> };
>>>>
>>>> drivers/mtd/spi-nor/spi-nor.c
>>>> -----------------------------
>>>>
>>>> static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
>>>> {
>>>>     // call to spi-nor erase nor->erase()
>>>> }
>>>>
>>>> static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
>>>>                         size_t *retlen, u_char *buf)
>>>> {
>>>>     // call to spi-nor erase nor->read()
>>>> }
>>>>
>>>> static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
>>>>         size_t *retlen, const u_char *buf)
>>>> {
>>>>     // call to spi-nor erase nor->erase()
>>>> }
>>>>
>>>> int spi_nor_scan(struct spi_nor *nor)
>>>> {
>>>>     struct mtd_info *mtd = nor->mtd;
>>>>
>>>>     // read_jedec
>>>>
>>>>     // assign mtd hooks
>>>>
>>>>     // other spi-nor stuff
>>>>
>>>> }
>>>>
>>>> drivers/mtd/spi-nor/m25p80.c
>>>> ----------------------------
>>>>
>>>> struct m25p80 {
>>>>         struct spi_nor nor;
>>>> };
>>>>
>>>> static int m25p80_probe(struct udevice *dev)
>>>> {
>>>>     struct spi_slave *spi   = dev_get_parentdata(dev);
>>>>     struct mtd_info  *mtd   = dev_get_uclass_priv(dev);
>>>>     struct m25p80    *flash = dev_get_priv(dev);
>>>>     struct spi_nor   *nor;
>>>>
>>>>     nor = &flash->nor;
>>>
>>> Is this a SPI nor device? See above question. It seems perhaps not, as
>>> dev_get_uclass_priv() returns an mtd_info, which suggests that it is
>>> an MTD uclass? This needs to be very clear...
>>
>> struct spi_nor is a low level device for mtd other wards from user
>> point-of-view, user doing an mtd operation on mtd flash device which
>> is SPI nor in this case. Since the driver is MTD uclass, driver probe
>> must assign hooks to spi_nor ops but struct spi_nor is not a uclass.
>
> OK, so are you working on a uclass for MTD?

Yes.

thanks!
-- 
Jagan.


More information about the U-Boot mailing list