* [PATCH v7 0/5] MTD: Add Initial HyperBus support @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Change log: Since v6: Fix up DT bindings for TI HBMC driver to move hyperbus node out of syscon Since v5: Fix up DT bindings comments for TI HBMC driver Move calibration sequence out of core into TI HBMC driver Since v4: Fix Rob's comments on dt-bindings of TI HBMC driver Since v3: * Drop reading QRY string twice in hyperbus_calibrate() * Fix doc/misc comments on v3. Since RFC v2: * use map_word_xxx() for handling status register to support interleaved flashes as suggested by Joakim Tjernlund <Joakim.Tjernlund@infinera.com> * Report error status/messages on erase/program failure by looking at status register bits. * Add "cfi-flash" as fallback compatible for cypress,hyperflash * Add support to select between HyperBus and OSPI using mmio mux Since RFC v1: * Re-work Hyperbus core to provide separate struct representation for controller and slave devices * Rename all files and func names to have hyperbus_ prefix * Provide default calibration routine for use by controller drivers * Fix up errors with patch spliting * Address comments by Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Cypress HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory(called HyperFlash) or self refresh DRAM(called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since Hyperbus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clk. But Hyperbus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers call hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Tested on modified TI AM654 EVM with Cypress Hyperflash S26KS512 by creating a UBIFS partition and writing and reading files to it. Stress tested by writing/reading 16MB flash repeatedly at different offsets using dd commmand. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] TI's HBMC controller details at[3] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Vignesh Raghavendra (5): mtd: cfi_cmdset_0002: Add support for polling status register dt-bindings: mtd: Add binding documentation for HyperFlash mtd: Add support for HyperBus memory devices dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller mtd: hyperbus: Add driver for TI's HyperBus memory controller .../bindings/mtd/cypress,hyperflash.txt | 13 ++ .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 ++++++ MAINTAINERS | 8 + drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/chips/cfi_cmdset_0002.c | 90 ++++++++++ drivers/mtd/hyperbus/Kconfig | 23 +++ drivers/mtd/hyperbus/Makefile | 4 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++ drivers/mtd/hyperbus/hyperbus-core.c | 154 ++++++++++++++++++ include/linux/mtd/cfi.h | 5 + include/linux/mtd/hyperbus.h | 86 ++++++++++ 12 files changed, 579 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h -- 2.22.0 ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v7 0/5] MTD: Add Initial HyperBus support @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Change log: Since v6: Fix up DT bindings for TI HBMC driver to move hyperbus node out of syscon Since v5: Fix up DT bindings comments for TI HBMC driver Move calibration sequence out of core into TI HBMC driver Since v4: Fix Rob's comments on dt-bindings of TI HBMC driver Since v3: * Drop reading QRY string twice in hyperbus_calibrate() * Fix doc/misc comments on v3. Since RFC v2: * use map_word_xxx() for handling status register to support interleaved flashes as suggested by Joakim Tjernlund <Joakim.Tjernlund@infinera.com> * Report error status/messages on erase/program failure by looking at status register bits. * Add "cfi-flash" as fallback compatible for cypress,hyperflash * Add support to select between HyperBus and OSPI using mmio mux Since RFC v1: * Re-work Hyperbus core to provide separate struct representation for controller and slave devices * Rename all files and func names to have hyperbus_ prefix * Provide default calibration routine for use by controller drivers * Fix up errors with patch spliting * Address comments by Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Cypress HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory(called HyperFlash) or self refresh DRAM(called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since Hyperbus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clk. But Hyperbus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers call hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Tested on modified TI AM654 EVM with Cypress Hyperflash S26KS512 by creating a UBIFS partition and writing and reading files to it. Stress tested by writing/reading 16MB flash repeatedly at different offsets using dd commmand. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] TI's HBMC controller details at[3] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Vignesh Raghavendra (5): mtd: cfi_cmdset_0002: Add support for polling status register dt-bindings: mtd: Add binding documentation for HyperFlash mtd: Add support for HyperBus memory devices dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller mtd: hyperbus: Add driver for TI's HyperBus memory controller .../bindings/mtd/cypress,hyperflash.txt | 13 ++ .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 ++++++ MAINTAINERS | 8 + drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/chips/cfi_cmdset_0002.c | 90 ++++++++++ drivers/mtd/hyperbus/Kconfig | 23 +++ drivers/mtd/hyperbus/Makefile | 4 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++ drivers/mtd/hyperbus/hyperbus-core.c | 154 ++++++++++++++++++ include/linux/mtd/cfi.h | 5 + include/linux/mtd/hyperbus.h | 86 ++++++++++ 12 files changed, 579 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h -- 2.22.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v7 0/5] MTD: Add Initial HyperBus support @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Change log: Since v6: Fix up DT bindings for TI HBMC driver to move hyperbus node out of syscon Since v5: Fix up DT bindings comments for TI HBMC driver Move calibration sequence out of core into TI HBMC driver Since v4: Fix Rob's comments on dt-bindings of TI HBMC driver Since v3: * Drop reading QRY string twice in hyperbus_calibrate() * Fix doc/misc comments on v3. Since RFC v2: * use map_word_xxx() for handling status register to support interleaved flashes as suggested by Joakim Tjernlund <Joakim.Tjernlund@infinera.com> * Report error status/messages on erase/program failure by looking at status register bits. * Add "cfi-flash" as fallback compatible for cypress,hyperflash * Add support to select between HyperBus and OSPI using mmio mux Since RFC v1: * Re-work Hyperbus core to provide separate struct representation for controller and slave devices * Rename all files and func names to have hyperbus_ prefix * Provide default calibration routine for use by controller drivers * Fix up errors with patch spliting * Address comments by Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Cypress HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory(called HyperFlash) or self refresh DRAM(called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since Hyperbus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clk. But Hyperbus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers call hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Tested on modified TI AM654 EVM with Cypress Hyperflash S26KS512 by creating a UBIFS partition and writing and reading files to it. Stress tested by writing/reading 16MB flash repeatedly at different offsets using dd commmand. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] TI's HBMC controller details at[3] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Vignesh Raghavendra (5): mtd: cfi_cmdset_0002: Add support for polling status register dt-bindings: mtd: Add binding documentation for HyperFlash mtd: Add support for HyperBus memory devices dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller mtd: hyperbus: Add driver for TI's HyperBus memory controller .../bindings/mtd/cypress,hyperflash.txt | 13 ++ .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 ++++++ MAINTAINERS | 8 + drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/chips/cfi_cmdset_0002.c | 90 ++++++++++ drivers/mtd/hyperbus/Kconfig | 23 +++ drivers/mtd/hyperbus/Makefile | 4 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++ drivers/mtd/hyperbus/hyperbus-core.c | 154 ++++++++++++++++++ include/linux/mtd/cfi.h | 5 + include/linux/mtd/hyperbus.h | 86 ++++++++++ 12 files changed, 579 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h -- 2.22.0 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v7 0/5] MTD: Add Initial HyperBus support @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Change log: Since v6: Fix up DT bindings for TI HBMC driver to move hyperbus node out of syscon Since v5: Fix up DT bindings comments for TI HBMC driver Move calibration sequence out of core into TI HBMC driver Since v4: Fix Rob's comments on dt-bindings of TI HBMC driver Since v3: * Drop reading QRY string twice in hyperbus_calibrate() * Fix doc/misc comments on v3. Since RFC v2: * use map_word_xxx() for handling status register to support interleaved flashes as suggested by Joakim Tjernlund <Joakim.Tjernlund@infinera.com> * Report error status/messages on erase/program failure by looking at status register bits. * Add "cfi-flash" as fallback compatible for cypress,hyperflash * Add support to select between HyperBus and OSPI using mmio mux Since RFC v1: * Re-work Hyperbus core to provide separate struct representation for controller and slave devices * Rename all files and func names to have hyperbus_ prefix * Provide default calibration routine for use by controller drivers * Fix up errors with patch spliting * Address comments by Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Cypress HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory(called HyperFlash) or self refresh DRAM(called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since Hyperbus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clk. But Hyperbus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers call hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Tested on modified TI AM654 EVM with Cypress Hyperflash S26KS512 by creating a UBIFS partition and writing and reading files to it. Stress tested by writing/reading 16MB flash repeatedly at different offsets using dd commmand. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] TI's HBMC controller details at[3] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Vignesh Raghavendra (5): mtd: cfi_cmdset_0002: Add support for polling status register dt-bindings: mtd: Add binding documentation for HyperFlash mtd: Add support for HyperBus memory devices dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller mtd: hyperbus: Add driver for TI's HyperBus memory controller .../bindings/mtd/cypress,hyperflash.txt | 13 ++ .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 ++++++ MAINTAINERS | 8 + drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/chips/cfi_cmdset_0002.c | 90 ++++++++++ drivers/mtd/hyperbus/Kconfig | 23 +++ drivers/mtd/hyperbus/Makefile | 4 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++ drivers/mtd/hyperbus/hyperbus-core.c | 154 ++++++++++++++++++ include/linux/mtd/cfi.h | 5 + include/linux/mtd/hyperbus.h | 86 ++++++++++ 12 files changed, 579 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h -- 2.22.0 ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register 2019-06-20 17:22 ` Vignesh Raghavendra (?) (?) @ 2019-06-20 17:22 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel HyperFlash devices are compliant with CFI AMD/Fujitsu Extended Command Set (0x0002) for flash operations, therefore drivers/mtd/chips/cfi_cmdset_0002.c can be used as is. But these devices do not support DQ polling method of determining chip ready/good status. These flashes provide Status Register whose bits can be polled to know status of flash operation. Cypress HyperFlash datasheet here[1], talks about CFI Amd/Fujitsu Extended Query version 1.5. Bit 0 of "Software Features supported" field of CFI Primary Vendor-Specific Extended Query table indicates presence/absence of status register and Bit 1 indicates whether or not DQ polling is supported. Using these bits, its possible to determine whether flash supports DQ polling or need to use Status Register. Add support for polling Status Register to know device ready/status of erase/write operations when DQ polling is not supported. Print error messages on erase/program failure by looking at related Status Register bits. [1] https://www.cypress.com/file/213346/download Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change drivers/mtd/chips/cfi_cmdset_0002.c | 90 +++++++++++++++++++++++++++++ include/linux/mtd/cfi.h | 5 ++ 2 files changed, 95 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c8fa5906bdf9..0f571f162e3b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -49,6 +49,16 @@ #define SST49LF008A 0x005a #define AT49BV6416 0x00d6 +/* + * Status Register bit description. Used by flash devices that don't + * support DQ polling (e.g. HyperFlash) + */ +#define CFI_SR_DRB BIT(7) +#define CFI_SR_ESB BIT(5) +#define CFI_SR_PSB BIT(4) +#define CFI_SR_WBASB BIT(3) +#define CFI_SR_SLSB BIT(1) + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -97,6 +107,48 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { .module = THIS_MODULE }; +/* + * Use status register to poll for Erase/write completion when DQ is not + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in + * CFI Primary Vendor-Specific Extended Query table 1.5 + */ +static int cfi_use_status_reg(struct cfi_private *cfi) +{ + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; + + return extp->MinorVersion >= '5' && + (extp->SoftwareFeatures & 0x3) == 0x1; +} + +static void cfi_check_err_status(struct map_info *map, unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + map_word status; + + if (!cfi_use_status_reg(cfi)) + return; + + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + status = map_read(map, adr); + + if (map_word_bitsset(map, status, CMD(0x3a))) { + unsigned long chipstatus = MERGESTATUS(status); + + if (chipstatus & CFI_SR_ESB) + pr_err("%s erase operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_PSB) + pr_err("%s program operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_WBASB) + pr_err("%s buffer program command aborted, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_SLSB) + pr_err("%s sector write protected, status %lx\n", + map->name, chipstatus); + } +} /* #define DEBUG_CFI_FEATURES */ @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) */ static int __xipram chip_ready(struct map_info *map, unsigned long addr) { + struct cfi_private *cfi = map->fldrv_priv; map_word d, t; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + /* + * For chips that support status register, check device + * ready bit + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + d = map_read(map, addr); + + return map_word_andequal(map, d, ready, ready); + } + d = map_read(map, addr); t = map_read(map, addr); @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) */ static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) { + struct cfi_private *cfi = map->fldrv_priv; map_word oldd, curd; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); + /* + * For chips that support status register, check device + * ready bit and Erase/Program status bit to know if + * operation succeeded. + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + curd = map_read(map, addr); + + if (map_word_andequal(map, curd, ready, ready)) + return !map_word_bitsset(map, curd, err); + + return 0; + } + oldd = map_read(map, addr); curd = map_read(map, addr); @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, * See e.g. * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf */ + cfi_check_err_status(map, adr); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 208c87cf2e3e..b50416169049 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { uint8_t VppMin; uint8_t VppMax; uint8_t TopBottom; + /* Below field are added from version 1.5 */ + uint8_t ProgramSuspend; + uint8_t UnlockBypass; + uint8_t SecureSiliconSector; + uint8_t SoftwareFeatures; } __packed; /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel HyperFlash devices are compliant with CFI AMD/Fujitsu Extended Command Set (0x0002) for flash operations, therefore drivers/mtd/chips/cfi_cmdset_0002.c can be used as is. But these devices do not support DQ polling method of determining chip ready/good status. These flashes provide Status Register whose bits can be polled to know status of flash operation. Cypress HyperFlash datasheet here[1], talks about CFI Amd/Fujitsu Extended Query version 1.5. Bit 0 of "Software Features supported" field of CFI Primary Vendor-Specific Extended Query table indicates presence/absence of status register and Bit 1 indicates whether or not DQ polling is supported. Using these bits, its possible to determine whether flash supports DQ polling or need to use Status Register. Add support for polling Status Register to know device ready/status of erase/write operations when DQ polling is not supported. Print error messages on erase/program failure by looking at related Status Register bits. [1] https://www.cypress.com/file/213346/download Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change drivers/mtd/chips/cfi_cmdset_0002.c | 90 +++++++++++++++++++++++++++++ include/linux/mtd/cfi.h | 5 ++ 2 files changed, 95 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c8fa5906bdf9..0f571f162e3b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -49,6 +49,16 @@ #define SST49LF008A 0x005a #define AT49BV6416 0x00d6 +/* + * Status Register bit description. Used by flash devices that don't + * support DQ polling (e.g. HyperFlash) + */ +#define CFI_SR_DRB BIT(7) +#define CFI_SR_ESB BIT(5) +#define CFI_SR_PSB BIT(4) +#define CFI_SR_WBASB BIT(3) +#define CFI_SR_SLSB BIT(1) + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -97,6 +107,48 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { .module = THIS_MODULE }; +/* + * Use status register to poll for Erase/write completion when DQ is not + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in + * CFI Primary Vendor-Specific Extended Query table 1.5 + */ +static int cfi_use_status_reg(struct cfi_private *cfi) +{ + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; + + return extp->MinorVersion >= '5' && + (extp->SoftwareFeatures & 0x3) == 0x1; +} + +static void cfi_check_err_status(struct map_info *map, unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + map_word status; + + if (!cfi_use_status_reg(cfi)) + return; + + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + status = map_read(map, adr); + + if (map_word_bitsset(map, status, CMD(0x3a))) { + unsigned long chipstatus = MERGESTATUS(status); + + if (chipstatus & CFI_SR_ESB) + pr_err("%s erase operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_PSB) + pr_err("%s program operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_WBASB) + pr_err("%s buffer program command aborted, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_SLSB) + pr_err("%s sector write protected, status %lx\n", + map->name, chipstatus); + } +} /* #define DEBUG_CFI_FEATURES */ @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) */ static int __xipram chip_ready(struct map_info *map, unsigned long addr) { + struct cfi_private *cfi = map->fldrv_priv; map_word d, t; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + /* + * For chips that support status register, check device + * ready bit + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + d = map_read(map, addr); + + return map_word_andequal(map, d, ready, ready); + } + d = map_read(map, addr); t = map_read(map, addr); @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) */ static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) { + struct cfi_private *cfi = map->fldrv_priv; map_word oldd, curd; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); + /* + * For chips that support status register, check device + * ready bit and Erase/Program status bit to know if + * operation succeeded. + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + curd = map_read(map, addr); + + if (map_word_andequal(map, curd, ready, ready)) + return !map_word_bitsset(map, curd, err); + + return 0; + } + oldd = map_read(map, addr); curd = map_read(map, addr); @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, * See e.g. * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf */ + cfi_check_err_status(map, adr); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 208c87cf2e3e..b50416169049 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { uint8_t VppMin; uint8_t VppMax; uint8_t TopBottom; + /* Below field are added from version 1.5 */ + uint8_t ProgramSuspend; + uint8_t UnlockBypass; + uint8_t SecureSiliconSector; + uint8_t SoftwareFeatures; } __packed; /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ -- 2.22.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel HyperFlash devices are compliant with CFI AMD/Fujitsu Extended Command Set (0x0002) for flash operations, therefore drivers/mtd/chips/cfi_cmdset_0002.c can be used as is. But these devices do not support DQ polling method of determining chip ready/good status. These flashes provide Status Register whose bits can be polled to know status of flash operation. Cypress HyperFlash datasheet here[1], talks about CFI Amd/Fujitsu Extended Query version 1.5. Bit 0 of "Software Features supported" field of CFI Primary Vendor-Specific Extended Query table indicates presence/absence of status register and Bit 1 indicates whether or not DQ polling is supported. Using these bits, its possible to determine whether flash supports DQ polling or need to use Status Register. Add support for polling Status Register to know device ready/status of erase/write operations when DQ polling is not supported. Print error messages on erase/program failure by looking at related Status Register bits. [1] https://www.cypress.com/file/213346/download Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change drivers/mtd/chips/cfi_cmdset_0002.c | 90 +++++++++++++++++++++++++++++ include/linux/mtd/cfi.h | 5 ++ 2 files changed, 95 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c8fa5906bdf9..0f571f162e3b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -49,6 +49,16 @@ #define SST49LF008A 0x005a #define AT49BV6416 0x00d6 +/* + * Status Register bit description. Used by flash devices that don't + * support DQ polling (e.g. HyperFlash) + */ +#define CFI_SR_DRB BIT(7) +#define CFI_SR_ESB BIT(5) +#define CFI_SR_PSB BIT(4) +#define CFI_SR_WBASB BIT(3) +#define CFI_SR_SLSB BIT(1) + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -97,6 +107,48 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { .module = THIS_MODULE }; +/* + * Use status register to poll for Erase/write completion when DQ is not + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in + * CFI Primary Vendor-Specific Extended Query table 1.5 + */ +static int cfi_use_status_reg(struct cfi_private *cfi) +{ + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; + + return extp->MinorVersion >= '5' && + (extp->SoftwareFeatures & 0x3) == 0x1; +} + +static void cfi_check_err_status(struct map_info *map, unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + map_word status; + + if (!cfi_use_status_reg(cfi)) + return; + + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + status = map_read(map, adr); + + if (map_word_bitsset(map, status, CMD(0x3a))) { + unsigned long chipstatus = MERGESTATUS(status); + + if (chipstatus & CFI_SR_ESB) + pr_err("%s erase operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_PSB) + pr_err("%s program operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_WBASB) + pr_err("%s buffer program command aborted, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_SLSB) + pr_err("%s sector write protected, status %lx\n", + map->name, chipstatus); + } +} /* #define DEBUG_CFI_FEATURES */ @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) */ static int __xipram chip_ready(struct map_info *map, unsigned long addr) { + struct cfi_private *cfi = map->fldrv_priv; map_word d, t; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + /* + * For chips that support status register, check device + * ready bit + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + d = map_read(map, addr); + + return map_word_andequal(map, d, ready, ready); + } + d = map_read(map, addr); t = map_read(map, addr); @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) */ static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) { + struct cfi_private *cfi = map->fldrv_priv; map_word oldd, curd; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); + /* + * For chips that support status register, check device + * ready bit and Erase/Program status bit to know if + * operation succeeded. + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + curd = map_read(map, addr); + + if (map_word_andequal(map, curd, ready, ready)) + return !map_word_bitsset(map, curd, err); + + return 0; + } + oldd = map_read(map, addr); curd = map_read(map, addr); @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, * See e.g. * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf */ + cfi_check_err_status(map, adr); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 208c87cf2e3e..b50416169049 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { uint8_t VppMin; uint8_t VppMax; uint8_t TopBottom; + /* Below field are added from version 1.5 */ + uint8_t ProgramSuspend; + uint8_t UnlockBypass; + uint8_t SecureSiliconSector; + uint8_t SoftwareFeatures; } __packed; /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ -- 2.22.0 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel HyperFlash devices are compliant with CFI AMD/Fujitsu Extended Command Set (0x0002) for flash operations, therefore drivers/mtd/chips/cfi_cmdset_0002.c can be used as is. But these devices do not support DQ polling method of determining chip ready/good status. These flashes provide Status Register whose bits can be polled to know status of flash operation. Cypress HyperFlash datasheet here[1], talks about CFI Amd/Fujitsu Extended Query version 1.5. Bit 0 of "Software Features supported" field of CFI Primary Vendor-Specific Extended Query table indicates presence/absence of status register and Bit 1 indicates whether or not DQ polling is supported. Using these bits, its possible to determine whether flash supports DQ polling or need to use Status Register. Add support for polling Status Register to know device ready/status of erase/write operations when DQ polling is not supported. Print error messages on erase/program failure by looking at related Status Register bits. [1] https://www.cypress.com/file/213346/download Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change drivers/mtd/chips/cfi_cmdset_0002.c | 90 +++++++++++++++++++++++++++++ include/linux/mtd/cfi.h | 5 ++ 2 files changed, 95 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c8fa5906bdf9..0f571f162e3b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -49,6 +49,16 @@ #define SST49LF008A 0x005a #define AT49BV6416 0x00d6 +/* + * Status Register bit description. Used by flash devices that don't + * support DQ polling (e.g. HyperFlash) + */ +#define CFI_SR_DRB BIT(7) +#define CFI_SR_ESB BIT(5) +#define CFI_SR_PSB BIT(4) +#define CFI_SR_WBASB BIT(3) +#define CFI_SR_SLSB BIT(1) + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -97,6 +107,48 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { .module = THIS_MODULE }; +/* + * Use status register to poll for Erase/write completion when DQ is not + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in + * CFI Primary Vendor-Specific Extended Query table 1.5 + */ +static int cfi_use_status_reg(struct cfi_private *cfi) +{ + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; + + return extp->MinorVersion >= '5' && + (extp->SoftwareFeatures & 0x3) == 0x1; +} + +static void cfi_check_err_status(struct map_info *map, unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + map_word status; + + if (!cfi_use_status_reg(cfi)) + return; + + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + status = map_read(map, adr); + + if (map_word_bitsset(map, status, CMD(0x3a))) { + unsigned long chipstatus = MERGESTATUS(status); + + if (chipstatus & CFI_SR_ESB) + pr_err("%s erase operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_PSB) + pr_err("%s program operation failed, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_WBASB) + pr_err("%s buffer program command aborted, status %lx\n", + map->name, chipstatus); + if (chipstatus & CFI_SR_SLSB) + pr_err("%s sector write protected, status %lx\n", + map->name, chipstatus); + } +} /* #define DEBUG_CFI_FEATURES */ @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) */ static int __xipram chip_ready(struct map_info *map, unsigned long addr) { + struct cfi_private *cfi = map->fldrv_priv; map_word d, t; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + /* + * For chips that support status register, check device + * ready bit + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + d = map_read(map, addr); + + return map_word_andequal(map, d, ready, ready); + } + d = map_read(map, addr); t = map_read(map, addr); @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) */ static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) { + struct cfi_private *cfi = map->fldrv_priv; map_word oldd, curd; + if (cfi_use_status_reg(cfi)) { + map_word ready = CMD(CFI_SR_DRB); + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); + /* + * For chips that support status register, check device + * ready bit and Erase/Program status bit to know if + * operation succeeded. + */ + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, + cfi->device_type, NULL); + curd = map_read(map, addr); + + if (map_word_andequal(map, curd, ready, ready)) + return !map_word_bitsset(map, curd, err); + + return 0; + } + oldd = map_read(map, addr); curd = map_read(map, addr); @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, * See e.g. * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf */ + cfi_check_err_status(map, adr); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, if (!chip_good(map, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, /* Did we succeed? */ if (ret) { /* reset on all failures. */ + cfi_check_err_status(map, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 208c87cf2e3e..b50416169049 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { uint8_t VppMin; uint8_t VppMax; uint8_t TopBottom; + /* Below field are added from version 1.5 */ + uint8_t ProgramSuspend; + uint8_t UnlockBypass; + uint8_t SecureSiliconSector; + uint8_t SoftwareFeatures; } __packed; /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register 2019-06-20 17:22 ` Vignesh Raghavendra (?) @ 2019-06-24 16:46 ` Tokunori Ikegami -1 siblings, 0 replies; 48+ messages in thread From: Tokunori Ikegami @ 2019-06-24 16:46 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel On 2019/06/21 2:22, Vignesh Raghavendra wrote: > HyperFlash devices are compliant with CFI AMD/Fujitsu Extended Command > Set (0x0002) for flash operations, therefore > drivers/mtd/chips/cfi_cmdset_0002.c can be used as is. But these devices > do not support DQ polling method of determining chip ready/good status. > These flashes provide Status Register whose bits can be polled to know > status of flash operation. > > Cypress HyperFlash datasheet here[1], talks about CFI Amd/Fujitsu > Extended Query version 1.5. Bit 0 of "Software Features supported" field > of CFI Primary Vendor-Specific Extended Query table indicates > presence/absence of status register and Bit 1 indicates whether or not > DQ polling is supported. Using these bits, its possible to determine > whether flash supports DQ polling or need to use Status Register. > > Add support for polling Status Register to know device ready/status of > erase/write operations when DQ polling is not supported. > Print error messages on erase/program failure by looking at related > Status Register bits. > > [1] https://www.cypress.com/file/213346/download > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > --- > v7: No change > > drivers/mtd/chips/cfi_cmdset_0002.c | 90 +++++++++++++++++++++++++++++ > include/linux/mtd/cfi.h | 5 ++ > 2 files changed, 95 insertions(+) > > diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c > index c8fa5906bdf9..0f571f162e3b 100644 > --- a/drivers/mtd/chips/cfi_cmdset_0002.c > +++ b/drivers/mtd/chips/cfi_cmdset_0002.c > @@ -49,6 +49,16 @@ > #define SST49LF008A 0x005a > #define AT49BV6416 0x00d6 > > +/* > + * Status Register bit description. Used by flash devices that don't > + * support DQ polling (e.g. HyperFlash) > + */ > +#define CFI_SR_DRB BIT(7) > +#define CFI_SR_ESB BIT(5) > +#define CFI_SR_PSB BIT(4) > +#define CFI_SR_WBASB BIT(3) > +#define CFI_SR_SLSB BIT(1) > + > static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); > static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); > static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); > @@ -97,6 +107,48 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { > .module = THIS_MODULE > }; > > +/* > + * Use status register to poll for Erase/write completion when DQ is not > + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in > + * CFI Primary Vendor-Specific Extended Query table 1.5 > + */ > +static int cfi_use_status_reg(struct cfi_private *cfi) > +{ > + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; > + > + return extp->MinorVersion >= '5' && > + (extp->SoftwareFeatures & 0x3) == 0x1; Seems to be better to use defined values instead of 0x3 and 0x1 hard coded values. > +} > + > +static void cfi_check_err_status(struct map_info *map, unsigned long adr) > +{ > + struct cfi_private *cfi = map->fldrv_priv; > + map_word status; > + > + if (!cfi_use_status_reg(cfi)) > + return; > + > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Is it not necessary to set chip->start as the base parameter for cfi_send_gen_cmd()? > + cfi->device_type, NULL); > + status = map_read(map, adr); > + > + if (map_word_bitsset(map, status, CMD(0x3a))) { > + unsigned long chipstatus = MERGESTATUS(status); > + > + if (chipstatus & CFI_SR_ESB) > + pr_err("%s erase operation failed, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_PSB) > + pr_err("%s program operation failed, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_WBASB) > + pr_err("%s buffer program command aborted, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_SLSB) > + pr_err("%s sector write protected, status %lx\n", > + map->name, chipstatus); > + } > +} > > /* #define DEBUG_CFI_FEATURES */ > > @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) > */ > static int __xipram chip_ready(struct map_info *map, unsigned long addr) > { > + struct cfi_private *cfi = map->fldrv_priv; > map_word d, t; > > + if (cfi_use_status_reg(cfi)) { > + map_word ready = CMD(CFI_SR_DRB); > + /* > + * For chips that support status register, check device > + * ready bit > + */ > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Same comment as cfi_check_err_status() about the base address. > + cfi->device_type, NULL); > + d = map_read(map, addr); > + > + return map_word_andequal(map, d, ready, ready); > + } > + > d = map_read(map, addr); > t = map_read(map, addr); > > @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) > */ > static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) > { > + struct cfi_private *cfi = map->fldrv_priv; > map_word oldd, curd; > > + if (cfi_use_status_reg(cfi)) { > + map_word ready = CMD(CFI_SR_DRB); > + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); Is it not necessary to check CFI_SR_WBASB and CFI_SR_SLSB that are checked by cfi_check_err_status()? > + /* > + * For chips that support status register, check device > + * ready bit and Erase/Program status bit to know if > + * operation succeeded. > + */ > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Same as cfi_check_err_status() and chip_ready() about the base address. > + cfi->device_type, NULL); > + curd = map_read(map, addr); > + > + if (map_word_andequal(map, curd, ready, ready)) > + return !map_word_bitsset(map, curd, err); > + > + return 0; > + } > + > oldd = map_read(map, addr); > curd = map_read(map, addr); > > @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, > /* Did we succeed? */ > if (!chip_good(map, adr, datum)) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, > * See e.g. > * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf > */ > + cfi_check_err_status(map, adr); > cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, > cfi->device_type, NULL); > cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, > @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, > > if (!chip_good(map, adr, datum)) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) > /* Did we succeed? */ > if (ret) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, > /* Did we succeed? */ > if (ret) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h > index 208c87cf2e3e..b50416169049 100644 > --- a/include/linux/mtd/cfi.h > +++ b/include/linux/mtd/cfi.h > @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { > uint8_t VppMin; > uint8_t VppMax; > uint8_t TopBottom; > + /* Below field are added from version 1.5 */ > + uint8_t ProgramSuspend; > + uint8_t UnlockBypass; > + uint8_t SecureSiliconSector; > + uint8_t SoftwareFeatures; > } __packed; > > /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register @ 2019-06-24 16:46 ` Tokunori Ikegami 0 siblings, 0 replies; 48+ messages in thread From: Tokunori Ikegami @ 2019-06-24 16:46 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel On 2019/06/21 2:22, Vignesh Raghavendra wrote: > HyperFlash devices are compliant with CFI AMD/Fujitsu Extended Command > Set (0x0002) for flash operations, therefore > drivers/mtd/chips/cfi_cmdset_0002.c can be used as is. But these devices > do not support DQ polling method of determining chip ready/good status. > These flashes provide Status Register whose bits can be polled to know > status of flash operation. > > Cypress HyperFlash datasheet here[1], talks about CFI Amd/Fujitsu > Extended Query version 1.5. Bit 0 of "Software Features supported" field > of CFI Primary Vendor-Specific Extended Query table indicates > presence/absence of status register and Bit 1 indicates whether or not > DQ polling is supported. Using these bits, its possible to determine > whether flash supports DQ polling or need to use Status Register. > > Add support for polling Status Register to know device ready/status of > erase/write operations when DQ polling is not supported. > Print error messages on erase/program failure by looking at related > Status Register bits. > > [1] https://www.cypress.com/file/213346/download > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > --- > v7: No change > > drivers/mtd/chips/cfi_cmdset_0002.c | 90 +++++++++++++++++++++++++++++ > include/linux/mtd/cfi.h | 5 ++ > 2 files changed, 95 insertions(+) > > diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c > index c8fa5906bdf9..0f571f162e3b 100644 > --- a/drivers/mtd/chips/cfi_cmdset_0002.c > +++ b/drivers/mtd/chips/cfi_cmdset_0002.c > @@ -49,6 +49,16 @@ > #define SST49LF008A 0x005a > #define AT49BV6416 0x00d6 > > +/* > + * Status Register bit description. Used by flash devices that don't > + * support DQ polling (e.g. HyperFlash) > + */ > +#define CFI_SR_DRB BIT(7) > +#define CFI_SR_ESB BIT(5) > +#define CFI_SR_PSB BIT(4) > +#define CFI_SR_WBASB BIT(3) > +#define CFI_SR_SLSB BIT(1) > + > static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); > static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); > static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); > @@ -97,6 +107,48 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { > .module = THIS_MODULE > }; > > +/* > + * Use status register to poll for Erase/write completion when DQ is not > + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in > + * CFI Primary Vendor-Specific Extended Query table 1.5 > + */ > +static int cfi_use_status_reg(struct cfi_private *cfi) > +{ > + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; > + > + return extp->MinorVersion >= '5' && > + (extp->SoftwareFeatures & 0x3) == 0x1; Seems to be better to use defined values instead of 0x3 and 0x1 hard coded values. > +} > + > +static void cfi_check_err_status(struct map_info *map, unsigned long adr) > +{ > + struct cfi_private *cfi = map->fldrv_priv; > + map_word status; > + > + if (!cfi_use_status_reg(cfi)) > + return; > + > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Is it not necessary to set chip->start as the base parameter for cfi_send_gen_cmd()? > + cfi->device_type, NULL); > + status = map_read(map, adr); > + > + if (map_word_bitsset(map, status, CMD(0x3a))) { > + unsigned long chipstatus = MERGESTATUS(status); > + > + if (chipstatus & CFI_SR_ESB) > + pr_err("%s erase operation failed, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_PSB) > + pr_err("%s program operation failed, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_WBASB) > + pr_err("%s buffer program command aborted, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_SLSB) > + pr_err("%s sector write protected, status %lx\n", > + map->name, chipstatus); > + } > +} > > /* #define DEBUG_CFI_FEATURES */ > > @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) > */ > static int __xipram chip_ready(struct map_info *map, unsigned long addr) > { > + struct cfi_private *cfi = map->fldrv_priv; > map_word d, t; > > + if (cfi_use_status_reg(cfi)) { > + map_word ready = CMD(CFI_SR_DRB); > + /* > + * For chips that support status register, check device > + * ready bit > + */ > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Same comment as cfi_check_err_status() about the base address. > + cfi->device_type, NULL); > + d = map_read(map, addr); > + > + return map_word_andequal(map, d, ready, ready); > + } > + > d = map_read(map, addr); > t = map_read(map, addr); > > @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) > */ > static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) > { > + struct cfi_private *cfi = map->fldrv_priv; > map_word oldd, curd; > > + if (cfi_use_status_reg(cfi)) { > + map_word ready = CMD(CFI_SR_DRB); > + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); Is it not necessary to check CFI_SR_WBASB and CFI_SR_SLSB that are checked by cfi_check_err_status()? > + /* > + * For chips that support status register, check device > + * ready bit and Erase/Program status bit to know if > + * operation succeeded. > + */ > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Same as cfi_check_err_status() and chip_ready() about the base address. > + cfi->device_type, NULL); > + curd = map_read(map, addr); > + > + if (map_word_andequal(map, curd, ready, ready)) > + return !map_word_bitsset(map, curd, err); > + > + return 0; > + } > + > oldd = map_read(map, addr); > curd = map_read(map, addr); > > @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, > /* Did we succeed? */ > if (!chip_good(map, adr, datum)) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, > * See e.g. > * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf > */ > + cfi_check_err_status(map, adr); > cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, > cfi->device_type, NULL); > cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, > @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, > > if (!chip_good(map, adr, datum)) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) > /* Did we succeed? */ > if (ret) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, > /* Did we succeed? */ > if (ret) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h > index 208c87cf2e3e..b50416169049 100644 > --- a/include/linux/mtd/cfi.h > +++ b/include/linux/mtd/cfi.h > @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { > uint8_t VppMin; > uint8_t VppMax; > uint8_t TopBottom; > + /* Below field are added from version 1.5 */ > + uint8_t ProgramSuspend; > + uint8_t UnlockBypass; > + uint8_t SecureSiliconSector; > + uint8_t SoftwareFeatures; > } __packed; > > /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register @ 2019-06-24 16:46 ` Tokunori Ikegami 0 siblings, 0 replies; 48+ messages in thread From: Tokunori Ikegami @ 2019-06-24 16:46 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel On 2019/06/21 2:22, Vignesh Raghavendra wrote: > HyperFlash devices are compliant with CFI AMD/Fujitsu Extended Command > Set (0x0002) for flash operations, therefore > drivers/mtd/chips/cfi_cmdset_0002.c can be used as is. But these devices > do not support DQ polling method of determining chip ready/good status. > These flashes provide Status Register whose bits can be polled to know > status of flash operation. > > Cypress HyperFlash datasheet here[1], talks about CFI Amd/Fujitsu > Extended Query version 1.5. Bit 0 of "Software Features supported" field > of CFI Primary Vendor-Specific Extended Query table indicates > presence/absence of status register and Bit 1 indicates whether or not > DQ polling is supported. Using these bits, its possible to determine > whether flash supports DQ polling or need to use Status Register. > > Add support for polling Status Register to know device ready/status of > erase/write operations when DQ polling is not supported. > Print error messages on erase/program failure by looking at related > Status Register bits. > > [1] https://www.cypress.com/file/213346/download > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > --- > v7: No change > > drivers/mtd/chips/cfi_cmdset_0002.c | 90 +++++++++++++++++++++++++++++ > include/linux/mtd/cfi.h | 5 ++ > 2 files changed, 95 insertions(+) > > diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c > index c8fa5906bdf9..0f571f162e3b 100644 > --- a/drivers/mtd/chips/cfi_cmdset_0002.c > +++ b/drivers/mtd/chips/cfi_cmdset_0002.c > @@ -49,6 +49,16 @@ > #define SST49LF008A 0x005a > #define AT49BV6416 0x00d6 > > +/* > + * Status Register bit description. Used by flash devices that don't > + * support DQ polling (e.g. HyperFlash) > + */ > +#define CFI_SR_DRB BIT(7) > +#define CFI_SR_ESB BIT(5) > +#define CFI_SR_PSB BIT(4) > +#define CFI_SR_WBASB BIT(3) > +#define CFI_SR_SLSB BIT(1) > + > static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); > static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); > static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); > @@ -97,6 +107,48 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { > .module = THIS_MODULE > }; > > +/* > + * Use status register to poll for Erase/write completion when DQ is not > + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in > + * CFI Primary Vendor-Specific Extended Query table 1.5 > + */ > +static int cfi_use_status_reg(struct cfi_private *cfi) > +{ > + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; > + > + return extp->MinorVersion >= '5' && > + (extp->SoftwareFeatures & 0x3) == 0x1; Seems to be better to use defined values instead of 0x3 and 0x1 hard coded values. > +} > + > +static void cfi_check_err_status(struct map_info *map, unsigned long adr) > +{ > + struct cfi_private *cfi = map->fldrv_priv; > + map_word status; > + > + if (!cfi_use_status_reg(cfi)) > + return; > + > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Is it not necessary to set chip->start as the base parameter for cfi_send_gen_cmd()? > + cfi->device_type, NULL); > + status = map_read(map, adr); > + > + if (map_word_bitsset(map, status, CMD(0x3a))) { > + unsigned long chipstatus = MERGESTATUS(status); > + > + if (chipstatus & CFI_SR_ESB) > + pr_err("%s erase operation failed, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_PSB) > + pr_err("%s program operation failed, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_WBASB) > + pr_err("%s buffer program command aborted, status %lx\n", > + map->name, chipstatus); > + if (chipstatus & CFI_SR_SLSB) > + pr_err("%s sector write protected, status %lx\n", > + map->name, chipstatus); > + } > +} > > /* #define DEBUG_CFI_FEATURES */ > > @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) > */ > static int __xipram chip_ready(struct map_info *map, unsigned long addr) > { > + struct cfi_private *cfi = map->fldrv_priv; > map_word d, t; > > + if (cfi_use_status_reg(cfi)) { > + map_word ready = CMD(CFI_SR_DRB); > + /* > + * For chips that support status register, check device > + * ready bit > + */ > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Same comment as cfi_check_err_status() about the base address. > + cfi->device_type, NULL); > + d = map_read(map, addr); > + > + return map_word_andequal(map, d, ready, ready); > + } > + > d = map_read(map, addr); > t = map_read(map, addr); > > @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) > */ > static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) > { > + struct cfi_private *cfi = map->fldrv_priv; > map_word oldd, curd; > > + if (cfi_use_status_reg(cfi)) { > + map_word ready = CMD(CFI_SR_DRB); > + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); Is it not necessary to check CFI_SR_WBASB and CFI_SR_SLSB that are checked by cfi_check_err_status()? > + /* > + * For chips that support status register, check device > + * ready bit and Erase/Program status bit to know if > + * operation succeeded. > + */ > + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, Same as cfi_check_err_status() and chip_ready() about the base address. > + cfi->device_type, NULL); > + curd = map_read(map, addr); > + > + if (map_word_andequal(map, curd, ready, ready)) > + return !map_word_bitsset(map, curd, err); > + > + return 0; > + } > + > oldd = map_read(map, addr); > curd = map_read(map, addr); > > @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, > /* Did we succeed? */ > if (!chip_good(map, adr, datum)) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, > * See e.g. > * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf > */ > + cfi_check_err_status(map, adr); > cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, > cfi->device_type, NULL); > cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, > @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, > > if (!chip_good(map, adr, datum)) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) > /* Did we succeed? */ > if (ret) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, > /* Did we succeed? */ > if (ret) { > /* reset on all failures. */ > + cfi_check_err_status(map, adr); > map_write(map, CMD(0xF0), chip->start); > /* FIXME - should have reset delay before continuing */ > > diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h > index 208c87cf2e3e..b50416169049 100644 > --- a/include/linux/mtd/cfi.h > +++ b/include/linux/mtd/cfi.h > @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { > uint8_t VppMin; > uint8_t VppMax; > uint8_t TopBottom; > + /* Below field are added from version 1.5 */ > + uint8_t ProgramSuspend; > + uint8_t UnlockBypass; > + uint8_t SecureSiliconSector; > + uint8_t SoftwareFeatures; > } __packed; > > /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register 2019-06-24 16:46 ` Tokunori Ikegami (?) @ 2019-06-25 5:52 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-25 5:52 UTC (permalink / raw) To: Tokunori Ikegami, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Hi, On 24/06/19 10:16 PM, Tokunori Ikegami wrote: > [...] >> +/* >> + * Use status register to poll for Erase/write completion when DQ is not >> + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in >> + * CFI Primary Vendor-Specific Extended Query table 1.5 >> + */ >> +static int cfi_use_status_reg(struct cfi_private *cfi) >> +{ >> + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; >> + >> + return extp->MinorVersion >= '5' && >> + (extp->SoftwareFeatures & 0x3) == 0x1; > > Seems to be better to use defined values instead of 0x3 and 0x1 hard > coded values. > Ok >> +} >> + >> +static void cfi_check_err_status(struct map_info *map, unsigned long >> adr) >> +{ >> + struct cfi_private *cfi = map->fldrv_priv; >> + map_word status; >> + >> + if (!cfi_use_status_reg(cfi)) >> + return; >> + >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Is it not necessary to set chip->start as the base parameter for > cfi_send_gen_cmd()? > Right now, I am not aware of any flash that supports status registers and are banked (that's when chip->start can be non zero). Therefore I did not think of using chip->start. But anyways, I will fix this up to use chip->start here and elsewhere for next version, assuming there will be such chips in the future. >> + cfi->device_type, NULL); >> + status = map_read(map, adr); >> + >> + if (map_word_bitsset(map, status, CMD(0x3a))) { >> + unsigned long chipstatus = MERGESTATUS(status); >> + >> + if (chipstatus & CFI_SR_ESB) >> + pr_err("%s erase operation failed, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_PSB) >> + pr_err("%s program operation failed, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_WBASB) >> + pr_err("%s buffer program command aborted, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_SLSB) >> + pr_err("%s sector write protected, status %lx\n", >> + map->name, chipstatus); >> + } >> +} >> /* #define DEBUG_CFI_FEATURES */ >> @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct >> mtd_info *mtd) >> */ >> static int __xipram chip_ready(struct map_info *map, unsigned long >> addr) >> { >> + struct cfi_private *cfi = map->fldrv_priv; >> map_word d, t; >> + if (cfi_use_status_reg(cfi)) { >> + map_word ready = CMD(CFI_SR_DRB); >> + /* >> + * For chips that support status register, check device >> + * ready bit >> + */ >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Same comment as cfi_check_err_status() about the base address. > >> + cfi->device_type, NULL); >> + d = map_read(map, addr); >> + >> + return map_word_andequal(map, d, ready, ready); >> + } >> + >> d = map_read(map, addr); >> t = map_read(map, addr); >> @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info >> *map, unsigned long addr) >> */ >> static int __xipram chip_good(struct map_info *map, unsigned long >> addr, map_word expected) >> { >> + struct cfi_private *cfi = map->fldrv_priv; >> map_word oldd, curd; >> + if (cfi_use_status_reg(cfi)) { >> + map_word ready = CMD(CFI_SR_DRB); >> + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); > > Is it not necessary to check CFI_SR_WBASB and CFI_SR_SLSB that are > checked by cfi_check_err_status()? > chip_good() is used to verify whether write or erase operation really succeeded. Looking at Cypress HyperFlash datasheets and app notes on status register polling, its enough to see if CFI_SR_PSB or CFI_SR_PSB is set to know if write or erase failed. Now, the reason for program or erase failure can be known by looking at CFI_SR_WBASB and CFI_SR_SLSB which is done for cfi_check_err_status(). Therefore, I feel, its enough to look for CFI_SR_PSB or CFI_SR_ESB here. Thanks for the review! Regards Vignesh >> + /* >> + * For chips that support status register, check device >> + * ready bit and Erase/Program status bit to know if >> + * operation succeeded. >> + */ >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Same as cfi_check_err_status() and chip_ready() about the base address. > >> + cfi->device_type, NULL); >> + curd = map_read(map, addr); >> + >> + if (map_word_andequal(map, curd, ready, ready)) >> + return !map_word_bitsset(map, curd, err); >> + >> + return 0; >> + } >> + >> oldd = map_read(map, addr); >> curd = map_read(map, addr); >> @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct >> map_info *map, struct flchip *chip, >> /* Did we succeed? */ >> if (!chip_good(map, adr, datum)) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct >> map_info *map, struct flchip *chip, >> * See e.g. >> * >> http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf >> >> */ >> + cfi_check_err_status(map, adr); >> cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, >> cfi->device_type, NULL); >> cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, >> @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct >> map_info *map, struct flchip *chip, >> if (!chip_good(map, adr, datum)) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct >> map_info *map, struct flchip *chip) >> /* Did we succeed? */ >> if (ret) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct >> map_info *map, struct flchip *chip, >> /* Did we succeed? */ >> if (ret) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h >> index 208c87cf2e3e..b50416169049 100644 >> --- a/include/linux/mtd/cfi.h >> +++ b/include/linux/mtd/cfi.h >> @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { >> uint8_t VppMin; >> uint8_t VppMax; >> uint8_t TopBottom; >> + /* Below field are added from version 1.5 */ >> + uint8_t ProgramSuspend; >> + uint8_t UnlockBypass; >> + uint8_t SecureSiliconSector; >> + uint8_t SoftwareFeatures; >> } __packed; >> /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ -- Regards Vignesh ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register @ 2019-06-25 5:52 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-25 5:52 UTC (permalink / raw) To: Tokunori Ikegami, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Hi, On 24/06/19 10:16 PM, Tokunori Ikegami wrote: > [...] >> +/* >> + * Use status register to poll for Erase/write completion when DQ is not >> + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in >> + * CFI Primary Vendor-Specific Extended Query table 1.5 >> + */ >> +static int cfi_use_status_reg(struct cfi_private *cfi) >> +{ >> + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; >> + >> + return extp->MinorVersion >= '5' && >> + (extp->SoftwareFeatures & 0x3) == 0x1; > > Seems to be better to use defined values instead of 0x3 and 0x1 hard > coded values. > Ok >> +} >> + >> +static void cfi_check_err_status(struct map_info *map, unsigned long >> adr) >> +{ >> + struct cfi_private *cfi = map->fldrv_priv; >> + map_word status; >> + >> + if (!cfi_use_status_reg(cfi)) >> + return; >> + >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Is it not necessary to set chip->start as the base parameter for > cfi_send_gen_cmd()? > Right now, I am not aware of any flash that supports status registers and are banked (that's when chip->start can be non zero). Therefore I did not think of using chip->start. But anyways, I will fix this up to use chip->start here and elsewhere for next version, assuming there will be such chips in the future. >> + cfi->device_type, NULL); >> + status = map_read(map, adr); >> + >> + if (map_word_bitsset(map, status, CMD(0x3a))) { >> + unsigned long chipstatus = MERGESTATUS(status); >> + >> + if (chipstatus & CFI_SR_ESB) >> + pr_err("%s erase operation failed, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_PSB) >> + pr_err("%s program operation failed, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_WBASB) >> + pr_err("%s buffer program command aborted, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_SLSB) >> + pr_err("%s sector write protected, status %lx\n", >> + map->name, chipstatus); >> + } >> +} >> /* #define DEBUG_CFI_FEATURES */ >> @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct >> mtd_info *mtd) >> */ >> static int __xipram chip_ready(struct map_info *map, unsigned long >> addr) >> { >> + struct cfi_private *cfi = map->fldrv_priv; >> map_word d, t; >> + if (cfi_use_status_reg(cfi)) { >> + map_word ready = CMD(CFI_SR_DRB); >> + /* >> + * For chips that support status register, check device >> + * ready bit >> + */ >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Same comment as cfi_check_err_status() about the base address. > >> + cfi->device_type, NULL); >> + d = map_read(map, addr); >> + >> + return map_word_andequal(map, d, ready, ready); >> + } >> + >> d = map_read(map, addr); >> t = map_read(map, addr); >> @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info >> *map, unsigned long addr) >> */ >> static int __xipram chip_good(struct map_info *map, unsigned long >> addr, map_word expected) >> { >> + struct cfi_private *cfi = map->fldrv_priv; >> map_word oldd, curd; >> + if (cfi_use_status_reg(cfi)) { >> + map_word ready = CMD(CFI_SR_DRB); >> + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); > > Is it not necessary to check CFI_SR_WBASB and CFI_SR_SLSB that are > checked by cfi_check_err_status()? > chip_good() is used to verify whether write or erase operation really succeeded. Looking at Cypress HyperFlash datasheets and app notes on status register polling, its enough to see if CFI_SR_PSB or CFI_SR_PSB is set to know if write or erase failed. Now, the reason for program or erase failure can be known by looking at CFI_SR_WBASB and CFI_SR_SLSB which is done for cfi_check_err_status(). Therefore, I feel, its enough to look for CFI_SR_PSB or CFI_SR_ESB here. Thanks for the review! Regards Vignesh >> + /* >> + * For chips that support status register, check device >> + * ready bit and Erase/Program status bit to know if >> + * operation succeeded. >> + */ >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Same as cfi_check_err_status() and chip_ready() about the base address. > >> + cfi->device_type, NULL); >> + curd = map_read(map, addr); >> + >> + if (map_word_andequal(map, curd, ready, ready)) >> + return !map_word_bitsset(map, curd, err); >> + >> + return 0; >> + } >> + >> oldd = map_read(map, addr); >> curd = map_read(map, addr); >> @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct >> map_info *map, struct flchip *chip, >> /* Did we succeed? */ >> if (!chip_good(map, adr, datum)) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct >> map_info *map, struct flchip *chip, >> * See e.g. >> * >> http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf >> >> */ >> + cfi_check_err_status(map, adr); >> cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, >> cfi->device_type, NULL); >> cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, >> @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct >> map_info *map, struct flchip *chip, >> if (!chip_good(map, adr, datum)) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct >> map_info *map, struct flchip *chip) >> /* Did we succeed? */ >> if (ret) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct >> map_info *map, struct flchip *chip, >> /* Did we succeed? */ >> if (ret) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h >> index 208c87cf2e3e..b50416169049 100644 >> --- a/include/linux/mtd/cfi.h >> +++ b/include/linux/mtd/cfi.h >> @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { >> uint8_t VppMin; >> uint8_t VppMax; >> uint8_t TopBottom; >> + /* Below field are added from version 1.5 */ >> + uint8_t ProgramSuspend; >> + uint8_t UnlockBypass; >> + uint8_t SecureSiliconSector; >> + uint8_t SoftwareFeatures; >> } __packed; >> /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ -- Regards Vignesh _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register @ 2019-06-25 5:52 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-25 5:52 UTC (permalink / raw) To: Tokunori Ikegami, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Hi, On 24/06/19 10:16 PM, Tokunori Ikegami wrote: > [...] >> +/* >> + * Use status register to poll for Erase/write completion when DQ is not >> + * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in >> + * CFI Primary Vendor-Specific Extended Query table 1.5 >> + */ >> +static int cfi_use_status_reg(struct cfi_private *cfi) >> +{ >> + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; >> + >> + return extp->MinorVersion >= '5' && >> + (extp->SoftwareFeatures & 0x3) == 0x1; > > Seems to be better to use defined values instead of 0x3 and 0x1 hard > coded values. > Ok >> +} >> + >> +static void cfi_check_err_status(struct map_info *map, unsigned long >> adr) >> +{ >> + struct cfi_private *cfi = map->fldrv_priv; >> + map_word status; >> + >> + if (!cfi_use_status_reg(cfi)) >> + return; >> + >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Is it not necessary to set chip->start as the base parameter for > cfi_send_gen_cmd()? > Right now, I am not aware of any flash that supports status registers and are banked (that's when chip->start can be non zero). Therefore I did not think of using chip->start. But anyways, I will fix this up to use chip->start here and elsewhere for next version, assuming there will be such chips in the future. >> + cfi->device_type, NULL); >> + status = map_read(map, adr); >> + >> + if (map_word_bitsset(map, status, CMD(0x3a))) { >> + unsigned long chipstatus = MERGESTATUS(status); >> + >> + if (chipstatus & CFI_SR_ESB) >> + pr_err("%s erase operation failed, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_PSB) >> + pr_err("%s program operation failed, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_WBASB) >> + pr_err("%s buffer program command aborted, status %lx\n", >> + map->name, chipstatus); >> + if (chipstatus & CFI_SR_SLSB) >> + pr_err("%s sector write protected, status %lx\n", >> + map->name, chipstatus); >> + } >> +} >> /* #define DEBUG_CFI_FEATURES */ >> @@ -744,8 +796,22 @@ static struct mtd_info *cfi_amdstd_setup(struct >> mtd_info *mtd) >> */ >> static int __xipram chip_ready(struct map_info *map, unsigned long >> addr) >> { >> + struct cfi_private *cfi = map->fldrv_priv; >> map_word d, t; >> + if (cfi_use_status_reg(cfi)) { >> + map_word ready = CMD(CFI_SR_DRB); >> + /* >> + * For chips that support status register, check device >> + * ready bit >> + */ >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Same comment as cfi_check_err_status() about the base address. > >> + cfi->device_type, NULL); >> + d = map_read(map, addr); >> + >> + return map_word_andequal(map, d, ready, ready); >> + } >> + >> d = map_read(map, addr); >> t = map_read(map, addr); >> @@ -769,8 +835,27 @@ static int __xipram chip_ready(struct map_info >> *map, unsigned long addr) >> */ >> static int __xipram chip_good(struct map_info *map, unsigned long >> addr, map_word expected) >> { >> + struct cfi_private *cfi = map->fldrv_priv; >> map_word oldd, curd; >> + if (cfi_use_status_reg(cfi)) { >> + map_word ready = CMD(CFI_SR_DRB); >> + map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); > > Is it not necessary to check CFI_SR_WBASB and CFI_SR_SLSB that are > checked by cfi_check_err_status()? > chip_good() is used to verify whether write or erase operation really succeeded. Looking at Cypress HyperFlash datasheets and app notes on status register polling, its enough to see if CFI_SR_PSB or CFI_SR_PSB is set to know if write or erase failed. Now, the reason for program or erase failure can be known by looking at CFI_SR_WBASB and CFI_SR_SLSB which is done for cfi_check_err_status(). Therefore, I feel, its enough to look for CFI_SR_PSB or CFI_SR_ESB here. Thanks for the review! Regards Vignesh >> + /* >> + * For chips that support status register, check device >> + * ready bit and Erase/Program status bit to know if >> + * operation succeeded. >> + */ >> + cfi_send_gen_cmd(0x70, cfi->addr_unlock1, 0, map, cfi, > > Same as cfi_check_err_status() and chip_ready() about the base address. > >> + cfi->device_type, NULL); >> + curd = map_read(map, addr); >> + >> + if (map_word_andequal(map, curd, ready, ready)) >> + return !map_word_bitsset(map, curd, err); >> + >> + return 0; >> + } >> + >> oldd = map_read(map, addr); >> curd = map_read(map, addr); >> @@ -1644,6 +1729,7 @@ static int __xipram do_write_oneword(struct >> map_info *map, struct flchip *chip, >> /* Did we succeed? */ >> if (!chip_good(map, adr, datum)) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -1901,6 +1987,7 @@ static int __xipram do_write_buffer(struct >> map_info *map, struct flchip *chip, >> * See e.g. >> * >> http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf >> >> */ >> + cfi_check_err_status(map, adr); >> cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, >> cfi->device_type, NULL); >> cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, >> @@ -2107,6 +2194,7 @@ static int do_panic_write_oneword(struct >> map_info *map, struct flchip *chip, >> if (!chip_good(map, adr, datum)) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -2316,6 +2404,7 @@ static int __xipram do_erase_chip(struct >> map_info *map, struct flchip *chip) >> /* Did we succeed? */ >> if (ret) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> @@ -2412,6 +2501,7 @@ static int __xipram do_erase_oneblock(struct >> map_info *map, struct flchip *chip, >> /* Did we succeed? */ >> if (ret) { >> /* reset on all failures. */ >> + cfi_check_err_status(map, adr); >> map_write(map, CMD(0xF0), chip->start); >> /* FIXME - should have reset delay before continuing */ >> diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h >> index 208c87cf2e3e..b50416169049 100644 >> --- a/include/linux/mtd/cfi.h >> +++ b/include/linux/mtd/cfi.h >> @@ -219,6 +219,11 @@ struct cfi_pri_amdstd { >> uint8_t VppMin; >> uint8_t VppMax; >> uint8_t TopBottom; >> + /* Below field are added from version 1.5 */ >> + uint8_t ProgramSuspend; >> + uint8_t UnlockBypass; >> + uint8_t SecureSiliconSector; >> + uint8_t SoftwareFeatures; >> } __packed; >> /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ -- Regards Vignesh ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v7 2/5] dt-bindings: mtd: Add binding documentation for HyperFlash 2019-06-20 17:22 ` Vignesh Raghavendra (?) (?) @ 2019-06-20 17:22 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Add DT binding documentation for HyperFlash devices. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Reviewed-by: Rob Herring <robh@kernel.org> --- v7: No change .../devicetree/bindings/mtd/cypress,hyperflash.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt diff --git a/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt new file mode 100644 index 000000000000..ad42f4db32f1 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt @@ -0,0 +1,13 @@ +Bindings for HyperFlash NOR flash chips compliant with Cypress HyperBus +specification and supports Cypress CFI specification 1.5 command set. + +Required properties: +- compatible : "cypress,hyperflash", "cfi-flash" for HyperFlash NOR chips +- reg : Address of flash's memory map + +Example: + + flash@0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x4000000>; + }; -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 2/5] dt-bindings: mtd: Add binding documentation for HyperFlash @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Add DT binding documentation for HyperFlash devices. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Reviewed-by: Rob Herring <robh@kernel.org> --- v7: No change .../devicetree/bindings/mtd/cypress,hyperflash.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt diff --git a/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt new file mode 100644 index 000000000000..ad42f4db32f1 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt @@ -0,0 +1,13 @@ +Bindings for HyperFlash NOR flash chips compliant with Cypress HyperBus +specification and supports Cypress CFI specification 1.5 command set. + +Required properties: +- compatible : "cypress,hyperflash", "cfi-flash" for HyperFlash NOR chips +- reg : Address of flash's memory map + +Example: + + flash@0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x4000000>; + }; -- 2.22.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 2/5] dt-bindings: mtd: Add binding documentation for HyperFlash @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Add DT binding documentation for HyperFlash devices. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Reviewed-by: Rob Herring <robh@kernel.org> --- v7: No change .../devicetree/bindings/mtd/cypress,hyperflash.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt diff --git a/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt new file mode 100644 index 000000000000..ad42f4db32f1 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt @@ -0,0 +1,13 @@ +Bindings for HyperFlash NOR flash chips compliant with Cypress HyperBus +specification and supports Cypress CFI specification 1.5 command set. + +Required properties: +- compatible : "cypress,hyperflash", "cfi-flash" for HyperFlash NOR chips +- reg : Address of flash's memory map + +Example: + + flash@0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x4000000>; + }; -- 2.22.0 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 2/5] dt-bindings: mtd: Add binding documentation for HyperFlash @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Add DT binding documentation for HyperFlash devices. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Reviewed-by: Rob Herring <robh@kernel.org> --- v7: No change .../devicetree/bindings/mtd/cypress,hyperflash.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt diff --git a/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt new file mode 100644 index 000000000000..ad42f4db32f1 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt @@ -0,0 +1,13 @@ +Bindings for HyperFlash NOR flash chips compliant with Cypress HyperBus +specification and supports Cypress CFI specification 1.5 command set. + +Required properties: +- compatible : "cypress,hyperflash", "cfi-flash" for HyperFlash NOR chips +- reg : Address of flash's memory map + +Example: + + flash@0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x4000000>; + }; -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 3/5] mtd: Add support for HyperBus memory devices 2019-06-20 17:22 ` Vignesh Raghavendra (?) (?) @ 2019-06-20 17:22 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory (called HyperFlash) or self refresh DRAM (called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since HyperBus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But HyperBus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. But, HyperBus memory controllers seem to abstract implementation details and expose a simple MMIO interface to access connected flash. Add support for registering HyperFlash devices with MTD framework. MTD maps framework along with CFI chip support framework are used to support communicating with flash. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers calls hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Some HBMC masters need calibration/training sequence[3] to be carried out, in order for DLL inside the controller to lock, by reading a known string/pattern. This is done by repeatedly reading CFI Query Identification String. Calibration needs to be done before trying to detect flash as part of CFI flash probe. HyperRAM is not supported at the moment. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Clarify read16()/write16() APIs Move calibration code out into TI specific driver MAINTAINERS | 7 ++ drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/hyperbus/Kconfig | 11 ++ drivers/mtd/hyperbus/Makefile | 3 + drivers/mtd/hyperbus/hyperbus-core.c | 154 +++++++++++++++++++++++++++ include/linux/mtd/hyperbus.h | 86 +++++++++++++++ 7 files changed, 264 insertions(+) create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h diff --git a/MAINTAINERS b/MAINTAINERS index ff7c2b7e67b9..58c6ad3dae66 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7353,6 +7353,13 @@ F: include/asm-generic/mshyperv.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus +HYPERBUS SUPPORT +M: Vignesh Raghavendra <vigneshr@ti.com> +S: Supported +F: drivers/mtd/hyperbus/ +F: include/linux/mtd/hyperbus.h +F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt + HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org S: Odd Fixes diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index fb31a7f649a3..80a6e2dcd085 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -274,4 +274,6 @@ source "drivers/mtd/spi-nor/Kconfig" source "drivers/mtd/ubi/Kconfig" +source "drivers/mtd/hyperbus/Kconfig" + endif # MTD diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 806287e80e84..62d649a959e2 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -34,3 +34,4 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ tests/ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ obj-$(CONFIG_MTD_UBI) += ubi/ +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig new file mode 100644 index 000000000000..98147e28caa0 --- /dev/null +++ b/drivers/mtd/hyperbus/Kconfig @@ -0,0 +1,11 @@ +menuconfig MTD_HYPERBUS + tristate "HyperBus support" + select MTD_CFI + select MTD_MAP_BANK_WIDTH_2 + select MTD_CFI_AMDSTD + select MTD_COMPLEX_MAPPINGS + help + This is the framework for the HyperBus which can be used by + the HyperBus Controller driver to communicate with + HyperFlash. See Cypress HyperBus specification for more + details diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile new file mode 100644 index 000000000000..ca61dedd730d --- /dev/null +++ b/drivers/mtd/hyperbus/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o diff --git a/drivers/mtd/hyperbus/hyperbus-core.c b/drivers/mtd/hyperbus/hyperbus-core.c new file mode 100644 index 000000000000..63a9e64895bc --- /dev/null +++ b/drivers/mtd/hyperbus/hyperbus-core.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/map.h> +#include <linux/mtd/mtd.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/types.h> + +static struct hyperbus_device *map_to_hbdev(struct map_info *map) +{ + return container_of(map, struct hyperbus_device, map); +} + +static map_word hyperbus_read16(struct map_info *map, unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + map_word read_data; + + read_data.x[0] = ctlr->ops->read16(hbdev, addr); + + return read_data; +} + +static void hyperbus_write16(struct map_info *map, map_word d, + unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->write16(hbdev, addr, d.x[0]); +} + +static void hyperbus_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_from(hbdev, to, from, len); +} + +static void hyperbus_copy_to(struct map_info *map, unsigned long to, + const void *from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_to(hbdev, to, from, len); +} + +int hyperbus_register_device(struct hyperbus_device *hbdev) +{ + const struct hyperbus_ops *ops; + struct hyperbus_ctlr *ctlr; + struct device_node *np; + struct map_info *map; + struct resource res; + struct device *dev; + int ret; + + if (!hbdev || !hbdev->np || !hbdev->ctlr || !hbdev->ctlr->dev) { + pr_err("hyperbus: please fill all the necessary fields!\n"); + return -EINVAL; + } + + np = hbdev->np; + ctlr = hbdev->ctlr; + if (!of_device_is_compatible(np, "cypress,hyperflash")) + return -ENODEV; + + hbdev->memtype = HYPERFLASH; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + return ret; + + dev = ctlr->dev; + map = &hbdev->map; + map->size = resource_size(&res); + map->virt = devm_ioremap_resource(dev, &res); + if (IS_ERR(map->virt)) + return PTR_ERR(map->virt); + + map->name = dev_name(dev); + map->bankwidth = 2; + map->device_node = np; + + simple_map_init(map); + ops = ctlr->ops; + if (ops) { + if (ops->read16) + map->read = hyperbus_read16; + if (ops->write16) + map->write = hyperbus_write16; + if (ops->copy_to) + map->copy_to = hyperbus_copy_to; + if (ops->copy_from) + map->copy_from = hyperbus_copy_from; + + if (ops->calibrate && !ctlr->calibrated) { + ret = ops->calibrate(hbdev); + if (!ret) { + dev_err(dev, "Calibration failed\n"); + return -ENODEV; + } + ctlr->calibrated = true; + } + } + + hbdev->mtd = do_map_probe("cfi_probe", map); + if (!hbdev->mtd) { + dev_err(dev, "probing of hyperbus device failed\n"); + return -ENODEV; + } + + hbdev->mtd->dev.parent = dev; + mtd_set_of_node(hbdev->mtd, np); + + ret = mtd_device_register(hbdev->mtd, NULL, 0); + if (ret) { + dev_err(dev, "failed to register mtd device\n"); + map_destroy(hbdev->mtd); + return ret; + } + hbdev->registered = true; + + return 0; +} +EXPORT_SYMBOL_GPL(hyperbus_register_device); + +int hyperbus_unregister_device(struct hyperbus_device *hbdev) +{ + int ret = 0; + + if (hbdev && hbdev->mtd && hbdev->registered) { + ret = mtd_device_unregister(hbdev->mtd); + map_destroy(hbdev->mtd); + } + + return ret; +} +EXPORT_SYMBOL_GPL(hyperbus_unregister_device); + +MODULE_DESCRIPTION("HyperBus Framework"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h new file mode 100644 index 000000000000..ead969aad35b --- /dev/null +++ b/include/linux/mtd/hyperbus.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#ifndef __LINUX_MTD_HYPERBUS_H__ +#define __LINUX_MTD_HYPERBUS_H__ + +#include <linux/mtd/map.h> + +enum hyperbus_memtype { + HYPERFLASH, + HYPERRAM, +}; + +/** + * struct hyperbus_device - struct representing HyperBus slave device + * @map: map_info struct for accessing MMIO HyperBus flash memory + * @np: pointer to HyperBus slave device node + * @mtd: pointer to MTD struct + * @ctlr: pointer to HyperBus controller struct + * @memtype: type of memory device: HyperFlash or HyperRAM + * @registered: flag to indicate whether device is registered with MTD core + */ + +struct hyperbus_device { + struct map_info map; + struct device_node *np; + struct mtd_info *mtd; + struct hyperbus_ctlr *ctlr; + enum hyperbus_memtype memtype; + bool registered; +}; + +/** + * struct hyperbus_ops - struct representing custom HyperBus operations + * @read16: read 16 bit of data to flash in a single burst. Used to read + * from non default address space, such as ID/CFI space + * @write16: write 16 bit of data to flash in a single burst. Used to + * send cmd to flash or write single 16 bit word at a time. + * @copy_from: copy data from flash memory + * @copy_to: copy data to flash memory + * @calibrate: calibrate HyperBus controller + */ + +struct hyperbus_ops { + u16 (*read16)(struct hyperbus_device *hbdev, unsigned long addr); + void (*write16)(struct hyperbus_device *hbdev, + unsigned long addr, u16 val); + void (*copy_from)(struct hyperbus_device *hbdev, void *to, + unsigned long from, ssize_t len); + void (*copy_to)(struct hyperbus_device *dev, unsigned long to, + const void *from, ssize_t len); + int (*calibrate)(struct hyperbus_device *dev); +}; + +/** + * struct hyperbus_ctlr - struct representing HyperBus controller + * @dev: pointer to HyperBus controller device + * @calibrated: flag to indicate ctlr calibration sequence is complete + * @ops: HyperBus controller ops + */ +struct hyperbus_ctlr { + struct device *dev; + bool calibrated; + + const struct hyperbus_ops *ops; +}; + +/** + * hyperbus_register_device - probe and register a HyperBus slave memory device + * @hbdev: hyperbus_device struct with dev, np and ctlr field populated + * + * Return: 0 for success, others for failure. + */ +int hyperbus_register_device(struct hyperbus_device *hbdev); + +/** + * hyperbus_unregister_device - deregister HyperBus slave memory device + * @hbdev: hyperbus_device to be unregistered + * + * Return: 0 for success, others for failure. + */ +int hyperbus_unregister_device(struct hyperbus_device *hbdev); + +#endif /* __LINUX_MTD_HYPERBUS_H__ */ -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory (called HyperFlash) or self refresh DRAM (called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since HyperBus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But HyperBus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. But, HyperBus memory controllers seem to abstract implementation details and expose a simple MMIO interface to access connected flash. Add support for registering HyperFlash devices with MTD framework. MTD maps framework along with CFI chip support framework are used to support communicating with flash. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers calls hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Some HBMC masters need calibration/training sequence[3] to be carried out, in order for DLL inside the controller to lock, by reading a known string/pattern. This is done by repeatedly reading CFI Query Identification String. Calibration needs to be done before trying to detect flash as part of CFI flash probe. HyperRAM is not supported at the moment. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Clarify read16()/write16() APIs Move calibration code out into TI specific driver MAINTAINERS | 7 ++ drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/hyperbus/Kconfig | 11 ++ drivers/mtd/hyperbus/Makefile | 3 + drivers/mtd/hyperbus/hyperbus-core.c | 154 +++++++++++++++++++++++++++ include/linux/mtd/hyperbus.h | 86 +++++++++++++++ 7 files changed, 264 insertions(+) create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h diff --git a/MAINTAINERS b/MAINTAINERS index ff7c2b7e67b9..58c6ad3dae66 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7353,6 +7353,13 @@ F: include/asm-generic/mshyperv.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus +HYPERBUS SUPPORT +M: Vignesh Raghavendra <vigneshr@ti.com> +S: Supported +F: drivers/mtd/hyperbus/ +F: include/linux/mtd/hyperbus.h +F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt + HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org S: Odd Fixes diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index fb31a7f649a3..80a6e2dcd085 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -274,4 +274,6 @@ source "drivers/mtd/spi-nor/Kconfig" source "drivers/mtd/ubi/Kconfig" +source "drivers/mtd/hyperbus/Kconfig" + endif # MTD diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 806287e80e84..62d649a959e2 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -34,3 +34,4 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ tests/ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ obj-$(CONFIG_MTD_UBI) += ubi/ +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig new file mode 100644 index 000000000000..98147e28caa0 --- /dev/null +++ b/drivers/mtd/hyperbus/Kconfig @@ -0,0 +1,11 @@ +menuconfig MTD_HYPERBUS + tristate "HyperBus support" + select MTD_CFI + select MTD_MAP_BANK_WIDTH_2 + select MTD_CFI_AMDSTD + select MTD_COMPLEX_MAPPINGS + help + This is the framework for the HyperBus which can be used by + the HyperBus Controller driver to communicate with + HyperFlash. See Cypress HyperBus specification for more + details diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile new file mode 100644 index 000000000000..ca61dedd730d --- /dev/null +++ b/drivers/mtd/hyperbus/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o diff --git a/drivers/mtd/hyperbus/hyperbus-core.c b/drivers/mtd/hyperbus/hyperbus-core.c new file mode 100644 index 000000000000..63a9e64895bc --- /dev/null +++ b/drivers/mtd/hyperbus/hyperbus-core.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/map.h> +#include <linux/mtd/mtd.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/types.h> + +static struct hyperbus_device *map_to_hbdev(struct map_info *map) +{ + return container_of(map, struct hyperbus_device, map); +} + +static map_word hyperbus_read16(struct map_info *map, unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + map_word read_data; + + read_data.x[0] = ctlr->ops->read16(hbdev, addr); + + return read_data; +} + +static void hyperbus_write16(struct map_info *map, map_word d, + unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->write16(hbdev, addr, d.x[0]); +} + +static void hyperbus_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_from(hbdev, to, from, len); +} + +static void hyperbus_copy_to(struct map_info *map, unsigned long to, + const void *from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_to(hbdev, to, from, len); +} + +int hyperbus_register_device(struct hyperbus_device *hbdev) +{ + const struct hyperbus_ops *ops; + struct hyperbus_ctlr *ctlr; + struct device_node *np; + struct map_info *map; + struct resource res; + struct device *dev; + int ret; + + if (!hbdev || !hbdev->np || !hbdev->ctlr || !hbdev->ctlr->dev) { + pr_err("hyperbus: please fill all the necessary fields!\n"); + return -EINVAL; + } + + np = hbdev->np; + ctlr = hbdev->ctlr; + if (!of_device_is_compatible(np, "cypress,hyperflash")) + return -ENODEV; + + hbdev->memtype = HYPERFLASH; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + return ret; + + dev = ctlr->dev; + map = &hbdev->map; + map->size = resource_size(&res); + map->virt = devm_ioremap_resource(dev, &res); + if (IS_ERR(map->virt)) + return PTR_ERR(map->virt); + + map->name = dev_name(dev); + map->bankwidth = 2; + map->device_node = np; + + simple_map_init(map); + ops = ctlr->ops; + if (ops) { + if (ops->read16) + map->read = hyperbus_read16; + if (ops->write16) + map->write = hyperbus_write16; + if (ops->copy_to) + map->copy_to = hyperbus_copy_to; + if (ops->copy_from) + map->copy_from = hyperbus_copy_from; + + if (ops->calibrate && !ctlr->calibrated) { + ret = ops->calibrate(hbdev); + if (!ret) { + dev_err(dev, "Calibration failed\n"); + return -ENODEV; + } + ctlr->calibrated = true; + } + } + + hbdev->mtd = do_map_probe("cfi_probe", map); + if (!hbdev->mtd) { + dev_err(dev, "probing of hyperbus device failed\n"); + return -ENODEV; + } + + hbdev->mtd->dev.parent = dev; + mtd_set_of_node(hbdev->mtd, np); + + ret = mtd_device_register(hbdev->mtd, NULL, 0); + if (ret) { + dev_err(dev, "failed to register mtd device\n"); + map_destroy(hbdev->mtd); + return ret; + } + hbdev->registered = true; + + return 0; +} +EXPORT_SYMBOL_GPL(hyperbus_register_device); + +int hyperbus_unregister_device(struct hyperbus_device *hbdev) +{ + int ret = 0; + + if (hbdev && hbdev->mtd && hbdev->registered) { + ret = mtd_device_unregister(hbdev->mtd); + map_destroy(hbdev->mtd); + } + + return ret; +} +EXPORT_SYMBOL_GPL(hyperbus_unregister_device); + +MODULE_DESCRIPTION("HyperBus Framework"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h new file mode 100644 index 000000000000..ead969aad35b --- /dev/null +++ b/include/linux/mtd/hyperbus.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#ifndef __LINUX_MTD_HYPERBUS_H__ +#define __LINUX_MTD_HYPERBUS_H__ + +#include <linux/mtd/map.h> + +enum hyperbus_memtype { + HYPERFLASH, + HYPERRAM, +}; + +/** + * struct hyperbus_device - struct representing HyperBus slave device + * @map: map_info struct for accessing MMIO HyperBus flash memory + * @np: pointer to HyperBus slave device node + * @mtd: pointer to MTD struct + * @ctlr: pointer to HyperBus controller struct + * @memtype: type of memory device: HyperFlash or HyperRAM + * @registered: flag to indicate whether device is registered with MTD core + */ + +struct hyperbus_device { + struct map_info map; + struct device_node *np; + struct mtd_info *mtd; + struct hyperbus_ctlr *ctlr; + enum hyperbus_memtype memtype; + bool registered; +}; + +/** + * struct hyperbus_ops - struct representing custom HyperBus operations + * @read16: read 16 bit of data to flash in a single burst. Used to read + * from non default address space, such as ID/CFI space + * @write16: write 16 bit of data to flash in a single burst. Used to + * send cmd to flash or write single 16 bit word at a time. + * @copy_from: copy data from flash memory + * @copy_to: copy data to flash memory + * @calibrate: calibrate HyperBus controller + */ + +struct hyperbus_ops { + u16 (*read16)(struct hyperbus_device *hbdev, unsigned long addr); + void (*write16)(struct hyperbus_device *hbdev, + unsigned long addr, u16 val); + void (*copy_from)(struct hyperbus_device *hbdev, void *to, + unsigned long from, ssize_t len); + void (*copy_to)(struct hyperbus_device *dev, unsigned long to, + const void *from, ssize_t len); + int (*calibrate)(struct hyperbus_device *dev); +}; + +/** + * struct hyperbus_ctlr - struct representing HyperBus controller + * @dev: pointer to HyperBus controller device + * @calibrated: flag to indicate ctlr calibration sequence is complete + * @ops: HyperBus controller ops + */ +struct hyperbus_ctlr { + struct device *dev; + bool calibrated; + + const struct hyperbus_ops *ops; +}; + +/** + * hyperbus_register_device - probe and register a HyperBus slave memory device + * @hbdev: hyperbus_device struct with dev, np and ctlr field populated + * + * Return: 0 for success, others for failure. + */ +int hyperbus_register_device(struct hyperbus_device *hbdev); + +/** + * hyperbus_unregister_device - deregister HyperBus slave memory device + * @hbdev: hyperbus_device to be unregistered + * + * Return: 0 for success, others for failure. + */ +int hyperbus_unregister_device(struct hyperbus_device *hbdev); + +#endif /* __LINUX_MTD_HYPERBUS_H__ */ -- 2.22.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory (called HyperFlash) or self refresh DRAM (called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since HyperBus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But HyperBus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. But, HyperBus memory controllers seem to abstract implementation details and expose a simple MMIO interface to access connected flash. Add support for registering HyperFlash devices with MTD framework. MTD maps framework along with CFI chip support framework are used to support communicating with flash. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers calls hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Some HBMC masters need calibration/training sequence[3] to be carried out, in order for DLL inside the controller to lock, by reading a known string/pattern. This is done by repeatedly reading CFI Query Identification String. Calibration needs to be done before trying to detect flash as part of CFI flash probe. HyperRAM is not supported at the moment. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Clarify read16()/write16() APIs Move calibration code out into TI specific driver MAINTAINERS | 7 ++ drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/hyperbus/Kconfig | 11 ++ drivers/mtd/hyperbus/Makefile | 3 + drivers/mtd/hyperbus/hyperbus-core.c | 154 +++++++++++++++++++++++++++ include/linux/mtd/hyperbus.h | 86 +++++++++++++++ 7 files changed, 264 insertions(+) create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h diff --git a/MAINTAINERS b/MAINTAINERS index ff7c2b7e67b9..58c6ad3dae66 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7353,6 +7353,13 @@ F: include/asm-generic/mshyperv.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus +HYPERBUS SUPPORT +M: Vignesh Raghavendra <vigneshr@ti.com> +S: Supported +F: drivers/mtd/hyperbus/ +F: include/linux/mtd/hyperbus.h +F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt + HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org S: Odd Fixes diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index fb31a7f649a3..80a6e2dcd085 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -274,4 +274,6 @@ source "drivers/mtd/spi-nor/Kconfig" source "drivers/mtd/ubi/Kconfig" +source "drivers/mtd/hyperbus/Kconfig" + endif # MTD diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 806287e80e84..62d649a959e2 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -34,3 +34,4 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ tests/ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ obj-$(CONFIG_MTD_UBI) += ubi/ +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig new file mode 100644 index 000000000000..98147e28caa0 --- /dev/null +++ b/drivers/mtd/hyperbus/Kconfig @@ -0,0 +1,11 @@ +menuconfig MTD_HYPERBUS + tristate "HyperBus support" + select MTD_CFI + select MTD_MAP_BANK_WIDTH_2 + select MTD_CFI_AMDSTD + select MTD_COMPLEX_MAPPINGS + help + This is the framework for the HyperBus which can be used by + the HyperBus Controller driver to communicate with + HyperFlash. See Cypress HyperBus specification for more + details diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile new file mode 100644 index 000000000000..ca61dedd730d --- /dev/null +++ b/drivers/mtd/hyperbus/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o diff --git a/drivers/mtd/hyperbus/hyperbus-core.c b/drivers/mtd/hyperbus/hyperbus-core.c new file mode 100644 index 000000000000..63a9e64895bc --- /dev/null +++ b/drivers/mtd/hyperbus/hyperbus-core.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/map.h> +#include <linux/mtd/mtd.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/types.h> + +static struct hyperbus_device *map_to_hbdev(struct map_info *map) +{ + return container_of(map, struct hyperbus_device, map); +} + +static map_word hyperbus_read16(struct map_info *map, unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + map_word read_data; + + read_data.x[0] = ctlr->ops->read16(hbdev, addr); + + return read_data; +} + +static void hyperbus_write16(struct map_info *map, map_word d, + unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->write16(hbdev, addr, d.x[0]); +} + +static void hyperbus_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_from(hbdev, to, from, len); +} + +static void hyperbus_copy_to(struct map_info *map, unsigned long to, + const void *from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_to(hbdev, to, from, len); +} + +int hyperbus_register_device(struct hyperbus_device *hbdev) +{ + const struct hyperbus_ops *ops; + struct hyperbus_ctlr *ctlr; + struct device_node *np; + struct map_info *map; + struct resource res; + struct device *dev; + int ret; + + if (!hbdev || !hbdev->np || !hbdev->ctlr || !hbdev->ctlr->dev) { + pr_err("hyperbus: please fill all the necessary fields!\n"); + return -EINVAL; + } + + np = hbdev->np; + ctlr = hbdev->ctlr; + if (!of_device_is_compatible(np, "cypress,hyperflash")) + return -ENODEV; + + hbdev->memtype = HYPERFLASH; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + return ret; + + dev = ctlr->dev; + map = &hbdev->map; + map->size = resource_size(&res); + map->virt = devm_ioremap_resource(dev, &res); + if (IS_ERR(map->virt)) + return PTR_ERR(map->virt); + + map->name = dev_name(dev); + map->bankwidth = 2; + map->device_node = np; + + simple_map_init(map); + ops = ctlr->ops; + if (ops) { + if (ops->read16) + map->read = hyperbus_read16; + if (ops->write16) + map->write = hyperbus_write16; + if (ops->copy_to) + map->copy_to = hyperbus_copy_to; + if (ops->copy_from) + map->copy_from = hyperbus_copy_from; + + if (ops->calibrate && !ctlr->calibrated) { + ret = ops->calibrate(hbdev); + if (!ret) { + dev_err(dev, "Calibration failed\n"); + return -ENODEV; + } + ctlr->calibrated = true; + } + } + + hbdev->mtd = do_map_probe("cfi_probe", map); + if (!hbdev->mtd) { + dev_err(dev, "probing of hyperbus device failed\n"); + return -ENODEV; + } + + hbdev->mtd->dev.parent = dev; + mtd_set_of_node(hbdev->mtd, np); + + ret = mtd_device_register(hbdev->mtd, NULL, 0); + if (ret) { + dev_err(dev, "failed to register mtd device\n"); + map_destroy(hbdev->mtd); + return ret; + } + hbdev->registered = true; + + return 0; +} +EXPORT_SYMBOL_GPL(hyperbus_register_device); + +int hyperbus_unregister_device(struct hyperbus_device *hbdev) +{ + int ret = 0; + + if (hbdev && hbdev->mtd && hbdev->registered) { + ret = mtd_device_unregister(hbdev->mtd); + map_destroy(hbdev->mtd); + } + + return ret; +} +EXPORT_SYMBOL_GPL(hyperbus_unregister_device); + +MODULE_DESCRIPTION("HyperBus Framework"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h new file mode 100644 index 000000000000..ead969aad35b --- /dev/null +++ b/include/linux/mtd/hyperbus.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#ifndef __LINUX_MTD_HYPERBUS_H__ +#define __LINUX_MTD_HYPERBUS_H__ + +#include <linux/mtd/map.h> + +enum hyperbus_memtype { + HYPERFLASH, + HYPERRAM, +}; + +/** + * struct hyperbus_device - struct representing HyperBus slave device + * @map: map_info struct for accessing MMIO HyperBus flash memory + * @np: pointer to HyperBus slave device node + * @mtd: pointer to MTD struct + * @ctlr: pointer to HyperBus controller struct + * @memtype: type of memory device: HyperFlash or HyperRAM + * @registered: flag to indicate whether device is registered with MTD core + */ + +struct hyperbus_device { + struct map_info map; + struct device_node *np; + struct mtd_info *mtd; + struct hyperbus_ctlr *ctlr; + enum hyperbus_memtype memtype; + bool registered; +}; + +/** + * struct hyperbus_ops - struct representing custom HyperBus operations + * @read16: read 16 bit of data to flash in a single burst. Used to read + * from non default address space, such as ID/CFI space + * @write16: write 16 bit of data to flash in a single burst. Used to + * send cmd to flash or write single 16 bit word at a time. + * @copy_from: copy data from flash memory + * @copy_to: copy data to flash memory + * @calibrate: calibrate HyperBus controller + */ + +struct hyperbus_ops { + u16 (*read16)(struct hyperbus_device *hbdev, unsigned long addr); + void (*write16)(struct hyperbus_device *hbdev, + unsigned long addr, u16 val); + void (*copy_from)(struct hyperbus_device *hbdev, void *to, + unsigned long from, ssize_t len); + void (*copy_to)(struct hyperbus_device *dev, unsigned long to, + const void *from, ssize_t len); + int (*calibrate)(struct hyperbus_device *dev); +}; + +/** + * struct hyperbus_ctlr - struct representing HyperBus controller + * @dev: pointer to HyperBus controller device + * @calibrated: flag to indicate ctlr calibration sequence is complete + * @ops: HyperBus controller ops + */ +struct hyperbus_ctlr { + struct device *dev; + bool calibrated; + + const struct hyperbus_ops *ops; +}; + +/** + * hyperbus_register_device - probe and register a HyperBus slave memory device + * @hbdev: hyperbus_device struct with dev, np and ctlr field populated + * + * Return: 0 for success, others for failure. + */ +int hyperbus_register_device(struct hyperbus_device *hbdev); + +/** + * hyperbus_unregister_device - deregister HyperBus slave memory device + * @hbdev: hyperbus_device to be unregistered + * + * Return: 0 for success, others for failure. + */ +int hyperbus_unregister_device(struct hyperbus_device *hbdev); + +#endif /* __LINUX_MTD_HYPERBUS_H__ */ -- 2.22.0 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate Bus interface between a host system master and one or more slave interfaces. HyperBus is used to connect microprocessor, microcontroller, or ASIC devices with random access NOR flash memory (called HyperFlash) or self refresh DRAM (called HyperRAM). Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) signal and either Single-ended clock(3.0V parts) or Differential clock (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. At bus level, it follows a separate protocol described in HyperBus specification[1]. HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar to that of existing parallel NORs. Since HyperBus is x8 DDR bus, its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But HyperBus operates at >166MHz frequencies. HyperRAM provides direct random read/write access to flash memory array. But, HyperBus memory controllers seem to abstract implementation details and expose a simple MMIO interface to access connected flash. Add support for registering HyperFlash devices with MTD framework. MTD maps framework along with CFI chip support framework are used to support communicating with flash. Framework is modelled along the lines of spi-nor framework. HyperBus memory controller (HBMC) drivers calls hyperbus_register_device() to register a single HyperFlash device. HyperFlash core parses MMIO access information from DT, sets up the map_info struct, probes CFI flash and registers it with MTD framework. Some HBMC masters need calibration/training sequence[3] to be carried out, in order for DLL inside the controller to lock, by reading a known string/pattern. This is done by repeatedly reading CFI Query Identification String. Calibration needs to be done before trying to detect flash as part of CFI flash probe. HyperRAM is not supported at the moment. HyperBus specification can be found at[1] HyperFlash datasheet can be found at[2] [1] https://www.cypress.com/file/213356/download [2] https://www.cypress.com/file/213346/download [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf Table 12-5741. HyperFlash Access Sequence Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Clarify read16()/write16() APIs Move calibration code out into TI specific driver MAINTAINERS | 7 ++ drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/hyperbus/Kconfig | 11 ++ drivers/mtd/hyperbus/Makefile | 3 + drivers/mtd/hyperbus/hyperbus-core.c | 154 +++++++++++++++++++++++++++ include/linux/mtd/hyperbus.h | 86 +++++++++++++++ 7 files changed, 264 insertions(+) create mode 100644 drivers/mtd/hyperbus/Kconfig create mode 100644 drivers/mtd/hyperbus/Makefile create mode 100644 drivers/mtd/hyperbus/hyperbus-core.c create mode 100644 include/linux/mtd/hyperbus.h diff --git a/MAINTAINERS b/MAINTAINERS index ff7c2b7e67b9..58c6ad3dae66 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7353,6 +7353,13 @@ F: include/asm-generic/mshyperv.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus +HYPERBUS SUPPORT +M: Vignesh Raghavendra <vigneshr@ti.com> +S: Supported +F: drivers/mtd/hyperbus/ +F: include/linux/mtd/hyperbus.h +F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt + HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org S: Odd Fixes diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index fb31a7f649a3..80a6e2dcd085 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -274,4 +274,6 @@ source "drivers/mtd/spi-nor/Kconfig" source "drivers/mtd/ubi/Kconfig" +source "drivers/mtd/hyperbus/Kconfig" + endif # MTD diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 806287e80e84..62d649a959e2 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -34,3 +34,4 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ tests/ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ obj-$(CONFIG_MTD_UBI) += ubi/ +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig new file mode 100644 index 000000000000..98147e28caa0 --- /dev/null +++ b/drivers/mtd/hyperbus/Kconfig @@ -0,0 +1,11 @@ +menuconfig MTD_HYPERBUS + tristate "HyperBus support" + select MTD_CFI + select MTD_MAP_BANK_WIDTH_2 + select MTD_CFI_AMDSTD + select MTD_COMPLEX_MAPPINGS + help + This is the framework for the HyperBus which can be used by + the HyperBus Controller driver to communicate with + HyperFlash. See Cypress HyperBus specification for more + details diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile new file mode 100644 index 000000000000..ca61dedd730d --- /dev/null +++ b/drivers/mtd/hyperbus/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o diff --git a/drivers/mtd/hyperbus/hyperbus-core.c b/drivers/mtd/hyperbus/hyperbus-core.c new file mode 100644 index 000000000000..63a9e64895bc --- /dev/null +++ b/drivers/mtd/hyperbus/hyperbus-core.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/map.h> +#include <linux/mtd/mtd.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/types.h> + +static struct hyperbus_device *map_to_hbdev(struct map_info *map) +{ + return container_of(map, struct hyperbus_device, map); +} + +static map_word hyperbus_read16(struct map_info *map, unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + map_word read_data; + + read_data.x[0] = ctlr->ops->read16(hbdev, addr); + + return read_data; +} + +static void hyperbus_write16(struct map_info *map, map_word d, + unsigned long addr) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->write16(hbdev, addr, d.x[0]); +} + +static void hyperbus_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_from(hbdev, to, from, len); +} + +static void hyperbus_copy_to(struct map_info *map, unsigned long to, + const void *from, ssize_t len) +{ + struct hyperbus_device *hbdev = map_to_hbdev(map); + struct hyperbus_ctlr *ctlr = hbdev->ctlr; + + ctlr->ops->copy_to(hbdev, to, from, len); +} + +int hyperbus_register_device(struct hyperbus_device *hbdev) +{ + const struct hyperbus_ops *ops; + struct hyperbus_ctlr *ctlr; + struct device_node *np; + struct map_info *map; + struct resource res; + struct device *dev; + int ret; + + if (!hbdev || !hbdev->np || !hbdev->ctlr || !hbdev->ctlr->dev) { + pr_err("hyperbus: please fill all the necessary fields!\n"); + return -EINVAL; + } + + np = hbdev->np; + ctlr = hbdev->ctlr; + if (!of_device_is_compatible(np, "cypress,hyperflash")) + return -ENODEV; + + hbdev->memtype = HYPERFLASH; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + return ret; + + dev = ctlr->dev; + map = &hbdev->map; + map->size = resource_size(&res); + map->virt = devm_ioremap_resource(dev, &res); + if (IS_ERR(map->virt)) + return PTR_ERR(map->virt); + + map->name = dev_name(dev); + map->bankwidth = 2; + map->device_node = np; + + simple_map_init(map); + ops = ctlr->ops; + if (ops) { + if (ops->read16) + map->read = hyperbus_read16; + if (ops->write16) + map->write = hyperbus_write16; + if (ops->copy_to) + map->copy_to = hyperbus_copy_to; + if (ops->copy_from) + map->copy_from = hyperbus_copy_from; + + if (ops->calibrate && !ctlr->calibrated) { + ret = ops->calibrate(hbdev); + if (!ret) { + dev_err(dev, "Calibration failed\n"); + return -ENODEV; + } + ctlr->calibrated = true; + } + } + + hbdev->mtd = do_map_probe("cfi_probe", map); + if (!hbdev->mtd) { + dev_err(dev, "probing of hyperbus device failed\n"); + return -ENODEV; + } + + hbdev->mtd->dev.parent = dev; + mtd_set_of_node(hbdev->mtd, np); + + ret = mtd_device_register(hbdev->mtd, NULL, 0); + if (ret) { + dev_err(dev, "failed to register mtd device\n"); + map_destroy(hbdev->mtd); + return ret; + } + hbdev->registered = true; + + return 0; +} +EXPORT_SYMBOL_GPL(hyperbus_register_device); + +int hyperbus_unregister_device(struct hyperbus_device *hbdev) +{ + int ret = 0; + + if (hbdev && hbdev->mtd && hbdev->registered) { + ret = mtd_device_unregister(hbdev->mtd); + map_destroy(hbdev->mtd); + } + + return ret; +} +EXPORT_SYMBOL_GPL(hyperbus_unregister_device); + +MODULE_DESCRIPTION("HyperBus Framework"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h new file mode 100644 index 000000000000..ead969aad35b --- /dev/null +++ b/include/linux/mtd/hyperbus.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#ifndef __LINUX_MTD_HYPERBUS_H__ +#define __LINUX_MTD_HYPERBUS_H__ + +#include <linux/mtd/map.h> + +enum hyperbus_memtype { + HYPERFLASH, + HYPERRAM, +}; + +/** + * struct hyperbus_device - struct representing HyperBus slave device + * @map: map_info struct for accessing MMIO HyperBus flash memory + * @np: pointer to HyperBus slave device node + * @mtd: pointer to MTD struct + * @ctlr: pointer to HyperBus controller struct + * @memtype: type of memory device: HyperFlash or HyperRAM + * @registered: flag to indicate whether device is registered with MTD core + */ + +struct hyperbus_device { + struct map_info map; + struct device_node *np; + struct mtd_info *mtd; + struct hyperbus_ctlr *ctlr; + enum hyperbus_memtype memtype; + bool registered; +}; + +/** + * struct hyperbus_ops - struct representing custom HyperBus operations + * @read16: read 16 bit of data to flash in a single burst. Used to read + * from non default address space, such as ID/CFI space + * @write16: write 16 bit of data to flash in a single burst. Used to + * send cmd to flash or write single 16 bit word at a time. + * @copy_from: copy data from flash memory + * @copy_to: copy data to flash memory + * @calibrate: calibrate HyperBus controller + */ + +struct hyperbus_ops { + u16 (*read16)(struct hyperbus_device *hbdev, unsigned long addr); + void (*write16)(struct hyperbus_device *hbdev, + unsigned long addr, u16 val); + void (*copy_from)(struct hyperbus_device *hbdev, void *to, + unsigned long from, ssize_t len); + void (*copy_to)(struct hyperbus_device *dev, unsigned long to, + const void *from, ssize_t len); + int (*calibrate)(struct hyperbus_device *dev); +}; + +/** + * struct hyperbus_ctlr - struct representing HyperBus controller + * @dev: pointer to HyperBus controller device + * @calibrated: flag to indicate ctlr calibration sequence is complete + * @ops: HyperBus controller ops + */ +struct hyperbus_ctlr { + struct device *dev; + bool calibrated; + + const struct hyperbus_ops *ops; +}; + +/** + * hyperbus_register_device - probe and register a HyperBus slave memory device + * @hbdev: hyperbus_device struct with dev, np and ctlr field populated + * + * Return: 0 for success, others for failure. + */ +int hyperbus_register_device(struct hyperbus_device *hbdev); + +/** + * hyperbus_unregister_device - deregister HyperBus slave memory device + * @hbdev: hyperbus_device to be unregistered + * + * Return: 0 for success, others for failure. + */ +int hyperbus_unregister_device(struct hyperbus_device *hbdev); + +#endif /* __LINUX_MTD_HYPERBUS_H__ */ -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices 2019-06-20 17:22 ` Vignesh Raghavendra (?) @ 2019-06-21 19:52 ` Sergei Shtylyov -1 siblings, 0 replies; 48+ messages in thread From: Sergei Shtylyov @ 2019-06-21 19:52 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Mason Yang, linux-arm-kernel, linux-kernel Hello! On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate > Bus interface between a host system master and one or more slave > interfaces. HyperBus is used to connect microprocessor, microcontroller, > or ASIC devices with random access NOR flash memory (called HyperFlash) > or self refresh DRAM (called HyperRAM). > > Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) > signal and either Single-ended clock(3.0V parts) or Differential clock > (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. > At bus level, it follows a separate protocol described in HyperBus > specification[1]. > > HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar > to that of existing parallel NORs. Since HyperBus is x8 DDR bus, > its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But > HyperBus operates at >166MHz frequencies. s/wrt/WRT/. > HyperRAM provides direct random read/write access to flash memory > array. > > But, HyperBus memory controllers seem to abstract implementation details > and expose a simple MMIO interface to access connected flash. > > Add support for registering HyperFlash devices with MTD framework. MTD > maps framework along with CFI chip support framework are used to support > communicating with flash. > > Framework is modelled along the lines of spi-nor framework. HyperBus > memory controller (HBMC) drivers calls hyperbus_register_device() to > register a single HyperFlash device. HyperFlash core parses MMIO access > information from DT, sets up the map_info struct, probes CFI flash and > registers it with MTD framework. > > Some HBMC masters need calibration/training sequence[3] to be carried > out, in order for DLL inside the controller to lock, by reading a known > string/pattern. This is done by repeatedly reading CFI Query > Identification String. Calibration needs to be done before trying to detect > flash as part of CFI flash probe. > > HyperRAM is not supported at the moment. > > HyperBus specification can be found at[1] > HyperFlash datasheet can be found at[2] > > [1] https://www.cypress.com/file/213356/download > [2] https://www.cypress.com/file/213346/download > [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf > Table 12-5741. HyperFlash Access Sequence > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> [...] > diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h > new file mode 100644 > index 000000000000..ead969aad35b > --- /dev/null > +++ b/include/linux/mtd/hyperbus.h > @@ -0,0 +1,86 @@ [...] > +/** > + * struct hyperbus_ops - struct representing custom HyperBus operations > + * @read16: read 16 bit of data to flash in a single burst. Used to read s/to flash/from flash/. [...] > +#endif /* __LINUX_MTD_HYPERBUS_H__ */ I thought you agreed to add the #defines for the HF commands. Well, I can add them as well... MBR, Sergei ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-21 19:52 ` Sergei Shtylyov 0 siblings, 0 replies; 48+ messages in thread From: Sergei Shtylyov @ 2019-06-21 19:52 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Hello! On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate > Bus interface between a host system master and one or more slave > interfaces. HyperBus is used to connect microprocessor, microcontroller, > or ASIC devices with random access NOR flash memory (called HyperFlash) > or self refresh DRAM (called HyperRAM). > > Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) > signal and either Single-ended clock(3.0V parts) or Differential clock > (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. > At bus level, it follows a separate protocol described in HyperBus > specification[1]. > > HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar > to that of existing parallel NORs. Since HyperBus is x8 DDR bus, > its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But > HyperBus operates at >166MHz frequencies. s/wrt/WRT/. > HyperRAM provides direct random read/write access to flash memory > array. > > But, HyperBus memory controllers seem to abstract implementation details > and expose a simple MMIO interface to access connected flash. > > Add support for registering HyperFlash devices with MTD framework. MTD > maps framework along with CFI chip support framework are used to support > communicating with flash. > > Framework is modelled along the lines of spi-nor framework. HyperBus > memory controller (HBMC) drivers calls hyperbus_register_device() to > register a single HyperFlash device. HyperFlash core parses MMIO access > information from DT, sets up the map_info struct, probes CFI flash and > registers it with MTD framework. > > Some HBMC masters need calibration/training sequence[3] to be carried > out, in order for DLL inside the controller to lock, by reading a known > string/pattern. This is done by repeatedly reading CFI Query > Identification String. Calibration needs to be done before trying to detect > flash as part of CFI flash probe. > > HyperRAM is not supported at the moment. > > HyperBus specification can be found at[1] > HyperFlash datasheet can be found at[2] > > [1] https://www.cypress.com/file/213356/download > [2] https://www.cypress.com/file/213346/download > [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf > Table 12-5741. HyperFlash Access Sequence > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> [...] > diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h > new file mode 100644 > index 000000000000..ead969aad35b > --- /dev/null > +++ b/include/linux/mtd/hyperbus.h > @@ -0,0 +1,86 @@ [...] > +/** > + * struct hyperbus_ops - struct representing custom HyperBus operations > + * @read16: read 16 bit of data to flash in a single burst. Used to read s/to flash/from flash/. [...] > +#endif /* __LINUX_MTD_HYPERBUS_H__ */ I thought you agreed to add the #defines for the HF commands. Well, I can add them as well... MBR, Sergei _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-21 19:52 ` Sergei Shtylyov 0 siblings, 0 replies; 48+ messages in thread From: Sergei Shtylyov @ 2019-06-21 19:52 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Hello! On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate > Bus interface between a host system master and one or more slave > interfaces. HyperBus is used to connect microprocessor, microcontroller, > or ASIC devices with random access NOR flash memory (called HyperFlash) > or self refresh DRAM (called HyperRAM). > > Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) > signal and either Single-ended clock(3.0V parts) or Differential clock > (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. > At bus level, it follows a separate protocol described in HyperBus > specification[1]. > > HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar > to that of existing parallel NORs. Since HyperBus is x8 DDR bus, > its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But > HyperBus operates at >166MHz frequencies. s/wrt/WRT/. > HyperRAM provides direct random read/write access to flash memory > array. > > But, HyperBus memory controllers seem to abstract implementation details > and expose a simple MMIO interface to access connected flash. > > Add support for registering HyperFlash devices with MTD framework. MTD > maps framework along with CFI chip support framework are used to support > communicating with flash. > > Framework is modelled along the lines of spi-nor framework. HyperBus > memory controller (HBMC) drivers calls hyperbus_register_device() to > register a single HyperFlash device. HyperFlash core parses MMIO access > information from DT, sets up the map_info struct, probes CFI flash and > registers it with MTD framework. > > Some HBMC masters need calibration/training sequence[3] to be carried > out, in order for DLL inside the controller to lock, by reading a known > string/pattern. This is done by repeatedly reading CFI Query > Identification String. Calibration needs to be done before trying to detect > flash as part of CFI flash probe. > > HyperRAM is not supported at the moment. > > HyperBus specification can be found at[1] > HyperFlash datasheet can be found at[2] > > [1] https://www.cypress.com/file/213356/download > [2] https://www.cypress.com/file/213346/download > [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf > Table 12-5741. HyperFlash Access Sequence > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> [...] > diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h > new file mode 100644 > index 000000000000..ead969aad35b > --- /dev/null > +++ b/include/linux/mtd/hyperbus.h > @@ -0,0 +1,86 @@ [...] > +/** > + * struct hyperbus_ops - struct representing custom HyperBus operations > + * @read16: read 16 bit of data to flash in a single burst. Used to read s/to flash/from flash/. [...] > +#endif /* __LINUX_MTD_HYPERBUS_H__ */ I thought you agreed to add the #defines for the HF commands. Well, I can add them as well... MBR, Sergei ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices 2019-06-21 19:52 ` Sergei Shtylyov (?) (?) @ 2019-06-24 13:33 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-24 13:33 UTC (permalink / raw) To: Sergei Shtylyov, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Mason Yang, linux-arm-kernel, linux-kernel On 22/06/19 1:22 AM, Sergei Shtylyov wrote: > Hello! > > On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. > > s/wrt/WRT/. OK [...] >> diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h >> new file mode 100644 >> index 000000000000..ead969aad35b >> --- /dev/null >> +++ b/include/linux/mtd/hyperbus.h >> @@ -0,0 +1,86 @@ > [...] >> +/** >> + * struct hyperbus_ops - struct representing custom HyperBus operations >> + * @read16: read 16 bit of data to flash in a single burst. Used to read > > s/to flash/from flash/. > Will fix > [...] >> +#endif /* __LINUX_MTD_HYPERBUS_H__ */ > > I thought you agreed to add the #defines for the HF commands. Well, I can add them > as well... > Sorry, I thought you were proposing to add them to your driver's header file. Anyways, I think its better to add defines when there is an actual user. If there are no further comments, I will fixup things locally and queue up for next release. -- Regards Vignesh ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-24 13:33 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-24 13:33 UTC (permalink / raw) To: Sergei Shtylyov, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel On 22/06/19 1:22 AM, Sergei Shtylyov wrote: > Hello! > > On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. > > s/wrt/WRT/. OK [...] >> diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h >> new file mode 100644 >> index 000000000000..ead969aad35b >> --- /dev/null >> +++ b/include/linux/mtd/hyperbus.h >> @@ -0,0 +1,86 @@ > [...] >> +/** >> + * struct hyperbus_ops - struct representing custom HyperBus operations >> + * @read16: read 16 bit of data to flash in a single burst. Used to read > > s/to flash/from flash/. > Will fix > [...] >> +#endif /* __LINUX_MTD_HYPERBUS_H__ */ > > I thought you agreed to add the #defines for the HF commands. Well, I can add them > as well... > Sorry, I thought you were proposing to add them to your driver's header file. Anyways, I think its better to add defines when there is an actual user. If there are no further comments, I will fixup things locally and queue up for next release. -- Regards Vignesh _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-24 13:33 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-24 13:33 UTC (permalink / raw) To: Sergei Shtylyov, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel On 22/06/19 1:22 AM, Sergei Shtylyov wrote: > Hello! > > On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. > > s/wrt/WRT/. OK [...] >> diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h >> new file mode 100644 >> index 000000000000..ead969aad35b >> --- /dev/null >> +++ b/include/linux/mtd/hyperbus.h >> @@ -0,0 +1,86 @@ > [...] >> +/** >> + * struct hyperbus_ops - struct representing custom HyperBus operations >> + * @read16: read 16 bit of data to flash in a single burst. Used to read > > s/to flash/from flash/. > Will fix > [...] >> +#endif /* __LINUX_MTD_HYPERBUS_H__ */ > > I thought you agreed to add the #defines for the HF commands. Well, I can add them > as well... > Sorry, I thought you were proposing to add them to your driver's header file. Anyways, I think its better to add defines when there is an actual user. If there are no further comments, I will fixup things locally and queue up for next release. -- Regards Vignesh ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-24 13:33 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-24 13:33 UTC (permalink / raw) To: Sergei Shtylyov, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Mason Yang, linux-arm-kernel, linux-kernel On 22/06/19 1:22 AM, Sergei Shtylyov wrote: > Hello! > > On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. > > s/wrt/WRT/. OK [...] >> diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h >> new file mode 100644 >> index 000000000000..ead969aad35b >> --- /dev/null >> +++ b/include/linux/mtd/hyperbus.h >> @@ -0,0 +1,86 @@ > [...] >> +/** >> + * struct hyperbus_ops - struct representing custom HyperBus operations >> + * @read16: read 16 bit of data to flash in a single burst. Used to read > > s/to flash/from flash/. > Will fix > [...] >> +#endif /* __LINUX_MTD_HYPERBUS_H__ */ > > I thought you agreed to add the #defines for the HF commands. Well, I can add them > as well... > Sorry, I thought you were proposing to add them to your driver's header file. Anyways, I think its better to add defines when there is an actual user. If there are no further comments, I will fixup things locally and queue up for next release. -- Regards Vignesh ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices 2019-06-20 17:22 ` Vignesh Raghavendra (?) (?) @ 2019-06-26 1:16 ` masonccyang -1 siblings, 0 replies; 48+ messages in thread From: masonccyang @ 2019-06-26 1:16 UTC (permalink / raw) To: Vignesh Raghavendra Cc: Boris Brezillon, devicetree, linux-arm-kernel, linux-kernel, linux-mtd, Marek Vasut, Miquel Raynal, Richard Weinberger, Rob Herring, Sergei Shtylyov, Vignesh Raghavendra Hi Vignesh, > > Subject > > [PATCH v7 3/5] mtd: Add support for HyperBus memory devices > > Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate > Bus interface between a host system master and one or more slave > interfaces. HyperBus is used to connect microprocessor, microcontroller, > or ASIC devices with random access NOR flash memory (called HyperFlash) > or self refresh DRAM (called HyperRAM). > > Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) > signal and either Single-ended clock(3.0V parts) or Differential clock > (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. > At bus level, it follows a separate protocol described in HyperBus > specification[1]. > > HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar > to that of existing parallel NORs. Since HyperBus is x8 DDR bus, > its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But > HyperBus operates at >166MHz frequencies. > HyperRAM provides direct random read/write access to flash memory > array. > > But, HyperBus memory controllers seem to abstract implementation details > and expose a simple MMIO interface to access connected flash. > > Add support for registering HyperFlash devices with MTD framework. MTD > maps framework along with CFI chip support framework are used to support > communicating with flash. > > Framework is modelled along the lines of spi-nor framework. HyperBus > memory controller (HBMC) drivers calls hyperbus_register_device() to > register a single HyperFlash device. HyperFlash core parses MMIO access > information from DT, sets up the map_info struct, probes CFI flash and > registers it with MTD framework. > > Some HBMC masters need calibration/training sequence[3] to be carried > out, in order for DLL inside the controller to lock, by reading a known > string/pattern. This is done by repeatedly reading CFI Query > Identification String. Calibration needs to be done before trying to detect > flash as part of CFI flash probe. > > HyperRAM is not supported at the moment. > > HyperBus specification can be found at[1] > HyperFlash datasheet can be found at[2] > > [1] https://www.cypress.com/file/213356/download > [2] https://www.cypress.com/file/213346/download > [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf > Table 12-5741. HyperFlash Access Sequence > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Cypress has announced the inclusion of Cypress’ high-bandwidth HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) electrical interface standard from the JEDEC Solid State Technology Association for detail, please goes to https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical FYI, thanks & best regards, Mason CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== ============================================================================ CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-26 1:16 ` masonccyang 0 siblings, 0 replies; 48+ messages in thread From: masonccyang @ 2019-06-26 1:16 UTC (permalink / raw) To: Vignesh Raghavendra Cc: devicetree, Vignesh Raghavendra, Sergei Shtylyov, Boris Brezillon, Richard Weinberger, linux-kernel, Marek Vasut, Rob Herring, linux-mtd, Miquel Raynal, linux-arm-kernel Hi Vignesh, > > Subject > > [PATCH v7 3/5] mtd: Add support for HyperBus memory devices > > Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate > Bus interface between a host system master and one or more slave > interfaces. HyperBus is used to connect microprocessor, microcontroller, > or ASIC devices with random access NOR flash memory (called HyperFlash) > or self refresh DRAM (called HyperRAM). > > Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) > signal and either Single-ended clock(3.0V parts) or Differential clock > (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. > At bus level, it follows a separate protocol described in HyperBus > specification[1]. > > HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar > to that of existing parallel NORs. Since HyperBus is x8 DDR bus, > its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But > HyperBus operates at >166MHz frequencies. > HyperRAM provides direct random read/write access to flash memory > array. > > But, HyperBus memory controllers seem to abstract implementation details > and expose a simple MMIO interface to access connected flash. > > Add support for registering HyperFlash devices with MTD framework. MTD > maps framework along with CFI chip support framework are used to support > communicating with flash. > > Framework is modelled along the lines of spi-nor framework. HyperBus > memory controller (HBMC) drivers calls hyperbus_register_device() to > register a single HyperFlash device. HyperFlash core parses MMIO access > information from DT, sets up the map_info struct, probes CFI flash and > registers it with MTD framework. > > Some HBMC masters need calibration/training sequence[3] to be carried > out, in order for DLL inside the controller to lock, by reading a known > string/pattern. This is done by repeatedly reading CFI Query > Identification String. Calibration needs to be done before trying to detect > flash as part of CFI flash probe. > > HyperRAM is not supported at the moment. > > HyperBus specification can be found at[1] > HyperFlash datasheet can be found at[2] > > [1] https://www.cypress.com/file/213356/download > [2] https://www.cypress.com/file/213346/download > [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf > Table 12-5741. HyperFlash Access Sequence > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Cypress has announced the inclusion of Cypress’ high-bandwidth HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) electrical interface standard from the JEDEC Solid State Technology Association for detail, please goes to https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical FYI, thanks & best regards, Mason CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== ============================================================================ CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-26 1:16 ` masonccyang 0 siblings, 0 replies; 48+ messages in thread From: masonccyang @ 2019-06-26 1:16 UTC (permalink / raw) To: Vignesh Raghavendra Cc: devicetree, Vignesh Raghavendra, Sergei Shtylyov, Boris Brezillon, Richard Weinberger, linux-kernel, Marek Vasut, Rob Herring, linux-mtd, Miquel Raynal, linux-arm-kernel Hi Vignesh, > > Subject > > [PATCH v7 3/5] mtd: Add support for HyperBus memory devices > > Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate > Bus interface between a host system master and one or more slave > interfaces. HyperBus is used to connect microprocessor, microcontroller, > or ASIC devices with random access NOR flash memory (called HyperFlash) > or self refresh DRAM (called HyperRAM). > > Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) > signal and either Single-ended clock(3.0V parts) or Differential clock > (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. > At bus level, it follows a separate protocol described in HyperBus > specification[1]. > > HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar > to that of existing parallel NORs. Since HyperBus is x8 DDR bus, > its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But > HyperBus operates at >166MHz frequencies. > HyperRAM provides direct random read/write access to flash memory > array. > > But, HyperBus memory controllers seem to abstract implementation details > and expose a simple MMIO interface to access connected flash. > > Add support for registering HyperFlash devices with MTD framework. MTD > maps framework along with CFI chip support framework are used to support > communicating with flash. > > Framework is modelled along the lines of spi-nor framework. HyperBus > memory controller (HBMC) drivers calls hyperbus_register_device() to > register a single HyperFlash device. HyperFlash core parses MMIO access > information from DT, sets up the map_info struct, probes CFI flash and > registers it with MTD framework. > > Some HBMC masters need calibration/training sequence[3] to be carried > out, in order for DLL inside the controller to lock, by reading a known > string/pattern. This is done by repeatedly reading CFI Query > Identification String. Calibration needs to be done before trying to detect > flash as part of CFI flash probe. > > HyperRAM is not supported at the moment. > > HyperBus specification can be found at[1] > HyperFlash datasheet can be found at[2] > > [1] https://www.cypress.com/file/213356/download > [2] https://www.cypress.com/file/213346/download > [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf > Table 12-5741. HyperFlash Access Sequence > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Cypress has announced the inclusion of Cypress’ high-bandwidth HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) electrical interface standard from the JEDEC Solid State Technology Association for detail, please goes to https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical FYI, thanks & best regards, Mason CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== ============================================================================ CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-26 1:16 ` masonccyang 0 siblings, 0 replies; 48+ messages in thread From: masonccyang @ 2019-06-26 1:16 UTC (permalink / raw) Cc: Boris Brezillon, devicetree, linux-arm-kernel, linux-kernel, linux-mtd, Marek Vasut, Miquel Raynal, Richard Weinberger, Rob Herring, Sergei Shtylyov, Vignesh Raghavendra Hi Vignesh, > > Subject > > [PATCH v7 3/5] mtd: Add support for HyperBus memory devices > > Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate > Bus interface between a host system master and one or more slave > interfaces. HyperBus is used to connect microprocessor, microcontroller, > or ASIC devices with random access NOR flash memory (called HyperFlash) > or self refresh DRAM (called HyperRAM). > > Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) > signal and either Single-ended clock(3.0V parts) or Differential clock > (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. > At bus level, it follows a separate protocol described in HyperBus > specification[1]. > > HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar > to that of existing parallel NORs. Since HyperBus is x8 DDR bus, > its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But > HyperBus operates at >166MHz frequencies. > HyperRAM provides direct random read/write access to flash memory > array. > > But, HyperBus memory controllers seem to abstract implementation details > and expose a simple MMIO interface to access connected flash. > > Add support for registering HyperFlash devices with MTD framework. MTD > maps framework along with CFI chip support framework are used to support > communicating with flash. > > Framework is modelled along the lines of spi-nor framework. HyperBus > memory controller (HBMC) drivers calls hyperbus_register_device() to > register a single HyperFlash device. HyperFlash core parses MMIO access > information from DT, sets up the map_info struct, probes CFI flash and > registers it with MTD framework. > > Some HBMC masters need calibration/training sequence[3] to be carried > out, in order for DLL inside the controller to lock, by reading a known > string/pattern. This is done by repeatedly reading CFI Query > Identification String. Calibration needs to be done before trying to detect > flash as part of CFI flash probe. > > HyperRAM is not supported at the moment. > > HyperBus specification can be found at[1] > HyperFlash datasheet can be found at[2] > > [1] https://www.cypress.com/file/213356/download > [2] https://www.cypress.com/file/213346/download > [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf > Table 12-5741. HyperFlash Access Sequence > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Cypress has announced the inclusion of Cypress’ high-bandwidth HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) electrical interface standard from the JEDEC Solid State Technology Association for detail, please goes to https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical FYI, thanks & best regards, Mason CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== ============================================================================ CONFIDENTIALITY NOTE: This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation. Macronix International Co., Ltd. ===================================================================== ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices 2019-06-26 1:16 ` masonccyang (?) (?) @ 2019-06-26 6:00 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-26 6:00 UTC (permalink / raw) To: masonccyang Cc: Boris Brezillon, devicetree, linux-arm-kernel, linux-kernel, linux-mtd, Marek Vasut, Miquel Raynal, Richard Weinberger, Rob Herring, Sergei Shtylyov On 26/06/19 6:46 AM, masonccyang@mxic.com.tw wrote: > Hi Vignesh, > >> >> Subject >> >> [PATCH v7 3/5] mtd: Add support for HyperBus memory devices >> >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. >> HyperRAM provides direct random read/write access to flash memory >> array. >> >> But, HyperBus memory controllers seem to abstract implementation details >> and expose a simple MMIO interface to access connected flash. >> >> Add support for registering HyperFlash devices with MTD framework. MTD >> maps framework along with CFI chip support framework are used to support >> communicating with flash. >> >> Framework is modelled along the lines of spi-nor framework. HyperBus >> memory controller (HBMC) drivers calls hyperbus_register_device() to >> register a single HyperFlash device. HyperFlash core parses MMIO access >> information from DT, sets up the map_info struct, probes CFI flash and >> registers it with MTD framework. >> >> Some HBMC masters need calibration/training sequence[3] to be carried >> out, in order for DLL inside the controller to lock, by reading a known >> string/pattern. This is done by repeatedly reading CFI Query >> Identification String. Calibration needs to be done before trying to > detect >> flash as part of CFI flash probe. >> >> HyperRAM is not supported at the moment. >> >> HyperBus specification can be found at[1] >> HyperFlash datasheet can be found at[2] >> >> [1] https://www.cypress.com/file/213356/download >> [2] https://www.cypress.com/file/213346/download >> [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf >> Table 12-5741. HyperFlash Access Sequence >> >> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > > Cypress has announced the inclusion of Cypress’ high-bandwidth > HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) > electrical interface standard from the JEDEC Solid State Technology > Association > > for detail, please goes to > https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical > Thanks for the link! Announcement seems to be from March 2018 since then Cypress has published detailed HyperBus protocol in public domain . Comparing JEDEC xSPI specification and HyperBus protocol that Cypress has published, they seem to be following 8D-8D-8D Profile 2.0 with Extended Command Modifier of JEDEC xSPI spec. Did you see anything missing/different? I need to study xSPI spec in more detail, but seems like as long as we support HyperBus Protocol spec from Cypress we should be safe. -- Regards Vignesh ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-26 6:00 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-26 6:00 UTC (permalink / raw) To: masonccyang Cc: devicetree, Sergei Shtylyov, Boris Brezillon, Richard Weinberger, linux-kernel, Marek Vasut, Rob Herring, linux-mtd, Miquel Raynal, linux-arm-kernel On 26/06/19 6:46 AM, masonccyang@mxic.com.tw wrote: > Hi Vignesh, > >> >> Subject >> >> [PATCH v7 3/5] mtd: Add support for HyperBus memory devices >> >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. >> HyperRAM provides direct random read/write access to flash memory >> array. >> >> But, HyperBus memory controllers seem to abstract implementation details >> and expose a simple MMIO interface to access connected flash. >> >> Add support for registering HyperFlash devices with MTD framework. MTD >> maps framework along with CFI chip support framework are used to support >> communicating with flash. >> >> Framework is modelled along the lines of spi-nor framework. HyperBus >> memory controller (HBMC) drivers calls hyperbus_register_device() to >> register a single HyperFlash device. HyperFlash core parses MMIO access >> information from DT, sets up the map_info struct, probes CFI flash and >> registers it with MTD framework. >> >> Some HBMC masters need calibration/training sequence[3] to be carried >> out, in order for DLL inside the controller to lock, by reading a known >> string/pattern. This is done by repeatedly reading CFI Query >> Identification String. Calibration needs to be done before trying to > detect >> flash as part of CFI flash probe. >> >> HyperRAM is not supported at the moment. >> >> HyperBus specification can be found at[1] >> HyperFlash datasheet can be found at[2] >> >> [1] https://www.cypress.com/file/213356/download >> [2] https://www.cypress.com/file/213346/download >> [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf >> Table 12-5741. HyperFlash Access Sequence >> >> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > > Cypress has announced the inclusion of Cypress’ high-bandwidth > HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) > electrical interface standard from the JEDEC Solid State Technology > Association > > for detail, please goes to > https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical > Thanks for the link! Announcement seems to be from March 2018 since then Cypress has published detailed HyperBus protocol in public domain . Comparing JEDEC xSPI specification and HyperBus protocol that Cypress has published, they seem to be following 8D-8D-8D Profile 2.0 with Extended Command Modifier of JEDEC xSPI spec. Did you see anything missing/different? I need to study xSPI spec in more detail, but seems like as long as we support HyperBus Protocol spec from Cypress we should be safe. -- Regards Vignesh _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-26 6:00 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-26 6:00 UTC (permalink / raw) To: masonccyang Cc: devicetree, Sergei Shtylyov, Boris Brezillon, Richard Weinberger, linux-kernel, Marek Vasut, Rob Herring, linux-mtd, Miquel Raynal, linux-arm-kernel On 26/06/19 6:46 AM, masonccyang@mxic.com.tw wrote: > Hi Vignesh, > >> >> Subject >> >> [PATCH v7 3/5] mtd: Add support for HyperBus memory devices >> >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. >> HyperRAM provides direct random read/write access to flash memory >> array. >> >> But, HyperBus memory controllers seem to abstract implementation details >> and expose a simple MMIO interface to access connected flash. >> >> Add support for registering HyperFlash devices with MTD framework. MTD >> maps framework along with CFI chip support framework are used to support >> communicating with flash. >> >> Framework is modelled along the lines of spi-nor framework. HyperBus >> memory controller (HBMC) drivers calls hyperbus_register_device() to >> register a single HyperFlash device. HyperFlash core parses MMIO access >> information from DT, sets up the map_info struct, probes CFI flash and >> registers it with MTD framework. >> >> Some HBMC masters need calibration/training sequence[3] to be carried >> out, in order for DLL inside the controller to lock, by reading a known >> string/pattern. This is done by repeatedly reading CFI Query >> Identification String. Calibration needs to be done before trying to > detect >> flash as part of CFI flash probe. >> >> HyperRAM is not supported at the moment. >> >> HyperBus specification can be found at[1] >> HyperFlash datasheet can be found at[2] >> >> [1] https://www.cypress.com/file/213356/download >> [2] https://www.cypress.com/file/213346/download >> [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf >> Table 12-5741. HyperFlash Access Sequence >> >> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > > Cypress has announced the inclusion of Cypress’ high-bandwidth > HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) > electrical interface standard from the JEDEC Solid State Technology > Association > > for detail, please goes to > https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical > Thanks for the link! Announcement seems to be from March 2018 since then Cypress has published detailed HyperBus protocol in public domain . Comparing JEDEC xSPI specification and HyperBus protocol that Cypress has published, they seem to be following 8D-8D-8D Profile 2.0 with Extended Command Modifier of JEDEC xSPI spec. Did you see anything missing/different? I need to study xSPI spec in more detail, but seems like as long as we support HyperBus Protocol spec from Cypress we should be safe. -- Regards Vignesh ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 3/5] mtd: Add support for HyperBus memory devices @ 2019-06-26 6:00 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-26 6:00 UTC (permalink / raw) To: masonccyang Cc: devicetree, Sergei Shtylyov, Boris Brezillon, Richard Weinberger, linux-kernel, Marek Vasut, Rob Herring, linux-mtd, Miquel Raynal, linux-arm-kernel On 26/06/19 6:46 AM, masonccyang@mxic.com.tw wrote: > Hi Vignesh, > >> >> Subject >> >> [PATCH v7 3/5] mtd: Add support for HyperBus memory devices >> >> Cypress' HyperBus is Low Signal Count, High Performance Double Data Rate >> Bus interface between a host system master and one or more slave >> interfaces. HyperBus is used to connect microprocessor, microcontroller, >> or ASIC devices with random access NOR flash memory (called HyperFlash) >> or self refresh DRAM (called HyperRAM). >> >> Its a 8-bit data bus (DQ[7:0]) with Read-Write Data Strobe (RWDS) >> signal and either Single-ended clock(3.0V parts) or Differential clock >> (1.8V parts). It uses ChipSelect lines to select b/w multiple slaves. >> At bus level, it follows a separate protocol described in HyperBus >> specification[1]. >> >> HyperFlash follows CFI AMD/Fujitsu Extended Command Set (0x0002) similar >> to that of existing parallel NORs. Since HyperBus is x8 DDR bus, >> its equivalent to x16 parallel NOR flash wrt bits per clock cycle. But >> HyperBus operates at >166MHz frequencies. >> HyperRAM provides direct random read/write access to flash memory >> array. >> >> But, HyperBus memory controllers seem to abstract implementation details >> and expose a simple MMIO interface to access connected flash. >> >> Add support for registering HyperFlash devices with MTD framework. MTD >> maps framework along with CFI chip support framework are used to support >> communicating with flash. >> >> Framework is modelled along the lines of spi-nor framework. HyperBus >> memory controller (HBMC) drivers calls hyperbus_register_device() to >> register a single HyperFlash device. HyperFlash core parses MMIO access >> information from DT, sets up the map_info struct, probes CFI flash and >> registers it with MTD framework. >> >> Some HBMC masters need calibration/training sequence[3] to be carried >> out, in order for DLL inside the controller to lock, by reading a known >> string/pattern. This is done by repeatedly reading CFI Query >> Identification String. Calibration needs to be done before trying to > detect >> flash as part of CFI flash probe. >> >> HyperRAM is not supported at the moment. >> >> HyperBus specification can be found at[1] >> HyperFlash datasheet can be found at[2] >> >> [1] https://www.cypress.com/file/213356/download >> [2] https://www.cypress.com/file/213346/download >> [3] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf >> Table 12-5741. HyperFlash Access Sequence >> >> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > > Cypress has announced the inclusion of Cypress’ high-bandwidth > HyperBus™ 8-bit serial memory interface into the new eXpanded SPI (xSPI) > electrical interface standard from the JEDEC Solid State Technology > Association > > for detail, please goes to > https://www.cypress.com/news/cypress-hyperbus-memory-interface-instant-applications-incorporated-jedec-xspi-electrical > Thanks for the link! Announcement seems to be from March 2018 since then Cypress has published detailed HyperBus protocol in public domain . Comparing JEDEC xSPI specification and HyperBus protocol that Cypress has published, they seem to be following 8D-8D-8D Profile 2.0 with Extended Command Modifier of JEDEC xSPI spec. Did you see anything missing/different? I need to study xSPI spec in more detail, but seems like as long as we support HyperBus Protocol spec from Cypress we should be safe. -- Regards Vignesh _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller 2019-06-20 17:22 ` Vignesh Raghavendra (?) (?) @ 2019-06-20 17:22 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Add binding documentation for TI's HyperBus memory controller present on AM654 SoC. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: Fix example to move HyperBus node out of syscon v6: Use generic names for bindings .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt new file mode 100644 index 000000000000..d424a0b88ab6 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt @@ -0,0 +1,52 @@ +Bindings for HyperBus Memory Controller (HBMC) on TI's K3 family of SoCs + +Required properties: +- compatible : "ti,am654-hbmc" for AM654 SoC +- reg : Two entries: + First entry pointed to the register space of HBMC controller + Second entry pointing to the memory map region dedicated for + MMIO access to attached flash devices +- ranges : Address translation from offset within CS to allocated MMIO + space in SoC + +Optional properties: +- mux-controls : phandle to the multiplexer that controls selection of + HBMC vs OSPI inside Flash SubSystem (FSS). Default is OSPI, + if property is absent. + See Documentation/devicetree/bindings/mux/reg-mux.txt + for mmio-mux binding details + +Example: + + system-controller@47000000 { + compatible = "syscon", "simple-mfd"; + reg = <0x0 0x47000000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hbmc_mux: multiplexer { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */ + }; + + }; + + hbmc: hyperbus@47034000 { + compatible = "ti,am654-hbmc"; + reg = <0x0 0x47034000 0x0 0x100>, + <0x5 0x00000000 0x1 0x0000000>; + power-domains = <&k3_pds 55>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */ + <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */ + mux-controls = <&hbmc_mux 0>; + + /* Slave flash node */ + flash@0,0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x0 0x4000000>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 58c6ad3dae66..0d5a8c36682d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7359,6 +7359,7 @@ S: Supported F: drivers/mtd/hyperbus/ F: include/linux/mtd/hyperbus.h F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt +F: Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Add binding documentation for TI's HyperBus memory controller present on AM654 SoC. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: Fix example to move HyperBus node out of syscon v6: Use generic names for bindings .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt new file mode 100644 index 000000000000..d424a0b88ab6 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt @@ -0,0 +1,52 @@ +Bindings for HyperBus Memory Controller (HBMC) on TI's K3 family of SoCs + +Required properties: +- compatible : "ti,am654-hbmc" for AM654 SoC +- reg : Two entries: + First entry pointed to the register space of HBMC controller + Second entry pointing to the memory map region dedicated for + MMIO access to attached flash devices +- ranges : Address translation from offset within CS to allocated MMIO + space in SoC + +Optional properties: +- mux-controls : phandle to the multiplexer that controls selection of + HBMC vs OSPI inside Flash SubSystem (FSS). Default is OSPI, + if property is absent. + See Documentation/devicetree/bindings/mux/reg-mux.txt + for mmio-mux binding details + +Example: + + system-controller@47000000 { + compatible = "syscon", "simple-mfd"; + reg = <0x0 0x47000000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hbmc_mux: multiplexer { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */ + }; + + }; + + hbmc: hyperbus@47034000 { + compatible = "ti,am654-hbmc"; + reg = <0x0 0x47034000 0x0 0x100>, + <0x5 0x00000000 0x1 0x0000000>; + power-domains = <&k3_pds 55>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */ + <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */ + mux-controls = <&hbmc_mux 0>; + + /* Slave flash node */ + flash@0,0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x0 0x4000000>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 58c6ad3dae66..0d5a8c36682d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7359,6 +7359,7 @@ S: Supported F: drivers/mtd/hyperbus/ F: include/linux/mtd/hyperbus.h F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt +F: Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org -- 2.22.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Add binding documentation for TI's HyperBus memory controller present on AM654 SoC. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: Fix example to move HyperBus node out of syscon v6: Use generic names for bindings .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt new file mode 100644 index 000000000000..d424a0b88ab6 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt @@ -0,0 +1,52 @@ +Bindings for HyperBus Memory Controller (HBMC) on TI's K3 family of SoCs + +Required properties: +- compatible : "ti,am654-hbmc" for AM654 SoC +- reg : Two entries: + First entry pointed to the register space of HBMC controller + Second entry pointing to the memory map region dedicated for + MMIO access to attached flash devices +- ranges : Address translation from offset within CS to allocated MMIO + space in SoC + +Optional properties: +- mux-controls : phandle to the multiplexer that controls selection of + HBMC vs OSPI inside Flash SubSystem (FSS). Default is OSPI, + if property is absent. + See Documentation/devicetree/bindings/mux/reg-mux.txt + for mmio-mux binding details + +Example: + + system-controller@47000000 { + compatible = "syscon", "simple-mfd"; + reg = <0x0 0x47000000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hbmc_mux: multiplexer { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */ + }; + + }; + + hbmc: hyperbus@47034000 { + compatible = "ti,am654-hbmc"; + reg = <0x0 0x47034000 0x0 0x100>, + <0x5 0x00000000 0x1 0x0000000>; + power-domains = <&k3_pds 55>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */ + <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */ + mux-controls = <&hbmc_mux 0>; + + /* Slave flash node */ + flash@0,0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x0 0x4000000>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 58c6ad3dae66..0d5a8c36682d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7359,6 +7359,7 @@ S: Supported F: drivers/mtd/hyperbus/ F: include/linux/mtd/hyperbus.h F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt +F: Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org -- 2.22.0 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Add binding documentation for TI's HyperBus memory controller present on AM654 SoC. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: Fix example to move HyperBus node out of syscon v6: Use generic names for bindings .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt new file mode 100644 index 000000000000..d424a0b88ab6 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt @@ -0,0 +1,52 @@ +Bindings for HyperBus Memory Controller (HBMC) on TI's K3 family of SoCs + +Required properties: +- compatible : "ti,am654-hbmc" for AM654 SoC +- reg : Two entries: + First entry pointed to the register space of HBMC controller + Second entry pointing to the memory map region dedicated for + MMIO access to attached flash devices +- ranges : Address translation from offset within CS to allocated MMIO + space in SoC + +Optional properties: +- mux-controls : phandle to the multiplexer that controls selection of + HBMC vs OSPI inside Flash SubSystem (FSS). Default is OSPI, + if property is absent. + See Documentation/devicetree/bindings/mux/reg-mux.txt + for mmio-mux binding details + +Example: + + system-controller@47000000 { + compatible = "syscon", "simple-mfd"; + reg = <0x0 0x47000000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hbmc_mux: multiplexer { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */ + }; + + }; + + hbmc: hyperbus@47034000 { + compatible = "ti,am654-hbmc"; + reg = <0x0 0x47034000 0x0 0x100>, + <0x5 0x00000000 0x1 0x0000000>; + power-domains = <&k3_pds 55>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */ + <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */ + mux-controls = <&hbmc_mux 0>; + + /* Slave flash node */ + flash@0,0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x0 0x0 0x4000000>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 58c6ad3dae66..0d5a8c36682d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7359,6 +7359,7 @@ S: Supported F: drivers/mtd/hyperbus/ F: include/linux/mtd/hyperbus.h F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt +F: Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller 2019-06-20 17:22 ` Vignesh Raghavendra (?) @ 2019-06-20 19:48 ` Sergei Shtylyov -1 siblings, 0 replies; 48+ messages in thread From: Sergei Shtylyov @ 2019-06-20 19:48 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Mason Yang, linux-arm-kernel, linux-kernel On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > Add binding documentation for TI's HyperBus memory controller present on > AM654 SoC. > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > --- > > v7: Fix example to move HyperBus node out of syscon > v6: Use generic names for bindings > > .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 +++++++++++++++++++ > MAINTAINERS | 1 + > 2 files changed, 53 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt > > diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt > new file mode 100644 > index 000000000000..d424a0b88ab6 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt [...] > +Example: > + > + system-controller@47000000 { > + compatible = "syscon", "simple-mfd"; > + reg = <0x0 0x47000000 0x0 0x100>; > + #address-cells = <2>; > + #size-cells = <2>; > + ranges; > + > + hbmc_mux: multiplexer { > + compatible = "mmio-mux"; > + #mux-control-cells = <1>; > + mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */ > + }; > + Empty line not needed here. > + }; > + > + hbmc: hyperbus@47034000 { > + compatible = "ti,am654-hbmc"; > + reg = <0x0 0x47034000 0x0 0x100>, > + <0x5 0x00000000 0x1 0x0000000>; > + power-domains = <&k3_pds 55>; > + #address-cells = <2>; > + #size-cells = <1>; > + ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */ > + <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */ > + mux-controls = <&hbmc_mux 0>; > + > + /* Slave flash node */ Overindented. > + flash@0,0 { > + compatible = "cypress,hyperflash", "cfi-flash"; > + reg = <0x0 0x0 0x4000000>; > + }; > + }; [...] MBR, Sergei ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller @ 2019-06-20 19:48 ` Sergei Shtylyov 0 siblings, 0 replies; 48+ messages in thread From: Sergei Shtylyov @ 2019-06-20 19:48 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > Add binding documentation for TI's HyperBus memory controller present on > AM654 SoC. > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > --- > > v7: Fix example to move HyperBus node out of syscon > v6: Use generic names for bindings > > .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 +++++++++++++++++++ > MAINTAINERS | 1 + > 2 files changed, 53 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt > > diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt > new file mode 100644 > index 000000000000..d424a0b88ab6 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt [...] > +Example: > + > + system-controller@47000000 { > + compatible = "syscon", "simple-mfd"; > + reg = <0x0 0x47000000 0x0 0x100>; > + #address-cells = <2>; > + #size-cells = <2>; > + ranges; > + > + hbmc_mux: multiplexer { > + compatible = "mmio-mux"; > + #mux-control-cells = <1>; > + mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */ > + }; > + Empty line not needed here. > + }; > + > + hbmc: hyperbus@47034000 { > + compatible = "ti,am654-hbmc"; > + reg = <0x0 0x47034000 0x0 0x100>, > + <0x5 0x00000000 0x1 0x0000000>; > + power-domains = <&k3_pds 55>; > + #address-cells = <2>; > + #size-cells = <1>; > + ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */ > + <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */ > + mux-controls = <&hbmc_mux 0>; > + > + /* Slave flash node */ Overindented. > + flash@0,0 { > + compatible = "cypress,hyperflash", "cfi-flash"; > + reg = <0x0 0x0 0x4000000>; > + }; > + }; [...] MBR, Sergei _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller @ 2019-06-20 19:48 ` Sergei Shtylyov 0 siblings, 0 replies; 48+ messages in thread From: Sergei Shtylyov @ 2019-06-20 19:48 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel On 06/20/2019 08:22 PM, Vignesh Raghavendra wrote: > Add binding documentation for TI's HyperBus memory controller present on > AM654 SoC. > > Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> > --- > > v7: Fix example to move HyperBus node out of syscon > v6: Use generic names for bindings > > .../devicetree/bindings/mtd/ti,am654-hbmc.txt | 52 +++++++++++++++++++ > MAINTAINERS | 1 + > 2 files changed, 53 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt > > diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt > new file mode 100644 > index 000000000000..d424a0b88ab6 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt [...] > +Example: > + > + system-controller@47000000 { > + compatible = "syscon", "simple-mfd"; > + reg = <0x0 0x47000000 0x0 0x100>; > + #address-cells = <2>; > + #size-cells = <2>; > + ranges; > + > + hbmc_mux: multiplexer { > + compatible = "mmio-mux"; > + #mux-control-cells = <1>; > + mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */ > + }; > + Empty line not needed here. > + }; > + > + hbmc: hyperbus@47034000 { > + compatible = "ti,am654-hbmc"; > + reg = <0x0 0x47034000 0x0 0x100>, > + <0x5 0x00000000 0x1 0x0000000>; > + power-domains = <&k3_pds 55>; > + #address-cells = <2>; > + #size-cells = <1>; > + ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */ > + <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */ > + mux-controls = <&hbmc_mux 0>; > + > + /* Slave flash node */ Overindented. > + flash@0,0 { > + compatible = "cypress,hyperflash", "cfi-flash"; > + reg = <0x0 0x0 0x4000000>; > + }; > + }; [...] MBR, Sergei ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v7 5/5] mtd: hyperbus: Add driver for TI's HyperBus memory controller 2019-06-20 17:22 ` Vignesh Raghavendra (?) (?) @ 2019-06-20 17:22 ` Vignesh Raghavendra -1 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Add driver for HyperBus memory controller on TI's AM654 SoC. Programming IP is pretty simple and provides direct memory mapped access to connected Flash devices. Add basic support for the IP without DMA. Second chipSelect is not supported for now. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Move calibration routine here from core. drivers/mtd/hyperbus/Kconfig | 12 +++ drivers/mtd/hyperbus/Makefile | 1 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig index 98147e28caa0..cff6bbd226f5 100644 --- a/drivers/mtd/hyperbus/Kconfig +++ b/drivers/mtd/hyperbus/Kconfig @@ -9,3 +9,15 @@ menuconfig MTD_HYPERBUS the HyperBus Controller driver to communicate with HyperFlash. See Cypress HyperBus specification for more details + +if MTD_HYPERBUS + +config HBMC_AM654 + tristate "HyperBus controller driver for AM65x SoC" + select MULTIPLEXER + select MUX_MMIO + help + This is the driver for HyperBus controller on TI's AM65x and + other SoCs + +endif # MTD_HYPERBUS diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile index ca61dedd730d..8a936e066f48 100644 --- a/drivers/mtd/hyperbus/Makefile +++ b/drivers/mtd/hyperbus/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o +obj-$(CONFIG_HBMC_AM654) += hbmc-am654.o diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c new file mode 100644 index 000000000000..ca3fe198169e --- /dev/null +++ b/drivers/mtd/hyperbus/hbmc-am654.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/cfi.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/mtd.h> +#include <linux/mux/consumer.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/types.h> + +#define AM654_HBMC_CALIB_COUNT 25 + +struct am654_hbmc_priv { + struct hyperbus_ctlr ctlr; + struct hyperbus_device hbdev; +}; + +static int am654_hbmc_calibrate(struct hyperbus_device *hbdev) +{ + struct map_info *map = &hbdev->map; + struct cfi_private cfi; + int count = AM654_HBMC_CALIB_COUNT; + int pass_count = 0; + int ret; + + cfi.interleave = 1; + cfi.device_type = CFI_DEVICETYPE_X16; + cfi_send_gen_cmd(0xF0, 0, 0, map, &cfi, cfi.device_type, NULL); + cfi_send_gen_cmd(0x98, 0x55, 0, map, &cfi, cfi.device_type, NULL); + + while (count--) { + ret = cfi_qry_present(map, 0, &cfi); + if (ret) + pass_count++; + else + pass_count = 0; + if (pass_count == 5) + break; + } + + cfi_qry_mode_off(0, map, &cfi); + + return ret; +} + +static const struct hyperbus_ops am654_hbmc_ops = { + .calibrate = am654_hbmc_calibrate, +}; + +static int am654_hbmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct am654_hbmc_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + if (of_property_read_bool(dev->of_node, "mux-controls")) { + struct mux_control *control = devm_mux_control_get(dev, NULL); + + if (IS_ERR(control)) + return PTR_ERR(control); + + ret = mux_control_select(control, 1); + if (ret) { + dev_err(dev, "Failed to select HBMC mux\n"); + return ret; + } + } + + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + goto disable_pm; + } + + priv->ctlr.dev = dev; + priv->ctlr.ops = &am654_hbmc_ops; + priv->hbdev.ctlr = &priv->ctlr; + priv->hbdev.np = of_get_next_child(dev->of_node, NULL); + ret = hyperbus_register_device(&priv->hbdev); + if (ret) { + dev_err(dev, "failed to register controller\n"); + pm_runtime_put_sync(&pdev->dev); + goto disable_pm; + } + + return 0; +disable_pm: + pm_runtime_disable(dev); + return ret; +} + +static int am654_hbmc_remove(struct platform_device *pdev) +{ + struct am654_hbmc_priv *priv = platform_get_drvdata(pdev); + int ret; + + ret = hyperbus_unregister_device(&priv->hbdev); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static const struct of_device_id am654_hbmc_dt_ids[] = { + { + .compatible = "ti,am654-hbmc", + }, + { /* end of table */ } +}; + +MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids); + +static struct platform_driver am654_hbmc_platform_driver = { + .probe = am654_hbmc_probe, + .remove = am654_hbmc_remove, + .driver = { + .name = "hbmc-am654", + .of_match_table = am654_hbmc_dt_ids, + }, +}; + +module_platform_driver(am654_hbmc_platform_driver); + +MODULE_DESCRIPTION("HBMC driver for AM654 SoC"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:hbmc-am654"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 5/5] mtd: hyperbus: Add driver for TI's HyperBus memory controller @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Add driver for HyperBus memory controller on TI's AM654 SoC. Programming IP is pretty simple and provides direct memory mapped access to connected Flash devices. Add basic support for the IP without DMA. Second chipSelect is not supported for now. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Move calibration routine here from core. drivers/mtd/hyperbus/Kconfig | 12 +++ drivers/mtd/hyperbus/Makefile | 1 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig index 98147e28caa0..cff6bbd226f5 100644 --- a/drivers/mtd/hyperbus/Kconfig +++ b/drivers/mtd/hyperbus/Kconfig @@ -9,3 +9,15 @@ menuconfig MTD_HYPERBUS the HyperBus Controller driver to communicate with HyperFlash. See Cypress HyperBus specification for more details + +if MTD_HYPERBUS + +config HBMC_AM654 + tristate "HyperBus controller driver for AM65x SoC" + select MULTIPLEXER + select MUX_MMIO + help + This is the driver for HyperBus controller on TI's AM65x and + other SoCs + +endif # MTD_HYPERBUS diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile index ca61dedd730d..8a936e066f48 100644 --- a/drivers/mtd/hyperbus/Makefile +++ b/drivers/mtd/hyperbus/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o +obj-$(CONFIG_HBMC_AM654) += hbmc-am654.o diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c new file mode 100644 index 000000000000..ca3fe198169e --- /dev/null +++ b/drivers/mtd/hyperbus/hbmc-am654.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/cfi.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/mtd.h> +#include <linux/mux/consumer.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/types.h> + +#define AM654_HBMC_CALIB_COUNT 25 + +struct am654_hbmc_priv { + struct hyperbus_ctlr ctlr; + struct hyperbus_device hbdev; +}; + +static int am654_hbmc_calibrate(struct hyperbus_device *hbdev) +{ + struct map_info *map = &hbdev->map; + struct cfi_private cfi; + int count = AM654_HBMC_CALIB_COUNT; + int pass_count = 0; + int ret; + + cfi.interleave = 1; + cfi.device_type = CFI_DEVICETYPE_X16; + cfi_send_gen_cmd(0xF0, 0, 0, map, &cfi, cfi.device_type, NULL); + cfi_send_gen_cmd(0x98, 0x55, 0, map, &cfi, cfi.device_type, NULL); + + while (count--) { + ret = cfi_qry_present(map, 0, &cfi); + if (ret) + pass_count++; + else + pass_count = 0; + if (pass_count == 5) + break; + } + + cfi_qry_mode_off(0, map, &cfi); + + return ret; +} + +static const struct hyperbus_ops am654_hbmc_ops = { + .calibrate = am654_hbmc_calibrate, +}; + +static int am654_hbmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct am654_hbmc_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + if (of_property_read_bool(dev->of_node, "mux-controls")) { + struct mux_control *control = devm_mux_control_get(dev, NULL); + + if (IS_ERR(control)) + return PTR_ERR(control); + + ret = mux_control_select(control, 1); + if (ret) { + dev_err(dev, "Failed to select HBMC mux\n"); + return ret; + } + } + + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + goto disable_pm; + } + + priv->ctlr.dev = dev; + priv->ctlr.ops = &am654_hbmc_ops; + priv->hbdev.ctlr = &priv->ctlr; + priv->hbdev.np = of_get_next_child(dev->of_node, NULL); + ret = hyperbus_register_device(&priv->hbdev); + if (ret) { + dev_err(dev, "failed to register controller\n"); + pm_runtime_put_sync(&pdev->dev); + goto disable_pm; + } + + return 0; +disable_pm: + pm_runtime_disable(dev); + return ret; +} + +static int am654_hbmc_remove(struct platform_device *pdev) +{ + struct am654_hbmc_priv *priv = platform_get_drvdata(pdev); + int ret; + + ret = hyperbus_unregister_device(&priv->hbdev); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static const struct of_device_id am654_hbmc_dt_ids[] = { + { + .compatible = "ti,am654-hbmc", + }, + { /* end of table */ } +}; + +MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids); + +static struct platform_driver am654_hbmc_platform_driver = { + .probe = am654_hbmc_probe, + .remove = am654_hbmc_remove, + .driver = { + .name = "hbmc-am654", + .of_match_table = am654_hbmc_dt_ids, + }, +}; + +module_platform_driver(am654_hbmc_platform_driver); + +MODULE_DESCRIPTION("HBMC driver for AM654 SoC"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:hbmc-am654"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); -- 2.22.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 5/5] mtd: hyperbus: Add driver for TI's HyperBus memory controller @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: devicetree, Sergei Shtylyov, linux-kernel, linux-mtd, Miquel Raynal, Mason Yang, linux-arm-kernel Add driver for HyperBus memory controller on TI's AM654 SoC. Programming IP is pretty simple and provides direct memory mapped access to connected Flash devices. Add basic support for the IP without DMA. Second chipSelect is not supported for now. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Move calibration routine here from core. drivers/mtd/hyperbus/Kconfig | 12 +++ drivers/mtd/hyperbus/Makefile | 1 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig index 98147e28caa0..cff6bbd226f5 100644 --- a/drivers/mtd/hyperbus/Kconfig +++ b/drivers/mtd/hyperbus/Kconfig @@ -9,3 +9,15 @@ menuconfig MTD_HYPERBUS the HyperBus Controller driver to communicate with HyperFlash. See Cypress HyperBus specification for more details + +if MTD_HYPERBUS + +config HBMC_AM654 + tristate "HyperBus controller driver for AM65x SoC" + select MULTIPLEXER + select MUX_MMIO + help + This is the driver for HyperBus controller on TI's AM65x and + other SoCs + +endif # MTD_HYPERBUS diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile index ca61dedd730d..8a936e066f48 100644 --- a/drivers/mtd/hyperbus/Makefile +++ b/drivers/mtd/hyperbus/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o +obj-$(CONFIG_HBMC_AM654) += hbmc-am654.o diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c new file mode 100644 index 000000000000..ca3fe198169e --- /dev/null +++ b/drivers/mtd/hyperbus/hbmc-am654.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/cfi.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/mtd.h> +#include <linux/mux/consumer.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/types.h> + +#define AM654_HBMC_CALIB_COUNT 25 + +struct am654_hbmc_priv { + struct hyperbus_ctlr ctlr; + struct hyperbus_device hbdev; +}; + +static int am654_hbmc_calibrate(struct hyperbus_device *hbdev) +{ + struct map_info *map = &hbdev->map; + struct cfi_private cfi; + int count = AM654_HBMC_CALIB_COUNT; + int pass_count = 0; + int ret; + + cfi.interleave = 1; + cfi.device_type = CFI_DEVICETYPE_X16; + cfi_send_gen_cmd(0xF0, 0, 0, map, &cfi, cfi.device_type, NULL); + cfi_send_gen_cmd(0x98, 0x55, 0, map, &cfi, cfi.device_type, NULL); + + while (count--) { + ret = cfi_qry_present(map, 0, &cfi); + if (ret) + pass_count++; + else + pass_count = 0; + if (pass_count == 5) + break; + } + + cfi_qry_mode_off(0, map, &cfi); + + return ret; +} + +static const struct hyperbus_ops am654_hbmc_ops = { + .calibrate = am654_hbmc_calibrate, +}; + +static int am654_hbmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct am654_hbmc_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + if (of_property_read_bool(dev->of_node, "mux-controls")) { + struct mux_control *control = devm_mux_control_get(dev, NULL); + + if (IS_ERR(control)) + return PTR_ERR(control); + + ret = mux_control_select(control, 1); + if (ret) { + dev_err(dev, "Failed to select HBMC mux\n"); + return ret; + } + } + + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + goto disable_pm; + } + + priv->ctlr.dev = dev; + priv->ctlr.ops = &am654_hbmc_ops; + priv->hbdev.ctlr = &priv->ctlr; + priv->hbdev.np = of_get_next_child(dev->of_node, NULL); + ret = hyperbus_register_device(&priv->hbdev); + if (ret) { + dev_err(dev, "failed to register controller\n"); + pm_runtime_put_sync(&pdev->dev); + goto disable_pm; + } + + return 0; +disable_pm: + pm_runtime_disable(dev); + return ret; +} + +static int am654_hbmc_remove(struct platform_device *pdev) +{ + struct am654_hbmc_priv *priv = platform_get_drvdata(pdev); + int ret; + + ret = hyperbus_unregister_device(&priv->hbdev); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static const struct of_device_id am654_hbmc_dt_ids[] = { + { + .compatible = "ti,am654-hbmc", + }, + { /* end of table */ } +}; + +MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids); + +static struct platform_driver am654_hbmc_platform_driver = { + .probe = am654_hbmc_probe, + .remove = am654_hbmc_remove, + .driver = { + .name = "hbmc-am654", + .of_match_table = am654_hbmc_dt_ids, + }, +}; + +module_platform_driver(am654_hbmc_platform_driver); + +MODULE_DESCRIPTION("HBMC driver for AM654 SoC"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:hbmc-am654"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); -- 2.22.0 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v7 5/5] mtd: hyperbus: Add driver for TI's HyperBus memory controller @ 2019-06-20 17:22 ` Vignesh Raghavendra 0 siblings, 0 replies; 48+ messages in thread From: Vignesh Raghavendra @ 2019-06-20 17:22 UTC (permalink / raw) To: Vignesh Raghavendra, Boris Brezillon, Marek Vasut, Richard Weinberger, Rob Herring Cc: linux-mtd, Miquel Raynal, devicetree, Sergei Shtylyov, Mason Yang, linux-arm-kernel, linux-kernel Add driver for HyperBus memory controller on TI's AM654 SoC. Programming IP is pretty simple and provides direct memory mapped access to connected Flash devices. Add basic support for the IP without DMA. Second chipSelect is not supported for now. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- v7: No change v6: Move calibration routine here from core. drivers/mtd/hyperbus/Kconfig | 12 +++ drivers/mtd/hyperbus/Makefile | 1 + drivers/mtd/hyperbus/hbmc-am654.c | 141 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 drivers/mtd/hyperbus/hbmc-am654.c diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig index 98147e28caa0..cff6bbd226f5 100644 --- a/drivers/mtd/hyperbus/Kconfig +++ b/drivers/mtd/hyperbus/Kconfig @@ -9,3 +9,15 @@ menuconfig MTD_HYPERBUS the HyperBus Controller driver to communicate with HyperFlash. See Cypress HyperBus specification for more details + +if MTD_HYPERBUS + +config HBMC_AM654 + tristate "HyperBus controller driver for AM65x SoC" + select MULTIPLEXER + select MUX_MMIO + help + This is the driver for HyperBus controller on TI's AM65x and + other SoCs + +endif # MTD_HYPERBUS diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile index ca61dedd730d..8a936e066f48 100644 --- a/drivers/mtd/hyperbus/Makefile +++ b/drivers/mtd/hyperbus/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o +obj-$(CONFIG_HBMC_AM654) += hbmc-am654.o diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c new file mode 100644 index 000000000000..ca3fe198169e --- /dev/null +++ b/drivers/mtd/hyperbus/hbmc-am654.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/cfi.h> +#include <linux/mtd/hyperbus.h> +#include <linux/mtd/mtd.h> +#include <linux/mux/consumer.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/types.h> + +#define AM654_HBMC_CALIB_COUNT 25 + +struct am654_hbmc_priv { + struct hyperbus_ctlr ctlr; + struct hyperbus_device hbdev; +}; + +static int am654_hbmc_calibrate(struct hyperbus_device *hbdev) +{ + struct map_info *map = &hbdev->map; + struct cfi_private cfi; + int count = AM654_HBMC_CALIB_COUNT; + int pass_count = 0; + int ret; + + cfi.interleave = 1; + cfi.device_type = CFI_DEVICETYPE_X16; + cfi_send_gen_cmd(0xF0, 0, 0, map, &cfi, cfi.device_type, NULL); + cfi_send_gen_cmd(0x98, 0x55, 0, map, &cfi, cfi.device_type, NULL); + + while (count--) { + ret = cfi_qry_present(map, 0, &cfi); + if (ret) + pass_count++; + else + pass_count = 0; + if (pass_count == 5) + break; + } + + cfi_qry_mode_off(0, map, &cfi); + + return ret; +} + +static const struct hyperbus_ops am654_hbmc_ops = { + .calibrate = am654_hbmc_calibrate, +}; + +static int am654_hbmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct am654_hbmc_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + if (of_property_read_bool(dev->of_node, "mux-controls")) { + struct mux_control *control = devm_mux_control_get(dev, NULL); + + if (IS_ERR(control)) + return PTR_ERR(control); + + ret = mux_control_select(control, 1); + if (ret) { + dev_err(dev, "Failed to select HBMC mux\n"); + return ret; + } + } + + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + goto disable_pm; + } + + priv->ctlr.dev = dev; + priv->ctlr.ops = &am654_hbmc_ops; + priv->hbdev.ctlr = &priv->ctlr; + priv->hbdev.np = of_get_next_child(dev->of_node, NULL); + ret = hyperbus_register_device(&priv->hbdev); + if (ret) { + dev_err(dev, "failed to register controller\n"); + pm_runtime_put_sync(&pdev->dev); + goto disable_pm; + } + + return 0; +disable_pm: + pm_runtime_disable(dev); + return ret; +} + +static int am654_hbmc_remove(struct platform_device *pdev) +{ + struct am654_hbmc_priv *priv = platform_get_drvdata(pdev); + int ret; + + ret = hyperbus_unregister_device(&priv->hbdev); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static const struct of_device_id am654_hbmc_dt_ids[] = { + { + .compatible = "ti,am654-hbmc", + }, + { /* end of table */ } +}; + +MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids); + +static struct platform_driver am654_hbmc_platform_driver = { + .probe = am654_hbmc_probe, + .remove = am654_hbmc_remove, + .driver = { + .name = "hbmc-am654", + .of_match_table = am654_hbmc_dt_ids, + }, +}; + +module_platform_driver(am654_hbmc_platform_driver); + +MODULE_DESCRIPTION("HBMC driver for AM654 SoC"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:hbmc-am654"); +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>"); -- 2.22.0 ^ permalink raw reply related [flat|nested] 48+ messages in thread
end of thread, other threads:[~2019-06-26 6:01 UTC | newest] Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-06-20 17:22 [PATCH v7 0/5] MTD: Add Initial HyperBus support Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` [PATCH v7 1/5] mtd: cfi_cmdset_0002: Add support for polling status register Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-24 16:46 ` Tokunori Ikegami 2019-06-24 16:46 ` Tokunori Ikegami 2019-06-24 16:46 ` Tokunori Ikegami 2019-06-25 5:52 ` Vignesh Raghavendra 2019-06-25 5:52 ` Vignesh Raghavendra 2019-06-25 5:52 ` Vignesh Raghavendra 2019-06-20 17:22 ` [PATCH v7 2/5] dt-bindings: mtd: Add binding documentation for HyperFlash Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` [PATCH v7 3/5] mtd: Add support for HyperBus memory devices Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-21 19:52 ` Sergei Shtylyov 2019-06-21 19:52 ` Sergei Shtylyov 2019-06-21 19:52 ` Sergei Shtylyov 2019-06-24 13:33 ` Vignesh Raghavendra 2019-06-24 13:33 ` Vignesh Raghavendra 2019-06-24 13:33 ` Vignesh Raghavendra 2019-06-24 13:33 ` Vignesh Raghavendra 2019-06-26 1:16 ` masonccyang 2019-06-26 1:16 ` masonccyang 2019-06-26 1:16 ` masonccyang 2019-06-26 1:16 ` masonccyang 2019-06-26 6:00 ` Vignesh Raghavendra 2019-06-26 6:00 ` Vignesh Raghavendra 2019-06-26 6:00 ` Vignesh Raghavendra 2019-06-26 6:00 ` Vignesh Raghavendra 2019-06-20 17:22 ` [PATCH v7 4/5] dt-bindings: mtd: Add bindings for TI's AM654 HyperBus memory controller Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 19:48 ` Sergei Shtylyov 2019-06-20 19:48 ` Sergei Shtylyov 2019-06-20 19:48 ` Sergei Shtylyov 2019-06-20 17:22 ` [PATCH v7 5/5] mtd: hyperbus: Add driver for TI's " Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra 2019-06-20 17:22 ` Vignesh Raghavendra
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.