dm: Generic MTD Subsystem, with SPI-NOR interface
Subsystems (6)
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor ULASS_SPI_NOR driver bind happen, the uclass driver of spinor will pass MTD_IF_TYPE_SPI_NOR interface type to create mtd device for spinor devices.
SPI-NOR:
=======
Some of the SPI device drivers at drivers/spi not a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex: drivers/spi/fsl_qspi.c
The problem with these were resides at drivers/spi is entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.
=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.c zynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================
#####SPI NOR chip######
=======================================
Changes for v10:
- Update Simon's R-B tag
- Add mtd dm test case
- implemented entire code wrt MTD, with interface type
code size:
==========
before:
$ arm-linux-gnueabi-size u-boot text data bss dec hex filename 473712 15152 222568 711432 adb08 u-boot $ du -hs u-boot-dtb.img 488K u-boot-dtb.img
after:
$ arm-linux-gnueabi-size u-boot text data bss dec hex filename 470124 14352 222584 707060 ac9f4 u-boot $ du -hs u-boot-dtb.img 484K u-boot-dtb.img
approximately 4KiB but DM_SPI_FLASH still there which can be removed once support added in SPL
test log:
========
Zynq> spinor
spinor - SPI-NOR Sub-system
Usage:
spinor list - show list of spinor devices spinor info - show current spinor device info spinor dev [devnum] - show or set current spinor device spinor erase offset len - erase 'len' bytes from 'offset' spinor write addr to len - write 'len' bytes to 'to' from 'addr' spinor read addr from len - read 'len' bytes from 'from' to 'addr'
spinor protect lock/unlock sector len - protect/unprotect 'len' bytes starting
at address 'sector'
Zynq> spinor list
flash at 0: 0
spi-nor at e000d000: 1
Zynq> spinor dev 0
switch to dev #0, OK
spinor0 is current device
Zynq> spinor info
bus: flash at 0: 0
device: s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase 0xE00000 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Erased: OK
Zynq> mw.b 0x100 0xcc 0x100000
Zynq> spinor write 0x100 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Written: OK
Zynq> spinor read 0x3000000 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Read: OK
Zynq> cmp.b 0x3000000 0x100 0x100000
Total of 1048576 byte(s) were the same
Zynq> spinor dev 1
switch to dev #1, OK
spinor1 is current device
Zynq> spinor info
bus: spi-nor at e000d000: 1
device: s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase 0xE00000 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Erased: OK
Zynq> mw.b 0x100 0xbb 0x100000
Zynq> spinor write 0x100 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Written: OK
Zynq> spinor read 0x3000000 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Read: OK
Zynq> cmp.b 0x3000000 0x100 0x100000
Total of 1048576 byte(s) were the same
WIP:
===
- to support non-dm code
- to support spinor SPL
Repo:
====
$ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b mtd-spinor-working origin/mtd-spinor-working
[1] https://lists.denx.de/pipermail/u-boot/2016-October/271459.html
[2] http://lists.denx.de/pipermail/u-boot/2016-March/249286.html
[3] http://lists.denx.de/pipermail/u-boot/2016-February/245418.html
[4] [PATCH RFC v8 00/16] SPI-NOR/MTD addition
Jagan Teki (27):
mtd: Add mtd core ops
mtd: add mtd device create operations
mtd: add SPI-NOR core support
mtd: spi-nor: sync/modify sst write operations
mtd: spi-nor: sync/modify lock operations
mtd: spi-nor: Kconfig: Add MTD_SPI_NOR entry
mtd: spi-nor: Kconfig: Add MTD_SPI_NOR_USE_4K_SECTORS
mtd: spi-nor: Kconfig: Add SPI_NOR_MISC entry
mtd: spi-nor: Kconfig: Add SPI_NOR_MACRONIX entry
mtd: spi-nor: Kconfig: Add SPI_NOR_SPANSION entry
mtd: spi-nor: Kconfig: Add SPI_NOR_STMICRO entry
mtd: spi-nor: Kconfig: Add SPI_NOR_SST entry
mtd: spi-nor: Kconfig: Add SPI_NOR_WINBOND entry
mtd-uclass: use platdata_auto_alloc
spi: Add spi_write_then_read
mtd: spi-nor: Add m25p80 driver
mtd: spi-nor: Kconfig: Add MTD_M25P80 entry
mtd: spi-nor: Add zynq qspinor driver
mtd: spi-nor: zynq_qspi: Kconfig: Add MTD_ZYNQ
mtd: spi-nor: Add 4-byte addresswidth support
cmd: add spinor cmd support
cmd: spinor: sync/update protect command
board_r: initialize spi_nor
env: add spi-nor environment
arm: dts: zynq: Add zynq-qspinor node
dm: zynq: microzed: enable MTD/SPI-NOR framework
test: dm: add tests for mtd devices
Makefile | 1 + arch/arm/dts/zynq-7000.dtsi | 12 + arch/arm/dts/zynq-microzed.dts | 12 +- cmd/Kconfig | 5 + cmd/Makefile | 1 + cmd/nvedit.c | 1 + cmd/spinor.c | 326 ++++++++++++ common/board_r.c | 13 + configs/sandbox_defconfig | 8 +- configs/zynq_microzed_defconfig | 17 +- drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 7 +- drivers/mtd/mtd-uclass.c | 203 +++++++- drivers/mtd/spi-nor/Kconfig | 89 ++++ drivers/mtd/spi-nor/Makefile | 15 + drivers/mtd/spi-nor/m25p80.c | 251 ++++++++++ drivers/mtd/spi-nor/spi-nor-ids.c | 184 +++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 160 ++++++ drivers/mtd/spi-nor/spi-nor.c | 940 +++++++++++++++++++++++++++++++++++ drivers/mtd/spi-nor/zynq_qspinor.c | 622 +++++++++++++++++++++++ drivers/spi/spi-uclass.c | 24 + env/Kconfig | 27 + env/Makefile | 1 + env/env.c | 2 + env/spinor.c | 113 +++++ include/dm/uclass-id.h | 1 + include/environment.h | 1 + include/linux/mtd/mtd.h | 14 + include/linux/mtd/spi-nor.h | 223 +++++++++ include/mtd.h | 176 +++++++ include/spi.h | 20 + test/dm/Makefile | 1 + test/dm/mtd.c | 33 ++ 33 files changed, 3493 insertions(+), 12 deletions(-) create mode 100644 cmd/spinor.c create mode 100644 drivers/mtd/spi-nor/Kconfig create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/m25p80.c create mode 100644 drivers/mtd/spi-nor/spi-nor-ids.c create mode 100644 drivers/mtd/spi-nor/spi-nor-uclass.c create mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 drivers/mtd/spi-nor/zynq_qspinor.c create mode 100644 env/spinor.c create mode 100644 include/linux/mtd/spi-nor.h create mode 100644 test/dm/mtd.c
Signature · 1 line
2.7.4
PATCH v10 1/27 mtd: Add mtd core ops
- Add generic mtd operations
- Add mtd_dread|derase|dwrite
The respetive MTD_UCLASS drivers must install the hooks to these mtd_ops and other core ops are act as a interface b/w drivers vs command code.
--- drivers/mtd/mtd-uclass.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ include/mtd.h | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+)
drivers/mtd/mtd-uclass.c +61 -0
@@ -1,4 +1,5 @@/* +* Copyright (C) 2016 Jagan Teki <[email protected]> * Copyright (C) 2015 Thomas Chou <[email protected]> * * SPDX-License-Identifier: GPL-2.0+
@@ -8,6 +9,66 @@#include <dm.h> #include <errno.h> #include <mtd.h> +#include <linux/log2.h> + +int mtd_dread (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen, +u_char *buf) +{ +struct udevice *dev = mtd->dev; +const struct mtd_ops *ops =mtd_get_ops (dev); + +if (!ops->read) +return -ENOSYS ; + + *retlen =0 ; +if (from <0 || from > mtd->size || len > mtd->size - from) +return -EINVAL ; +if (!len) +return 0 ; + +return ops->read (dev, from, len, retlen, buf); +} + +int mtd_derase (struct mtd_info *mtd,struct erase_info *instr) +{ +struct udevice *dev = mtd->dev; +const struct mtd_ops *ops =mtd_get_ops (dev); + +if (!ops->erase) +return -ENOSYS ; + +if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr) +return -EINVAL ; +if (!(mtd->flags &MTD_WRITEABLE )) +return -EROFS ; + instr->fail_addr =MTD_FAIL_ADDR_UNKNOWN ; +if (!instr->len) { + instr->state =MTD_ERASE_DONE ; +return 0 ; + } + +return ops->erase (dev, instr); +} + +int mtd_dwrite (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen, +const u_char *buf) +{ +struct udevice *dev = mtd->dev; +const struct mtd_ops *ops =mtd_get_ops (dev); + +if (!ops->write) +return -ENOSYS ; + + *retlen =0 ; +if (to <0 || to > mtd->size || len > mtd->size - to) +return -EINVAL ; +if (!ops->write || !(mtd->flags &MTD_WRITEABLE )) +return -EROFS ; +if (!len) +return 0 ; + +return ops->write (dev, to, len, retlen, buf); +}/* * Implement a MTD uclass which should include most flash drivers.
include/mtd.h +46 -0
50 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v10 2/27 mtd: add mtd device create operations
In reply to Jagan Tekimtd is common device interaction for most of memory technology flashes like nand, parallel nor, spi-nor, dataflash etc, these are terminated as interface types in u-boot driver model.
This patch add common way of creating mtd device for respective underlying interface type. once the interface driver bind happen, the receptive uclass will pass an interface type to mtd layer to create a device for it.
MTD_IF_TYPE_SPI_NOR in an interface type for all spi nor devices.
--- drivers/mtd/mtd-uclass.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/mtd.h | 14 ++++++ include/mtd.h | 116 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 251 insertions(+)
drivers/mtd/mtd-uclass.c +121 -0
@@ -11,6 +11,9 @@#include <mtd.h> #include <linux/log2.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +int mtd_dread (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf) {
@@ -70,6 +73,124 @@ int mtd_dwrite(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,return ops->write (dev, to, len, retlen, buf); } +int mtd_find_device (int mtd_if_type,int devnum,struct udevice **devp) +{ +struct uclass *uc; +struct udevice *dev; +int ret; + + ret =uclass_get (UCLASS_MTD , &uc); +if (ret) +return ret; + uclass_foreach_dev(dev, uc) { +struct mtd_info *mtd =dev_get_uclass_platdata (dev); + +debug ("%s: mtd_if_type=%d, devnum=%d: %s, %d, %d\n" , __func__, + mtd_if_type, devnum, dev->name, mtd->mtd_if_type, mtd->devnum); +if (mtd->mtd_if_type == mtd_if_type && mtd->devnum == devnum) { + *devp = dev; +return 0 ; + } + } + +return -ENODEV ; +} + +int mtd_get_device (int mtd_if_type,int devnum,struct udevice **devp) +{ +int ret; + + ret =mtd_find_device (mtd_if_type, devnum, devp); +if (ret) +return ret; + +return device_probe (*devp); +} + +int mtd_select_devnum (enum mtd_if_type mtd_if_type,int devnum) +{ +struct udevice *dev; + +return mtd_get_device (mtd_if_type, devnum, &dev); +} + +int mtd_find_max_devnum (enum mtd_if_type mtd_if_type) +{ +struct udevice *dev; +int max_devnum = -ENODEV ; +struct uclass *uc; +int ret; + + ret =uclass_get (UCLASS_MTD , &uc); +if (ret) +return ret; + uclass_foreach_dev(dev, uc) { +struct mtd_info *mtd =dev_get_uclass_platdata (dev); + +if (mtd->mtd_if_type == mtd_if_type && mtd->devnum > max_devnum) + max_devnum = mtd->devnum; + } + +return max_devnum; +} + +static int mtd_next_free_devnum (enum mtd_if_type mtd_if_type) +{ +int ret; + + ret =mtd_find_max_devnum (mtd_if_type); +if (ret == -ENODEV ) +return 0 ; +if (ret <0 ) +return ret; + +return ret +1 ; +} + +int mtd_create_device (struct udevice *parent,const char *drv_name, +const char *name,int mtd_if_type,struct udevice **devp) +{ +struct mtd_info *mtd; +struct udevice *dev; +int devnum, ret; + + devnum =mtd_next_free_devnum (mtd_if_type); +if (devnum <0 ) +return devnum; + ret =device_bind_driver (parent, drv_name, name, &dev); +if (ret) +return ret; + mtd =dev_get_uclass_platdata (dev); + mtd->mtd_if_type = mtd_if_type; + mtd->dev = dev; + mtd->devnum = devnum; + *devp = dev; + +return 0 ; +} + +int mtd_create_devicef (struct udevice *parent,const char *drv_name, +const char *name,int mtd_if_type, +struct udevice **devp) +{ +char dev_name[30 ], *str; +int ret; + +snprintf (dev_name,sizeof (dev_name),"%s.%s" , parent->name, name); + str =strdup (dev_name); +if (!str) +return -ENOMEM ; + + ret =mtd_create_device (parent, drv_name, str, mtd_if_type, devp); +if (ret) { +free (str); +return ret; + } +device_set_name_alloced (*devp); + +return ret; +} +/* * Implement a MTD uclass which should include most flash drivers. * The uclass private is pointed to mtd_info.
include/linux/mtd/mtd.h +14 -0
@@ -149,6 +149,16 @@ struct nand_ecclayout {struct module ;/* only needed for owner field in mtd_info */ +#ifdef CONFIG_MTD +/* Interface types: */ +enum mtd_if_type { +MTD_IF_TYPE_UNKNOWN =0 , +MTD_IF_TYPE_SPI_NOR , + +MTD_IF_TYPE_COUNT , +}; +#endif +struct mtd_info {u_char type;uint32_t flags;
@@ -309,6 +319,10 @@ struct mtd_info {struct udevice *dev;#endif int usecount; +#ifdef CONFIG_MTD +enum mtd_if_type mtd_if_type;/* type of mtd interface */ +int devnum;/* device number */ +#endif }; int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
include/mtd.h +116 -0
120 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v10 3/27 mtd: add SPI-NOR core support
In reply to Jagan TekiSome of the SPI device drivers at drivers/spi not a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex: drivers/spi/fsl_qspi.c
The problem with these were resides at drivers/spi is entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.
=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.c zynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================
#####SPI NOR chip######
=======================================
--- Makefile | 1 + drivers/mtd/spi-nor/Makefile | 7 + drivers/mtd/spi-nor/spi-nor-ids.c | 184 +++++++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 143 +++++++++ drivers/mtd/spi-nor/spi-nor.c | 569 +++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/linux/mtd/spi-nor.h | 217 +++++++++++++ 7 files changed, 1122 insertions(+) create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/spi-nor-ids.c create mode 100644 drivers/mtd/spi-nor/spi-nor-uclass.c create mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 include/linux/mtd/spi-nor.h
Makefile +1 -0
@@ -662,6 +662,7 @@ libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/ libs-y += drivers/mtd/onenand/ libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/ libs-y += drivers/mtd/spi/ +libs-y += drivers/mtd/spi-nor/ libs-y += drivers/net/ libs-y += drivers/net/phy/ libs-y += drivers/pci/
drivers/mtd/spi-nor/Makefile new file +7 -0
@@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Jagan Teki <[email protected]> +# +# SPDX-License-Identifier: GPL-2.0+ + +## spi-nor core +obj-y += spi-nor.o spi-nor-uclass.o spi-nor-ids.o
drivers/mtd/spi-nor/spi-nor-ids.c new file +184 -0
184 lines not on this page · raw message
drivers/mtd/spi-nor/spi-nor-uclass.c new file +143 -0
143 lines not on this page · raw message
drivers/mtd/spi-nor/spi-nor.c new file +569 -0
569 lines not on this page · raw message
include/dm/uclass-id.h +1 -0
@@ -75,6 +75,7 @@ enum uclass_id {UCLASS_SERIAL ,/* Serial UART */ UCLASS_SPI ,/* SPI bus */ UCLASS_SPMI ,/* System Power Management Interface bus */ +UCLASS_SPI_NOR ,/* SPI NOR flash */ UCLASS_SPI_FLASH ,/* SPI flash */ UCLASS_SPI_GENERIC ,/* Generic SPI flash target */ UCLASS_SYSCON, /* System configuration device */
include/linux/mtd/spi-nor.h new file +217 -0
217 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v10 3/27 mtd: add SPI-NOR core support
Hi Jagan:
2017-12-28 14:12 GMT+08:00 Jagan Teki <[email protected]>:
Quoted 587 lines
Some of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cThe problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================#####SPI NOR chip######=======================================
Signed-off-by Suneel Garapati <[email protected]>Signed-off-by Jagan Teki <[email protected]>--- Makefile | 1 + drivers/mtd/spi-nor/Makefile | 7 + drivers/mtd/spi-nor/spi-nor-ids.c | 184 +++++++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 143 +++++++++ drivers/mtd/spi-nor/spi-nor.c | 569 ++++++++++++++++++++++++++++++ +++++ include/dm/uclass-id.h | 1 + include/linux/mtd/spi-nor.h | 217 +++++++++++++ 7 files changed, 1122 insertions(+) create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/spi-nor-ids.c create mode 100644 drivers/mtd/spi-nor/spi-nor-uclass.c create mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 include/linux/mtd/spi-nor.hMakefile +1
-0@@ -662,6 +662,7 @@ libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/ libs-y += drivers/mtd/onenand/ libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/ libs-y += drivers/mtd/spi/ +libs-y += drivers/mtd/spi-nor/ libs-y += drivers/net/ libs-y += drivers/net/phy/ libs-y += drivers/pci/drivers/mtd/spi-nor/Makefile new file +7
-0@@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Jagan Teki <[email protected]> +# +# SPDX-License-Identifier: GPL-2.0+ + +## spi-nor core +obj-y += spi-nor.o spi-nor-uclass.o spi-nor-ids.odrivers/mtd/spi-nor/spi-nor-ids.c new file +49
-0@@ -0,0 +1,184 @@ +/* +* SPI NOR IDs. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <linux/mtd/spi-nor.h> + +/* Used when the "_ext_id" is two bytes at most */ +#define INFO (_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + .id = { \ + ((_jedec_id) >> 16) & 0xff, \ + ((_jedec_id) >> 8) & 0xff, \ + (_jedec_id) & 0xff, \ + ((_ext_id) >> 8) & 0xff, \ + (_ext_id) & 0xff, \ + }, \ + .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), + +#define INFO6 (_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + .id = { \ + ((_jedec_id) >> 16) & 0xff, \ + ((_jedec_id) >> 8) & 0xff, \ + (_jedec_id) & 0xff, \ + ((_ext_id) >> 16) & 0xff, \ + ((_ext_id) >> 8) & 0xff, \ + (_ext_id) & 0xff, \ + }, \ + .id_len = 6, \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), + +const struct spi_nor_info spi_nor_ids[] = { +#ifdef CONFIG_SPI_NOR_MACRONIX /* MACRONIX */ + {"mx25l2006e" ,INFO (0xc22012 ,0x0 ,64 *1024 ,4 ,0 ) }, + {"mx25l4005" ,INFO (0xc22013 ,0x0 ,64 *1024 ,8 ,0 ) }, + {"mx25l8005" ,INFO (0xc22014 ,0x0 ,64 *1024 ,16 ,0 ) }, + {"mx25l1605d" ,INFO (0xc22015 ,0x0 ,64 *1024 ,32 ,0 ) }, + {"mx25l3205d" ,INFO (0xc22016 ,0x0 ,64 *1024 ,64 ,0 ) }, + {"mx25l6405d" ,INFO (0xc22017 ,0x0 ,64 *1024 ,128 ,0 ) }, + {"mx25l12805", INFO(0xc22018, 0x0, 64 * 1024, 256, RD_FULL |
WR_QPP) },
+ {"mx25l25635f", INFO(0xc22019,0x0, 64 * 1024, 512,RD_FULL|WR_QPP) },
+ {"mx25l51235f", INFO(0xc2201a,0x0, 64 * 1024, 1024,RD_FULL|WR_QPP) },
+ {"mx25u6435f", INFO(0xc22537,0x0, 64 * 1024, 128,RD_FULL|WR_QPP) },
+ {"mx25l12855e", INFO(0xc22618,0x0, 64 * 1024, 256,RD_FULL|WR_QPP) },drivers/mtd/spi-nor/spi-nor-ids.c new file +2
-0+ {"mx25u1635e", INFO(0xc22535, 0x0, 64 * 1024, 32, SECT_4K) }, + {"mx66u51235f", INFO(0xc2253a, 0x0, 64 * 1024, 1024, RD_FULL |
WR_QPP) },
+ {"mx66l1g45g", INFO(0xc2201b,0x0, 64 * 1024, 2048,RD_FULL|WR_QPP) },drivers/mtd/spi-nor/spi-nor-ids.c new file +9
-0+#endif +#ifdef CONFIG_SPI_NOR_SPANSION /* SPANSION */ + {"s25fl008a", INFO(0x010213, 0x0, 64 * 1024, 16, 0) }, + {"s25fl016a", INFO(0x010214, 0x0, 64 * 1024, 32, 0) }, + {"s25fl032a", INFO(0x010215, 0x0, 64 * 1024, 64, 0) }, + {"s25fl064a", INFO(0x010216, 0x0, 64 * 1024, 128, 0) }, + {"s25fl116k", INFO(0x014015, 0x0, 64 * 1024, 32, 0) }, + {"s25fl164k", INFO(0x014017, 0x0140, 64 * 1024, 128, 0) }, + {"s25fl128p_256k", INFO(0x012018, 0x0300, 256 * 1024, 64,RD_FULL | WR_QPP) }, + {"s25fl128p_64k", INFO(0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"s25fl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, RD_FULL | WR_QPP) }, + {"s25fl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP) }, + {"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) }, + {"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP) }, + {"s25fs256s_64k", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) }, + {"s25fs512s", INFO6(0x010220, 0x4d0081, 128 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, RD_FULL | WR_QPP) }, + {"s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL | WR_QPP) }, + {"s25fl512s_512k", INFO(0x010220, 0x4f00, 256 * 1024, 256, RD_FULL | WR_QPP) },drivers/mtd/spi-nor/spi-nor-ids.c new file +9
-0+#endif +#ifdef CONFIG_SPI_NOR_STMICRO /* STMICRO */ + {"m25p10", INFO(0x202011, 0x0, 32 * 1024, 4, 0) }, + {"m25p20", INFO(0x202012, 0x0, 64 * 1024, 4, 0) }, + {"m25p40", INFO(0x202013, 0x0, 64 * 1024, 8, 0) }, + {"m25p80", INFO(0x202014, 0x0, 64 * 1024, 16, 0) }, + {"m25p16", INFO(0x202015, 0x0, 64 * 1024, 32, 0) }, + {"m25pE16", INFO(0x208015, 0x1000, 64 * 1024, 32, 0) }, + {"m25pX16", INFO(0x207115, 0x1000, 64 * 1024, 32, RD_QUAD |
RD_DUAL) },drivers/mtd/spi-nor/spi-nor-ids.c new file +4
-0+ {"m25p32", INFO(0x202016, 0x0, 64 * 1024, 64, 0) }, + {"m25p64", INFO(0x202017, 0x0, 64 * 1024, 128, 0) }, + {"m25p128", INFO(0x202018, 0x0, 256 * 1024, 64, 0) }, + {"m25pX64", INFO(0x207117, 0x0, 64 * 1024, 128, SECT_4K)},
+ {"n25q016a",INFO(0x20bb15, 0x0, 64 * 1024, 32, SECT_4K)
},
+ {"n25q32", INFO(0x20ba16,0x0, 64 * 1024, 64,RD_FULL| WR_QPP | SECT_4K) }, + {"n25q32a", INFO(0x20bb16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q64", INFO(0x20ba17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q64a", INFO(0x20bb17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q128", INFO(0x20ba18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"n25q128a", INFO(0x20bb18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"n25q256", INFO(0x20ba19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q256a", INFO(0x20bb19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q512", INFO(0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"n25q512a", INFO(0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"n25q1024", INFO(0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"n25q1024a", INFO(0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"mt25qu02g", INFO(0x20bb22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"mt25ql02g", INFO(0x20ba22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"mt35xu512g", INFO6(0x2c5b1a, 0x104100, 128 * 1024, 512, E_FSR | SECT_4K) },drivers/mtd/spi-nor/spi-nor-ids.c new file +3
-0+#endif +#ifdef CONFIG_SPI_NOR_SST /* SST */ + {"sst25vf040b", INFO(0xbf258d, 0x0, 64 * 1024, 8, SECT_4K|
SST_WR) },
+ {"sst25vf080b", INFO(0xbf258e,0x0, 64 * 1024, 16,SECT_4K
|SST_WR) },
+ {"sst25vf016b", INFO(0xbf2541,0x0, 64 * 1024, 32,SECT_4K
|SST_WR) },
+ {"sst25vf032b", INFO(0xbf254a,0x0, 64 * 1024, 64,SECT_4K
|SST_WR) },
+ {"sst25vf064c",INFO(0xbf254b, 0x0, 64 * 1024, 128, SECT_4K)
},
+ {"sst25wf512", INFO(0xbf2501,0x0, 64 * 1024, 1,SECT_4K
|SST_WR) },
+ {"sst25wf010", INFO(0xbf2502,0x0, 64 * 1024, 2,SECT_4K
|SST_WR) },
+ {"sst25wf020", INFO(0xbf2503,0x0, 64 * 1024, 4,SECT_4K
|SST_WR) },
+ {"sst25wf040", INFO(0xbf2504,0x0, 64 * 1024, 8,SECT_4K
|SST_WR) },
+ {"sst25wf040b",INFO(0x621613, 0x0, 64 * 1024, 8, SECT_4K)
},
+ {"sst25wf080", INFO(0xbf2505,0x0, 64 * 1024, 16,SECT_4K
|SST_WR) },drivers/mtd/spi-nor/spi-nor-ids.c new file +6
-0+#endif +#ifdef CONFIG_SPI_NOR_WINBOND /* WINBOND */ + {"w25p80", INFO(0xef2014, 0x0, 64 * 1024, 16, 0) }, + {"w25p16", INFO(0xef2015, 0x0, 64 * 1024, 32, 0) }, + {"w25p32", INFO(0xef2016, 0x0, 64 * 1024, 64, 0) }, + {"w25x40", INFO(0xef3013, 0x0, 64 * 1024, 8, SECT_4K)},
+ {"w25x16",INFO(0xef3015, 0x0, 64 * 1024, 32, SECT_4K)
},
+ {"w25x32",INFO(0xef3016, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"w25x64",INFO(0xef3017, 0x0, 64 * 1024, 128, SECT_4K)
},
+ {"w25q80bl", INFO(0xef4014,0x0, 64 * 1024, 16,RD_FULL| WR_QPP | SECT_4K) }, + {"w25q16cl", INFO(0xef4015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q32bv", INFO(0xef4016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q64cv", INFO(0xef4017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q128bv", INFO(0xef4018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q256", INFO(0xef4019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q80bw", INFO(0xef5014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q16dw", INFO(0xef6015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q32dw", INFO(0xef6016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q64dw", INFO(0xef6017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q128fw", INFO(0xef6018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) },drivers/mtd/spi-nor/spi-nor-ids.c new file +4
-0+#endif +#ifdef CONFIG_SPI_NOR_MISC +/* ATMEL */ + {"at45db011d" ,INFO (0x1f2200 ,0x0 ,64 *1024 ,4 ,SECT_4K )},
+ {"at45db021d",INFO(0x1f2300, 0x0, 64 * 1024, 8, SECT_4K)
},
+ {"at45db041d",INFO(0x1f2400, 0x0, 64 * 1024, 8, SECT_4K)
},
+ {"at45db081d",INFO(0x1f2500, 0x0, 64 * 1024, 16, SECT_4K)
},
+ {"at45db161d",INFO(0x1f2600, 0x0, 64 * 1024, 32, SECT_4K)
},
+ {"at45db321d",INFO(0x1f2700, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"at45db641d",INFO(0x1f2800, 0x0, 64 * 1024, 128, SECT_4K)
},
+ {"at25df321a",INFO(0x1f4701, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"at25df321",INFO(0x1f4700, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"at26df081a",INFO(0x1f4501, 0x0, 64 * 1024, 16, SECT_4K)
},drivers/mtd/spi-nor/spi-nor-ids.c new file +4
-0+ +/* EON */ + {"en25q32b", INFO(0x1c3016, 0x0, 64 * 1024, 64, 0) }, + {"en25q64", INFO(0x1c3017, 0x0, 64 * 1024, 128, SECT_4K)},
drivers/mtd/spi-nor/spi-nor-ids.c new file +5
-0+ {"en25q128b", INFO(0x1c3018, 0x0, 64 * 1024, 256, 0) }, + {"en25s64", INFO(0x1c3817, 0x0, 64 * 1024, 128, 0) }, + +/* GIGADEVICE */ + {"gd25q64b", INFO(0xc84017, 0x0, 64 * 1024, 128, SECT_4K)},
+ {"gd25lq32",INFO(0xc86016, 0x0, 64 * 1024, 64, SECT_4K)
},drivers/mtd/spi-nor/spi-nor-ids.c new file +22
-0+ + /* ISSI */ + {"is25lq040b", INFO(0x9d4013, 0x0, 64 * 1024, 8, 0) }, + {"is25lp032", INFO(0x9d6016, 0x0, 64 * 1024, 64, 0) }, + {"is25lp064", INFO(0x9d6017, 0x0, 64 * 1024, 128, 0) }, + {"is25lp128", INFO(0x9d6018, 0x0, 64 * 1024, 256, 0) }, +#endif + {}, /* Empty entry to terminate the list */ + /* + * Note: + * Below paired flash devices has similar spi_nor params. + * (s25fl129p_64k, s25fl128s_64k) + * (w25q80bl, w25q80bv) + * (w25q16cl, w25q16dv) + * (w25q32bv, w25q32fv_spi) + * (w25q64cv, w25q64fv_spi) + * (w25q128bv, w25q128fv_spi) + * (w25q32dw, w25q32fv_qpi) + * (w25q64dw, w25q64fv_qpi) + * (w25q128fw, w25q128fv_qpi) + */ +};drivers/mtd/spi-nor/spi-nor-uclass.c new file +80
-0@@ -0,0 +1,143 @@ +/* +* SPI NOR Core framework. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <mtd.h> + +#include <dm/device-internal.h> +#include <linux/mtd/spi-nor.h> + +DECLARE_GLOBAL_DATA_PTR ; + +struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev) +{ +struct spi_nor_uclass_priv *upriv; + +if (!device_active (dev)) +return NULL ; + upriv =dev_get_uclass_priv (dev); +return upriv->spi_nor; +} + +struct spi_nor *find_spi_nor_device (int dev_num) +{ +struct udevice *dev, *spi_nor_dev; +int ret; + + ret =mtd_find_device (MTD_IF_TYPE_SPI_NOR , dev_num, &dev); +if (ret) { +printf ("SPI-NOR Device %d not found\n" , dev_num); +return NULL ; + } + + spi_nor_dev =dev_get_parent (dev); + +struct spi_nor *nor =spi_nor_get_spi_nor_dev (spi_nor_dev); + +return nor; +} + +int get_spi_nor_num (void ) +{ +return max ((mtd_find_max_devnum (MTD_IF_TYPE_SPI_NOR ) +1 ),0 ); +} + +struct mtd_info *spi_nor_get_mtd_info (struct spi_nor *nor) +{ +struct mtd_info *mtd; +struct udevice *dev; + +device_find_first_child (nor->dev, &dev); +if (!dev) +return NULL ; + mtd =dev_get_uclass_platdata (dev); + +return mtd; +} + +void print_spi_nor_devices (char separator) +{ +struct udevice *dev; +bool first = true; + +for (uclass_first_device (UCLASS_SPI_NOR , &dev); + dev; +uclass_next_device (&dev), first = false) { +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); + +if (!first) { +printf ("%c" , separator); +if (separator !='\n' ) +puts (" " ); + } + + printf("%s: %d", dev->name, spi_nor_get_mtd_info(nor)->devnum);
drivers/mtd/spi-nor/spi-nor-uclass.c new file +14
-0+ } + +printf ("\n" ); +} + +int spi_nor_bind (struct udevice *dev,struct spi_nor *nor) +{ +struct udevice *mdev; +int ret; + +if (!spi_nor_get_ops (dev)) +return -ENOSYS ; + + ret = mtd_create_devicef(dev, "spinor_mtd", "mtd",
MTD_IF_TYPE_SPI_NOR,drivers/mtd/spi-nor/spi-nor-uclass.c new file +14
-0+ &mdev); +if (ret) { +debug ("Cannot create mtd device\n" ); +return ret; + } + nor->dev = dev; + +return 0 ; +} + +static int spi_nor_mtd_probe (struct udevice *dev) +{ +struct udevice *spi_nor_dev =dev_get_parent (dev); + struct spi_nor_uclass_priv *upriv = dev_get_uclass_priv(spi_nor_dev);
drivers/mtd/spi-nor/spi-nor-uclass.c new file +6
-0+struct spi_nor *nor = upriv->spi_nor; +int ret; + + ret =spi_nor_scan (nor); +if (ret) { + debug("%s: spi_nor_scan() failed (err=%d)\n", __func__,ret);
drivers/mtd/spi-nor/spi-nor-uclass.c new file +29
-0+return ret; + } + +return 0 ; +} + +static const struct mtd_ops spi_nor_mtd_ops = { + .read = spi_nor_mread, + .erase = spi_nor_merase, +}; + +U_BOOT_DRIVER (spinor_mtd) = { + .name ="spinor_mtd" , + .id =UCLASS_MTD , + .ops = &spi_nor_mtd_ops, + .probe = spi_nor_mtd_probe, +}; + +U_BOOT_DRIVER (spinor) = { + .name ="spinor" , + .id =UCLASS_SPI_NOR , +}; + +UCLASS_DRIVER (spinor) = { + .id =UCLASS_SPI_NOR , + .name ="spinor" , + .flags =DM_UC_FLAG_SEQ_ALIAS , + .per_device_auto_alloc_size =sizeof (struct spi_nor_uclass_priv ), +};drivers/mtd/spi-nor/spi-nor.c new file +25
-0@@ -0,0 +1,569 @@ +/* +* SPI NOR Core framework. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <mapmem.h> +#include <mtd.h> + +#include <dm/device-internal.h> +#include <linux/math64.h> +#include <linux/types.h> +#include <linux/mtd/spi-nor.h> + +DECLARE_GLOBAL_DATA_PTR ; + +/* Set write enable latch with Write Enable command */ +static inline int write_enable (struct udevice *dev) +{ + return spi_nor_get_ops(dev)->write_reg(dev, SNOR_OP_WREN, NULL,0);
drivers/mtd/spi-nor/spi-nor.c new file +6
-0+} + +/* Re-set write enable latch with Write Disable command */ +static inline int write_disable (struct udevice *dev) +{ + return spi_nor_get_ops(dev)->write_reg(dev, SNOR_OP_WRDI, NULL,0);
drivers/mtd/spi-nor/spi-nor.c new file +49
-0+} + +static int read_sr (struct udevice *dev) +{ +u8 sr; +int ret; + + ret =spi_nor_get_ops (dev)->read_reg (dev,SNOR_OP_RDSR , &sr,1 ); +if (ret <0 ) { +debug ("spi-nor: fail to read status register\n" ); +return ret; + } + +return sr; +} + +static int read_fsr (struct udevice *dev) +{ +u8 fsr; +int ret; + + ret =spi_nor_get_ops (dev)->read_reg (dev,SNOR_OP_RDFSR , &fsr,1 ); +if (ret <0 ) { +debug ("spi-nor: fail to read flag status register\n" ); +return ret; + } + +return fsr; +} + +static int write_sr (struct udevice *dev,u8 ws) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); + + nor->cmd_buf[0 ] = ws; +return ops->write_reg (dev,SNOR_OP_WRSR , nor->cmd_buf,1 ); +} + +#if defined(CONFIG_SPI_NOR_SPANSION ) || defined(CONFIG_SPI_NOR_WINBOND ) +static int read_cr (struct udevice *dev) +{ +u8 cr; +int ret; + + ret =spi_nor_get_ops (dev)->read_reg (dev,SNOR_OP_RDCR , &cr,1 ); +if (ret <0 ) { +debug ("spi-nor: fail to read config register\n" ); +return ret;
drivers/mtd/spi-nor/spi-nor.c line 90
Quoted 10 lines
drivers/mtd/spi-nor/spi-nor.c new file +10
-0+ } + +return cr; +} + +/* +* Write status Register and configuration register with 2 bytes +* - First byte will be written to the status register. +* - Second byte will be written to the configuration register. +* Return negative if error occured.
s/occured/occurred
Quoted 354 lines
+ */
drivers/mtd/spi-nor/spi-nor.c new file +50
-0+static int write_sr_cr (struct udevice *dev,u16 val) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); + + nor->cmd_buf[0 ] = val &0xff ; + nor->cmd_buf[1 ] = (val >>8 ); + +return ops->write_reg (dev,SNOR_OP_WRSR , nor->cmd_buf,2 ); +} +#endif + +static int spi_nor_sr_ready (struct udevice *dev) +{ +int sr =read_sr (dev); +if (sr <0 ) +return sr; +else +return !(sr &SR_WIP ); +} + +static int spi_nor_fsr_ready (struct udevice *dev) +{ +int fsr =read_fsr (dev); +if (fsr <0 ) +return fsr; +else +return fsr &FSR_READY ; +} + +static int spi_nor_ready (struct udevice *dev) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +int sr, fsr; + + sr =spi_nor_sr_ready (dev); +if (sr <0 ) +return sr; + + fsr =1 ; +if (nor->flags &SNOR_F_USE_FSR ) { + fsr =spi_nor_fsr_ready (dev); +if (fsr <0 ) +return fsr; + } + +return sr && fsr; +} + +static int spi_nor_wait_till_ready(struct udevice *dev, unsigned longtimeout)
drivers/mtd/spi-nor/spi-nor.c new file +76
-0+{ +int timebase, ret; + + timebase =get_timer (0 ); + +while (get_timer (timebase) < timeout) { + ret =spi_nor_ready (dev); +if (ret <0 ) +return ret; +if (ret) +return 0 ; + } + +printf ("spi-nor: Timeout!\n" ); + +return -ETIMEDOUT ; +} + +static const struct spi_nor_info *spi_nor_id (struct udevice *dev) +{ +int tmp; +u8 id[SPI_NOR_MAX_ID_LEN ]; +const struct spi_nor_info *info; +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); + + tmp = ops->read_reg (dev,SNOR_OP_RDID , id,SPI_NOR_MAX_ID_LEN ); +if (tmp <0 ) { +printf ("spi-nor: error %d reading JEDEC ID\n" , tmp); +return ERR_PTR (tmp); + } + + info = spi_nor_ids; +for (; info->name !=NULL ; info++) { +if (info->id_len) { +if (!memcmp (info->id, id, info->id_len)) +return info; + } + } + +printf ("spi-nor: unrecognized JEDEC id bytes: %02x, %2x, %2x\n" , + id[0 ], id[1 ], id[2 ]); +return ERR_PTR (-ENODEV ); +} + +int spi_nor_merase (struct udevice *dev,struct erase_info *instr) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +const struct spi_nor_ops *ops; +u32 addr, len, erase_addr; +uint32_t rem; +int ret =-1 ; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + ops =spi_nor_get_ops (nor->dev); + +div_u64_rem (instr->len, mtd->erasesize, &rem); +if (rem) +return -EINVAL ; + + addr = instr->addr; + len = instr->len; + +while (len) { + erase_addr = addr; + +write_enable (nor->dev); + + ret = ops->write (nor->dev, erase_addr,0 ,NULL ); +if (ret <0 ) + goto erase_err; + + ret = spi_nor_wait_till_ready(nor->dev,
SNOR_READY_WAIT_ERASE);drivers/mtd/spi-nor/spi-nor.c new file +43
-0+if (ret <0 ) + goto erase_err; + + addr += mtd->erasesize; + len -= mtd->erasesize; + } + +write_disable (nor->dev); + + instr->state =MTD_ERASE_DONE ; +mtd_erase_callback (instr); + +return ret; + +erase_err: + instr->state =MTD_ERASE_FAILED ; +return ret; +} + +static int spi_nor_mwrite (struct udevice *dev,loff_t to,size_t len, +size_t *retlen,const u_char *buf) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +const struct spi_nor_ops *ops; +size_t addr, byte_addr; +size_t chunk_len, actual; +uint32_t page_size; +int ret =-1 ; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + ops =spi_nor_get_ops (nor->dev); + + page_size = mtd->writebufsize; + +for (actual =0 ; actual < len; actual += chunk_len) { + addr = to; + + byte_addr = addr % page_size; + chunk_len = min(len - actual, (size_t)(page_size -
byte_addr));drivers/mtd/spi-nor/spi-nor.c new file +12
-0+ +if (nor->max_write_size) + chunk_len =min (chunk_len, + (size_t )nor->max_write_size); + +write_enable (nor->dev); + + ret = ops->write (nor->dev, addr, chunk_len, buf + actual); +if (ret <0 ) +break ; + + ret = spi_nor_wait_till_ready(nor->dev,
SNOR_READY_WAIT_PROG);drivers/mtd/spi-nor/spi-nor.c new file +110
-0+if (ret <0 ) +return ret; + + to += chunk_len; + *retlen += chunk_len; + } + +return ret; +} + +int spi_nor_mread (struct udevice *dev,loff_t from,size_t len, +size_t *retlen,u_char *buf) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +const struct spi_nor_ops *ops; +int ret; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + ops =spi_nor_get_ops (nor->dev); + +/* Handle memory-mapped SPI */ +if (nor->memory_map) { + ret = ops->read (nor->dev, from, len, buf); +if (ret) { +debug ("spi-nor: mmap read failed\n" ); +return ret; + } + +return ret; + } + + ret = ops->read (nor->dev, from, len, buf); +if (ret <0 ) { +printf ("%s ret = %d\n" , __func__, ret); +return ret; + } + + *retlen += len; + +return ret; +} + +#ifdef CONFIG_SPI_NOR_MACRONIX +static int macronix_quad_enable (struct udevice *dev) +{ +int ret, val; + + val =read_sr (dev); +if (val <0 ) +return val; + +if (val &SR_QUAD_EN_MX ) +return 0 ; + +write_enable (dev); + + ret =write_sr (dev, val |SR_QUAD_EN_MX ); +if (ret <0 ) +return ret; + +if (spi_nor_wait_till_ready (dev,SNOR_READY_WAIT_PROG )) +return 1 ; + + ret =read_sr (dev); +if (!(ret >0 && (ret &SR_QUAD_EN_MX ))) { +printf ("spi-nor: Macronix Quad bit not set\n" ); +return -EINVAL ; + } + +return 0 ; +} +#endif + +#if defined(CONFIG_SPI_NOR_SPANSION ) || defined(CONFIG_SPI_NOR_WINBOND ) +static int spansion_quad_enable (struct udevice *dev) +{ +int ret, val; + + val =read_cr (dev); +if (val <0 ) +return val; + +if (val &CR_QUAD_EN_SPAN ) +return 0 ; + +write_enable (dev); + + ret =write_sr_cr (dev, val |CR_QUAD_EN_SPAN ); +if (ret <0 ) +return ret; + +if (spi_nor_wait_till_ready (dev,SNOR_READY_WAIT_PROG )) +return 1 ; + +/* read back and check it */ + ret =read_cr (dev); +if (!(ret >0 && (ret &CR_QUAD_EN_SPAN ))) { +printf ("spi-nor: Spansion Quad bit not set\n" ); +return -EINVAL ; + } + +return 0 ; +} +#endif + +static int set_quad_mode(struct udevice *dev, const struct spi_nor_info*info)
drivers/mtd/spi-nor/spi-nor.c new file +44
-0+{ +switch (JEDEC_MFR (info)) { +#ifdef CONFIG_SPI_NOR_MACRONIX +case SNOR_MFR_MACRONIX : +return macronix_quad_enable (dev); +#endif +#if defined(CONFIG_SPI_NOR_SPANSION ) || defined(CONFIG_SPI_NOR_WINBOND ) +case SNOR_MFR_SPANSION : +case SNOR_MFR_WINBOND : +return spansion_quad_enable (dev); +#endif +#ifdef CONFIG_SPI_NOR_STMICRO +case SNOR_MFR_MICRON : +return 0 ; +#endif +default : +printf ("spi-nor: Need set QEB func for %02x flash\n" , +JEDEC_MFR (info)); +return -1 ; + } +} + +#if CONFIG_IS_ENABLED (OF_CONTROL ) +int spi_nor_decode_fdt (const void *blob,struct spi_nor *nor) +{ +struct udevice *dev = nor->dev; +struct mtd_info *mtd =mtd_get_info (dev); +fdt_addr_t addr; +fdt_size_t size; +int node; + +/* If there is no node, do nothing */ + node =fdtdec_next_compatible (blob,0 ,COMPAT_GENERIC_SPI_FLASH ); +if (node <0 ) +return 0 ; + + addr =fdtdec_get_addr_size (blob, node,"memory-map" , &size); +if (addr ==FDT_ADDR_T_NONE ) { +debug ("%s: Cannot decode address\n" , __func__); +return 0 ; + } + +if (mtd->size != size) { + debug("%s: Memory map must cover entire device\n",
__func__);drivers/mtd/spi-nor/spi-nor.c new file +11
-0+ return -1; + } + nor->memory_map =map_sysmem (addr, size); + +return 0 ; +} +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + +int spi_nor_scan (struct spi_nor *nor) +{ +struct mtd_info *mtd =spi_nor_get_mtd_info (nor);
drivers/mtd/spi-nor/spi-nor.c line 447
Quoted 10 lines
drivers/mtd/spi-nor/spi-nor.c new file +10
-0+struct mtd_ops *ops =mtd_get_ops (mtd->dev); +const struct spi_nor_info *info =NULL ; +int ret; + +struct spi_nor_uclass_priv *upriv =dev_get_uclass_priv (nor->dev); + upriv->spi_nor = nor; + +if (nor->init_done) +return 0 ; +
trailing whitespace
+ info = spi_nor_id(nor->dev);
Quoted 116 lines
drivers/mtd/spi-nor/spi-nor.c new file +9
-0+if (IS_ERR_OR_NULL (info)) { + ret = -ENOENT ; + goto err; + } + +/* +* Flash powers up read-only, so clear BP# bits. +* +* Note on some flash (like Macronix), QE (quad enable) bit is in the
+ * same status register as BP# bits, and we need preserve its
original
+ * value during a reboot cycle as this is required by some
platformsdrivers/mtd/spi-nor/spi-nor.c new file +30
-0+* (like Intel ICH SPI controller working under descriptor mode). +*/ +if (JEDEC_MFR (info) ==SNOR_MFR_ATMEL || + (JEDEC_MFR (info) ==SNOR_MFR_SST ) || + (JEDEC_MFR (info) ==SNOR_MFR_MACRONIX )) { +u8 sr =0 ; + +if (JEDEC_MFR (info) ==SNOR_MFR_MACRONIX ) + sr =read_sr (nor->dev) &SR_QUAD_EN_MX ; +write_sr (nor->dev, sr); + } + + mtd->name = info->name; + mtd->priv = nor; + mtd->type =MTD_NORFLASH ; + mtd->writesize =1 ; + mtd->flags =MTD_CAP_NORFLASH ; + +if (info->flags &E_FSR ) + nor->flags |=SNOR_F_USE_FSR ; + +if (info->flags &SST_WR ) + nor->flags |=SNOR_F_SST_WRITE ; + + ops->write = spi_nor_mwrite; + +/* compute the flash size */ + nor->page_size = info->page_size; +/* +* The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
+ *0x4d00Extended JEDEC code. The rest of the Spansion flashes
with
+ * the0x4d00Extended JEDEC code have 512b pages. All of the
othersdrivers/mtd/spi-nor/spi-nor.c new file +45
-0+* have 256b pages. +*/ +if (JEDEC_EXT (info) ==0x4d00 ) { +if ((JEDEC_ID (info) !=0x0215 ) && + (JEDEC_ID (info) !=0x0216 )) + nor->page_size =512 ; + } + mtd->writebufsize = nor->page_size; + mtd->size = info->sector_size * info->n_sectors; + +#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS +/* prefer "small sector" erase if possible */ +if (info->flags &SECT_4K ) { + nor->erase_opcode =SNOR_OP_BE_4K ; + mtd->erasesize =4096 ; + } else +#endif + { + nor->erase_opcode =SNOR_OP_SE ; + mtd->erasesize = info->sector_size; + } + +/* Look for read opcode */ + nor->read_opcode =SNOR_OP_READ_FAST ; +if (nor->mode &SNOR_READ ) + nor->read_opcode =SNOR_OP_READ ; +else if (nor->mode &SNOR_READ_1_1_4 && info->flags &RD_QUAD ) + nor->read_opcode =SNOR_OP_READ_1_1_4 ; +else if (nor->mode &SNOR_READ_1_1_2 && info->flags &RD_DUAL ) + nor->read_opcode =SNOR_OP_READ_1_1_2 ; + +/* Look for program opcode */ +if (info->flags &WR_QPP && nor->mode &SNOR_WRITE_1_1_4 ) + nor->program_opcode =SNOR_OP_QPP ; +else +/* Go for default supported write cmd */ + nor->program_opcode =SNOR_OP_PP ; + +/* Set the quad enable bit - only for quad commands */ +if ((nor->read_opcode ==SNOR_OP_READ_1_1_4 ) || + (nor->read_opcode ==SNOR_OP_READ_1_1_4_IO ) || + (nor->program_opcode ==SNOR_OP_QPP )) { + ret =set_quad_mode (nor->dev, info); +if (ret) { + debug("spi-nor: quad mode not supported for%02x\n",
drivers/mtd/spi-nor/spi-nor.c new file +20
-0+ JEDEC_MFR(info)); + goto err; + } + } + + nor->addr_width =3 ; + +/* Dummy cycles for read */ +switch (nor->read_opcode) { +case SNOR_OP_READ_1_1_4_IO : + nor->read_dummy =16 ; +break ; +case SNOR_OP_READ : + nor->read_dummy =0 ; +break ; +default : + nor->read_dummy =8 ; + } + +#if CONFIG_IS_ENABLED (OF_CONTROL )
drivers/mtd/spi-nor/spi-nor.c line 566
Quoted 10 lines
drivers/mtd/spi-nor/spi-nor.c new file +10
-0+ ret =spi_nor_decode_fdt (gd->fdt_blob, nor); +if (ret) { +debug ("spi-nor: FDT decode error\n" ); + goto err; + } +#endif + + nor->init_done =1 ; +return 0 ; +err:
trailing whitespace
Quoted 259 lines
drivers/mtd/spi-nor/spi-nor.c new file +3
-0+ nor->init_done =0 ; +return ret; +}include/dm/uclass-id.h +1
-0@@ -75,6 +75,7 @@ enum uclass_id {UCLASS_SERIAL ,/* Serial UART */ UCLASS_SPI ,/* SPI bus */ UCLASS_SPMI ,/* System Power Management Interface bus */ +UCLASS_SPI_NOR ,/* SPI NOR flash */ UCLASS_SPI_FLASH ,/* SPI flash */ UCLASS_SPI_GENERIC ,/* Generic SPI flash target */ UCLASS_SYSCON, /* System configuration device */include/linux/mtd/spi-nor.h new file +18
-0@@ -0,0 +1,217 @@ +/* +* SPI NOR Core header file. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef __MTD_SPI_NOR_H +#define __MTD_SPI_NOR_H + +#include <common.h> +#include <linux/mtd/mtd.h> + +/* +* Manufacturer IDs +* +* The first byte returned from the flash after sending opcode
SPINOR_OP_RDID.
+ * Sometimes these are the same as CFI IDs, but sometimes they aren't.
+ */include/linux/mtd/spi-nor.h new file +12
-0+#define SNOR_MFR_ATMEL 0x1f +#define SNOR_MFR_MACRONIX 0xc2 +#define SNOR_MFR_MICRON 0x20/* ST Micro <--> Micron */ +#define SNOR_MFR_SPANSION 0x01 +#define SNOR_MFR_SST 0xbf +#define SNOR_MFR_WINBOND 0xef + +/** +* SPI NOR opcodes. +* +* Note on opcode nomenclature: some opcodes have a format like +* SNOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
+ * of I/O lines used for the opcode, address, and data (respectively). The
+ * FUNCTION has an optional suffix of '4', to represent an opcode which
+ * requires a 4-byte (32-bit) address.
+ */include/linux/mtd/spi-nor.h new file +5
-0+#define SNOR_OP_WRDI 0x04/* Write disable */ +#define SNOR_OP_WREN 0x06/* Write enable */ +#define SNOR_OP_RDSR 0x05/* Read status register */ +#define SNOR_OP_WRSR 0x01/* Write status register 1 byte */ +#define SNOR_OP_READ 0x03/* Read data bytes (low frequency) */
+#defineSNOR_OP_READ_FAST0x0b/* Read data bytes (high
frequency) */include/linux/mtd/spi-nor.h new file +7
-0+#define SNOR_OP_READ_1_1_2 0x3b/* Read data bytes (Dual SPI) */ +#define SNOR_OP_READ_1_1_2_IO 0xbb/* Read data bytes (Dual IO SPI) */ +#define SNOR_OP_READ_1_1_4 0x6b/* Read data bytes (Quad SPI) */ +#define SNOR_OP_READ_1_1_4_IO 0xeb/* Read data bytes (Quad IO SPI) */ +#define SNOR_OP_BRWR 0x17/* Bank register write */ +#define SNOR_OP_BRRD 0x16/* Bank register read */ +#define SNOR_OP_WREAR 0xC5/* Write extended address register */
+#defineSNOR_OP_RDEAR0xC8/* Read extended address register
*/
+#defineSNOR_OP_PP0x02/* Page program (up to 256 bytes)
*/include/linux/mtd/spi-nor.h new file +13
-0+#define SNOR_OP_QPP 0x32/* Quad Page program */ +#define SNOR_OP_BE_4K 0x20/* Erase 4KiB block */ +#define SNOR_OP_BE_4K_PMC 0xd7/* Erase 4KiB block on PMC chips */ +#define SNOR_OP_BE_32K 0x52/* Erase 32KiB block */ +#define SPINOR_OP_CHIP_ERASE 0xc7/* Erase whole flash chip */ +#define SNOR_OP_SE 0xd8/* Sector erase (usually 64KiB) */ +#define SNOR_OP_RDID 0x9f/* Read JEDEC ID */ +#define SNOR_OP_RDCR 0x35/* Read configuration register */ +#define SNOR_OP_RDFSR 0x70/* Read flag status register */ + +/* Used for SST flashes only. */ +#define SNOR_OP_BP 0x02/* Byte program */ +#define SNOR_OP_AAI_WP 0xad/* Auto addr increment word program */
include/linux/mtd/spi-nor.h new file +18
-0+ +/* Status Register bits. */ +#define SR_WIP BIT(0)/* Write in progress */ +#define SR_WEL BIT(1)/* Write enable latch */ + +/* meaning of other SR_* bits may differ between vendors */ +#define SR_BP0 BIT(2)/* Block protect 0 */ +#define SR_BP1 BIT(3)/* Block protect 1 */ +#define SR_BP2 BIT(4)/* Block protect 2 */ +#define SR_SRWD BIT(7)/* SR write protect */ + +#define SR_QUAD_EN_MX BIT(6)/* Macronix Quad I/O */ + +/* Flag Status Register bits */ +#define FSR_READY BIT(7) + +/* Configuration Register bits. */ +#define CR_QUAD_EN_SPAN BIT(1)/* Spansion/Winbond Quad I/O */
include/linux/mtd/spi-nor.h new file +9
-0+ +/* Flash timeout values */ +#define SNOR_READY_WAIT_PROG (2 * CONFIG_SYS_HZ) +#define SNOR_READY_WAIT_ERASE (5 * CONFIG_SYS_HZ) +#define SNOR_MAX_CMD_SIZE 4 +#define SNOR_16MB_BOUN 0x1000000 + +/** +* struct spi_nor_uclass_priv - Holds information about a device used by the uclass
+ */include/linux/mtd/spi-nor.h new file +23
-0+struct spi_nor_uclass_priv { +struct spi_nor *spi_nor; +}; + +enum snor_option_flags { +SNOR_F_SST_WRITE =BIT (0 ), +SNOR_F_USE_FSR =BIT (1 ), +SNOR_F_U_PAGE =BIT (1 ), +}; + +enum mode { +SNOR_READ =BIT (0 ), +SNOR_READ_1_1_2 =BIT (1 ), +SNOR_READ_1_1_4 =BIT (2 ), +SNOR_READ_1_1_2_IO =BIT (3 ), +SNOR_READ_1_1_4_IO =BIT (4 ), +SNOR_WRITE_1_1_BYTE =BIT (5 ), +SNOR_WRITE_1_1_4 =BIT (6 ), +}; + +#define JEDEC_MFR (info) ((info)->id[0]) +#define JEDEC_ID (info) (((info)->id[1]) << 8 | ((info)->id[2])) +#define JEDEC_EXT (info) (((info)->id[3]) << 8 |((info)->id[4]))
include/linux/mtd/spi-nor.h new file +31
-0+#define SPI_NOR_MAX_ID_LEN 6 + +struct spi_nor_info { +char *name; + +/* +* This array stores the ID bytes. +* The first three bytes are the JEDIC ID. +* JEDEC ID zero means "no ID" (mostly older chips). +*/ +u8 id[SPI_NOR_MAX_ID_LEN ]; +u8 id_len; + +/* The size listed here is what works with SNOR_OP_SE, which isn't +* necessarily called a "sector" by the vendor. +*/ +unsigned sector_size; +u16 n_sectors; + +u16 page_size; + +u16 flags; +#define SECT_4K BIT(0) +#define E_FSR BIT(1) +#define SST_WR BIT(2) +#define WR_QPP BIT(3) +#define RD_QUAD BIT(4) +#define RD_DUAL BIT(5) +#define RD_QUADIO BIT(6) +#define RD_DUALIO BIT(7) +#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO |
RD_DUALIO)include/linux/mtd/spi-nor.h new file +14
-0+}; + +extern const struct spi_nor_info spi_nor_ids[]; + +/** +* struct spi_nor - Structure for defining a the SPI NOR layer +* +* @dev: SPI NOR device +* @name: name of the SPI NOR device +* @page_size: the page size of the SPI NOR +* @addr_width: number of address bytes +* @erase_opcode: the opcode for erasing a sector +* @read_opcode: the read opcode +* @read_dummy: the dummy bytes needed by the read operation
+ * @program_opcode: the program opcode + * @max_write_size: If non-zero, the maximum number of bytes which can + * be written at once, excluding command bytes. + * @flags: flag options for the current SPI-NOR (SNOR_F_*) + * @mode: read, write mode or any other mode bits. + * @read_mode: read mode. + * @cmd_buf: used by the write_reg + * @read_reg: [DRIVER-SPECIFIC] read out the register + * @write_reg: [DRIVER-SPECIFIC] write data to the register + * @read: [DRIVER-SPECIFIC] read data from the SPI NOR + * @write: [DRIVER-SPECIFIC] write data to the SPI NOR + * @memory_map: address of read-only SPI NOR access+ */
include/linux/mtd/spi-nor.h new file +44
-1+struct spi_nor { +struct udevice *dev; +const char *name; +u8 init_done; +u32 page_size; +u8 addr_width; +u8 erase_opcode; +u8 read_opcode; +u8 read_dummy; +u8 program_opcode; +u32 max_write_size; +u32 flags; +u8 mode; +u8 read_mode; +u8 cmd_buf[SNOR_MAX_CMD_SIZE ]; + +void *memory_map; +}; + +struct spi_nor_ops { +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)(struct udevice *dev,loff_t from,size_t len, +u_char *buf); +int (*write)(struct udevice *dev,loff_t to,size_t len, +const u_char *buf); +}; + +#define spi_nor_get_ops (dev) ((struct spi_nor_ops *)(dev)->driver->ops) + +int spi_nor_merase (struct udevice *dev,struct erase_info *instr); +int spi_nor_mread (struct udevice *dev,loff_t from,size_t len, +size_t *retlen,u_char *buf); + +int spi_nor_scan (struct spi_nor *nor); +int spi_nor_bind (struct udevice *dev,struct spi_nor *nor); + +struct spi_nor *find_spi_nor_device (int dev_num); +int get_spi_nor_num (void ); +struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev); +struct mtd_info *spi_nor_get_mtd_info (struct spi_nor *nor); + +#endif /* __MTD_SPI_NOR_H */ --2.7.4
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
PATCH v10 3/27 mtd: add SPI-NOR core support
In reply to Jagan TekiHi Jagan,
Quoted 39 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:42 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core supportSome of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cThe problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================#####SPI NOR chip######=======================================
<snip>
Quoted 92 lines
+ * SPDX-License-Identifier: GPL-2.0+
+ */(quoted diff) +90
-0+ +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <mapmem.h> +#include <mtd.h> + +#include <dm/device-internal.h> +#include <linux/math64.h> +#include <linux/types.h> +#include <linux/mtd/spi-nor.h> + +int spi_nor_scan(struct spi_nor *nor) +{ + struct mtd_info *mtd = spi_nor_get_mtd_info(nor); + struct mtd_ops *ops = mtd_get_ops(mtd->dev); + const struct spi_nor_info *info = NULL; + int ret; + + struct spi_nor_uclass_priv *upriv = dev_get_uclass_priv(nor->dev); + upriv->spi_nor = nor; + + if (nor->init_done) + return 0; + + info = spi_nor_id(nor->dev); + if (IS_ERR_OR_NULL(info)) { + ret = -ENOENT; + goto err; + } + + /* + * Flash powers up read-only, so clear BP# bits. + * + * Note on some flash (like Macronix), QE (quad enable) bit is in the + * same status register as BP# bits, and we need preserve its original + * value during a reboot cycle as this is required by some platforms + * (like Intel ICH SPI controller working under descriptor mode). + */ + if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || + (JEDEC_MFR(info) == SNOR_MFR_SST) || + (JEDEC_MFR(info) == SNOR_MFR_MACRONIX)) { + u8 sr = 0; + + if (JEDEC_MFR(info) == SNOR_MFR_MACRONIX) + sr = read_sr(nor->dev) & SR_QUAD_EN_MX; + write_sr(nor->dev, sr); + } + + mtd->name = info->name; + mtd->priv = nor; + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; + + if (info->flags & E_FSR) + nor->flags |= SNOR_F_USE_FSR; + + if (info->flags & SST_WR) + nor->flags |= SNOR_F_SST_WRITE; + + ops->write = spi_nor_mwrite; + + /* compute the flash size */ + nor->page_size = info->page_size; + /* + * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the + * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with + * the 0x4d00 Extended JEDEC code have 512b pages. All of the others + * have 256b pages. + */ + if (JEDEC_EXT(info) == 0x4d00) { + if ((JEDEC_ID(info) != 0x0215) && + (JEDEC_ID(info) != 0x0216)) + nor->page_size = 512; + } + mtd->writebufsize = nor->page_size; + mtd->size = info->sector_size * info->n_sectors; + +#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + /* prefer "small sector" erase if possible */ + if (info->flags & SECT_4K) { + nor->erase_opcode = SNOR_OP_BE_4K; + mtd->erasesize = 4096; + } else +#endif + { + nor->erase_opcode = SNOR_OP_SE; + mtd->erasesize = info->sector_size; + }
Review
Quoted 10 lines
(quoted diff) +10
-0+ + /* Look for read opcode */ + nor->read_opcode = SNOR_OP_READ_FAST; + if (nor->mode & SNOR_READ) + nor->read_opcode = SNOR_OP_READ; + else if (nor->mode & SNOR_READ_1_1_4 && info->flags & RD_QUAD) + nor->read_opcode = SNOR_OP_READ_1_1_4; + else if (nor->mode & SNOR_READ_1_1_2 && info->flags & RD_DUAL) + nor->read_opcode = SNOR_OP_READ_1_1_2; +
Are you planning to store read_protocol i.e. 1-1-1. 1-1-2, 1-4-4, 4-4-4 etc information in nor structure?
It will help low level controller driver to configure number of lines to be used during read in instruction, address and data phase.
Similar framework is present in Linux.
struct spi_nor :
* @read_proto: the SPI protocol for read operations
* @write_proto: the SPI protocol for write operations
* @reg_proto the SPI protocol for read_reg/write_reg/erase operations
--pk
PATCH v10 3/27 mtd: add SPI-NOR core support
Quoted 152 lines · Prabhakar Kushwaha
Hi Jagan,
Quoted 39 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:42 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core supportSome of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cThe problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================#####SPI NOR chip######=======================================
<snip>
Quoted 92 lines
+ * SPDX-License-Identifier: GPL-2.0+
+ */(quoted diff) +90
-0+ +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <mapmem.h> +#include <mtd.h> + +#include <dm/device-internal.h> +#include <linux/math64.h> +#include <linux/types.h> +#include <linux/mtd/spi-nor.h> + +int spi_nor_scan(struct spi_nor *nor) +{ + struct mtd_info *mtd = spi_nor_get_mtd_info(nor); + struct mtd_ops *ops = mtd_get_ops(mtd->dev); + const struct spi_nor_info *info = NULL; + int ret; + + struct spi_nor_uclass_priv *upriv = dev_get_uclass_priv(nor->dev); + upriv->spi_nor = nor; + + if (nor->init_done) + return 0; + + info = spi_nor_id(nor->dev); + if (IS_ERR_OR_NULL(info)) { + ret = -ENOENT; + goto err; + } + + /* + * Flash powers up read-only, so clear BP# bits. + * + * Note on some flash (like Macronix), QE (quad enable) bit is in the + * same status register as BP# bits, and we need preserve its original + * value during a reboot cycle as this is required by some platforms + * (like Intel ICH SPI controller working under descriptor mode). + */ + if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || + (JEDEC_MFR(info) == SNOR_MFR_SST) || + (JEDEC_MFR(info) == SNOR_MFR_MACRONIX)) { + u8 sr = 0; + + if (JEDEC_MFR(info) == SNOR_MFR_MACRONIX) + sr = read_sr(nor->dev) & SR_QUAD_EN_MX; + write_sr(nor->dev, sr); + } + + mtd->name = info->name; + mtd->priv = nor; + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; + + if (info->flags & E_FSR) + nor->flags |= SNOR_F_USE_FSR; + + if (info->flags & SST_WR) + nor->flags |= SNOR_F_SST_WRITE; + + ops->write = spi_nor_mwrite; + + /* compute the flash size */ + nor->page_size = info->page_size; + /* + * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the + * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with + * the 0x4d00 Extended JEDEC code have 512b pages. All of the others + * have 256b pages. + */ + if (JEDEC_EXT(info) == 0x4d00) { + if ((JEDEC_ID(info) != 0x0215) && + (JEDEC_ID(info) != 0x0216)) + nor->page_size = 512; + } + mtd->writebufsize = nor->page_size; + mtd->size = info->sector_size * info->n_sectors; + +#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + /* prefer "small sector" erase if possible */ + if (info->flags & SECT_4K) { + nor->erase_opcode = SNOR_OP_BE_4K; + mtd->erasesize = 4096; + } else +#endif + { + nor->erase_opcode = SNOR_OP_SE; + mtd->erasesize = info->sector_size; + }Review
Quoted 10 lines
(quoted diff) +10
-0+ + /* Look for read opcode */ + nor->read_opcode = SNOR_OP_READ_FAST; + if (nor->mode & SNOR_READ) + nor->read_opcode = SNOR_OP_READ; + else if (nor->mode & SNOR_READ_1_1_4 && info->flags & RD_QUAD) + nor->read_opcode = SNOR_OP_READ_1_1_4; + else if (nor->mode & SNOR_READ_1_1_2 && info->flags & RD_DUAL) + nor->read_opcode = SNOR_OP_READ_1_1_2; +Are you planning to store
read_protocoli.e. 1-1-1. 1-1-2, 1-4-4, 4-4-4 etc information in nor structure?
It will help low level controller driver to configure number of lines to be used during read in instruction, address and data phase.
Quoted 6 lines
Similar framework is present in Linux.
struct
spi_nor:* @read_proto: the SPI protocol for read operations * @write_proto: the SPI protocol for write operations * @reg_proto the SPI protocol for read_reg/write_reg/erase operations
ok try these and mention code sizes for the same.
Vignesh R
maintainerPATCH v10 3/27 mtd: add SPI-NOR core support
In reply to Jagan TekiOn Thursday 28 December 2017 11:42 AM, Jagan Teki wrote:
[...]
drivers/mtd/spi-nor/spi-nor-uclass.c line 125
Quoted 5 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +5
-0+static const struct mtd_ops spi_nor_mtd_ops = { + .read = spi_nor_mread, + .erase = spi_nor_merase, +}; +
Wondering why spi_nor_mwrite is not hooked up here?
Quoted 18 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +18
-0+U_BOOT_DRIVER (spinor_mtd) = { + .name ="spinor_mtd" , + .id =UCLASS_MTD , + .ops = &spi_nor_mtd_ops, + .probe = spi_nor_mtd_probe, +}; + +U_BOOT_DRIVER (spinor) = { + .name ="spinor" , + .id =UCLASS_SPI_NOR , +}; + +UCLASS_DRIVER (spinor) = { + .id =UCLASS_SPI_NOR , + .name ="spinor" , + .flags =DM_UC_FLAG_SEQ_ALIAS , + .per_device_auto_alloc_size =sizeof (struct spi_nor_uclass_priv ), +};
[...]
Quoted 6 lines
include/linux/mtd/spi-nor.h new file +0
-0@@ -0,0 +1,217 @@
[...]
Quoted 5 lines
include/linux/mtd/spi-nor.h new file +5
-0+struct spi_nor { +struct udevice *dev; +const char *name; +u8 init_done; +u32 page_size;
include/linux/mtd/spi-nor.h line 187
Quoted 10 lines
include/linux/mtd/spi-nor.h new file +9
-0+u8 addr_width; +u8 erase_opcode; +u8 read_opcode; +u8 read_dummy; +u8 program_opcode; +u32 max_write_size; +u32 flags; +u8 mode; +u8 read_mode;
Where is this field used? Shouldn't this field carry single/dual/quad mode information?
Quoted 31 lines
include/linux/mtd/spi-nor.h new file +30
-0+u8 cmd_buf[SNOR_MAX_CMD_SIZE ]; + +void *memory_map; +}; + +struct spi_nor_ops { +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)(struct udevice *dev,loff_t from,size_t len, +u_char *buf); +int (*write)(struct udevice *dev,loff_t to,size_t len, +const u_char *buf); +}; + +#define spi_nor_get_ops (dev) ((struct spi_nor_ops *)(dev)->driver->ops) + +int spi_nor_merase (struct udevice *dev,struct erase_info *instr); +int spi_nor_mread (struct udevice *dev,loff_t from,size_t len, +size_t *retlen,u_char *buf); + +int spi_nor_scan (struct spi_nor *nor); +int spi_nor_bind (struct udevice *dev,struct spi_nor *nor); + +struct spi_nor *find_spi_nor_device (int dev_num); +int get_spi_nor_num (void ); +struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev); +struct mtd_info *spi_nor_get_mtd_info (struct spi_nor *nor); + +#endif /* __MTD_SPI_NOR_H */
Signature · 2 lines
Regards Vignesh
PATCH v10 3/27 mtd: add SPI-NOR core support
Quoted 11 lines · Vignesh R
On Thursday 28 December 2017 11:42 AM, Jagan Teki wrote:
[...]drivers/mtd/spi-nor/spi-nor-uclass.c line 125
Quoted 5 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +5
-0+static const struct mtd_ops spi_nor_mtd_ops = { + .read = spi_nor_mread, + .erase = spi_nor_merase, +}; +Wondering why
spi_nor_mwriteis not hooked up here?
yes, because of sst we need to assign the write hook during scan, see spi-nor.c
Quoted 43 lines
Quoted 19 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +18
-0+U_BOOT_DRIVER (spinor_mtd) = { + .name ="spinor_mtd" , + .id =UCLASS_MTD , + .ops = &spi_nor_mtd_ops, + .probe = spi_nor_mtd_probe, +}; + +U_BOOT_DRIVER (spinor) = { + .name ="spinor" , + .id =UCLASS_SPI_NOR , +}; + +UCLASS_DRIVER (spinor) = { + .id =UCLASS_SPI_NOR , + .name ="spinor" , + .flags =DM_UC_FLAG_SEQ_ALIAS , + .per_device_auto_alloc_size =sizeof (struct spi_nor_uclass_priv ), +};[...]
Quoted 6 lines
include/linux/mtd/spi-nor.h new file +0
-0@@ -0,0 +1,217 @@[...]
Quoted 13 lines
include/linux/mtd/spi-nor.h new file +13
-0+struct spi_nor { +struct udevice *dev; +const char *name; +u8 init_done; +u32 page_size; +u8 addr_width; +u8 erase_opcode; +u8 read_opcode; +u8 read_dummy; +u8 program_opcode; +u32 max_write_size; +u32 flags; +u8 mode;
Quoted 4 lines
Quoted 1 line
+ u8
read_mode;Where is this field used? Shouldn't this field carry single/dual/quad mode information?
I think it came up from previous versions, no real use as of now will check and update in next version
thanks!
Signature · 4 lines
Jagan Teki Free Software Engineer | www.openedev.com U-Boot, Linux | Upstream Maintainer Hyderabad, India.
Vignesh R
maintainerPATCH v10 3/27 mtd: add SPI-NOR core support
Quoted 58 lines · Jagan Teki
Quoted 11 lines · Vignesh R
On Thursday 28 December 2017 11:42 AM, Jagan Teki wrote:
[...]drivers/mtd/spi-nor/spi-nor-uclass.c line 125
Quoted 5 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +5
-0+static const struct mtd_ops spi_nor_mtd_ops = { + .read = spi_nor_mread, + .erase = spi_nor_merase, +}; +Wondering why
spi_nor_mwriteis not hooked up here?yes, because of sst we need to assign the write hook during scan, see
spi-nor.cQuoted 43 lines
Quoted 19 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +18
-0+U_BOOT_DRIVER (spinor_mtd) = { + .name ="spinor_mtd" , + .id =UCLASS_MTD , + .ops = &spi_nor_mtd_ops, + .probe = spi_nor_mtd_probe, +}; + +U_BOOT_DRIVER (spinor) = { + .name ="spinor" , + .id =UCLASS_SPI_NOR , +}; + +UCLASS_DRIVER (spinor) = { + .id =UCLASS_SPI_NOR , + .name ="spinor" , + .flags =DM_UC_FLAG_SEQ_ALIAS , + .per_device_auto_alloc_size =sizeof (struct spi_nor_uclass_priv ), +};[...]
Quoted 6 lines
include/linux/mtd/spi-nor.h new file +0
-0@@ -0,0 +1,217 @@[...]
Quoted 13 lines
include/linux/mtd/spi-nor.h new file +13
-0+struct spi_nor { +struct udevice *dev; +const char *name; +u8 init_done; +u32 page_size; +u8 addr_width; +u8 erase_opcode; +u8 read_opcode; +u8 read_dummy; +u8 program_opcode; +u32 max_write_size; +u32 flags; +u8 mode;
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
+ u8
read_mode;Where is this field used? Shouldn't this field carry single/dual/quad mode information?
I think it came up from previous versions, no real use as of now will check and update in next version
This field is very much needed to inform SPI NOR controllers where to use 1-1-2 or 1-1-4 or 1-1-1 mode for reading data from flash. It should be the SPI NOR framework providing this info and not expecting driver to assume this or infer from DT.
Signature · 2 lines
Regards Vignesh
PATCH v10 3/27 mtd: add SPI-NOR core support
Quoted 66 lines · Vignesh R
Quoted 63 lines · Jagan Teki
Quoted 11 lines · Vignesh R
On Thursday 28 December 2017 11:42 AM, Jagan Teki wrote:
[...]drivers/mtd/spi-nor/spi-nor-uclass.c line 125
Quoted 5 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +5
-0+static const struct mtd_ops spi_nor_mtd_ops = { + .read = spi_nor_mread, + .erase = spi_nor_merase, +}; +Wondering why
spi_nor_mwriteis not hooked up here?yes, because of sst we need to assign the write hook during scan, see
spi-nor.cQuoted 47 lines
Quoted 19 lines
drivers/mtd/spi-nor/spi-nor-uclass.c new file +18
-0+U_BOOT_DRIVER (spinor_mtd) = { + .name ="spinor_mtd" , + .id =UCLASS_MTD , + .ops = &spi_nor_mtd_ops, + .probe = spi_nor_mtd_probe, +}; + +U_BOOT_DRIVER (spinor) = { + .name ="spinor" , + .id =UCLASS_SPI_NOR , +}; + +UCLASS_DRIVER (spinor) = { + .id =UCLASS_SPI_NOR , + .name ="spinor" , + .flags =DM_UC_FLAG_SEQ_ALIAS , + .per_device_auto_alloc_size =sizeof (struct spi_nor_uclass_priv ), +};[...]
Quoted 6 lines
include/linux/mtd/spi-nor.h new file +0
-0@@ -0,0 +1,217 @@[...]
Quoted 5 lines
include/linux/mtd/spi-nor.h new file +5
-0+struct spi_nor { +struct udevice *dev; +const char *name; +u8 init_done; +u32 page_size;include/linux/mtd/spi-nor.h line 187
Quoted 10 lines
include/linux/mtd/spi-nor.h new file +9
-0+u8 addr_width; +u8 erase_opcode; +u8 read_opcode; +u8 read_dummy; +u8 program_opcode; +u32 max_write_size; +u32 flags; +u8 mode; +u8 read_mode;Where is this field used? Shouldn't this field carry single/dual/quad mode information?
Quoted 7 lines
Quoted 2 lines
I think it came up from previous versions, no real use as of now will check and update in next version
This field is very much needed to inform SPI NOR controllers where to use 1-1-2 or 1-1-4 or 1-1-1 mode for reading data from flash. It should be the SPI NOR framework providing this info and not expecting driver to assume this or infer from DT.
yes remember, we have common mode(for both read and write) ie initialized and used in spi-nor instead have read_mode.
PATCH v10 3/27 mtd: add SPI-NOR core support
In reply to Jagan TekiHi Jagan:
2017-12-28 14:12 GMT+08:00 Jagan Teki <[email protected]>:
Quoted 710 lines
Some of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cThe problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================#####SPI NOR chip######=======================================
Signed-off-by Suneel Garapati <[email protected]>Signed-off-by Jagan Teki <[email protected]>--- Makefile | 1 + drivers/mtd/spi-nor/Makefile | 7 + drivers/mtd/spi-nor/spi-nor-ids.c | 184 +++++++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 143 +++++++++ drivers/mtd/spi-nor/spi-nor.c | 569 ++++++++++++++++++++++++++++++ +++++ include/dm/uclass-id.h | 1 + include/linux/mtd/spi-nor.h | 217 +++++++++++++ 7 files changed, 1122 insertions(+) create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/spi-nor-ids.c create mode 100644 drivers/mtd/spi-nor/spi-nor-uclass.c create mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 include/linux/mtd/spi-nor.hMakefile +1
-0@@ -662,6 +662,7 @@ libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/ libs-y += drivers/mtd/onenand/ libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/ libs-y += drivers/mtd/spi/ +libs-y += drivers/mtd/spi-nor/ libs-y += drivers/net/ libs-y += drivers/net/phy/ libs-y += drivers/pci/drivers/mtd/spi-nor/Makefile new file +7
-0@@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Jagan Teki <[email protected]> +# +# SPDX-License-Identifier: GPL-2.0+ + +## spi-nor core +obj-y += spi-nor.o spi-nor-uclass.o spi-nor-ids.odrivers/mtd/spi-nor/spi-nor-ids.c new file +49
-0@@ -0,0 +1,184 @@ +/* +* SPI NOR IDs. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <linux/mtd/spi-nor.h> + +/* Used when the "_ext_id" is two bytes at most */ +#define INFO (_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + .id = { \ + ((_jedec_id) >> 16) & 0xff, \ + ((_jedec_id) >> 8) & 0xff, \ + (_jedec_id) & 0xff, \ + ((_ext_id) >> 8) & 0xff, \ + (_ext_id) & 0xff, \ + }, \ + .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), + +#define INFO6 (_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + .id = { \ + ((_jedec_id) >> 16) & 0xff, \ + ((_jedec_id) >> 8) & 0xff, \ + (_jedec_id) & 0xff, \ + ((_ext_id) >> 16) & 0xff, \ + ((_ext_id) >> 8) & 0xff, \ + (_ext_id) & 0xff, \ + }, \ + .id_len = 6, \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), + +const struct spi_nor_info spi_nor_ids[] = { +#ifdef CONFIG_SPI_NOR_MACRONIX /* MACRONIX */ + {"mx25l2006e" ,INFO (0xc22012 ,0x0 ,64 *1024 ,4 ,0 ) }, + {"mx25l4005" ,INFO (0xc22013 ,0x0 ,64 *1024 ,8 ,0 ) }, + {"mx25l8005" ,INFO (0xc22014 ,0x0 ,64 *1024 ,16 ,0 ) }, + {"mx25l1605d" ,INFO (0xc22015 ,0x0 ,64 *1024 ,32 ,0 ) }, + {"mx25l3205d" ,INFO (0xc22016 ,0x0 ,64 *1024 ,64 ,0 ) }, + {"mx25l6405d" ,INFO (0xc22017 ,0x0 ,64 *1024 ,128 ,0 ) }, + {"mx25l12805", INFO(0xc22018, 0x0, 64 * 1024, 256, RD_FULL |
WR_QPP) },
+ {"mx25l25635f", INFO(0xc22019,0x0, 64 * 1024, 512,RD_FULL|WR_QPP) },
+ {"mx25l51235f", INFO(0xc2201a,0x0, 64 * 1024, 1024,RD_FULL|WR_QPP) },
+ {"mx25u6435f", INFO(0xc22537,0x0, 64 * 1024, 128,RD_FULL|WR_QPP) },
+ {"mx25l12855e", INFO(0xc22618,0x0, 64 * 1024, 256,RD_FULL|WR_QPP) },drivers/mtd/spi-nor/spi-nor-ids.c new file +2
-0+ {"mx25u1635e", INFO(0xc22535, 0x0, 64 * 1024, 32, SECT_4K) }, + {"mx66u51235f", INFO(0xc2253a, 0x0, 64 * 1024, 1024, RD_FULL |
WR_QPP) },
+ {"mx66l1g45g", INFO(0xc2201b,0x0, 64 * 1024, 2048,RD_FULL|WR_QPP) },drivers/mtd/spi-nor/spi-nor-ids.c new file +9
-0+#endif +#ifdef CONFIG_SPI_NOR_SPANSION /* SPANSION */ + {"s25fl008a", INFO(0x010213, 0x0, 64 * 1024, 16, 0) }, + {"s25fl016a", INFO(0x010214, 0x0, 64 * 1024, 32, 0) }, + {"s25fl032a", INFO(0x010215, 0x0, 64 * 1024, 64, 0) }, + {"s25fl064a", INFO(0x010216, 0x0, 64 * 1024, 128, 0) }, + {"s25fl116k", INFO(0x014015, 0x0, 64 * 1024, 32, 0) }, + {"s25fl164k", INFO(0x014017, 0x0140, 64 * 1024, 128, 0) }, + {"s25fl128p_256k", INFO(0x012018, 0x0300, 256 * 1024, 64,RD_FULL | WR_QPP) }, + {"s25fl128p_64k", INFO(0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"s25fl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, RD_FULL | WR_QPP) }, + {"s25fl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP) }, + {"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) }, + {"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP) }, + {"s25fs256s_64k", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) }, + {"s25fs512s", INFO6(0x010220, 0x4d0081, 128 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, RD_FULL | WR_QPP) }, + {"s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL | WR_QPP) }, + {"s25fl512s_512k", INFO(0x010220, 0x4f00, 256 * 1024, 256, RD_FULL | WR_QPP) },drivers/mtd/spi-nor/spi-nor-ids.c new file +9
-0+#endif +#ifdef CONFIG_SPI_NOR_STMICRO /* STMICRO */ + {"m25p10", INFO(0x202011, 0x0, 32 * 1024, 4, 0) }, + {"m25p20", INFO(0x202012, 0x0, 64 * 1024, 4, 0) }, + {"m25p40", INFO(0x202013, 0x0, 64 * 1024, 8, 0) }, + {"m25p80", INFO(0x202014, 0x0, 64 * 1024, 16, 0) }, + {"m25p16", INFO(0x202015, 0x0, 64 * 1024, 32, 0) }, + {"m25pE16", INFO(0x208015, 0x1000, 64 * 1024, 32, 0) }, + {"m25pX16", INFO(0x207115, 0x1000, 64 * 1024, 32, RD_QUAD |
RD_DUAL) },drivers/mtd/spi-nor/spi-nor-ids.c new file +4
-0+ {"m25p32", INFO(0x202016, 0x0, 64 * 1024, 64, 0) }, + {"m25p64", INFO(0x202017, 0x0, 64 * 1024, 128, 0) }, + {"m25p128", INFO(0x202018, 0x0, 256 * 1024, 64, 0) }, + {"m25pX64", INFO(0x207117, 0x0, 64 * 1024, 128, SECT_4K)},
+ {"n25q016a",INFO(0x20bb15, 0x0, 64 * 1024, 32, SECT_4K)
},
+ {"n25q32", INFO(0x20ba16,0x0, 64 * 1024, 64,RD_FULL| WR_QPP | SECT_4K) }, + {"n25q32a", INFO(0x20bb16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q64", INFO(0x20ba17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q64a", INFO(0x20bb17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q128", INFO(0x20ba18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"n25q128a", INFO(0x20bb18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"n25q256", INFO(0x20ba19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q256a", INFO(0x20bb19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"n25q512", INFO(0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"n25q512a", INFO(0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"n25q1024", INFO(0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"n25q1024a", INFO(0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"mt25qu02g", INFO(0x20bb22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"mt25ql02g", INFO(0x20ba22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"mt35xu512g", INFO6(0x2c5b1a, 0x104100, 128 * 1024, 512, E_FSR | SECT_4K) },drivers/mtd/spi-nor/spi-nor-ids.c new file +3
-0+#endif +#ifdef CONFIG_SPI_NOR_SST /* SST */ + {"sst25vf040b", INFO(0xbf258d, 0x0, 64 * 1024, 8, SECT_4K|
SST_WR) },
+ {"sst25vf080b", INFO(0xbf258e,0x0, 64 * 1024, 16,SECT_4K
|SST_WR) },
+ {"sst25vf016b", INFO(0xbf2541,0x0, 64 * 1024, 32,SECT_4K
|SST_WR) },
+ {"sst25vf032b", INFO(0xbf254a,0x0, 64 * 1024, 64,SECT_4K
|SST_WR) },
+ {"sst25vf064c",INFO(0xbf254b, 0x0, 64 * 1024, 128, SECT_4K)
},
+ {"sst25wf512", INFO(0xbf2501,0x0, 64 * 1024, 1,SECT_4K
|SST_WR) },
+ {"sst25wf010", INFO(0xbf2502,0x0, 64 * 1024, 2,SECT_4K
|SST_WR) },
+ {"sst25wf020", INFO(0xbf2503,0x0, 64 * 1024, 4,SECT_4K
|SST_WR) },
+ {"sst25wf040", INFO(0xbf2504,0x0, 64 * 1024, 8,SECT_4K
|SST_WR) },
+ {"sst25wf040b",INFO(0x621613, 0x0, 64 * 1024, 8, SECT_4K)
},
+ {"sst25wf080", INFO(0xbf2505,0x0, 64 * 1024, 16,SECT_4K
|SST_WR) },drivers/mtd/spi-nor/spi-nor-ids.c new file +6
-0+#endif +#ifdef CONFIG_SPI_NOR_WINBOND /* WINBOND */ + {"w25p80", INFO(0xef2014, 0x0, 64 * 1024, 16, 0) }, + {"w25p16", INFO(0xef2015, 0x0, 64 * 1024, 32, 0) }, + {"w25p32", INFO(0xef2016, 0x0, 64 * 1024, 64, 0) }, + {"w25x40", INFO(0xef3013, 0x0, 64 * 1024, 8, SECT_4K)},
+ {"w25x16",INFO(0xef3015, 0x0, 64 * 1024, 32, SECT_4K)
},
+ {"w25x32",INFO(0xef3016, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"w25x64",INFO(0xef3017, 0x0, 64 * 1024, 128, SECT_4K)
},
+ {"w25q80bl", INFO(0xef4014,0x0, 64 * 1024, 16,RD_FULL| WR_QPP | SECT_4K) }, + {"w25q16cl", INFO(0xef4015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q32bv", INFO(0xef4016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q64cv", INFO(0xef4017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q128bv", INFO(0xef4018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q256", INFO(0xef4019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q80bw", INFO(0xef5014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q16dw", INFO(0xef6015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q32dw", INFO(0xef6016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q64dw", INFO(0xef6017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, + {"w25q128fw", INFO(0xef6018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) },drivers/mtd/spi-nor/spi-nor-ids.c new file +4
-0+#endif +#ifdef CONFIG_SPI_NOR_MISC +/* ATMEL */ + {"at45db011d" ,INFO (0x1f2200 ,0x0 ,64 *1024 ,4 ,SECT_4K )},
+ {"at45db021d",INFO(0x1f2300, 0x0, 64 * 1024, 8, SECT_4K)
},
+ {"at45db041d",INFO(0x1f2400, 0x0, 64 * 1024, 8, SECT_4K)
},
+ {"at45db081d",INFO(0x1f2500, 0x0, 64 * 1024, 16, SECT_4K)
},
+ {"at45db161d",INFO(0x1f2600, 0x0, 64 * 1024, 32, SECT_4K)
},
+ {"at45db321d",INFO(0x1f2700, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"at45db641d",INFO(0x1f2800, 0x0, 64 * 1024, 128, SECT_4K)
},
+ {"at25df321a",INFO(0x1f4701, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"at25df321",INFO(0x1f4700, 0x0, 64 * 1024, 64, SECT_4K)
},
+ {"at26df081a",INFO(0x1f4501, 0x0, 64 * 1024, 16, SECT_4K)
},drivers/mtd/spi-nor/spi-nor-ids.c new file +4
-0+ +/* EON */ + {"en25q32b", INFO(0x1c3016, 0x0, 64 * 1024, 64, 0) }, + {"en25q64", INFO(0x1c3017, 0x0, 64 * 1024, 128, SECT_4K)},
drivers/mtd/spi-nor/spi-nor-ids.c new file +5
-0+ {"en25q128b", INFO(0x1c3018, 0x0, 64 * 1024, 256, 0) }, + {"en25s64", INFO(0x1c3817, 0x0, 64 * 1024, 128, 0) }, + +/* GIGADEVICE */ + {"gd25q64b", INFO(0xc84017, 0x0, 64 * 1024, 128, SECT_4K)},
+ {"gd25lq32",INFO(0xc86016, 0x0, 64 * 1024, 64, SECT_4K)
},drivers/mtd/spi-nor/spi-nor-ids.c new file +22
-0+ + /* ISSI */ + {"is25lq040b", INFO(0x9d4013, 0x0, 64 * 1024, 8, 0) }, + {"is25lp032", INFO(0x9d6016, 0x0, 64 * 1024, 64, 0) }, + {"is25lp064", INFO(0x9d6017, 0x0, 64 * 1024, 128, 0) }, + {"is25lp128", INFO(0x9d6018, 0x0, 64 * 1024, 256, 0) }, +#endif + {}, /* Empty entry to terminate the list */ + /* + * Note: + * Below paired flash devices has similar spi_nor params. + * (s25fl129p_64k, s25fl128s_64k) + * (w25q80bl, w25q80bv) + * (w25q16cl, w25q16dv) + * (w25q32bv, w25q32fv_spi) + * (w25q64cv, w25q64fv_spi) + * (w25q128bv, w25q128fv_spi) + * (w25q32dw, w25q32fv_qpi) + * (w25q64dw, w25q64fv_qpi) + * (w25q128fw, w25q128fv_qpi) + */ +};drivers/mtd/spi-nor/spi-nor-uclass.c new file +80
-0@@ -0,0 +1,143 @@ +/* +* SPI NOR Core framework. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <mtd.h> + +#include <dm/device-internal.h> +#include <linux/mtd/spi-nor.h> + +DECLARE_GLOBAL_DATA_PTR ; + +struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev) +{ +struct spi_nor_uclass_priv *upriv; + +if (!device_active (dev)) +return NULL ; + upriv =dev_get_uclass_priv (dev); +return upriv->spi_nor; +} + +struct spi_nor *find_spi_nor_device (int dev_num) +{ +struct udevice *dev, *spi_nor_dev; +int ret; + + ret =mtd_find_device (MTD_IF_TYPE_SPI_NOR , dev_num, &dev); +if (ret) { +printf ("SPI-NOR Device %d not found\n" , dev_num); +return NULL ; + } + + spi_nor_dev =dev_get_parent (dev); + +struct spi_nor *nor =spi_nor_get_spi_nor_dev (spi_nor_dev); + +return nor; +} + +int get_spi_nor_num (void ) +{ +return max ((mtd_find_max_devnum (MTD_IF_TYPE_SPI_NOR ) +1 ),0 ); +} + +struct mtd_info *spi_nor_get_mtd_info (struct spi_nor *nor) +{ +struct mtd_info *mtd; +struct udevice *dev; + +device_find_first_child (nor->dev, &dev); +if (!dev) +return NULL ; + mtd =dev_get_uclass_platdata (dev); + +return mtd; +} + +void print_spi_nor_devices (char separator) +{ +struct udevice *dev; +bool first = true; + +for (uclass_first_device (UCLASS_SPI_NOR , &dev); + dev; +uclass_next_device (&dev), first = false) { +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); + +if (!first) { +printf ("%c" , separator); +if (separator !='\n' ) +puts (" " ); + } + + printf("%s: %d", dev->name, spi_nor_get_mtd_info(nor)->devnum);
drivers/mtd/spi-nor/spi-nor-uclass.c new file +14
-0+ } + +printf ("\n" ); +} + +int spi_nor_bind (struct udevice *dev,struct spi_nor *nor) +{ +struct udevice *mdev; +int ret; + +if (!spi_nor_get_ops (dev)) +return -ENOSYS ; + + ret = mtd_create_devicef(dev, "spinor_mtd", "mtd",
MTD_IF_TYPE_SPI_NOR,drivers/mtd/spi-nor/spi-nor-uclass.c new file +14
-0+ &mdev); +if (ret) { +debug ("Cannot create mtd device\n" ); +return ret; + } + nor->dev = dev; + +return 0 ; +} + +static int spi_nor_mtd_probe (struct udevice *dev) +{ +struct udevice *spi_nor_dev =dev_get_parent (dev); + struct spi_nor_uclass_priv *upriv = dev_get_uclass_priv(spi_nor_dev);
drivers/mtd/spi-nor/spi-nor-uclass.c new file +6
-0+struct spi_nor *nor = upriv->spi_nor; +int ret; + + ret =spi_nor_scan (nor); +if (ret) { + debug("%s: spi_nor_scan() failed (err=%d)\n", __func__,ret);
drivers/mtd/spi-nor/spi-nor-uclass.c new file +29
-0+return ret; + } + +return 0 ; +} + +static const struct mtd_ops spi_nor_mtd_ops = { + .read = spi_nor_mread, + .erase = spi_nor_merase, +}; + +U_BOOT_DRIVER (spinor_mtd) = { + .name ="spinor_mtd" , + .id =UCLASS_MTD , + .ops = &spi_nor_mtd_ops, + .probe = spi_nor_mtd_probe, +}; + +U_BOOT_DRIVER (spinor) = { + .name ="spinor" , + .id =UCLASS_SPI_NOR , +}; + +UCLASS_DRIVER (spinor) = { + .id =UCLASS_SPI_NOR , + .name ="spinor" , + .flags =DM_UC_FLAG_SEQ_ALIAS , + .per_device_auto_alloc_size =sizeof (struct spi_nor_uclass_priv ), +};drivers/mtd/spi-nor/spi-nor.c new file +25
-0@@ -0,0 +1,569 @@ +/* +* SPI NOR Core framework. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <mapmem.h> +#include <mtd.h> + +#include <dm/device-internal.h> +#include <linux/math64.h> +#include <linux/types.h> +#include <linux/mtd/spi-nor.h> + +DECLARE_GLOBAL_DATA_PTR ; + +/* Set write enable latch with Write Enable command */ +static inline int write_enable (struct udevice *dev) +{ + return spi_nor_get_ops(dev)->write_reg(dev, SNOR_OP_WREN, NULL,0);
drivers/mtd/spi-nor/spi-nor.c new file +6
-0+} + +/* Re-set write enable latch with Write Disable command */ +static inline int write_disable (struct udevice *dev) +{ + return spi_nor_get_ops(dev)->write_reg(dev, SNOR_OP_WRDI, NULL,0);
drivers/mtd/spi-nor/spi-nor.c new file +110
-0+} + +static int read_sr (struct udevice *dev) +{ +u8 sr; +int ret; + + ret =spi_nor_get_ops (dev)->read_reg (dev,SNOR_OP_RDSR , &sr,1 ); +if (ret <0 ) { +debug ("spi-nor: fail to read status register\n" ); +return ret; + } + +return sr; +} + +static int read_fsr (struct udevice *dev) +{ +u8 fsr; +int ret; + + ret =spi_nor_get_ops (dev)->read_reg (dev,SNOR_OP_RDFSR , &fsr,1 ); +if (ret <0 ) { +debug ("spi-nor: fail to read flag status register\n" ); +return ret; + } + +return fsr; +} + +static int write_sr (struct udevice *dev,u8 ws) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); + + nor->cmd_buf[0 ] = ws; +return ops->write_reg (dev,SNOR_OP_WRSR , nor->cmd_buf,1 ); +} + +#if defined(CONFIG_SPI_NOR_SPANSION ) || defined(CONFIG_SPI_NOR_WINBOND ) +static int read_cr (struct udevice *dev) +{ +u8 cr; +int ret; + + ret =spi_nor_get_ops (dev)->read_reg (dev,SNOR_OP_RDCR , &cr,1 ); +if (ret <0 ) { +debug ("spi-nor: fail to read config register\n" ); +return ret; + } + +return cr; +} + +/* +* Write status Register and configuration register with 2 bytes +* - First byte will be written to the status register. +* - Second byte will be written to the configuration register. +* Return negative if error occured. +*/ +static int write_sr_cr (struct udevice *dev,u16 val) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); + + nor->cmd_buf[0 ] = val &0xff ; + nor->cmd_buf[1 ] = (val >>8 ); + +return ops->write_reg (dev,SNOR_OP_WRSR , nor->cmd_buf,2 ); +} +#endif + +static int spi_nor_sr_ready (struct udevice *dev) +{ +int sr =read_sr (dev); +if (sr <0 ) +return sr; +else +return !(sr &SR_WIP ); +} + +static int spi_nor_fsr_ready (struct udevice *dev) +{ +int fsr =read_fsr (dev); +if (fsr <0 ) +return fsr; +else +return fsr &FSR_READY ; +} + +static int spi_nor_ready (struct udevice *dev) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +int sr, fsr; + + sr =spi_nor_sr_ready (dev); +if (sr <0 ) +return sr; + + fsr =1 ; +if (nor->flags &SNOR_F_USE_FSR ) { + fsr =spi_nor_fsr_ready (dev); +if (fsr <0 ) +return fsr; + } + +return sr && fsr; +} + +static int spi_nor_wait_till_ready(struct udevice *dev, unsigned longtimeout)
drivers/mtd/spi-nor/spi-nor.c new file +61
-0+{ +int timebase, ret; + + timebase =get_timer (0 ); + +while (get_timer (timebase) < timeout) { + ret =spi_nor_ready (dev); +if (ret <0 ) +return ret; +if (ret) +return 0 ; + } + +printf ("spi-nor: Timeout!\n" ); + +return -ETIMEDOUT ; +} + +static const struct spi_nor_info *spi_nor_id (struct udevice *dev) +{ +int tmp; +u8 id[SPI_NOR_MAX_ID_LEN ]; +const struct spi_nor_info *info; +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); + + tmp = ops->read_reg (dev,SNOR_OP_RDID , id,SPI_NOR_MAX_ID_LEN ); +if (tmp <0 ) { +printf ("spi-nor: error %d reading JEDEC ID\n" , tmp); +return ERR_PTR (tmp); + } + + info = spi_nor_ids; +for (; info->name !=NULL ; info++) { +if (info->id_len) { +if (!memcmp (info->id, id, info->id_len)) +return info; + } + } + +printf ("spi-nor: unrecognized JEDEC id bytes: %02x, %2x, %2x\n" , + id[0 ], id[1 ], id[2 ]); +return ERR_PTR (-ENODEV ); +} + +int spi_nor_merase (struct udevice *dev,struct erase_info *instr) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +const struct spi_nor_ops *ops; +u32 addr, len, erase_addr; +uint32_t rem; +int ret =-1 ; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + ops =spi_nor_get_ops (nor->dev); + +div_u64_rem (instr->len, mtd->erasesize, &rem); +if (rem)
drivers/mtd/spi-nor/spi-nor.c line 213
Quoted 10 lines
drivers/mtd/spi-nor/spi-nor.c new file +9
-0+return -EINVAL ; + + addr = instr->addr; + len = instr->len; + +while (len) { + erase_addr = addr; +write_enable (nor->dev); + + ret = ops->write (nor->dev, erase_addr,0 ,NULL );
Can we considering use ops->write_reg(nor->dev, nor->erase_opcode, &addr, len) here , keep sync with
the linux upstream spi-nor does.[0]
+ if (ret < 0)
Quoted 623 lines
drivers/mtd/spi-nor/spi-nor.c new file +3
-0+ goto erase_err; + + ret = spi_nor_wait_till_ready(nor->dev,
SNOR_READY_WAIT_ERASE);drivers/mtd/spi-nor/spi-nor.c new file +43
-0+if (ret <0 ) + goto erase_err; + + addr += mtd->erasesize; + len -= mtd->erasesize; + } + +write_disable (nor->dev); + + instr->state =MTD_ERASE_DONE ; +mtd_erase_callback (instr); + +return ret; + +erase_err: + instr->state =MTD_ERASE_FAILED ; +return ret; +} + +static int spi_nor_mwrite (struct udevice *dev,loff_t to,size_t len, +size_t *retlen,const u_char *buf) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +const struct spi_nor_ops *ops; +size_t addr, byte_addr; +size_t chunk_len, actual; +uint32_t page_size; +int ret =-1 ; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + ops =spi_nor_get_ops (nor->dev); + + page_size = mtd->writebufsize; + +for (actual =0 ; actual < len; actual += chunk_len) { + addr = to; + + byte_addr = addr % page_size; + chunk_len = min(len - actual, (size_t)(page_size -
byte_addr));drivers/mtd/spi-nor/spi-nor.c new file +12
-0+ +if (nor->max_write_size) + chunk_len =min (chunk_len, + (size_t )nor->max_write_size); + +write_enable (nor->dev); + + ret = ops->write (nor->dev, addr, chunk_len, buf + actual); +if (ret <0 ) +break ; + + ret = spi_nor_wait_till_ready(nor->dev,
SNOR_READY_WAIT_PROG);drivers/mtd/spi-nor/spi-nor.c new file +110
-0+if (ret <0 ) +return ret; + + to += chunk_len; + *retlen += chunk_len; + } + +return ret; +} + +int spi_nor_mread (struct udevice *dev,loff_t from,size_t len, +size_t *retlen,u_char *buf) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +const struct spi_nor_ops *ops; +int ret; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + ops =spi_nor_get_ops (nor->dev); + +/* Handle memory-mapped SPI */ +if (nor->memory_map) { + ret = ops->read (nor->dev, from, len, buf); +if (ret) { +debug ("spi-nor: mmap read failed\n" ); +return ret; + } + +return ret; + } + + ret = ops->read (nor->dev, from, len, buf); +if (ret <0 ) { +printf ("%s ret = %d\n" , __func__, ret); +return ret; + } + + *retlen += len; + +return ret; +} + +#ifdef CONFIG_SPI_NOR_MACRONIX +static int macronix_quad_enable (struct udevice *dev) +{ +int ret, val; + + val =read_sr (dev); +if (val <0 ) +return val; + +if (val &SR_QUAD_EN_MX ) +return 0 ; + +write_enable (dev); + + ret =write_sr (dev, val |SR_QUAD_EN_MX ); +if (ret <0 ) +return ret; + +if (spi_nor_wait_till_ready (dev,SNOR_READY_WAIT_PROG )) +return 1 ; + + ret =read_sr (dev); +if (!(ret >0 && (ret &SR_QUAD_EN_MX ))) { +printf ("spi-nor: Macronix Quad bit not set\n" ); +return -EINVAL ; + } + +return 0 ; +} +#endif + +#if defined(CONFIG_SPI_NOR_SPANSION ) || defined(CONFIG_SPI_NOR_WINBOND ) +static int spansion_quad_enable (struct udevice *dev) +{ +int ret, val; + + val =read_cr (dev); +if (val <0 ) +return val; + +if (val &CR_QUAD_EN_SPAN ) +return 0 ; + +write_enable (dev); + + ret =write_sr_cr (dev, val |CR_QUAD_EN_SPAN ); +if (ret <0 ) +return ret; + +if (spi_nor_wait_till_ready (dev,SNOR_READY_WAIT_PROG )) +return 1 ; + +/* read back and check it */ + ret =read_cr (dev); +if (!(ret >0 && (ret &CR_QUAD_EN_SPAN ))) { +printf ("spi-nor: Spansion Quad bit not set\n" ); +return -EINVAL ; + } + +return 0 ; +} +#endif + +static int set_quad_mode(struct udevice *dev, const struct spi_nor_info*info)
drivers/mtd/spi-nor/spi-nor.c new file +44
-0+{ +switch (JEDEC_MFR (info)) { +#ifdef CONFIG_SPI_NOR_MACRONIX +case SNOR_MFR_MACRONIX : +return macronix_quad_enable (dev); +#endif +#if defined(CONFIG_SPI_NOR_SPANSION ) || defined(CONFIG_SPI_NOR_WINBOND ) +case SNOR_MFR_SPANSION : +case SNOR_MFR_WINBOND : +return spansion_quad_enable (dev); +#endif +#ifdef CONFIG_SPI_NOR_STMICRO +case SNOR_MFR_MICRON : +return 0 ; +#endif +default : +printf ("spi-nor: Need set QEB func for %02x flash\n" , +JEDEC_MFR (info)); +return -1 ; + } +} + +#if CONFIG_IS_ENABLED (OF_CONTROL ) +int spi_nor_decode_fdt (const void *blob,struct spi_nor *nor) +{ +struct udevice *dev = nor->dev; +struct mtd_info *mtd =mtd_get_info (dev); +fdt_addr_t addr; +fdt_size_t size; +int node; + +/* If there is no node, do nothing */ + node =fdtdec_next_compatible (blob,0 ,COMPAT_GENERIC_SPI_FLASH ); +if (node <0 ) +return 0 ; + + addr =fdtdec_get_addr_size (blob, node,"memory-map" , &size); +if (addr ==FDT_ADDR_T_NONE ) { +debug ("%s: Cannot decode address\n" , __func__); +return 0 ; + } + +if (mtd->size != size) { + debug("%s: Memory map must cover entire device\n",
__func__);drivers/mtd/spi-nor/spi-nor.c new file +31
-0+ return -1; + } + nor->memory_map =map_sysmem (addr, size); + +return 0 ; +} +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + +int spi_nor_scan (struct spi_nor *nor) +{ +struct mtd_info *mtd =spi_nor_get_mtd_info (nor); +struct mtd_ops *ops =mtd_get_ops (mtd->dev); +const struct spi_nor_info *info =NULL ; +int ret; + +struct spi_nor_uclass_priv *upriv =dev_get_uclass_priv (nor->dev); + upriv->spi_nor = nor; + +if (nor->init_done) +return 0 ; + + info =spi_nor_id (nor->dev); +if (IS_ERR_OR_NULL (info)) { + ret = -ENOENT ; + goto err; + } + +/* +* Flash powers up read-only, so clear BP# bits. +* +* Note on some flash (like Macronix), QE (quad enable) bit is in the
+ * same status register as BP# bits, and we need preserve its
original
+ * value during a reboot cycle as this is required by some
platformsdrivers/mtd/spi-nor/spi-nor.c new file +30
-0+* (like Intel ICH SPI controller working under descriptor mode). +*/ +if (JEDEC_MFR (info) ==SNOR_MFR_ATMEL || + (JEDEC_MFR (info) ==SNOR_MFR_SST ) || + (JEDEC_MFR (info) ==SNOR_MFR_MACRONIX )) { +u8 sr =0 ; + +if (JEDEC_MFR (info) ==SNOR_MFR_MACRONIX ) + sr =read_sr (nor->dev) &SR_QUAD_EN_MX ; +write_sr (nor->dev, sr); + } + + mtd->name = info->name; + mtd->priv = nor; + mtd->type =MTD_NORFLASH ; + mtd->writesize =1 ; + mtd->flags =MTD_CAP_NORFLASH ; + +if (info->flags &E_FSR ) + nor->flags |=SNOR_F_USE_FSR ; + +if (info->flags &SST_WR ) + nor->flags |=SNOR_F_SST_WRITE ; + + ops->write = spi_nor_mwrite; + +/* compute the flash size */ + nor->page_size = info->page_size; +/* +* The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
+ *0x4d00Extended JEDEC code. The rest of the Spansion flashes
with
+ * the0x4d00Extended JEDEC code have 512b pages. All of the
othersdrivers/mtd/spi-nor/spi-nor.c new file +45
-0+* have 256b pages. +*/ +if (JEDEC_EXT (info) ==0x4d00 ) { +if ((JEDEC_ID (info) !=0x0215 ) && + (JEDEC_ID (info) !=0x0216 )) + nor->page_size =512 ; + } + mtd->writebufsize = nor->page_size; + mtd->size = info->sector_size * info->n_sectors; + +#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS +/* prefer "small sector" erase if possible */ +if (info->flags &SECT_4K ) { + nor->erase_opcode =SNOR_OP_BE_4K ; + mtd->erasesize =4096 ; + } else +#endif + { + nor->erase_opcode =SNOR_OP_SE ; + mtd->erasesize = info->sector_size; + } + +/* Look for read opcode */ + nor->read_opcode =SNOR_OP_READ_FAST ; +if (nor->mode &SNOR_READ ) + nor->read_opcode =SNOR_OP_READ ; +else if (nor->mode &SNOR_READ_1_1_4 && info->flags &RD_QUAD ) + nor->read_opcode =SNOR_OP_READ_1_1_4 ; +else if (nor->mode &SNOR_READ_1_1_2 && info->flags &RD_DUAL ) + nor->read_opcode =SNOR_OP_READ_1_1_2 ; + +/* Look for program opcode */ +if (info->flags &WR_QPP && nor->mode &SNOR_WRITE_1_1_4 ) + nor->program_opcode =SNOR_OP_QPP ; +else +/* Go for default supported write cmd */ + nor->program_opcode =SNOR_OP_PP ; + +/* Set the quad enable bit - only for quad commands */ +if ((nor->read_opcode ==SNOR_OP_READ_1_1_4 ) || + (nor->read_opcode ==SNOR_OP_READ_1_1_4_IO ) || + (nor->program_opcode ==SNOR_OP_QPP )) { + ret =set_quad_mode (nor->dev, info); +if (ret) { + debug("spi-nor: quad mode not supported for%02x\n",
drivers/mtd/spi-nor/spi-nor.c new file +33
-0+ JEDEC_MFR(info)); + goto err; + } + } + + nor->addr_width =3 ; + +/* Dummy cycles for read */ +switch (nor->read_opcode) { +case SNOR_OP_READ_1_1_4_IO : + nor->read_dummy =16 ; +break ; +case SNOR_OP_READ : + nor->read_dummy =0 ; +break ; +default : + nor->read_dummy =8 ; + } + +#if CONFIG_IS_ENABLED (OF_CONTROL ) + ret =spi_nor_decode_fdt (gd->fdt_blob, nor); +if (ret) { +debug ("spi-nor: FDT decode error\n" ); + goto err; + } +#endif + + nor->init_done =1 ; +return 0 ; +err: + nor->init_done =0 ; +return ret; +}include/dm/uclass-id.h +1
-0@@ -75,6 +75,7 @@ enum uclass_id {UCLASS_SERIAL ,/* Serial UART */ UCLASS_SPI ,/* SPI bus */ UCLASS_SPMI ,/* System Power Management Interface bus */ +UCLASS_SPI_NOR ,/* SPI NOR flash */ UCLASS_SPI_FLASH ,/* SPI flash */ UCLASS_SPI_GENERIC ,/* Generic SPI flash target */ UCLASS_SYSCON, /* System configuration device */include/linux/mtd/spi-nor.h new file +18
-0@@ -0,0 +1,217 @@ +/* +* SPI NOR Core header file. +* +* Copyright (C) 2016 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef __MTD_SPI_NOR_H +#define __MTD_SPI_NOR_H + +#include <common.h> +#include <linux/mtd/mtd.h> + +/* +* Manufacturer IDs +* +* The first byte returned from the flash after sending opcode
SPINOR_OP_RDID.
+ * Sometimes these are the same as CFI IDs, but sometimes they aren't.
+ */include/linux/mtd/spi-nor.h new file +12
-0+#define SNOR_MFR_ATMEL 0x1f +#define SNOR_MFR_MACRONIX 0xc2 +#define SNOR_MFR_MICRON 0x20/* ST Micro <--> Micron */ +#define SNOR_MFR_SPANSION 0x01 +#define SNOR_MFR_SST 0xbf +#define SNOR_MFR_WINBOND 0xef + +/** +* SPI NOR opcodes. +* +* Note on opcode nomenclature: some opcodes have a format like +* SNOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
+ * of I/O lines used for the opcode, address, and data (respectively). The
+ * FUNCTION has an optional suffix of '4', to represent an opcode which
+ * requires a 4-byte (32-bit) address.
+ */include/linux/mtd/spi-nor.h new file +5
-0+#define SNOR_OP_WRDI 0x04/* Write disable */ +#define SNOR_OP_WREN 0x06/* Write enable */ +#define SNOR_OP_RDSR 0x05/* Read status register */ +#define SNOR_OP_WRSR 0x01/* Write status register 1 byte */ +#define SNOR_OP_READ 0x03/* Read data bytes (low frequency) */
+#defineSNOR_OP_READ_FAST0x0b/* Read data bytes (high
frequency) */include/linux/mtd/spi-nor.h new file +7
-0+#define SNOR_OP_READ_1_1_2 0x3b/* Read data bytes (Dual SPI) */ +#define SNOR_OP_READ_1_1_2_IO 0xbb/* Read data bytes (Dual IO SPI) */ +#define SNOR_OP_READ_1_1_4 0x6b/* Read data bytes (Quad SPI) */ +#define SNOR_OP_READ_1_1_4_IO 0xeb/* Read data bytes (Quad IO SPI) */ +#define SNOR_OP_BRWR 0x17/* Bank register write */ +#define SNOR_OP_BRRD 0x16/* Bank register read */ +#define SNOR_OP_WREAR 0xC5/* Write extended address register */
+#defineSNOR_OP_RDEAR0xC8/* Read extended address register
*/
+#defineSNOR_OP_PP0x02/* Page program (up to 256 bytes)
*/include/linux/mtd/spi-nor.h new file +13
-0+#define SNOR_OP_QPP 0x32/* Quad Page program */ +#define SNOR_OP_BE_4K 0x20/* Erase 4KiB block */ +#define SNOR_OP_BE_4K_PMC 0xd7/* Erase 4KiB block on PMC chips */ +#define SNOR_OP_BE_32K 0x52/* Erase 32KiB block */ +#define SPINOR_OP_CHIP_ERASE 0xc7/* Erase whole flash chip */ +#define SNOR_OP_SE 0xd8/* Sector erase (usually 64KiB) */ +#define SNOR_OP_RDID 0x9f/* Read JEDEC ID */ +#define SNOR_OP_RDCR 0x35/* Read configuration register */ +#define SNOR_OP_RDFSR 0x70/* Read flag status register */ + +/* Used for SST flashes only. */ +#define SNOR_OP_BP 0x02/* Byte program */ +#define SNOR_OP_AAI_WP 0xad/* Auto addr increment word program */
include/linux/mtd/spi-nor.h new file +18
-0+ +/* Status Register bits. */ +#define SR_WIP BIT(0)/* Write in progress */ +#define SR_WEL BIT(1)/* Write enable latch */ + +/* meaning of other SR_* bits may differ between vendors */ +#define SR_BP0 BIT(2)/* Block protect 0 */ +#define SR_BP1 BIT(3)/* Block protect 1 */ +#define SR_BP2 BIT(4)/* Block protect 2 */ +#define SR_SRWD BIT(7)/* SR write protect */ + +#define SR_QUAD_EN_MX BIT(6)/* Macronix Quad I/O */ + +/* Flag Status Register bits */ +#define FSR_READY BIT(7) + +/* Configuration Register bits. */ +#define CR_QUAD_EN_SPAN BIT(1)/* Spansion/Winbond Quad I/O */
include/linux/mtd/spi-nor.h new file +9
-0+ +/* Flash timeout values */ +#define SNOR_READY_WAIT_PROG (2 * CONFIG_SYS_HZ) +#define SNOR_READY_WAIT_ERASE (5 * CONFIG_SYS_HZ) +#define SNOR_MAX_CMD_SIZE 4 +#define SNOR_16MB_BOUN 0x1000000 + +/** +* struct spi_nor_uclass_priv - Holds information about a device used by the uclass
+ */include/linux/mtd/spi-nor.h new file +23
-0+struct spi_nor_uclass_priv { +struct spi_nor *spi_nor; +}; + +enum snor_option_flags { +SNOR_F_SST_WRITE =BIT (0 ), +SNOR_F_USE_FSR =BIT (1 ), +SNOR_F_U_PAGE =BIT (1 ), +}; + +enum mode { +SNOR_READ =BIT (0 ), +SNOR_READ_1_1_2 =BIT (1 ), +SNOR_READ_1_1_4 =BIT (2 ), +SNOR_READ_1_1_2_IO =BIT (3 ), +SNOR_READ_1_1_4_IO =BIT (4 ), +SNOR_WRITE_1_1_BYTE =BIT (5 ), +SNOR_WRITE_1_1_4 =BIT (6 ), +}; + +#define JEDEC_MFR (info) ((info)->id[0]) +#define JEDEC_ID (info) (((info)->id[1]) << 8 | ((info)->id[2])) +#define JEDEC_EXT (info) (((info)->id[3]) << 8 |((info)->id[4]))
include/linux/mtd/spi-nor.h new file +31
-0+#define SPI_NOR_MAX_ID_LEN 6 + +struct spi_nor_info { +char *name; + +/* +* This array stores the ID bytes. +* The first three bytes are the JEDIC ID. +* JEDEC ID zero means "no ID" (mostly older chips). +*/ +u8 id[SPI_NOR_MAX_ID_LEN ]; +u8 id_len; + +/* The size listed here is what works with SNOR_OP_SE, which isn't +* necessarily called a "sector" by the vendor. +*/ +unsigned sector_size; +u16 n_sectors; + +u16 page_size; + +u16 flags; +#define SECT_4K BIT(0) +#define E_FSR BIT(1) +#define SST_WR BIT(2) +#define WR_QPP BIT(3) +#define RD_QUAD BIT(4) +#define RD_DUAL BIT(5) +#define RD_QUADIO BIT(6) +#define RD_DUALIO BIT(7) +#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO |
RD_DUALIO)include/linux/mtd/spi-nor.h new file +14
-0+}; + +extern const struct spi_nor_info spi_nor_ids[]; + +/** +* struct spi_nor - Structure for defining a the SPI NOR layer +* +* @dev: SPI NOR device +* @name: name of the SPI NOR device +* @page_size: the page size of the SPI NOR +* @addr_width: number of address bytes +* @erase_opcode: the opcode for erasing a sector +* @read_opcode: the read opcode +* @read_dummy: the dummy bytes needed by the read operation
+ * @program_opcode: the program opcode + * @max_write_size: If non-zero, the maximum number of bytes which can + * be written at once, excluding command bytes. + * @flags: flag options for the current SPI-NOR (SNOR_F_*) + * @mode: read, write mode or any other mode bits. + * @read_mode: read mode. + * @cmd_buf: used by the write_reg + * @read_reg: [DRIVER-SPECIFIC] read out the register + * @write_reg: [DRIVER-SPECIFIC] write data to the register + * @read: [DRIVER-SPECIFIC] read data from the SPI NOR + * @write: [DRIVER-SPECIFIC] write data to the SPI NOR + * @memory_map: address of read-only SPI NOR access+ */
include/linux/mtd/spi-nor.h new file +44
-1+struct spi_nor { +struct udevice *dev; +const char *name; +u8 init_done; +u32 page_size; +u8 addr_width; +u8 erase_opcode; +u8 read_opcode; +u8 read_dummy; +u8 program_opcode; +u32 max_write_size; +u32 flags; +u8 mode; +u8 read_mode; +u8 cmd_buf[SNOR_MAX_CMD_SIZE ]; + +void *memory_map; +}; + +struct spi_nor_ops { +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)(struct udevice *dev,loff_t from,size_t len, +u_char *buf); +int (*write)(struct udevice *dev,loff_t to,size_t len, +const u_char *buf); +}; + +#define spi_nor_get_ops (dev) ((struct spi_nor_ops *)(dev)->driver->ops) + +int spi_nor_merase (struct udevice *dev,struct erase_info *instr); +int spi_nor_mread (struct udevice *dev,loff_t from,size_t len, +size_t *retlen,u_char *buf); + +int spi_nor_scan (struct spi_nor *nor); +int spi_nor_bind (struct udevice *dev,struct spi_nor *nor); + +struct spi_nor *find_spi_nor_device (int dev_num); +int get_spi_nor_num (void ); +struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev); +struct mtd_info *spi_nor_get_mtd_info (struct spi_nor *nor); + +#endif /* __MTD_SPI_NOR_H */ --2.7.4
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
PATCH v10 3/27 mtd: add SPI-NOR core support
In reply to Jagan Teki[Resending on correct patch of the patch-set]
Dear Jagan,
Quoted 36 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:42 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core supportSome of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cThe problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================
Quoted 3 lines
#####SPI NOR chip######=======================================
As per this patch-set, fsl_qspi is looks to be getting proposed in driver/mtd/spi-nor/ folder.
fsl_qspi is supporting both flash and fpga. We are not sure about its location.
There is an on-going effort for similar type of requirement in Linux by Boris Brezillon . It is dealing with controllers supporting NORs, NANDs, SRAMs etc.
http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088
Borris has also ported fsl_qspi in driver/spi to use this new framework. It is still not completely tested.
https://github.com/bbrezillon/linux/commit/43cc45764b975bfbb191de3f6a37e073da1a2706
Will you also follow similar approach as being done in http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088 for longer term?
For Now, We are planning to update fsl_qspi driver to support dynamic LUT. Similar patch is in progress in Linux http://patchwork.ozlabs.org/project/linux-mtd/list/?series=26084
Now we are confused, should be port fsl_qspi in driver/mtd/spi-nor and then update driver Or We update driver/spi/fsl_qspi for dynamic LUTs. We may need to modify existing framework to get all required info for dynamic LUT.
Also we want some change in framework like support of
- 4 byte address and SFDP : http://patchwork.ozlabs.org/project/uboot/list/?series=19621&state=*
- SMPT : in discussion in Linux http://patchwork.ozlabs.org/patch/869718/
Which code base should we use? u-boot-spi.git branch mtd-spinor-working or u-boot.git master branch
--pk
PATCH v10 3/27 mtd: add SPI-NOR core support
Prabhakar, Jagan,
Quoted 17 lines · On Wed, 28 Feb 2018 09:42:11 +0000 Prabhakar Kushwaha…
[Resending on correct patch of the patch-set]
Dear Jagan,
Quoted 12 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:42 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core supportSome of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.c
Okay, I've been working a bit with this controller, and can say it's not quite true. This controller supports any kind of device that expects memory-like operations (or whatever you want to call them), that is, everything that is formed of one opcode, X address cycles, Y dummy cycles and Z data in/out cycles (X, Y and Z can be zero).
Actually, I even think it could support regular SPI transfers, all we'd have to do is use READ/WRITE instructions to do the transfers.
Quoted 9 lines
Quoted 9 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.
I've discussed it privately with Cyrille before I sent the spi-mem extension proposal, and he seemed to agree with the approach. I don't know what his opinion is now that the RFC has been posted, but if he hasn't changed his mind, that means Linux implementation is going in the opposite direction. So it's probably worth reconsidering this move.
Cyrille, could you clarify your opinion? I'm also waiting your feedback on the RFC to send a v2 addressing the comments I had from other people.
Quoted 31 lines
Quoted 16 lines
=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================Quoted 3 lines
#####SPI NOR chip######=======================================
As per this patch-set,
fsl_qspiis looks to be getting proposed in driver/mtd/spi-nor/ folder.
fsl_qspiis supporting both flash and fpga. We are not sure about its location.There is an on-going effort for similar type of requirement in Linux by Boris Brezillon . It is dealing with controllers supporting NORs, NANDs, SRAMs etc.
http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088
Quoted 8 lines
Borris has also ported
fsl_qspiin driver/spi to use this new framework. It is still not completely tested.
https://github.com/bbrezillon/linux/commit/43cc45764b975bfbb191de3f6a37e073da1a2706Will you also follow similar approach as being done in
http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088 for longer term?
That would be great if the code base could converge.
Regards,
Boris
Signature · 3 lines
Boris Brezillon, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com
PATCH v10 3/27 mtd: add SPI-NOR core support
Dear Jagan,
Quoted 101 lines
-----Original Message-----
From: Boris Brezillon [mailto:boris.brezillon at bootlin.com]
Sent: Wednesday, February 28, 2018 5:40 PM
To: Prabhakar Kushwaha <[email protected]>; Jagan Teki <[email protected]>; Cyrille Pitchen <[email protected]>
Cc: u-boot at lists.denx.de; Suresh Gupta <[email protected]>; Yogesh Narayan Gaur <[email protected]>; Poonam Aggrwal <[email protected]>; Ashish Kumar <[email protected]>; Han Xu <[email protected]>; Frieder Schrempf <[email protected]>; Boris Brezillon <boris.brezillon@free- electrons.com>
Subject: Re: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core supportPrabhakar, Jagan,
Quoted 17 lines · On Wed, 28 Feb 2018 09:42:11 +0000 Prabhakar Kushwaha…
[Resending on correct patch of the patch-set]
Dear Jagan,
Quoted 12 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:42 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core supportSome of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cOkay, I've been working a bit with this controller, and can say it's not quite true. This controller supports any kind of device that expects memory-like operations (or whatever you want to call them), that is, everything that is formed of one opcode, X address cycles, Y dummy cycles and Z data in/out cycles (X, Y and Z can be zero).
Actually, I even think it could support regular SPI transfers, all we'd have to do is use READ/WRITE instructions to do the transfers.
Quoted 9 lines
Quoted 9 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.I've discussed it privately with Cyrille before I sent the spi-mem extension proposal, and he seemed to agree with the approach. I don't know what his opinion is now that the RFC has been posted, but if he hasn't changed his mind, that means Linux implementation is going in the opposite direction. So it's probably worth reconsidering this move.
Cyrille, could you clarify your opinion? I'm also waiting your feedback on the RFC to send a v2 addressing the comments I had from other people.
Quoted 36 lines
Quoted 16 lines
=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================Quoted 3 lines
#####SPI NOR chip######=======================================
As per this patch-set,
fsl_qspiis looks to be getting proposed in driver/mtd/spi-nor/ folder.
fsl_qspiis supporting both flash and fpga. We are not sure about its location.There is an on-going effort for similar type of requirement in Linux by Boris Brezillon . It is dealing with controllers supporting NORs, NANDs, SRAMs etc.
http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088Borris has also ported
fsl_qspiin driver/spi to use this new framework. It is still not completely tested.
https://github.com/bbrezillon/linux/commit/43cc45764b975bfbb191de3f6a37e073da1a2706
Quoted 5 lines
Quoted 3 lines
Will you also follow similar approach as being done in
http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088 for longer term?That would be great if the code base could converge.
Please help us with your strategy towards qspi framework.
We are waiting for your direction before creating/sending patches of qspi driver & framework in upstream.
--pk
PATCH v10 3/27 mtd: add SPI-NOR core support
In reply to Prabhakar KushwahaQuoted 47 lines · Prabhakar Kushwaha
[Resending on correct patch of the patch-set]
Dear Jagan,
Quoted 36 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:42 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core supportSome of the SPI device drivers at
drivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cThe problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================Quoted 3 lines
#####SPI NOR chip######=======================================
As per this patch-set,
fsl_qspiis looks to be getting proposed in driver/mtd/spi-nor/ folder.
Quoted 7 lines
fsl_qspiis supporting both flash and fpga. We are not sure about its location.There is an on-going effort for similar type of requirement in Linux by Boris Brezillon . It is dealing with controllers supporting NORs, NANDs, SRAMs etc.
http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088Borris has also ported
fsl_qspiin driver/spi to use this new framework. It is still not completely tested.
https://github.com/bbrezillon/linux/commit/43cc45764b975bfbb191de3f6a37e073da1a2706
These look going in reverse direction, since drivers/mtd/spi-nor/fsl_qspi was meant for SPI-NOR flash(from initial version SPI-NOR framework patches) and now it going in driver/spi.. look like it need more discussion with respective people who involved on these.
Quoted 6 lines
Will you also follow similar approach as being done in http://patchwork.ozlabs.org/project/linux-mtd/list/?series=27088 for longer term?
For Now, We are planning to update
fsl_qspidriver to support dynamic LUT. Similar patch is in progress in Linux http://patchwork.ozlabs.org/project/linux-mtd/list/?series=26084
Now we are confused, should be portfsl_qspiin driver/mtd/spi-nor and then update driver Or We update driver/spi/fsl_qspi for dynamic LUTs. We may need to modify existing framework to get all required info for dynamic LUT.
As of now, I would like to write it in driver/mtd/spi-nor assuming all LUT or fsl related changes donesn't harm core areas so-that moving back to drivers/spi might be easy if Linux does.
Quoted 5 lines
Also we want some change in framework like support of
- 4 byte address and SFDP : http://patchwork.ozlabs.org/project/uboot/list/?series=19621&state=*
- SMPT : in discussion in Linux http://patchwork.ozlabs.org/patch/869718/
Which code base should we use? u-boot-spi.git branch mtd-spinor-working or u-boot.git master branch
Pls use this https://github.com/openedev/u-boot-spi/commits/master
PATCH v10 4/27 mtd: spi-nor: sync/modify sst write operations
In reply to Jagan Tekisst write operations can be changed based on the mode set from the controller with byte program or word program, so sync the similar code from legacy spi_flash.c and update accordingly with mtd operations.
--- drivers/mtd/spi-nor/spi-nor.c | 115 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+)
drivers/mtd/spi-nor/spi-nor.c +115 -0
@@ -316,6 +316,113 @@ int spi_nor_mread(struct udevice *dev, loff_t from, size_t len,return ret; } +#ifdef CONFIG_SPI_NOR_SST +static int sst_byte_write (struct spi_nor *nor,u32 addr,const void *buf, +size_t *retlen) +{ +const struct spi_nor_ops *ops =spi_nor_get_ops (nor->dev); +int ret; + + ret =write_enable (nor->dev); +if (ret) +return ret; + + nor->program_opcode =SNOR_OP_BP ; + + ret = ops->write (nor->dev, addr,1 , buf); +if (ret) +return ret; + + *retlen +=1 ; + +return spi_nor_wait_till_ready (nor->dev,SNOR_READY_WAIT_PROG ); +} + +static int sst_mwrite_wp (struct udevice *dev,loff_t to,size_t len, +size_t *retlen,const u_char *buf) +{ +struct mtd_info *mtd =mtd_get_info (dev); +int devnum = mtd->devnum; +const struct spi_nor_ops *ops; +struct spi_nor *nor; +size_t actual; +int ret; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + ops =spi_nor_get_ops (nor->dev); + +/* If the data is not word aligned, write out leading single byte */ + actual = to %2 ; +if (actual) { + ret =sst_byte_write (nor, to, buf, retlen); +if (ret) + goto done; + } + to += actual; + + ret =write_enable (nor->dev); +if (ret) + goto done; + +for (; actual < len -1 ; actual +=2 ) { + nor->program_opcode =SNOR_OP_AAI_WP ; + + ret = ops->write (nor->dev, to,2 , buf + actual); +if (ret) { +debug ("spi-nor: sst word program failed\n" ); +break ; + } + + ret =spi_nor_wait_till_ready (nor->dev,SNOR_READY_WAIT_PROG ); +if (ret) +break ; + + to +=2 ; + *retlen +=2 ; + } + +if (!ret) + ret =write_disable (nor->dev); + +/* If there is a single trailing byte, write it out */ +if (!ret && actual != len) + ret =sst_byte_write (nor, to, buf + actual, retlen); + + done: +return ret; +} + +static int sst_mwrite_bp (struct udevice *dev,loff_t to,size_t len, +size_t *retlen,const u_char *buf) +{ +struct mtd_info *mtd =mtd_get_info (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +size_t actual; +int ret; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + +for (actual =0 ; actual < len; actual++) { + ret =sst_byte_write (nor, to, buf + actual, retlen); +if (ret) { +debug ("spi-nor: sst byte program failed\n" ); +break ; + } + to++; + } + +if (!ret) + ret =write_disable (nor->dev); + +return ret; +} +#endif +#ifdef CONFIG_SPI_NOR_MACRONIX static int macronix_quad_enable (struct udevice *dev) {
@@ -482,6 +589,14 @@ int spi_nor_scan(struct spi_nor *nor) nor->flags |=SNOR_F_SST_WRITE ; ops->write = spi_nor_mwrite; +#if defined(CONFIG_SPI_NOR_SST ) +if (nor->flags &SNOR_F_SST_WRITE ) { +if (nor->mode &SNOR_WRITE_1_1_BYTE ) + ops->write = sst_mwrite_bp; +else + ops->write = sst_mwrite_wp; + } +#endif /* compute the flash size */ nor->page_size = info->page_size;
Signature · 1 line
2.7.4
PATCH v10 5/27 mtd: spi-nor: sync/modify lock operations
In reply to Jagan Tekisync the lock operations from legacy spi_flash.c and update them according to current spi-nor framework.
--- drivers/mtd/spi-nor/spi-nor.c | 218 ++++++++++++++++++++++++++++++++++++++++++ include/mtd.h | 3 + 2 files changed, 221 insertions(+)
drivers/mtd/spi-nor/spi-nor.c +218 -0
@@ -186,6 +186,7 @@ static const struct spi_nor_info *spi_nor_id(struct udevice *dev)int spi_nor_merase (struct udevice *dev,struct erase_info *instr) {struct mtd_info *mtd =dev_get_uclass_platdata (dev); +const struct mtd_ops *mops =mtd_get_ops (mtd->dev);int devnum = mtd->devnum;struct spi_nor *nor;const struct spi_nor_ops *ops;
@@ -205,6 +206,14 @@ int spi_nor_merase(struct udevice *dev, struct erase_info *instr) addr = instr->addr; len = instr->len; +if (mops->is_locked) { + ret = mops->is_locked (mtd->dev, addr, len); +if (ret >0 ) { +printf ("spi-nor: offset 0x%x is locked, cannot be erased\n" , addr); +return -EINVAL ; + } + } +while (len) { erase_addr = addr;
@@ -238,6 +247,7 @@ static int spi_nor_mwrite(struct udevice *dev, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct mtd_info *mtd = dev_get_uclass_platdata(dev); +const struct mtd_ops *mops =mtd_get_ops (mtd->dev);int devnum = mtd->devnum;struct spi_nor *nor;const struct spi_nor_ops *ops;
@@ -253,6 +263,14 @@ static int spi_nor_mwrite(struct udevice *dev, loff_t to, size_t len, page_size = mtd->writebufsize; +if (mops->is_locked) { + ret = mops->is_locked (mtd->dev, to, len); +if (ret >0 ) { +printf ("spi-nor: offset 0x%llx is locked, cannot be written\n" , to); +return -EINVAL ; + } + } +for (actual =0 ; actual < len; actual += chunk_len) { addr = to;
@@ -423,6 +441,197 @@ static int sst_mwrite_bp(struct udevice *dev, loff_t to, size_t len, }#endif +#if defined(CONFIG_SPI_NOR_STMICRO ) || defined(CONFIG_SPI_NOR_SST ) +static void stm_get_locked_range (struct mtd_info *mtd,u8 sr,loff_t *ofs, +u64 *len) +{ +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +int shift =ffs (mask) -1 ; +int pow; + +if (!(sr & mask)) { +/* No protection */ + *ofs =0 ; + *len =0 ; + }else { + pow = ((sr & mask) ^ mask) >> shift; + *len = mtd->size >> pow; + *ofs = mtd->size - *len; + } +} + +/* Return 1 if the entire region is locked, 0 otherwise */ +static int stm_is_locked_sr (struct mtd_info *mtd,loff_t ofs,u64 len, +u8 sr) +{ +loff_t lock_offs; +u64 lock_len; + +stm_get_locked_range (mtd, sr, &lock_offs, &lock_len); + +return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); +} + +/* +* Check if a region of the flash is (completely) locked. See stm_lock() for +* more info. +* +* Returns 1 if entire region is locked, 0 if any portion is unlocked, and +* negative on errors. +*/ +static int stm_is_locked (struct udevice *dev,loff_t ofs,uint64_t len) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +int status; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + + status =read_sr (nor->dev); +if (status <0 ) +return status; + +return stm_is_locked_sr (mtd, ofs, len, status); +} + +/* +* Lock a region of the flash. Compatible with ST Micro and similar flash. +* Supports only the block protection bits BP{0,1,2} in the status register +* (SR). Does not support these features found in newer SR bitfields: +* - TB: top/bottom protect - only handle TB=0 (top protect) +* - SEC: sector/block protect - only handle SEC=0 (block protect) +* - CMP: complement protect - only support CMP=0 (range is not complemented) +* +* Sample table portion for 8MB flash (Winbond w25q64fw): +* +* SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion +* -------------------------------------------------------------------------- +* X | X | 0 | 0 | 0 | NONE | NONE +* 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 +* 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 +* 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 +* 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 +* 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 +* 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 +* X | X | 1 | 1 | 1 | 8 MB | ALL +* +* Returns negative on errors, 0 on success. +*/ +static int stm_lock (struct udevice *dev,loff_t ofs,uint64_t len) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +u8 status_old, status_new; +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +u8 shift =ffs (mask) -1 , pow, val; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + + status_old =read_sr (nor->dev); +if (status_old <0 ) +return status_old; + +/* SPI NOR always locks to the end */ +if (ofs + len != mtd->size) { +/* Does combined region extend to end? */ +if (!stm_is_locked_sr (mtd, ofs + len, mtd->size - ofs - len, + status_old)) +return -EINVAL ; + len = mtd->size - ofs; + } + +/* +* Need smallest pow such that: +* +* 1 / (2^pow) <= (len / size) +* +* so (assuming power-of-2 size) we do: +* +* pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) +*/ + pow =ilog2 (mtd->size) -ilog2 (len); + val = mask - (pow << shift); +if (val & ~mask) +return -EINVAL ; + +/* Don't "lock" with no region! */ +if (!(val & mask)) +return -EINVAL ; + + status_new = (status_old & ~mask) | val; + +/* Only modify protection if it will not unlock other areas */ +if ((status_new & mask) <= (status_old & mask)) +return -EINVAL ; + +write_sr (nor->dev, status_new); + +return 0 ; +} + +/* +* Unlock a region of the flash. See stm_lock() for more info +* +* Returns negative on errors, 0 on success. +*/ +static int stm_unlock (struct udevice *dev,loff_t ofs,uint64_t len) +{ +struct mtd_info *mtd =dev_get_uclass_platdata (dev); +int devnum = mtd->devnum; +struct spi_nor *nor; +uint8_t status_old, status_new; +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +u8 shift =ffs (mask) -1 , pow, val; + + nor =find_spi_nor_device (devnum); +if (!nor) +return -ENODEV ; + + status_old =read_sr (nor->dev); +if (status_old <0 ) +return status_old; + +/* Cannot unlock; would unlock larger region than requested */ +if (stm_is_locked_sr (mtd, ofs - mtd->erasesize, mtd->erasesize, + status_old)) +return -EINVAL ; +/* +* Need largest pow such that: +* +* 1 / (2^pow) >= (len / size) +* +* so (assuming power-of-2 size) we do: +* +* pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) +*/ + pow =ilog2 (mtd->size) -order_base_2 (mtd->size - (ofs + len)); +if (ofs + len == mtd->size) { + val =0 ;/* fully unlocked */ + }else { + val = mask - (pow << shift); +/* Some power-of-two sizes are not supported */ +if (val & ~mask) +return -EINVAL ; + } + + status_new = (status_old & ~mask) | val; + +/* Only modify protection if it will not lock other areas */ +if ((status_new & mask) >= (status_old & mask)) +return -EINVAL ; + +write_sr (nor->dev, status_new); + +return 0 ; +} +#endif +#ifdef CONFIG_SPI_NOR_MACRONIX static int macronix_quad_enable (struct udevice *dev) {
@@ -598,6 +807,15 @@ int spi_nor_scan(struct spi_nor *nor) }#endif +#if defined(CONFIG_SPI_NOR_STMICRO ) || defined(CONFIG_SPI_NOR_SST ) +/* NOR protection support for STmicro/Micron chips and similar */ +if (JEDEC_MFR (info) ==SNOR_MFR_MICRON || +JEDEC_MFR (info) ==SNOR_MFR_SST ) { + ops->lock = stm_lock; + ops->unlock = stm_unlock; + ops->is_locked = stm_is_locked; + } +#endif /* compute the flash size */ nor->page_size = info->page_size;/*
include/mtd.h +3 -0
@@ -26,6 +26,9 @@ struct mtd_ops { size_t *retlen, u_char *buf);int (*write)(struct udevice *dev,loff_t to,size_t len,size_t *retlen,const u_char *buf); +int (*lock) (struct udevice *dev,loff_t ofs,uint64_t len); +int (*unlock) (struct udevice *dev,loff_t ofs,uint64_t len); +int (*is_locked) (struct udevice *dev,loff_t ofs,uint64_t len); };/* Access the serial operations for a device */
Signature · 1 line
2.7.4
PATCH v10 6/27 mtd: spi-nor: Kconfig: Add MTD_SPI_NOR entry
In reply to Jagan TekiAdded CONFIG_MTD_SPI_NOR kconfig entry
--- drivers/mtd/Kconfig | 2 ++ drivers/mtd/spi-nor/Kconfig | 14 ++++++++++++++ drivers/mtd/spi-nor/Makefile | 2 ++ 3 files changed, 18 insertions(+) create mode 100644 drivers/mtd/spi-nor/Kconfig
drivers/mtd/Kconfig +2 -0
@@ -46,4 +46,6 @@ source "drivers/mtd/nand/Kconfig" source "drivers/mtd/spi/Kconfig" +source "drivers/mtd/spi-nor/Kconfig" + source "drivers/mtd/ubi/Kconfig"
drivers/mtd/spi-nor/Kconfig new file +14 -0
@@ -0,0 +1,14 @@ +menuconfig MTD_SPI_NOR + tristate "SPI-NOR device support" + depends on MTD + help + This is the core SPI NOR framework which can be used to interact SPI-NOR + to SPI driver interface layer and the SPI-NOR controller driver. + + Unlike normal/generic spi controllers, they are few controllers which are + exclusively used to connect SPI-NOR devices, called SPI-NOR controllers. + So technically these controllers shouldn't reside at drivers/spi as these + may effect the generic SPI bus functionalities, so this SPI-NOR core acts + as a common core framework between the generic SPI controller drivers vs + SPI-NOR controller drivers for SPI-NOR device access. Note that from SPI-NOR + core to SPI drivers there should be an interface layer.
drivers/mtd/spi-nor/Makefile +2 -0
@@ -4,4 +4,6 @@ # SPDX-License-Identifier: GPL-2.0+ ## spi-nor core +ifdef CONFIG_MTD_SPI_NOR obj-y += spi-nor.o spi-nor-uclass.o spi-nor-ids.o +endif
Signature · 1 line
2.7.4
PATCH v10 7/27 mtd: spi-nor: Kconfig: Add MTD_SPI_NOR_USE_4K_SECTORS
In reply to Jagan TekiAdded CONFIG_MTD_SPI_NOR_USE_4K_SECTORS kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/mtd/spi-nor/Kconfig +18 -0
@@ -12,3 +12,21 @@ menuconfig MTD_SPI_NOR as a common core framework between the generic SPI controller drivers vs SPI-NOR controller drivers for SPI-NOR device access. Note that from SPI-NOR core to SPI drivers there should be an interface layer. + +if MTD_SPI_NOR + +config MTD_SPI_NOR_USE_4K_SECTORS + bool "Use small 4096 B erase sectors" + default y + help + Many flash memories support erasing small (4096 B) sectors. Depending + on the usage this feature may provide performance gain in comparison + to erasing whole blocks (32/64 KiB). + Changing a small part of the flash's contents is usually faster with + small sectors. On the other hand erasing should be faster when using + 64 KiB block instead of 16 × 4 KiB sectors. + + Please note that some tools/drivers/filesystems may not work with + 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). + +endif # MTD_SPI_NOR
Signature · 1 line
2.7.4
PATCH v10 8/27 mtd: spi-nor: Kconfig: Add SPI_NOR_MISC entry
In reply to Jagan TekiAdded CONFIG_SPI_NOR_MISC kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/mtd/spi-nor/Kconfig +6 -0
@@ -29,4 +29,10 @@ config MTD_SPI_NOR_USE_4K_SECTORS Please note that some tools/drivers/filesystems may not work with 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). +config SPI_NOR_MISC + bool "Miscellaneous SPI NOR flash's support" + help + Add SPI-NOR support for various flash chips like Atmel, EON, + GigaDevice, and ISSI. + endif # MTD_SPI_NOR
Signature · 1 line
2.7.4
PATCH v10 9/27 mtd: spi-nor: Kconfig: Add SPI_NOR_MACRONIX entry
In reply to Jagan TekiAdded CONFIG_SPI_NOR_MACRONIX kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 5 +++++ 1 file changed, 5 insertions(+)
drivers/mtd/spi-nor/Kconfig +5 -0
@@ -35,4 +35,9 @@ config SPI_NOR_MISC Add SPI-NOR support for various flash chips like Atmel, EON, GigaDevice, and ISSI. +config SPI_NOR_MACRONIX + bool "Macronix SPI NOR flash support" + help + Add support for various Macronix SPI flash chips (MX25Lxxx) + endif # MTD_SPI_NOR
Signature · 1 line
2.7.4
PATCH v10 10/27 mtd: spi-nor: Kconfig: Add SPI_NOR_SPANSION entry
In reply to Jagan TekiAdded CONFIG_SPI_NOR_SPANSION kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 5 +++++ 1 file changed, 5 insertions(+)
drivers/mtd/spi-nor/Kconfig +5 -0
@@ -40,4 +40,9 @@ config SPI_NOR_MACRONIX help Add support for various Macronix SPI flash chips (MX25Lxxx) +config SPI_NOR_SPANSION + bool "Spansion SPI NOR flash support" + help + Add support for various Spansion SPI flash chips (S25FLxxx) + endif # MTD_SPI_NOR
Signature · 1 line
2.7.4
PATCH v10 11/27 mtd: spi-nor: Kconfig: Add SPI_NOR_STMICRO entry
In reply to Jagan TekiAdded CONFIG_SPI_NOR_STMICRO kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 5 +++++ 1 file changed, 5 insertions(+)
drivers/mtd/spi-nor/Kconfig +5 -0
@@ -45,4 +45,9 @@ config SPI_NOR_SPANSION help Add support for various Spansion SPI flash chips (S25FLxxx) +config SPI_NOR_STMICRO + bool "STMicro SPI NOR flash support" + help + Add support for various STMicro SPI flash chips (M25Pxxx and N25Qxxx) + endif # MTD_SPI_NOR
Signature · 1 line
2.7.4
PATCH v10 12/27 mtd: spi-nor: Kconfig: Add SPI_NOR_SST entry
In reply to Jagan TekiAdded CONFIG_SPI_NOR_SST kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 5 +++++ 1 file changed, 5 insertions(+)
drivers/mtd/spi-nor/Kconfig +5 -0
@@ -50,4 +50,9 @@ config SPI_NOR_STMICRO help Add support for various STMicro SPI flash chips (M25Pxxx and N25Qxxx) +config SPI_NOR_SST + bool "SST SPI NOR flash support" + help + Add support for various SST SPI flash chips (SST25xxx) + endif # MTD_SPI_NOR
Signature · 1 line
2.7.4
PATCH v10 13/27 mtd: spi-nor: Kconfig: Add SPI_NOR_WINBOND entry
In reply to Jagan TekiAdded CONFIG_SPI_NOR_WINBOND kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 5 +++++ 1 file changed, 5 insertions(+)
drivers/mtd/spi-nor/Kconfig +5 -0
@@ -55,4 +55,9 @@ config SPI_NOR_SST help Add support for various SST SPI flash chips (SST25xxx) +config SPI_NOR_WINBOND + bool "Winbond SPI NOR flash support" + help + Add support for various Winbond SPI flash chips (W25xxx) + endif # MTD_SPI_NOR
Signature · 1 line
2.7.4
PATCH v10 14/27 mtd-uclass: use platdata_auto_alloc
In reply to Jagan TekiNow, mtd uclass can hold platdata for underlying interface uclass drivers so use platdata_auto_alloc and access via dev->uclass_platdata.
--- drivers/mtd/mtd-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/mtd-uclass.c +1 -1
@@ -199,5 +199,5 @@ int mtd_create_devicef(struct udevice *parent, const char *drv_name,UCLASS_DRIVER (mtd) = { .id =UCLASS_MTD , .name ="mtd" , - .per_device_auto_alloc_size =sizeof (struct mtd_info ), + .per_device_platdata_auto_alloc_size =sizeof (struct mtd_info ), };
Signature · 1 line
2.7.4
PATCH v10 15/27 spi: Add spi_write_then_read
In reply to Jagan TekiAdd support for SPI synchronous write followed by read, this is common interface call from spi-nor to spi drivers.
--- drivers/spi/spi-uclass.c | 24 ++++++++++++++++++++++++ include/spi.h | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+)
drivers/spi/spi-uclass.c +24 -0
@@ -107,6 +107,30 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,return dm_spi_xfer (slave->dev, bitlen, dout, din, flags); } +int spi_write_then_read (struct spi_slave *slave,const u8 *opcode, +size_t n_opcode,const u8 *txbuf,u8 *rxbuf, +size_t n_buf) +{ +unsigned long flags =SPI_XFER_BEGIN ; +int ret; + +if (n_buf ==0 ) + flags |=SPI_XFER_END ; + + ret =spi_xfer (slave, n_opcode *8 , opcode,NULL , flags); +if (ret) { +debug ("spi: failed to send command (%zu bytes): %d\n" , + n_opcode, ret); + }else if (n_buf !=0 ) { + ret =spi_xfer (slave, n_buf *8 , txbuf, rxbuf,SPI_XFER_END ); +if (ret) +debug ("spi: failed to transfer %zu bytes of data: %d\n" , + n_buf, ret); + } + +return ret; +} +#if !CONFIG_IS_ENABLED (OF_PLATDATA )static int spi_child_post_bind (struct udevice *dev) {
include/spi.h +20 -0
@@ -252,6 +252,26 @@ int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen);int spi_xfer (struct spi_slave *slave,unsigned int bitlen,const void *dout,void *din,unsigned long flags); +/** +* spi_write_then_read - SPI synchronous write followed by read +* +* This performs a half duplex transaction in which the first transaction +* is to send the opcode and if the length of buf is non-zero then it start +* the second transaction as tx or rx based on the need from respective slave. +* +* @slave: slave device with which opcode/data will be exchanged +* @opcode: opcode used for specific transfer +* @n_opcode: size of opcode, in bytes +* @txbuf: buffer into which data to be written +* @rxbuf: buffer into which data will be read +* @n_buf: size of buf (whether it's [tx|rx]buf), in bytes +* +* Returns: 0 on success, not 0 on failure +*/ +int spi_write_then_read (struct spi_slave *slave,const u8 *opcode, +size_t n_opcode,const u8 *txbuf,u8 *rxbuf, +size_t n_buf); +/* Copy memory mapped data */ void spi_flash_copy_mmap (void *data,void *offset,size_t len);
Signature · 1 line
2.7.4
PATCH v10 16/27 mtd: spi-nor: Add m25p80 driver
In reply to Jagan TekiThis is MTD SPI-NOR driver for ST M25Pxx (and similar) serial flash chips which is written as MTD_UCLASS.
--- drivers/mtd/spi-nor/Makefile | 3 + drivers/mtd/spi-nor/m25p80.c | 250 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 drivers/mtd/spi-nor/m25p80.c
drivers/mtd/spi-nor/Makefile +3 -0
@@ -7,3 +7,6 @@ ifdef CONFIG_MTD_SPI_NOR obj-y += spi-nor.o spi-nor-uclass.o spi-nor-ids.o endif + +## spi-nor to spi interface driver +obj-$(CONFIG_MTD_M25P80) += m25p80.o
drivers/mtd/spi-nor/m25p80.c new file +250 -0
250 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v10 17/27 mtd: spi-nor: Kconfig: Add MTD_M25P80 entry
In reply to Jagan TekiAdd CONFIG_MTD_M25P80 kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
drivers/mtd/spi-nor/Kconfig +17 -0
@@ -15,6 +15,23 @@ menuconfig MTD_SPI_NOR if MTD_SPI_NOR +config MTD_M25P80 + tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)" + depends on DM_SPI + help + This enables access to most modern SPI flash chips, used for + program and data storage. Series supported include Atmel AT26DF, + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips + are supported as well. See the driver source for the current list, + or to add other chips. + + Note that the original DataFlash chips (AT45 series, not AT26DF), + need an entirely different driver. + + Set up your spi devices with the right board-specific platform data, + if you want to specify device partitioning or to use a device which + doesn't support the JEDEC ID instruction. + config MTD_SPI_NOR_USE_4K_SECTORS bool "Use small 4096 B erase sectors" default y
Signature · 1 line
2.7.4
PATCH v10 18/27 mtd: spi-nor: Add zynq qspinor driver
In reply to Jagan TekiZynq qspinor controller is works similar way as generic spi controller with additional features that make this controller work more specific to flash chips as salve devices.
Why, zynq qspi written as spi-nor controller driver.
(1) dual flash:
This describes two/dual memories are connected with a single chip select line from a controller like dual stack and dual parallel connections see doc/SPI/README.dual-flash for more details.
Adding this support to spi-nor core looks quite managable and other generic code might effect and more over this is controller specific.
--- drivers/mtd/spi-nor/Makefile | 3 + drivers/mtd/spi-nor/zynq_qspinor.c | 622 +++++++++++++++++++++++++++++++++++++ 2 files changed, 625 insertions(+) create mode 100644 drivers/mtd/spi-nor/zynq_qspinor.c
drivers/mtd/spi-nor/Makefile +3 -0
@@ -10,3 +10,6 @@ endif ## spi-nor to spi interface driver obj-$(CONFIG_MTD_M25P80) += m25p80.o + +## spi-nor drivers +obj-$(CONFIG_MTD_ZYNQ_QSPI) += zynq_qspinor.o
drivers/mtd/spi-nor/zynq_qspinor.c new file +622 -0
622 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v10 19/27 mtd: spi-nor: zynq_qspi: Kconfig: Add MTD_ZYNQ
In reply to Jagan TekiAdd CONFIG_MTD_ZYNQ_QSPI kconfig entry
--- drivers/mtd/spi-nor/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/mtd/spi-nor/Kconfig +9 -0
@@ -46,6 +46,15 @@ config MTD_SPI_NOR_USE_4K_SECTORS Please note that some tools/drivers/filesystems may not work with 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). +config MTD_ZYNQ_QSPI + bool "Zynq QSPI NOR controller driver" + depends on ARCH_ZYNQ + help + Enable the Zynq Quad-SPI (QSPI) driver. This driver can be + used to access the SPI NOR flash on platforms embedding this + Zynq QSPI IP core. This IP is used to connect the flash in + 4-bit qspi, 8-bit dual stacked and shared 4-bit dual parallel. + config SPI_NOR_MISC bool "Miscellaneous SPI NOR flash's support" help
Signature · 1 line
2.7.4
PATCH v10 20/27 mtd: spi-nor: Add 4-byte addresswidth support
In reply to Jagan TekiAdd 4-byte address supports, so-that SPI-NOR chips has > 16MiB should accessible.
--- drivers/mtd/spi-nor/m25p80.c | 1 + drivers/mtd/spi-nor/spi-nor.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 6 +++++- 3 files changed, 44 insertions(+), 1 deletion(-)
drivers/mtd/spi-nor/m25p80.c +1 -0
@@ -35,6 +35,7 @@ static void m25p_addr2cmd(struct spi_nor *nor, unsigned int addr, u8 *cmd) cmd[1 ] = addr >> (nor->addr_width *8 -8 ); cmd[2 ] = addr >> (nor->addr_width *8 -16 ); cmd[3 ] = addr >> (nor->addr_width *8 -24 ); + cmd[4 ] = addr >> (nor->addr_width *8 -32 ); }static int m25p_cmdsz (struct spi_nor *nor)
drivers/mtd/spi-nor/spi-nor.c +38 -0
@@ -632,6 +632,38 @@ static int stm_unlock(struct udevice *dev, loff_t ofs, uint64_t len) }#endif +/* Enable/disable 4-byte addressing mode. */ +static int set_4byte (struct udevice *dev,const struct spi_nor_info *info, +int enable) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); +int status; +bool need_wren = false; +u8 cmd; + +switch (JEDEC_MFR (info)) { +case SNOR_MFR_MICRON : +/* Some Micron need WREN command; all will accept it */ + need_wren = true; +case SNOR_MFR_MACRONIX : +case SNOR_MFR_WINBOND : +if (need_wren) +write_enable (dev); + + cmd = enable ?SNOR_OP_EN4B :SNOR_OP_EX4B ; + status = ops->write_reg (dev, cmd,NULL ,0 ); +if (need_wren) +write_disable (dev); + +return status; +default : +/* Spansion style */ + nor->cmd_buf[0 ] = enable <<7 ; +return ops->write_reg (dev,SNOR_OP_BRWR , nor->cmd_buf,1 ); + } +} +#ifdef CONFIG_SPI_NOR_MACRONIX static int macronix_quad_enable (struct udevice *dev) {
@@ -873,6 +905,12 @@ int spi_nor_scan(struct spi_nor *nor) } nor->addr_width =3 ; +if (mtd->size >SNOR_16MB_BOUN ) { + nor->addr_width =4 ; + ret =set_4byte (nor->dev, info, true); +if (ret) + goto err; + }/* Dummy cycles for read */ switch (nor->read_opcode) {
include/linux/mtd/spi-nor.h +5 -1
@@ -63,6 +63,10 @@#define SNOR_OP_BP 0x02/* Byte program */ #define SNOR_OP_AAI_WP 0xad/* Auto addr increment word program */ +/* Used for Macronix and Winbond flashes. */ +#define SNOR_OP_EN4B 0xb7/* Enter 4-byte mode */ +#define SNOR_OP_EX4B 0xe9/* Exit 4-byte mode */ +/* Status Register bits. */ #define SR_WIP BIT(0)/* Write in progress */ #define SR_WEL BIT(1)/* Write enable latch */
@@ -84,7 +88,7 @@/* Flash timeout values */ #define SNOR_READY_WAIT_PROG (2 * CONFIG_SYS_HZ)#define SNOR_READY_WAIT_ERASE (5 * CONFIG_SYS_HZ) -#define SNOR_MAX_CMD_SIZE 4 +#define SNOR_MAX_CMD_SIZE 6#define SNOR_16MB_BOUN 0x1000000/**
Signature · 1 line
2.7.4
PATCH v10 20/27 mtd: spi-nor: Add 4-byte addresswidth support
Hi Jagan,
Quoted 66 lines · Jagan Teki
Add 4-byte address supports, so-that SPI-NOR chips has > 16MiB should accessible.
Signed-off-by Jagan Teki <[email protected]>--- drivers/mtd/spi-nor/m25p80.c | 1 + drivers/mtd/spi-nor/spi-nor.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 6 +++++- 3 files changed, 44 insertions(+), 1 deletion(-)drivers/mtd/spi-nor/m25p80.c +1
-0@@ -35,6 +35,7 @@ static void m25p_addr2cmd(struct spi_nor *nor, unsigned int addr, u8 *cmd) cmd[1 ] = addr >> (nor->addr_width *8 -8 ); cmd[2 ] = addr >> (nor->addr_width *8 -16 ); cmd[3 ] = addr >> (nor->addr_width *8 -24 ); + cmd[4 ] = addr >> (nor->addr_width *8 -32 ); }static int m25p_cmdsz (struct spi_nor *nor)drivers/mtd/spi-nor/spi-nor.c +32
-0@@ -632,6 +632,38 @@ static int stm_unlock(struct udevice *dev, loff_t ofs, uint64_t len) }#endif +/* Enable/disable 4-byte addressing mode. */ +static int set_4byte (struct udevice *dev,const struct spi_nor_info *info, +int enable) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); +int status; +bool need_wren = false; +u8 cmd; + +switch (JEDEC_MFR (info)) { +case SNOR_MFR_MICRON : +/* Some Micron need WREN command; all will accept it */ + need_wren = true; +case SNOR_MFR_MACRONIX : +case SNOR_MFR_WINBOND : +if (need_wren) +write_enable (dev); + + cmd = enable ?SNOR_OP_EN4B :SNOR_OP_EX4B ; + status = ops->write_reg (dev, cmd,NULL ,0 ); +if (need_wren) +write_disable (dev); + +return status; +default : +/* Spansion style */ + nor->cmd_buf[0 ] = enable <<7 ; +return ops->write_reg (dev,SNOR_OP_BRWR , nor->cmd_buf,1 ); + } +} +#ifdef CONFIG_SPI_NOR_MACRONIX static int macronix_quad_enable (struct udevice *dev) {
drivers/mtd/spi-nor/spi-nor.c int spi_nor_scan(struct spi_nor *nor) · line 914
Quoted 10 lines
drivers/mtd/spi-nor/spi-nor.c +6
-0@@ -873,6 +905,12 @@ int spi_nor_scan(struct spi_nor *nor) } nor->addr_width =3 ; +if (mtd->size >SNOR_16MB_BOUN ) { + nor->addr_width =4 ; + ret =set_4byte (nor->dev, info, true); +if (ret) + goto err; + }
This is a bad idea: you make the SPI NOR memory enter its 4-byte address mode, which is statefull. Then, once in Linux for instance, the memory would still be in its 4-byte address mode but expected to be in its reset state, hence in 3-byte address mode.
At this point, this might not be an issue yet because spi-nor under linux is likely to use the 4-byte address instruction set if available, which is stateless by the way, so whatever the memory is in its 3-byte or in 4-byte address mode, the op codes of the 4-byte address instruction set are always expected to be followed by a 4-byte address. So Linux won't notice that the SPI NOR memory is in its 4-byte mode but not in its 3-byte mode as expected.
However, if a spurious reboot occurs at the CPU side after the SPI NOR memory has entered its 4-byte address mode, either still in u-boot or already in linux or whatever running code, the SPI NOR memory, likely not reset on its side, would still be in its 4-byte address mode, whereas many earlier boot-loaders would expect the memory to be in it's reset state, ie in its 3-byte address mode. Hence those boot-loaders, running before u-boot, would not be able to read data (load u-boot) from the SPI NOR memory:
the boot would fail!
Examples of those early boot-loaders are the ROM Codes of many Atmel SAMA5Dx SoCs but I'm pretty sure this issue also applies to other manufacturers based on patches I've seen on the linux-mtd mailing list to add the SPI_NOR_4B_OPCODES flag to some memory parts:
https://patchwork.ozlabs.org/patch/750305/
Think about a watchdog resetting the CPU for instance.
TL;DR
You should avoid making the SPI NOR memory enter its statefull 4-byte address mode but consider using the stateless 4-byte address instruction set instead, when possible.
Almost all recent SPI NOR memories with sizes > 16MiB support the 4-byte address mode.
Best regards,
Cyrille
Quoted 27 lines
drivers/mtd/spi-nor/spi-nor.c +0
-0/* Dummy cycles for read */ switch (nor->read_opcode) {include/linux/mtd/spi-nor.h +5
-1@@ -63,6 +63,10 @@#define SNOR_OP_BP 0x02/* Byte program */ #define SNOR_OP_AAI_WP 0xad/* Auto addr increment word program */ +/* Used for Macronix and Winbond flashes. */ +#define SNOR_OP_EN4B 0xb7/* Enter 4-byte mode */ +#define SNOR_OP_EX4B 0xe9/* Exit 4-byte mode */ +/* Status Register bits. */ #define SR_WIP BIT(0)/* Write in progress */ #define SR_WEL BIT(1)/* Write enable latch */ @@ -84,7 +88,7 @@/* Flash timeout values */ #define SNOR_READY_WAIT_PROG (2 * CONFIG_SYS_HZ)#define SNOR_READY_WAIT_ERASE (5 * CONFIG_SYS_HZ) -#define SNOR_MAX_CMD_SIZE 4 +#define SNOR_MAX_CMD_SIZE 6#define SNOR_16MB_BOUN 0x1000000/**
PATCH v10 20/27 mtd: spi-nor: Add 4-byte addresswidth support
Le 28/12/2017 à 09:06, Cyrille Pitchen a écrit :
Quoted 110 lines
Hi Jagan,
Quoted 66 lines · Jagan Teki
Add 4-byte address supports, so-that SPI-NOR chips has > 16MiB should accessible.
Signed-off-by Jagan Teki <[email protected]>--- drivers/mtd/spi-nor/m25p80.c | 1 + drivers/mtd/spi-nor/spi-nor.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 6 +++++- 3 files changed, 44 insertions(+), 1 deletion(-)drivers/mtd/spi-nor/m25p80.c +1
-0@@ -35,6 +35,7 @@ static void m25p_addr2cmd(struct spi_nor *nor, unsigned int addr, u8 *cmd) cmd[1 ] = addr >> (nor->addr_width *8 -8 ); cmd[2 ] = addr >> (nor->addr_width *8 -16 ); cmd[3 ] = addr >> (nor->addr_width *8 -24 ); + cmd[4 ] = addr >> (nor->addr_width *8 -32 ); }static int m25p_cmdsz (struct spi_nor *nor)drivers/mtd/spi-nor/spi-nor.c +32
-0@@ -632,6 +632,38 @@ static int stm_unlock(struct udevice *dev, loff_t ofs, uint64_t len) }#endif +/* Enable/disable 4-byte addressing mode. */ +static int set_4byte (struct udevice *dev,const struct spi_nor_info *info, +int enable) +{ +struct spi_nor *nor =spi_nor_get_spi_nor_dev (dev); +const struct spi_nor_ops *ops =spi_nor_get_ops (dev); +int status; +bool need_wren = false; +u8 cmd; + +switch (JEDEC_MFR (info)) { +case SNOR_MFR_MICRON : +/* Some Micron need WREN command; all will accept it */ + need_wren = true; +case SNOR_MFR_MACRONIX : +case SNOR_MFR_WINBOND : +if (need_wren) +write_enable (dev); + + cmd = enable ?SNOR_OP_EN4B :SNOR_OP_EX4B ; + status = ops->write_reg (dev, cmd,NULL ,0 ); +if (need_wren) +write_disable (dev); + +return status; +default : +/* Spansion style */ + nor->cmd_buf[0 ] = enable <<7 ; +return ops->write_reg (dev,SNOR_OP_BRWR , nor->cmd_buf,1 ); + } +} +#ifdef CONFIG_SPI_NOR_MACRONIX static int macronix_quad_enable (struct udevice *dev) {drivers/mtd/spi-nor/spi-nor.c int spi_nor_scan(struct spi_nor *nor) · line 914
Quoted 10 lines
drivers/mtd/spi-nor/spi-nor.c +6
-0@@ -873,6 +905,12 @@ int spi_nor_scan(struct spi_nor *nor) } nor->addr_width =3 ; +if (mtd->size >SNOR_16MB_BOUN ) { + nor->addr_width =4 ; + ret =set_4byte (nor->dev, info, true); +if (ret) + goto err; + }This is a bad idea: you make the SPI NOR memory enter its 4-byte address mode, which is statefull. Then, once in Linux for instance, the memory would still be in its 4-byte address mode but expected to be in its reset state, hence in 3-byte address mode.
At this point, this might not be an issue yet because spi-nor under linux is likely to use the 4-byte address instruction set if available, which is stateless by the way, so whatever the memory is in its 3-byte or in 4-byte address mode, the op codes of the 4-byte address instruction set are always expected to be followed by a 4-byte address. So Linux won't notice that the SPI NOR memory is in its 4-byte mode but not in its 3-byte mode as expected.
However, if a spurious reboot occurs at the CPU side after the SPI NOR memory has entered its 4-byte address mode, either still in u-boot or already in linux or whatever running code, the SPI NOR memory, likely not reset on its side, would still be in its 4-byte address mode, whereas many earlier boot-loaders would expect the memory to be in it's reset state, ie in its 3-byte address mode. Hence those boot-loaders, running before u-boot, would not be able to read data (load u-boot) from the SPI NOR memory:
the boot would fail!Examples of those early boot-loaders are the ROM Codes of many Atmel SAMA5Dx SoCs but I'm pretty sure this issue also applies to other manufacturers based on patches I've seen on the linux-mtd mailing list to add the
SPI_NOR_4B_OPCODESflag to some memory parts:
https://patchwork.ozlabs.org/patch/750305/Think about a watchdog resetting the CPU for instance.
Quoted 7 lines
TL;DR
You should avoid making the SPI NOR memory enter its statefull 4-byte address mode but consider using the stateless 4-byte address instruction set instead, when possible.Almost all recent SPI NOR memories with sizes > 16MiB support the 4-byte address mode.
I meant the 4-byte address instruction set ;)
Quoted 33 lines
Best regards,
Cyrille
Quoted 27 lines
drivers/mtd/spi-nor/spi-nor.c +0
-0/* Dummy cycles for read */ switch (nor->read_opcode) {include/linux/mtd/spi-nor.h +5
-1@@ -63,6 +63,10 @@#define SNOR_OP_BP 0x02/* Byte program */ #define SNOR_OP_AAI_WP 0xad/* Auto addr increment word program */ +/* Used for Macronix and Winbond flashes. */ +#define SNOR_OP_EN4B 0xb7/* Enter 4-byte mode */ +#define SNOR_OP_EX4B 0xe9/* Exit 4-byte mode */ +/* Status Register bits. */ #define SR_WIP BIT(0)/* Write in progress */ #define SR_WEL BIT(1)/* Write enable latch */ @@ -84,7 +88,7 @@/* Flash timeout values */ #define SNOR_READY_WAIT_PROG (2 * CONFIG_SYS_HZ)#define SNOR_READY_WAIT_ERASE (5 * CONFIG_SYS_HZ) -#define SNOR_MAX_CMD_SIZE 4 +#define SNOR_MAX_CMD_SIZE 6#define SNOR_16MB_BOUN 0x1000000/**
PATCH v10 21/27 cmd: add spinor cmd support
In reply to Jagan TekiNow, spi-nor framework is up so access spi-nor device from command prompt via 'spinor'
--- cmd/Kconfig | 5 + cmd/Makefile | 1 + cmd/spinor.c | 281 ++++++++++++++++++++++++++++++++++++++++++++ drivers/mtd/Makefile | 7 +- include/linux/mtd/spi-nor.h | 1 + 5 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 cmd/spinor.c
cmd/Kconfig +5 -0
@@ -870,6 +870,11 @@ config CMD_SDRAM SDRAM has an EEPROM with information that can be read using the I2C bus. This is only available on some boards. +config CMD_SPINOR + bool "spinor" + help + SPI NOR Flash support + config CMD_SF bool "sf" help
cmd/Makefile +1 -0
@@ -108,6 +108,7 @@ obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o obj-$(CONFIG_SANDBOX) += host.o obj-$(CONFIG_CMD_SATA) += sata.o obj-$(CONFIG_CMD_NVME) += nvme.o +obj-$(CONFIG_CMD_SPINOR) += spinor.o obj-$(CONFIG_CMD_SF) += sf.o obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
cmd/spinor.c new file +281 -0
281 lines not on this page · raw message
drivers/mtd/Makefile +5 -2
@@ -5,8 +5,11 @@ # SPDX-License-Identifier: GPL-2.0+ # -ifneq (,$(findstring y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND)$(CONFIG_CMD_SF))) -obj-y += mtdcore.o mtd_uboot.o +ifneq (,$(findstring y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND)$(CONFIG_CMD_SF),$(CONFIG_CMD_SPINOR))) +obj-y += mtd_uboot.o +ifndef CONFIG_MTD +obj-y += mtdcore.o +endif endif obj-$(CONFIG_MTD) += mtd-uclass.o obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
include/linux/mtd/spi-nor.h +1 -0
@@ -217,5 +217,6 @@ struct spi_nor *find_spi_nor_device(int dev_num);int get_spi_nor_num (void );struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev);struct mtd_info *spi_nor_get_mtd_info (struct spi_nor *nor); +void print_spi_nor_devices (char separator);#endif /* __MTD_SPI_NOR_H */
Signature · 1 line
2.7.4
PATCH v10 22/27 cmd: spinor: sync/update protect command
In reply to Jagan Tekisync the protect command from legacy cmd/sf.c and update them according to current spi-nor framework.
--- cmd/spinor.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- drivers/mtd/mtd-uclass.c | 19 +++++++++++++++++++ include/mtd.h | 11 +++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-)
cmd/spinor.c +46 -1
@@ -151,6 +151,44 @@ static int do_spinor_write_read(int argc, char * const argv[])return ret ==0 ?CMD_RET_SUCCESS :CMD_RET_FAILURE ; } +static int do_spinor_protect (int argc,char *const argv[]) +{ +struct mtd_info *mtd; +struct spi_nor *nor; +loff_t sector, len, maxsize; +char *endp; +int idx =0 ; +bool prot = false; +int ret =CMD_RET_FAILURE ; + +if (argc !=4 ) +return CMD_RET_USAGE ; + + nor =init_spinor_device (curr_device, false); +if (!nor) +return CMD_RET_FAILURE ; + + sector =simple_strtoul (argv[2 ], &endp,16 ); +if (*argv[2 ] ==0 || *endp !=0 ) +return CMD_RET_FAILURE ; + + mtd =spi_nor_get_mtd_info (nor); +if (mtd_arg_off_size (argc -3 , &argv[3 ], &idx, §or, &len, + &maxsize,MTD_DEV_TYPE_NOR , mtd->size)) +return CMD_RET_FAILURE ; + +if (strcmp (argv[1 ],"lock" ) ==0 ) + prot = true; +else if (strcmp (argv[1 ],"unlock" ) ==0 ) + prot = false; +else +return -1 ;/* Unknown parameter */ + + ret =mtd_dprotect (mtd, sector, len, prot); + +return ret ==0 ?CMD_RET_SUCCESS :CMD_RET_FAILURE ; +} +static int mtd_parse_len_arg (struct mtd_info *mtd,char *arg,loff_t *len) {char *ep;
@@ -258,6 +296,11 @@ static int do_spinor(cmd_tbl_t *cmdtp, int flag, int argc, goto done; } +if (strcmp (cmd,"protect" ) ==0 ) { + ret =do_spinor_protect (argc, argv); + goto done; + } + done:if (ret !=-1 )return ret;
@@ -272,7 +315,9 @@ static char spinor_help_text[] ="spinor dev [devnum] - show or set current spinor device\n" "spinor erase offset len - erase 'len' bytes from 'offset'\n" "spinor write addr to len - write 'len' bytes to 'to' from 'addr'\n" -"spinor read addr from len - read 'len' bytes from 'from' to 'addr'" ; +"spinor read addr from len - read 'len' bytes from 'from' to 'addr'\n" +"spinor protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n" +" at address 'sector'" ; U_BOOT_CMD( spinor, 5, 1, do_spinor,
drivers/mtd/mtd-uclass.c +19 -0
@@ -73,6 +73,25 @@ int mtd_dwrite(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,return ops->write (dev, to, len, retlen, buf); } +int mtd_dprotect (struct mtd_info *mtd,loff_t ofs,uint64_t len,bool prot) +{ +struct udevice *dev = mtd->dev; +const struct mtd_ops *ops =mtd_get_ops (dev); + +if (!ops->lock || !ops->unlock) +return -ENOSYS ; + +if (ofs <0 || ofs > mtd->size || len > mtd->size - ofs) +return -EINVAL ; +if (!len) +return 0 ; + +if (prot) +return ops->lock (dev, ofs, len); +else +return ops->unlock (dev, ofs, len); +} +int mtd_find_device (int mtd_if_type,int devnum,struct udevice **devp) {struct uclass *uc;
include/mtd.h +11 -0
@@ -61,6 +61,17 @@ int mtd_dwrite(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);/** +* mtd_dprotect - protect area of MTD device +* +* @mtd: MTD device +* @ofs: sector start offset into device in bytes to protect to +* @len: len of bytes to protect +* @prot: protect boolean, true for lock, false for unlock +* @return 0 if OK, -ve on error +*/ +int mtd_dprotect (struct mtd_info *mtd,loff_t ofs,uint64_t len,bool prot); + +/** * mtd_derase() - erase blocks of the MTD device * * @mtd: MTD device
Signature · 1 line
2.7.4
PATCH v10 23/27 board_r: initialize spi_nor
In reply to Jagan Tekiinitialize spi-nor framework during boot, so-that detected buses can appears at boot log.
--- common/board_r.c | 13 +++++++++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 17 +++++++++++++++++ include/linux/mtd/spi-nor.h | 1 + 3 files changed, 31 insertions(+)
common/board_r.c +13 -0
@@ -42,6 +42,7 @@#include <scsi.h> #include <serial.h> #include <spi.h> +#include <linux/mtd/spi-nor.h> #include <stdio_dev.h> #include <timer.h> #include <trace.h>
@@ -400,6 +401,15 @@ static int initr_spi(void) }#endif +#ifdef CONFIG_MTD_SPI_NOR +static int initr_spi_nor (void ) +{ +puts ("SPI-NOR: " ); +spi_nor_init (); +return 0 ; +} +#endif +#ifdef CONFIG_CMD_NAND /* go init the NAND */ static int initr_nand (void )
@@ -762,6 +772,9 @@ static init_fnc_t init_sequence_r[] = {#ifdef CONFIG_PPC initr_spi,#endif +#ifdef CONFIG_MTD_SPI_NOR + initr_spi_nor, +#endif #ifdef CONFIG_CMD_NAND initr_nand,#endif
drivers/mtd/spi-nor/spi-nor-uclass.c +17 -0
@@ -15,6 +15,23 @@DECLARE_GLOBAL_DATA_PTR ; +int spi_nor_init (void ) +{ +struct udevice *bus; + +for (uclass_first_device (UCLASS_SPI_NOR , &bus); + bus; +uclass_next_device (&bus)) { + ; + } + +#ifndef CONFIG_SPL_BUILD +print_spi_nor_devices (',' ); +#endif + +return 0 ; +} +struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev) {struct spi_nor_uclass_priv *upriv;
include/linux/mtd/spi-nor.h +1 -0
@@ -218,5 +218,6 @@ int get_spi_nor_num(void);struct spi_nor *spi_nor_get_spi_nor_dev (struct udevice *dev);struct mtd_info *spi_nor_get_mtd_info (struct spi_nor *nor);void print_spi_nor_devices (char separator); +int spi_nor_init (void );#endif /* __MTD_SPI_NOR_H */
Signature · 1 line
2.7.4
PATCH v10 23/27 board_r: initialize spi_nor
Hi Jagan,
Quoted 11 lines · Jagan Teki
initialize spi-nor framework during boot, so-that detected buses can appears at boot log.
Signed-off-by Suneel Garapati <[email protected]>Signed-off-by Jagan Teki <[email protected]>--- common/board_r.c | 13 +++++++++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 17 +++++++++++++++++ include/linux/mtd/spi-nor.h | 1 + 3 files changed, 31 insertions(+)
We should rely on driver model to init this when it is first probed, so this should not be needed.
Regards,
Simon
PATCH v10 24/27 env: add spi-nor environment
In reply to Jagan TekiNow spi-nor framework is up so access the environment through en/spinor.c
--- cmd/nvedit.c | 1 + env/Kconfig | 27 ++++++++++++ env/Makefile | 1 + env/env.c | 2 + env/spinor.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/environment.h | 1 + 6 files changed, 145 insertions(+) create mode 100644 env/spinor.c
cmd/nvedit.c +1 -0
@@ -50,6 +50,7 @@ DECLARE_GLOBAL_DATA_PTR; !defined (CONFIG_ENV_IS_IN_ONENAND ) && \ !defined (CONFIG_ENV_IS_IN_SATA ) && \ !defined (CONFIG_ENV_IS_IN_SPI_FLASH ) && \ + !defined (CONFIG_ENV_IS_IN_SPI_NOR ) && \ !defined (CONFIG_ENV_IS_IN_REMOTE ) && \ !defined (CONFIG_ENV_IS_IN_UBI ) && \ !defined (CONFIG_ENV_IS_NOWHERE )
env/Kconfig +27 -0
@@ -329,6 +329,22 @@ config ENV_IS_IN_SPI_FLASH Define the SPI work mode. If not defined then use SPI_MODE_3. +config ENV_IS_IN_SPI_NOR + bool "Environment is in SPI-NOR flash" + depends on !CHAIN_OF_TRUST + help + Define this if you have a SPI NOR Flash memory device which you + want to use for the environment. + + - CONFIG_ENV_OFFSET: + - CONFIG_ENV_SIZE: + + These two #defines specify the offset and size of the + environment area within the SPI NOR Flash. CONFIG_ENV_OFFSET must be + aligned to an erase sector boundary. + + - CONFIG_ENV_SECT_SIZE: + config ENV_IS_IN_UBI bool "Environment in a UBI volume" depends on !CHAIN_OF_TRUST
@@ -396,6 +412,17 @@ config ENV_FAT_FILE It's a string of the FAT file name. This file use to store the environment. +config ENV_SPI_NOR_DEVNUM + int "SPI-NOR device number for the environment" + depends on ENV_IS_IN_SPI_NOR + default 0 + help + Define this an integer of spi nor device number for the environment. + Since spi nor framework assign device numbers automatically by devicetree + node definition which start from 0, so assign 0 as default. + + If board need different devnum then, this can be change. + if ARCH_SUNXI config ENV_OFFSET
env/Makefile +1 -0
@@ -25,6 +25,7 @@ obj-$(CONFIG_ENV_IS_IN_NVRAM) += nvram.o obj-$(CONFIG_ENV_IS_IN_ONENAND) += onenand.o obj-$(CONFIG_ENV_IS_IN_SATA) += sata.o obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += sf.o +obj-$(CONFIG_ENV_IS_IN_SPI_NOR) += spinor.o obj-$(CONFIG_ENV_IS_IN_REMOTE) += remote.o obj-$(CONFIG_ENV_IS_IN_UBI) += ubi.o obj-$(CONFIG_ENV_IS_NOWHERE) += nowhere.o
env/env.c +2 -0
@@ -44,6 +44,8 @@ static enum env_location env_get_default_location(void)return ENVL_REMOTE ; else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH) return ENVL_SPI_FLASH; + else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_NOR) + return ENVL_SPI_NOR; else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI) return ENVL_UBI; else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
env/spinor.c new file +113 -0
113 lines not on this page · raw message
include/environment.h +1 -0
@@ -198,6 +198,7 @@ enum env_location {ENVL_ONENAND ,ENVL_REMOTE ,ENVL_SPI_FLASH , +ENVL_SPI_NOR ,ENVL_UBI , ENVL_NOWHERE,
Signature · 1 line
2.7.4
PATCH v10 24/27 env: add spi-nor environment
Hi Jagan,
Quoted 7 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:43 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 24/27] env: add spi-nor environment
Quoted 5 lines
Now spi-nor framework is up so access the environment through
en/spinor.cSigned-off-by Suneel Garapati <[email protected]>Signed-off-by Jagan Teki <[email protected]>
This patch is only considering environment to be used after relocation to DDR.
What about the scenario where environment is required during SPL.
SPL may not be having MTD sub-system ready for env read. In SPL case raw read is required. Similar to below patch.
http://patchwork.ozlabs.org/patch/848511/
I request you to consider this patch also.
--pk
PATCH v10 25/27 arm: dts: zynq: Add zynq-qspinor node
In reply to Jagan Tekizynq qspi controller can be considered as spi-nor controller since controller meant for accessing spi-nor chips along with flash related functionalities.
--- arch/arm/dts/zynq-7000.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/arm/dts/zynq-7000.dtsi +12 -0
@@ -213,6 +213,18 @@ #size-cells = <0>; }; + qspinor: spi-nor at e000d000 { + clock-names = "ref_clk", "pclk"; + clocks = <&clkc 10>, <&clkc 43>; + compatible = "xlnx,zynq-qspinor-1.0"; + status = "disabled"; + interrupt-parent = <&intc>; + interrupts = <0 19 4>; + reg = <0xe000d000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + }; + gem0: ethernet at e000b000 { compatible = "cdns,zynq-gem", "cdns,gem"; reg = <0xe000b000 0x1000>;
Signature · 1 line
2.7.4
PATCH v10 26/27 dm: zynq: microzed: enable MTD/SPI-NOR framework
In reply to Jagan TekiEnable spi-nor framework for zynq microzed board, the zynq_qspi controller at spi still there for testing once the framework is mature will drop.
test log:
========
Zynq> spinor
spinor - SPI-NOR Sub-system
Usage:
spinor list - show list of spinor devices spinor info - show current spinor device info spinor dev [devnum] - show or set current spinor device spinor erase offset len - erase 'len' bytes from 'offset' spinor write addr to len - write 'len' bytes to 'to' from 'addr' spinor read addr from len - read 'len' bytes from 'from' to 'addr'
spinor protect lock/unlock sector len - protect/unprotect 'len' bytes starting
at address 'sector'
Zynq> spinor list
flash at 0: 0
spi-nor at e000d000: 1
Zynq> spinor dev 0
switch to dev #0, OK
spinor0 is current device
Zynq> spinor info
bus: flash at 0: 0
device: s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase 0xE00000 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Erased: OK
Zynq> mw.b 0x100 0xcc 0x100000
Zynq> spinor write 0x100 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Written: OK
Zynq> spinor read 0x3000000 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Read: OK
Zynq> cmp.b 0x3000000 0x100 0x100000
Total of 1048576 byte(s) were the same
Zynq> spinor dev 1
switch to dev #1, OK
spinor1 is current device
Zynq> spinor info
bus: spi-nor at e000d000: 1
device: s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase 0xE00000 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Erased: OK
Zynq> mw.b 0x100 0xbb 0x100000
Zynq> spinor write 0x100 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Written: OK
Zynq> spinor read 0x3000000 0xE00000 0x100000
device 0 offset 0xe00000, size 0x100000
SPI-NOR: 1048576 bytes @ 0xe00000 Read: OK
Zynq> cmp.b 0x3000000 0x100 0x100000
Total of 1048576 byte(s) were the same
--- arch/arm/dts/zynq-microzed.dts | 12 +++++++++++- configs/zynq_microzed_defconfig | 17 ++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-)
arch/arm/dts/zynq-microzed.dts +11 -1
@@ -14,7 +14,6 @@ aliases { serial0 = &uart1; - spi0 = &qspi; mmc0 = &sdhci0; };
@@ -41,6 +40,17 @@ &qspi { u-boot,dm-pre-reloc; status = "okay"; + + s25fl128s_64k: flash at 0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "jedec,spi-nor"; + }; +}; + +&qspinor { + status = "okay"; }; &uart1 {
configs/zynq_microzed_defconfig +10 -7
@@ -19,7 +19,7 @@ CONFIG_CMD_FPGA_LOADMK=y CONFIG_CMD_FPGA_LOADP=y CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y -CONFIG_CMD_SF=y +CONFIG_CMD_SPINOR=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TFTPPUT=y
@@ -32,7 +32,7 @@ CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y -CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_IS_IN_SPI_NOR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DFU_MMC=y
@@ -40,14 +40,17 @@ CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y -CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_SPI_FLASH_WINBOND=y CONFIG_ZYNQ_GEM=y CONFIG_ZYNQ_SERIAL=y CONFIG_ZYNQ_QSPI=y +CONFIG_MTD=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_ZYNQ_QSPI=y +CONFIG_SPI_NOR_STMICRO=y +CONFIG_SPI_NOR_SPANSION=y +CONFIG_SPI_NOR_WINBOND=y +CONFIG_SPI_NOR_MACRONIX=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_ULPI_VIEWPORT=y
Signature · 1 line
2.7.4
PATCH v10 27/27 test: dm: add tests for mtd devices
In reply to Jagan TekiAdd some tests to check that mtd devices work as expected, more tests will add it in future.
Also removed CMD_MTDPARTS which breaking driver-model MTD.
--- configs/sandbox_defconfig | 8 +++++++- test/dm/Makefile | 1 + test/dm/mtd.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/dm/mtd.c
configs/sandbox_defconfig +7 -1
@@ -65,7 +65,6 @@ CONFIG_CMD_BTRFS=y CONFIG_CMD_CBFS=y CONFIG_CMD_CRAMFS=y CONFIG_CMD_EXT4_WRITE=y -CONFIG_CMD_MTDPARTS=y CONFIG_CMD_LOG=y CONFIG_MAC_PARTITION=y CONFIG_AMIGA_PARTITION=y
@@ -197,3 +196,10 @@ CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_UT_ENV=y CONFIG_UT_OVERLAY=y +CONFIG_MTD=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_M25P80=y +CONFIG_SPI_NOR_STMICRO=y +CONFIG_SPI_NOR_SPANSION=y +CONFIG_SPI_NOR_WINBOND=y +CONFIG_SPI_NOR_MACRONIX=y
test/dm/Makefile +1 -0
@@ -22,6 +22,7 @@ obj-$(CONFIG_DM_GPIO) += gpio.o obj-$(CONFIG_DM_I2C) += i2c.o obj-$(CONFIG_LED) += led.o obj-$(CONFIG_DM_MAILBOX) += mailbox.o +obj-$(CONFIG_MTD) += mtd.o obj-$(CONFIG_DM_MMC) += mmc.o obj-$(CONFIG_DM_PCI) += pci.o obj-$(CONFIG_PHY) += phy.o
test/dm/mtd.c new file +33 -0
@@ -0,0 +1,33 @@ +/* +* Copyright (C) 2017 Jagan Teki <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <asm/state.h> +#include <dm/test.h> +#include <test/ut.h> + +#include <mtd.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/spi-nor.h> + +DECLARE_GLOBAL_DATA_PTR ; + +/* Test that we can find mtd devices without probing them */ +static int dm_test_mtd_find (struct unit_test_state *uts) +{ +struct udevice *mtd, *spinor, *dev; + +ut_assertok (mtd_create_device (mtd,"spinor_mtd" ,"test" , +MTD_IF_TYPE_SPI_NOR , &spinor)); + +ut_asserteq (-ENODEV ,mtd_find_device (MTD_IF_TYPE_SPI_NOR ,1 , &dev)); +ut_assertok (mtd_find_device (MTD_IF_TYPE_SPI_NOR ,0 , &dev)); +ut_asserteq_ptr (spinor, dev); + +return 0 ; +} +DM_TEST (dm_test_mtd_find,DM_TESTF_SCAN_PDATA |DM_TESTF_SCAN_FDT );
Signature · 1 line
2.7.4
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
In reply to Jagan TekiHi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.c
Quoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.
I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 3 lines
=======================================
cmd/spinor.c
^^^^^ - this would be a new set of commands to comply with DM?
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
Quoted 2 lines
=======================================
mtd-uclass.c
^^^^^ - here we will have a generic MTD layer (as it is in Linux)
Quoted 4 lines
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
^^^^^^ - why do we need to have spi-nor.c ? Cannot we have its functionality in the spi-nor-uclass.c ? (I'm just curious)
Quoted 2 lines
=======================================
m25p80.czynq_qspinor.c
^^^^^ - this is the ^^^^^^^^ - [*]
"generic" spi-nor
driver used in Linux.
I suppose that it will
be reused here?
Quoted 2 lines
=======================================
spi-uclass.c
^^^^^^^ - why do we
need this uclass?
Quoted 2 lines
=======================================
zynq_qspi.c
^^^^^ - This is probably
the low-level driver for
zynq QSPI IP block - why
do we have zynq_qspinor.c file above [*]?
What is the difference/need of such division?
Quoted 33 lines
=======================================
#####SPI NOR chip######=======================================
Changes for v10:
- Update Simon's R-B tag
- Add mtd dm test case
- implemented entire code wrt MTD, with interface typecode size:
==========
before:$ arm-linux-gnueabi-size u-boot text data bss dec hex filename 473712 15152 222568 711432 adb08 u-boot $ du -hs u-boot-dtb.img 488K u-boot-dtb.imgafter:
$ arm-linux-gnueabi-size u-boot text data bss dec hex filename 470124 14352 222584 707060 ac9f4 u-boot $ du -hs u-boot-dtb.img 484K u-boot-dtb.imgapproximately 4KiB but
DM_SPI_FLASHstill there which can be removed once support added in SPLtest log:
========
Zynq> spinor
spinor - SPI-NOR Sub-system
Quoted 6 lines
Usage:
spinor list - show list of spinor devices spinor info - show current spinor device info spinor dev [devnum] - show or set current spinor device spinor erase offset len - erase 'len' bytes from 'offset' spinor write addr to len - write 'len' bytes to 'to' from
^^^^^^^^^^^^^^^^ I would love to see support for "mtdparts=" It would facilitate handling SPI-NOR "partitions" like u-boot/SPI/envs/ etc.
I also suppose that "sf probe" (or any its replacement with spinor) would be not necessary to call before using other SPI-NOR related commands?
Maybe the biggest request - would it be possible to add ./doc/README.spi-nor entry with good explanation of this?
Quoted 129 lines
'addr' spinor read addr from len - read 'len' bytes from 'from'
to 'addr' spinor protect lock/unlock sector len - protect/unprotect 'len' bytes starting at address 'sector'
Zynq> spinor list
flash at 0: 0
spi-nor ate000d000: 1
Zynq> spinor dev 0
switch to dev #0, OK
spinor0 is current device
Zynq> spinor info
bus: flash at 0: 0
device:s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase0xE000000x100000
SPI-NOR: 1048576 bytes @0xe00000Erased: OK
Zynq> mw.b0x1000xcc0x100000
Zynq> spinor write0x1000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Written: OK
Zynq> spinor read0x30000000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Read: OK
Zynq> cmp.b0x30000000x1000x100000
Total of 1048576 byte(s) were the same
Zynq> spinor dev 1
switch to dev #1, OK
spinor1 is current device
Zynq> spinor info
bus: spi-nor ate000d000: 1
device:s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase0xE000000x100000
SPI-NOR: 1048576 bytes @0xe00000Erased: OK
Zynq> mw.b0x1000xbb0x100000
Zynq> spinor write0x1000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Written: OK
Zynq> spinor read0x30000000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Read: OK
Zynq> cmp.b0x30000000x1000x100000
Total of 1048576 byte(s) were the sameWIP:
===
- to support non-dm code
- to support spinor SPLRepo:
====$ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b mtd-spinor-working origin/mtd-spinor-working[1] https://lists.denx.de/pipermail/u-boot/2016-October/271459.html
[2] http://lists.denx.de/pipermail/u-boot/2016-March/249286.html
[3] http://lists.denx.de/pipermail/u-boot/2016-February/245418.html
[4] [PATCH RFC v8 00/16] SPI-NOR/MTD additionJagan Teki (27):
mtd: Add mtd core ops
mtd: add mtd device create operations
mtd: add SPI-NOR core support
mtd: spi-nor: sync/modify sst write operations
mtd: spi-nor: sync/modify lock operations
mtd: spi-nor:Kconfig: AddMTD_SPI_NORentry
mtd: spi-nor:Kconfig: AddMTD_SPI_NOR_USE_4K_SECTORS
mtd: spi-nor:Kconfig: AddSPI_NOR_MISCentry
mtd: spi-nor:Kconfig: AddSPI_NOR_MACRONIXentry
mtd: spi-nor:Kconfig: AddSPI_NOR_SPANSIONentry
mtd: spi-nor:Kconfig: AddSPI_NOR_STMICROentry
mtd: spi-nor:Kconfig: AddSPI_NOR_SSTentry
mtd: spi-nor:Kconfig: AddSPI_NOR_WINBONDentry
mtd-uclass: useplatdata_auto_alloc
spi: Addspi_write_then_read
mtd: spi-nor: Add m25p80 driver
mtd: spi-nor:Kconfig: AddMTD_M25P80entry
mtd: spi-nor: Add zynq qspinor driver
mtd: spi-nor:zynq_qspi:Kconfig: AddMTD_ZYNQ
mtd: spi-nor: Add 4-byte addresswidth support
cmd: add spinor cmd support
cmd: spinor: sync/update protect command
board_r: initializespi_nor
env: add spi-nor environment
arm: dts: zynq: Add zynq-qspinor node
dm: zynq: microzed: enable MTD/SPI-NOR framework
test: dm: add tests for mtd devicesMakefile | 1 + arch/arm/dts/zynq-7000.dtsi | 12 + arch/arm/dts/zynq-microzed.dts | 12 +- cmd/Kconfig | 5 + cmd/Makefile | 1 + cmd/nvedit.c | 1 + cmd/spinor.c | 326 ++++++++++++ common/board_r.c | 13 + configs/sandbox_defconfig | 8 +- configs/zynq_microzed_defconfig | 17 +- drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 7 +- drivers/mtd/mtd-uclass.c | 203 +++++++- drivers/mtd/spi-nor/Kconfig | 89 ++++ drivers/mtd/spi-nor/Makefile | 15 + drivers/mtd/spi-nor/m25p80.c | 251 ++++++++++ drivers/mtd/spi-nor/spi-nor-ids.c | 184 +++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 160 ++++++ drivers/mtd/spi-nor/spi-nor.c | 940 +++++++++++++++++++++++++++++++++++ drivers/mtd/spi-nor/zynq_qspinor.c | 622 +++++++++++++++++++++++ drivers/spi/spi-uclass.c | 24 + env/Kconfig | 27 + env/Makefile | 1 + env/env.c | 2 + env/spinor.c | 113 +++++ include/dm/uclass-id.h | 1 + include/environment.h | 1 + include/linux/mtd/mtd.h | 14 + include/linux/mtd/spi-nor.h | 223 +++++++++ include/mtd.h | 176 +++++++ include/spi.h | 20 + test/dm/Makefile | 1 + test/dm/mtd.c | 33 ++ 33 files changed, 3493 insertions(+), 12 deletions(-) create mode 100644 cmd/spinor.c create mode 100644 drivers/mtd/spi-nor/Kconfig create mode 100644 drivers/mtd/spi-nor/Makefile
Quoted 9 lines
create mode 100644 drivers/mtd/spi-nor/m25p80.c create mode 100644 drivers/mtd/spi-nor/spi-nor-ids.c create mode 100644 drivers/mtd/spi-nor/spi-nor-uclass.c create mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 drivers/mtd/spi-nor/zynq_qspinor.c create mode 100644 env/spinor.c create mode 100644 include/linux/mtd/spi-nor.h create mode 100644 test/dm/mtd.c
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de -------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20171228/79f7f7f9/attachment.sig>
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Quoted 42 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to comply with DM?
with this series yes, and we're working on supporting the same with non-dm.
Quoted 4 lines
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 5 lines
Quoted 3 lines
=======================================
mtd-uclass.c^^^^^ - here we will have a generic MTD layer (as it is in Linux)
it is not like in Linux, leaving ops names apart all the code is for creating mtd device for underlying flash devices in the form of interface type during bind. the interface types as of now is spi-nor it can be nand, nor, dataflash etc in future if could be.
Quoted 8 lines
Quoted 5 lines
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c^^^^^^ - why do we need to have
spi-nor.c? Cannot we have its functionality in thespi-nor-uclass.c? (I'm just curious)
spi-nor-uclass.c is an uclass driver for underlying UCLASS_SPI_NOR drivers like m25p80, zynq_qspinor etc but the spi-nor.c is the actual spi-nor core code which handle actual flash specific stuff. and also syncing Linux stuff(if require) becomes easy with spi-nor.c as a separate file.
Quoted 8 lines
Quoted 3 lines
=======================================
m25p80.czynq_qspinor.c^^^^^ - this is the ^^^^^^^^ - [*]
"generic" spi-nor
driver used in Linux.
I suppose that it will
be reused here?
yes - name reused because, I do think the Linux and U-Boot development on spi-nor will follow in-line at some point but the most of code is following U-Boot driver-model.
Quoted 5 lines
Quoted 3 lines
=======================================
spi-uclass.c^^^^^^^ - why do we
need this uclass?
This is an existing uclass spi driver for underlying UCLASS_SPI drivers like drivers/spi/zynq_qspi.c etc
Quoted 8 lines
Quoted 3 lines
=======================================
zynq_qspi.c^^^^^ - This is probably
the low-level driver for
zynq QSPI IP block - why
do we havezynq_qspinor.cfile above [*]?
What is the difference/need of such division?
Both the drivers are same, the reason for zynq_qspinor is for testing framework work for two directions like
- spi driver interface side through m25p80 cmd/spinor->mtd->spi-nor-uclass->spi-nor->m25p80->zynq_qspi.c
- direct spi-nor controller side spinor->mtd->spi-nor-uclass->spi-nor->zynq_qspinor
Will remove drivers/spi/zynq_qspi.c once all set.
Jagan.
Signature · 4 lines
Jagan Teki Free Software Engineer | www.openedev.com U-Boot, Linux | Upstream Maintainer Hyderabad, India.
Vignesh R
maintainerv10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Quoted 52 lines · Jagan Teki
Quoted 42 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to comply with DM?
with this series yes, and we're working on supporting the same with non-dm.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
I don't agree on adding new cmd and removing sf. It would be impractical to change all boot cmds to replace sf with spinor cmd all over U-Boot. Not to forget the envs already stored on non volatile media need updation to work with new cmd.
If SPI NOR framework is to abstract all accesses to nor flash devices in U-Boot, then why cannot it replace the logic implementing cmd sf? All that is changing is that mtd/spi/* is replaced by spi-nor.c + m25p80.c. sf probe can be modified achieve what spinor dev does
sf read for spinor read and so on. Board configs would just need to enable MTD related configs.
Signature · 2 lines
Regards Vignesh
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Quoted 63 lines · Vignesh R
Quoted 52 lines · Jagan Teki
Quoted 42 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to comply with DM?
with this series yes, and we're working on supporting the same with non-dm.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 10 lines
I don't agree on adding new cmd and removing sf. It would be impractical to change all boot cmds to replace sf with spinor cmd all over U-Boot. Not to forget the envs already stored on non volatile media need updation to work with new cmd.
If SPI NOR framework is to abstract all accesses to nor flash devices in U-Boot, then why cannot it replace the logic implementing cmd sf? All that is changing is that mtd/spi/* is replaced byspi-nor.c+m25p80.c. sf probe can be modified achieve what spinor dev does
sf read for spinor read and so on. Board configs would just need to enable MTD related configs.
I know how hard it is adding new command in u-boot, you can understood the reason for adding new command if you follow the previous versions on this series and I hope you does. we have been adding mtd, spi-nor changes to existing mtd/spi and sf.c since from first series and observed many issue with respective to framework design(where we move spi-nor controller drivers on to mtd side) along with driver model. In v9 we worked on designing MTD UCLASS where mtd command can be commonly interfaced to all underlying flash devices. and from continuous evaluation on driver model this series we designed MTD uclass can be a generic and make run-time creation of underlying flash devices with interface type, spi-nor is one of the interface. So to make the framework suitable to command interface the new command named as spinor. adding/supporting all these new design on top of mtd/spi or sf doesn’t smooth easy which is proved on previous version. technically sf termed as spi-flash comprise of spinor and spinand, spinand can be another interface type with spinand command and adding new features on legacy code doesn't make sense to me it will eventually breaking legacy dependencies.
Will all these new framework design, driver model, feasibility to sync Linux spi-nor.c we adding relevant command, and env.
Signature · 4 lines
Jagan Teki Free Software Engineer | www.openedev.com U-Boot, Linux | Upstream Maintainer Hyderabad, India.
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Hi Jagan,
Quoted 77 lines · Vignesh R
Quoted 65 lines · Jagan Teki
Quoted 54 lines
Quoted 43 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to
comply with DM?with this series yes, and we're working on supporting the same with non-dm.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
What about "sf" command which we use now to get
access to SPI-NOR memory? A lot of boards already use "sf"
command... which may be tricky to replace.end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 10 lines
I don't agree on adding new cmd and removing sf. It would be impractical to change all boot cmds to replace sf with spinor cmd all over U-Boot. Not to forget the envs already stored on non volatile media need updation to work with new cmd.
If SPI NOR framework is to abstract all accesses to nor flash devices in U-Boot, then why cannot it replace the logic implementing cmd sf? All that is changing is that mtd/spi/* is replaced byspi-nor.c+m25p80.c. sf probe can be modified achieve what spinor dev does sf read for spinor read and so on. Board configs would just need to enable MTD related configs.
Quoted 1 line
I know how hard it is adding new command in u-boot,
Yes, it is. Especially command which duplicates already present functionality.
Quoted 3 lines
you can understood
the reason for adding new command if you follow the previous versions on this series and I hope you does.
I must admit that this is the first version, which I reviewed.
The only feasible way would be to have new Kconfig option for this framework, force spinor for new boards and ..... wait.
After some long time (how long do we struggle with DM conversion/Kconfig?) we could think about removing "sf" command.
I do want to emphasis that I do agree with Vignesh - there are many boards out there, which do use sf command, with even more dangerous situation when company X only plan to update u-boot, but has envs in a separate partition. Breaking "sf" equals to brick of on-field devices....
IMHO - we shall have sf command as an alias to new "spinor" command (even by calling run_command("spinor....");).
Quoted 17 lines
we have been adding mtd, spi-nor
changes to existing mtd/spi andsf.csince from first series and observed many issue with respective to framework design(where we move spi-nor controller drivers on to mtd side) along with driver model. In v9 we worked on designing MTD UCLASS where mtd command can be commonly interfaced to all underlying flash devices. and from continuous evaluation on driver model this series we designed MTD uclass can be a generic and make run-time creation of underlying flash devices with interface type, spi-nor is one of the interface. So to make the framework suitable to command interface the new command named as spinor. adding/supporting all these new design on top of mtd/spi or sf doesn’t smooth easy which is proved on previous version. technically sf termed as spi-flash comprise of spinor and spinand, spinand can be another interface type with spinand command and adding new features on legacy code doesn't make sense to me it will eventually breaking legacy dependencies.
Quoted 3 lines
Will all these new framework design, driver model, feasibility to sync Linux
spi-nor.cwe adding relevant command, and env.
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de -------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180103/bd12ca0b/attachment.sig>
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Hi :
2018-01-03 18:59 GMT+08:00 Lukasz Majewski <[email protected]>:
Quoted 96 lines
Hi Jagan,
Quoted 77 lines · Vignesh R
Quoted 65 lines · Jagan Teki
Quoted 54 lines
Quoted 43 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to
comply with DM?with this series yes, and we're working on supporting the same with non-dm.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
What about "sf" command which we use now to get
access to SPI-NOR memory? A lot of boards already use "sf"
command... which may be tricky to replace.end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 10 lines
I don't agree on adding new cmd and removing sf. It would be impractical to change all boot cmds to replace sf with spinor cmd all over U-Boot. Not to forget the envs already stored on non volatile media need updation to work with new cmd.
If SPI NOR framework is to abstract all accesses to nor flash devices in U-Boot, then why cannot it replace the logic implementing cmd sf? All that is changing is that mtd/spi/* is replaced byspi-nor.c+m25p80.c. sf probe can be modified achieve what spinor dev does sf read for spinor read and so on. Board configs would just need to enable MTD related configs.Quoted 1 line
I know how hard it is adding new command in u-boot,
Yes, it is. Especially command which duplicates already present functionality.
Quoted 3 lines
you can understood
the reason for adding new command if you follow the previous versions on this series and I hope you does.I must admit that this is the first version, which I reviewed.
The only feasible way would be to have new
Kconfigoption for this framework, force spinor for new boards and ..... wait.After some long time (how long do we struggle with DM conversion/Kconfig?) we could think about removing "sf" command.
Quoted 32 lines
I do want to emphasis that I do agree with Vignesh - there are many boards out there, which do use sf command, with even more dangerous situation when company X only plan to update u-boot, but has envs in a separate partition. Breaking "sf" equals to brick of on-field devices....
IMHO - we shall have sf command as an alias to new "spinor" command (even by calling
run_command("spinor....");).Quoted 20 lines
we have been adding mtd, spi-nor
changes to existing mtd/spi andsf.csince from first series and observed many issue with respective to framework design(where we move spi-nor controller drivers on to mtd side) along with driver model. In v9 we worked on designing MTD UCLASS where mtd command can be commonly interfaced to all underlying flash devices. and from continuous evaluation on driver model this series we designed MTD uclass can be a generic and make run-time creation of underlying flash devices with interface type, spi-nor is one of the interface. So to make the framework suitable to command interface the new command named as spinor. adding/supporting all these new design on top of mtd/spi or sf doesn’t smooth easy which is proved on previous version. technically sf termed as spi-flash comprise of spinor and spinand, spinand can be another interface type with spinand command and adding new features on legacy code doesn't make sense to me it will eventually breaking legacy dependencies.Will all these new framework design, driver model, feasibility to sync Linux
spi-nor.cwe adding relevant command, and env.
Can we make a finall direction now, more than one year passed since Jagan's first version, and now it gets V10.
From the Linux kernel upstream, the spi nor framework switch to mtd/spi-nor for a long time, and it works fine now.
I hope u-boot spi nor can switch to mtd/spi-nor too, so we can share many logic with the kernel code.
Besides, I have a rockchip SPI-NOR controller(SFC), I wrote two different version drivers, one is based ondrivers/spi, another is based on Jagan's mtd/spi-nor , but I don't know how to move forward, as the direction is not
clear.
Quoted 17 lines
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
Vignesh R
maintainerv10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
In reply to Jagan TekiQuoted 2 lines · Jagan Teki
Quoted 1 line · Vignesh R
[...]
Quoted 29 lines
Quoted 18 lines
Quoted 10 lines
Quoted 6 lines
Quoted 3 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to comply with DM?
with this series yes, and we're working on supporting the same with non-dm.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 10 lines
I don't agree on adding new cmd and removing sf. It would be impractical to change all boot cmds to replace sf with spinor cmd all over U-Boot. Not to forget the envs already stored on non volatile media need updation to work with new cmd.
If SPI NOR framework is to abstract all accesses to nor flash devices in U-Boot, then why cannot it replace the logic implementing cmd sf? All that is changing is that mtd/spi/* is replaced byspi-nor.c+m25p80.c. sf probe can be modified achieve what spinor dev does
sf read for spinor read and so on. Board configs would just need to enable MTD related configs.
Quoted 6 lines
I know how hard it is adding new command in u-boot, you can understood the reason for adding new command if you follow the previous versions on this series and I hope you does. we have been adding mtd, spi-nor changes to existing mtd/spi and
sf.csince from first series and observed many issue with respective to framework design(where we move spi-nor controller drivers on to mtd side) along with driver model.
I don't remember. Its been a year since RFC v8 which used cmd_sf.c. Looking at the mailing list archives, I don't see any comments opposing cmd_sf.c and move to mtd command, that you used in v9
Quoted 8 lines
In v9 we worked on designing MTD UCLASS where mtd command can be commonly interfaced to all underlying flash devices. and from continuous evaluation on driver model this series we designed MTD uclass can be a generic and make run-time creation of underlying flash devices with interface type, spi-nor is one of the interface. So to make the framework suitable to command interface the new command named as spinor. adding/supporting all these new design on top of mtd/spi or sf doesn’t smooth easy which is proved on previous version.
Could you point to/summarize the exact problems that force us to move to spinor cmd? I failed to find them on archives.
Quoted 5 lines
technically sf termed as spi-flash comprise of spinor and spinand, spinand can be another interface type with spinand command and adding new features on legacy code doesn't make sense to me it will eventually breaking legacy dependencies.
AFAIK, spinand is not yet supported and can be added under MTD with different U-Boot cmd to access it.
Signature · 2 lines
Regards Vignesh
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
In reply to Jagan TekiHi Jagan,
Quoted 128 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Tuesday, January 02, 2018 3:39 PM
To: Lukasz Majewski <[email protected]>
Cc: U-Boot Mailing List <[email protected]>; Tom Rini <[email protected]>
Subject: Re: [U-Boot] [PATCH v10 00/27] dm: Generic MTD Subsystem, with SPI-NOR interfaceQuoted 42 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to comply with DM?
with this series yes, and we're working on supporting the same with non- dm.
Quoted 4 lines
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 5 lines
Quoted 3 lines
=======================================
mtd-uclass.c^^^^^ - here we will have a generic MTD layer (as it is in Linux)
it is not like in Linux, leaving ops names apart all the code is for creating mtd device for underlying flash devices in the form of interface type during bind. the interface types as of now is spi-nor it can be nand, nor, dataflash etc in future if could be.
Quoted 8 lines
Quoted 5 lines
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c^^^^^^ - why do we need to have
spi-nor.c? Cannot we have its functionality in thespi-nor-uclass.c? (I'm just curious)
spi-nor-uclass.cis an uclass driver for underlyingUCLASS_SPI_NORdrivers like m25p80,zynq_qspinoretc but thespi-nor.cis the actual spi-nor core code which handle actual flash specific stuff. and also syncing Linux stuff(if require) becomes easy withspi-nor.cas a separate file.Quoted 8 lines
Quoted 3 lines
=======================================
m25p80.czynq_qspinor.c^^^^^ - this is the ^^^^^^^^ - [*]
"generic" spi-nor
driver used in Linux.
I suppose that it will
be reused here?yes - name reused because, I do think the Linux and U-Boot development on spi-nor will follow in-line at some point but the most of code is following U- Boot driver-model.
Quoted 5 lines
Quoted 3 lines
=======================================
spi-uclass.c^^^^^^^ - why do we
need this uclass?This is an existing uclass spi driver for underlying
UCLASS_SPIdrivers likedrivers/spi/zynq_qspi.cetcQuoted 8 lines
Quoted 3 lines
=======================================
zynq_qspi.c^^^^^ - This is probably
the low-level driver for
zynq QSPI IP block - why
do we havezynq_qspinor.cfile above [*]?
What is the difference/need of such division?
Quoted 8 lines
Both the drivers are same, the reason for
zynq_qspinoris for testing framework work for two directions like
- spi driver interface side through m25p80 cmd/spinor->mtd->spi-nor- uclass->spi-nor->m25p80->zynq_qspi.c
- direct spi-nor controller side spinor->mtd->spi-nor-uclass->spi-nor->zynq_qspinorWill remove
drivers/spi/zynq_qspi.conce all set.
As mentioned in Zynq TRM, Zynq qspi controller can work in legacy spi mode as well which is same as regular spi controller. As you mentioned if you remove from drivers/spi/zynq_qspi and moving it to spi-nor, none can use it in spi legacy mode. Right?
Thanks,
Siva
Quoted 11 lines
Jagan.
--
Jagan Teki
Free Software Engineer | www.openedev.com U-Boot, Linux | Upstream Maintainer Hyderabad, India.
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Quoted 138 lines · Siva Durga Prasad Paladugu
Hi Jagan,
Quoted 135 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Tuesday, January 02, 2018 3:39 PM
To: Lukasz Majewski <[email protected]>
Cc: U-Boot Mailing List <[email protected]>; Tom Rini <[email protected]>
Subject: Re: [U-Boot] [PATCH v10 00/27] dm: Generic MTD Subsystem, with SPI-NOR interfaceQuoted 42 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to comply with DM?
with this series yes, and we're working on supporting the same with non- dm.
Quoted 4 lines
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 5 lines
Quoted 3 lines
=======================================
mtd-uclass.c^^^^^ - here we will have a generic MTD layer (as it is in Linux)
it is not like in Linux, leaving ops names apart all the code is for creating mtd device for underlying flash devices in the form of interface type during bind. the interface types as of now is spi-nor it can be nand, nor, dataflash etc in future if could be.
Quoted 8 lines
Quoted 5 lines
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c^^^^^^ - why do we need to have
spi-nor.c? Cannot we have its functionality in thespi-nor-uclass.c? (I'm just curious)
spi-nor-uclass.cis an uclass driver for underlyingUCLASS_SPI_NORdrivers like m25p80,zynq_qspinoretc but thespi-nor.cis the actual spi-nor core code which handle actual flash specific stuff. and also syncing Linux stuff(if require) becomes easy withspi-nor.cas a separate file.Quoted 8 lines
Quoted 3 lines
=======================================
m25p80.czynq_qspinor.c^^^^^ - this is the ^^^^^^^^ - [*]
"generic" spi-nor
driver used in Linux.
I suppose that it will
be reused here?yes - name reused because, I do think the Linux and U-Boot development on spi-nor will follow in-line at some point but the most of code is following U- Boot driver-model.
Quoted 5 lines
Quoted 3 lines
=======================================
spi-uclass.c^^^^^^^ - why do we
need this uclass?This is an existing uclass spi driver for underlying
UCLASS_SPIdrivers likedrivers/spi/zynq_qspi.cetcQuoted 8 lines
Quoted 3 lines
=======================================
zynq_qspi.c^^^^^ - This is probably
the low-level driver for
zynq QSPI IP block - why
do we havezynq_qspinor.cfile above [*]?
What is the difference/need of such division?Both the drivers are same, the reason for
zynq_qspinoris for testing framework work for two directions like
- spi driver interface side through m25p80 cmd/spinor->mtd->spi-nor- uclass->spi-nor->m25p80->zynq_qspi.c
- direct spi-nor controller side spinor->mtd->spi-nor-uclass->spi-nor->zynq_qspinor
Quoted 4 lines
Quoted 1 line
Will remove
drivers/spi/zynq_qspi.conce all set.As mentioned in Zynq TRM, Zynq qspi controller can work in legacy spi mode as well which is same as regular spi controller. As you mentioned if you remove from
drivers/spi/zynq_qspiand moving it to spi-nor, none can use it in spi legacy mode. Right?
AFAIK, none used till know for generic slaves except for spi-nor. and main motive here to have support for controller features like BAR, dual flash however writing this on drivers/spi make difficult have these.
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
Hi Jagan,
Quoted 152 lines
-----Original Message-----
From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
Sent: Tuesday, January 23, 2018 3:29 PM
To: Siva Durga Prasad Paladugu <[email protected]>
Cc: Lukasz Majewski <[email protected]>; U-Boot Mailing List <u- boot at lists.denx.de>; Tom Rini <[email protected]>
Subject: Re: [U-Boot] [PATCH v10 00/27] dm: Generic MTD Subsystem, with SPI-NOR interfaceQuoted 141 lines · Siva Durga Prasad Paladugu
Hi Jagan,
Quoted 137 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Tuesday, January 02, 2018 3:39 PM
To: Lukasz Majewski <[email protected]>
Cc: U-Boot Mailing List <[email protected]>; Tom Rini <[email protected]>
Subject: Re: [U-Boot] [PATCH v10 00/27] dm: Generic MTD Subsystem, with SPI-NOR interfaceQuoted 42 lines · Lukasz Majewski
Hi Jagan,
Quoted 24 lines
Compared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.cQuoted 8 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.I must admit that I'm a bit confused....
If you don't mind I would like to ask for clarification of a few things:
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
=======================================
cmd/spinor.c^^^^^ - this would be a new set of commands to comply with DM?
with this series yes, and we're working on supporting the same with non- dm.
Quoted 4 lines
What about "sf" command which we use now to get access to SPI-NOR memory? A lot of boards already use "sf" command... which may be tricky to replace.
end-goal will be replace sf with spinor command and removal of 'sf' will be done when the new spi-nor framework stable enough to handle all scenarios which are spi-flash supporting as of now.
Quoted 5 lines
Quoted 3 lines
=======================================
mtd-uclass.c^^^^^ - here we will have a generic MTD layer (as it is in Linux)
it is not like in Linux, leaving ops names apart all the code is for creating mtd device for underlying flash devices in the form of interface type during bind. the interface types as of now is spi-nor it can be nand, nor, dataflash etc in future if could be.
Quoted 8 lines
Quoted 5 lines
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c^^^^^^ - why do we need to have
spi-nor.c? Cannot we have its functionality in thespi-nor-uclass.c? (I'm just curious)
spi-nor-uclass.cis an uclass driver for underlyingUCLASS_SPI_NORdrivers like m25p80,zynq_qspinoretc but thespi-nor.cis the actual spi-nor core code which handle actual flash specific stuff. and also syncing Linux stuff(if
require) becomes easy withspi-nor.cas a separate file.Quoted 8 lines
Quoted 3 lines
=======================================
m25p80.czynq_qspinor.c^^^^^ - this is the ^^^^^^^^ - [*]
"generic" spi-nor
driver used in Linux.
I suppose that it will
be reused here?yes - name reused because, I do think the Linux and U-Boot development on spi-nor will follow in-line at some point but the most of code is following U- Boot driver-model.
Quoted 5 lines
Quoted 3 lines
=======================================
spi-uclass.c^^^^^^^ - why do we
need this uclass?This is an existing uclass spi driver for underlying
UCLASS_SPIdrivers likedrivers/spi/zynq_qspi.cetcQuoted 8 lines
Quoted 3 lines
=======================================
zynq_qspi.c^^^^^ - This is probably
the low-level driver for
zynq QSPI IP block - why
do we havezynq_qspinor.cfile above [*]?
What is the difference/need of such division?Both the drivers are same, the reason for
zynq_qspinoris for testing framework work for two directions like
- spi driver interface side through m25p80 cmd/spinor->mtd->spi-nor- uclass->spi-nor->m25p80->zynq_qspi.c
- direct spi-nor controller side spinor->mtd->spi-nor-uclass->spi-nor->zynq_qspinorWill remove
drivers/spi/zynq_qspi.conce all set.
Quoted 8 lines
Quoted 1 line
As mentioned in Zynq TRM, Zynq qspi controller can work in legacy spi
mode as well which is same as regular spi controller.
Quoted 1 line
As you mentioned if you remove from
drivers/spi/zynq_qspiand movingit to spi-nor, none can use it in spi legacy mode. Right?
AFAIK, none used till know for generic slaves except for spi-nor. and main motive here to have support for controller features like BAR, dual flash however writing this on
drivers/spimake difficult have these.
This means, we have to duplicate driver if someone wants to use for legacy spi which is bothering to me.
Thanks,
Siva
v10 cover dm: Generic MTD Subsystem, with SPI-NOR interface
In reply to Jagan TekiHi Jagan,
Quoted 31 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
Sent: Thursday, December 28, 2017 11:42 AM
To: u-boot at lists.denx.de
Cc: Tom Rini <[email protected]>
Subject: [U-Boot] [PATCH v10 00/27] dm: Generic MTD Subsystem, with SPI-NOR interfaceCompared to previous series’s [1], [2], [3] and [4] this patch set redefined most of the implementation suitable to fit into existing driver-model.
MTD is generic subsystem for underlying flash devices like nand, parallel nor, spinor, dataflash etc. So to drive this theory with driver model(with an example of block layer) mtd is common device interaction for most of memory technology flashes like nand, parallel nor, spinor, dataflash etc, these are treated as interface types wrt u-boot driver model.
Once the respective interface driver bind happen, the uclass driver will pass an 'interface type' to mtd layer to create device for it, for example once spinor
ULASS_SPI_NORdriver bind happen, the uclass driver of spinor will passMTD_IF_TYPE_SPI_NORinterface type to create mtd device for spinor devices.SPI-NOR:
=======
Some of the SPI device drivers atdrivers/spinot a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex:drivers/spi/fsl_qspi.c
Quoted 7 lines
The problem with these were resides at
drivers/spiis entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI- NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver.
Sorry for very late response. What's your approach on a controller that supports both flash with some flash specific functionalities(Like different flash connection topologies) and legacy spi devices.
Thanks,
Siva
Quoted 199 lines
=======================================
cmd/spinor.c
=======================================
mtd-uclass.c
=======================================
spi-nor-uclass.c
=======================================
spi-nor.c
=======================================m25p80.czynq_qspinor.c
=======================================spi-uclass.c
=======================================zynq_qspi.c
=======================================#####SPI NOR chip######=======================================
Changes for v10:
- Update Simon's R-B tag
- Add mtd dm test case
- implemented entire code wrt MTD, with interface typecode size:
==========
before:$ arm-linux-gnueabi-size u-boot text data bss dec hex filename 473712 15152 222568 711432 adb08 u- boot $ du -hs u-boot-dtb.img 488K u-boot-dtb.imgafter:
$ arm-linux-gnueabi-size u-boot text data bss dec hex filename 470124 14352 222584 707060 ac9f4 u- boot $ du -hs u-boot-dtb.img 484K u-boot-dtb.imgapproximately 4KiB but
DM_SPI_FLASHstill there which can be removed once support added in SPLtest log:
========
Zynq> spinor
spinor - SPI-NOR Sub-systemUsage:
spinor list - show list of spinor devices spinor info - show current spinor device info spinor dev [devnum] - show or set current spinor device spinor erase offset len - erase 'len' bytes from 'offset' spinor write addr to len - write 'len' bytes to 'to' from 'addr' spinor read addr from len - read 'len' bytes from 'from' to 'addr'spinor protect lock/unlock sector len - protect/unprotect 'len' bytes starting
at address 'sector'
Zynq> spinor list
flash at 0: 0
spi-nor ate000d000: 1
Zynq> spinor dev 0
switch to dev #0, OK
spinor0 is current device
Zynq> spinor info
bus: flash at 0: 0
device:s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase0xE000000x100000
SPI-NOR: 1048576 bytes @0xe00000Erased: OK
Zynq> mw.b0x1000xcc0x100000
Zynq> spinor write0x1000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Written: OK
Zynq> spinor read0x30000000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Read: OK
Zynq> cmp.b0x30000000x1000x100000
Total of 1048576 byte(s) were the same
Zynq> spinor dev 1
switch to dev #1, OK
spinor1 is current device
Zynq> spinor info
bus: spi-nor ate000d000: 1
device:s25fl128s_64k
page size: 256 B
erase size: 64 KiB
size: 16 MiB
Zynq> spinor erase0xE000000x100000
SPI-NOR: 1048576 bytes @0xe00000Erased: OK
Zynq> mw.b0x1000xbb0x100000
Zynq> spinor write0x1000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Written: OK
Zynq> spinor read0x30000000xE000000x100000
device 0 offset0xe00000, size0x100000
SPI-NOR: 1048576 bytes @0xe00000Read: OK
Zynq> cmp.b0x30000000x1000x100000
Total of 1048576 byte(s) were the sameWIP:
===
- to support non-dm code
- to support spinor SPLRepo:
====$ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b mtd-spinor-working origin/mtd-spinor-working[1] https://lists.denx.de/pipermail/u-boot/2016-October/271459.html
[2] http://lists.denx.de/pipermail/u-boot/2016-March/249286.html
[3] http://lists.denx.de/pipermail/u-boot/2016-February/245418.html
[4] [PATCH RFC v8 00/16] SPI-NOR/MTD additionJagan Teki (27):
mtd: Add mtd core ops
mtd: add mtd device create operations
mtd: add SPI-NOR core support
mtd: spi-nor: sync/modify sst write operations
mtd: spi-nor: sync/modify lock operations
mtd: spi-nor:Kconfig: AddMTD_SPI_NORentry
mtd: spi-nor:Kconfig: AddMTD_SPI_NOR_USE_4K_SECTORS
mtd: spi-nor:Kconfig: AddSPI_NOR_MISCentry
mtd: spi-nor:Kconfig: AddSPI_NOR_MACRONIXentry
mtd: spi-nor:Kconfig: AddSPI_NOR_SPANSIONentry
mtd: spi-nor:Kconfig: AddSPI_NOR_STMICROentry
mtd: spi-nor:Kconfig: AddSPI_NOR_SSTentry
mtd: spi-nor:Kconfig: AddSPI_NOR_WINBONDentry
mtd-uclass: useplatdata_auto_alloc
spi: Addspi_write_then_read
mtd: spi-nor: Add m25p80 driver
mtd: spi-nor:Kconfig: AddMTD_M25P80entry
mtd: spi-nor: Add zynq qspinor driver
mtd: spi-nor:zynq_qspi:Kconfig: AddMTD_ZYNQ
mtd: spi-nor: Add 4-byte addresswidth support
cmd: add spinor cmd support
cmd: spinor: sync/update protect command
board_r: initializespi_nor
env: add spi-nor environment
arm: dts: zynq: Add zynq-qspinor node
dm: zynq: microzed: enable MTD/SPI-NOR framework
test: dm: add tests for mtd devicesMakefile | 1 + arch/arm/dts/zynq-7000.dtsi | 12 + arch/arm/dts/zynq-microzed.dts | 12 +- cmd/Kconfig | 5 + cmd/Makefile | 1 + cmd/nvedit.c | 1 + cmd/spinor.c | 326 ++++++++++++ common/board_r.c | 13 + configs/sandbox_defconfig | 8 +- configs/zynq_microzed_defconfig | 17 +- drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 7 +- drivers/mtd/mtd-uclass.c | 203 +++++++- drivers/mtd/spi-nor/Kconfig | 89 ++++ drivers/mtd/spi-nor/Makefile | 15 + drivers/mtd/spi-nor/m25p80.c | 251 ++++++++++ drivers/mtd/spi-nor/spi-nor-ids.c | 184 +++++++ drivers/mtd/spi-nor/spi-nor-uclass.c | 160 ++++++ drivers/mtd/spi-nor/spi-nor.c | 940 +++++++++++++++++++++++++++++++++++ drivers/mtd/spi-nor/zynq_qspinor.c | 622 +++++++++++++++++++++++ drivers/spi/spi-uclass.c | 24 + env/Kconfig | 27 + env/Makefile | 1 + env/env.c | 2 + env/spinor.c | 113 +++++ include/dm/uclass-id.h | 1 + include/environment.h | 1 + include/linux/mtd/mtd.h | 14 + include/linux/mtd/spi-nor.h | 223 +++++++++ include/mtd.h | 176 +++++++ include/spi.h | 20 + test/dm/Makefile | 1 + test/dm/mtd.c | 33 ++ 33 files changed, 3493 insertions(+), 12 deletions(-) create mode 100644
cmd/spinor.ccreate mode 100644drivers/mtd/spi-nor/Kconfigcreate mode 100644drivers/mtd/spi-nor/Makefilecreate mode 100644drivers/mtd/spi-nor/m25p80.ccreate mode 100644drivers/mtd/spi-nor/spi-nor-ids.ccreate mode 100644drivers/mtd/spi-nor/spi-nor-uclass.ccreate mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 drivers/mtd/spi-nor/zynq_qspinor.c create mode 100644 env/spinor.c create mode 100644 include/linux/mtd/spi-nor.h create mode 100644
test/dm/mtd.c--
2.7.4_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot