From 34354d4bf845c85f9795a9f39239ca3aa46c3a94 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 19 Nov 2017 00:48:23 +0100 Subject: [PATCH 01/15] mtd: spi-nor: add support for ISSI is25lp128 Add support for ISSI is25lp128 spi nor flash. Signed-off-by: Angelo Dureghello Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index bc266f70a15b..7139ad6ada4e 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1021,6 +1021,8 @@ static const struct flash_info spi_nor_ids[] = { /* ISSI */ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, + { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ) }, /* Macronix */ { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, From 6d17969c8eb454116d906005a6c4752f4f560b26 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 3 Dec 2017 20:36:24 -0200 Subject: [PATCH 02/15] dt-bindings: mtd: fsl-quadspi: Pass the qspi clock names In order to improve the bindings documentation, explicitly pass the name of the clocks: "qspi_en" and "qspi", which are mandatory. Signed-off-by: Fabio Estevam Reviewed-by: Rob Herring Signed-off-by: Cyrille Pitchen --- Documentation/devicetree/bindings/mtd/fsl-quadspi.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt index c34aa6f8a424..63d4d626fbd5 100644 --- a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt @@ -12,7 +12,7 @@ Required properties: - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory" - interrupts : Should contain the interrupt for the device - clocks : The clocks needed by the QuadSPI controller - - clock-names : the name of the clocks + - clock-names : Should contain the name of the clocks: "qspi_en" and "qspi". Optional properties: - fsl,qspi-has-second-chip: The controller has two buses, bus A and bus B. From 20ccb993f29bd6ad17699dd0b349db086e3ca719 Mon Sep 17 00:00:00 2001 From: "Bean Huo (beanhuo)" Date: Mon, 4 Dec 2017 12:34:47 +0000 Subject: [PATCH 03/15] mtd: spi-nor: check FSR error bits for Micron memories For Micron spi nor device, when erase/program operation fails, especially the failure results from intending to modify protected space, spi-nor upper layers still get the return which shows the operation succeeds. This is because current spi_nor_fsr_ready() only uses FSR bit.7 (flag status register) to check device whether ready. This patch fixes this issue by checking relevant error bits in FSR. The FSR is a powerful tool to investigate the status of device, checking information regarding what the memory is actually doing and detecting possible error conditions. Signed-off-by: beanhuo Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 18 ++++++++++++++++-- include/linux/mtd/spi-nor.h | 6 +++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 7139ad6ada4e..07d040ff574b 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -330,8 +330,22 @@ static inline int spi_nor_fsr_ready(struct spi_nor *nor) int fsr = read_fsr(nor); if (fsr < 0) return fsr; - else - return fsr & FSR_READY; + + if (fsr & (FSR_E_ERR | FSR_P_ERR)) { + if (fsr & FSR_E_ERR) + dev_err(nor->dev, "Erase operation failed.\n"); + else + dev_err(nor->dev, "Program operation failed.\n"); + + if (fsr & FSR_PT_ERR) + dev_err(nor->dev, + "Attempted to modify a protected sector.\n"); + + nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); + return -EIO; + } + + return fsr & FSR_READY; } static int spi_nor_ready(struct spi_nor *nor) diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index d0c66a0975cf..c0836cca5280 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -61,6 +61,7 @@ #define SPINOR_OP_RDSFDP 0x5a /* Read SFDP */ #define SPINOR_OP_RDCR 0x35 /* Read configuration register */ #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ +#define SPINOR_OP_CLFSR 0x50 /* Clear flag status register */ /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ #define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */ @@ -130,7 +131,10 @@ #define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */ /* Flag Status Register bits */ -#define FSR_READY BIT(7) +#define FSR_READY BIT(7) /* Device status, 0 = Busy, 1 = Ready */ +#define FSR_E_ERR BIT(5) /* Erase operation status */ +#define FSR_P_ERR BIT(4) /* Program operation status */ +#define FSR_PT_ERR BIT(1) /* Protection error bit */ /* Configuration Register bits. */ #define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ From 2666067fdba26a0a87cf50bb38f5a73aabd0f517 Mon Sep 17 00:00:00 2001 From: Aaron Sierra Date: Tue, 5 Dec 2017 12:13:44 -0600 Subject: [PATCH 04/15] mtd: spi-nor: Check that BP bits are set properly Previously, the lock and unlock functions returned success even if the BP bits were not actually updated in the status register due to hardware write protection. Introduce write_sr_and_check() to write and read back the status register to ensure the desired BP bits are actually set as requested. Signed-off-by: Joe Schultz Signed-off-by: Aaron Sierra Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 07d040ff574b..1e4b4dfe26b5 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -566,6 +566,27 @@ erase_err: return ret; } +/* Write status register and ensure bits in mask match written values */ +static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) +{ + int ret; + + write_enable(nor); + ret = write_sr(nor, status_new); + if (ret) + return ret; + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + ret = read_sr(nor); + if (ret < 0) + return ret; + + return ((ret & mask) != (status_new & mask)) ? -EIO : 0; +} + static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, uint64_t *len) { @@ -664,7 +685,6 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; - int ret; status_old = read_sr(nor); if (status_old < 0) @@ -728,11 +748,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) if ((status_new & mask) < (status_old & mask)) return -EINVAL; - write_enable(nor); - ret = write_sr(nor, status_new); - if (ret) - return ret; - return spi_nor_wait_till_ready(nor); + return write_sr_and_check(nor, status_new, mask); } /* @@ -749,7 +765,6 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; - int ret; status_old = read_sr(nor); if (status_old < 0) @@ -816,11 +831,7 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) if ((status_new & mask) > (status_old & mask)) return -EINVAL; - write_enable(nor); - ret = write_sr(nor, status_new); - if (ret) - return ret; - return spi_nor_wait_till_ready(nor); + return write_sr_and_check(nor, status_new, mask); } /* From 8dee1d971af9af2f7b5f54c2eac4ebd04c5c237c Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Wed, 6 Dec 2017 10:53:41 +0800 Subject: [PATCH 05/15] mtd: spi-nor: add an API to restore the status of SPI flash chip Add this API to restore the status of SPI flash chip to the default such as addressing mode, whenever detach the driver from device or reboot the system. Signed-off-by: Hou Zhiqiang Signed-off-by: Cyrille Pitchen --- Documentation/mtd/spi-nor.txt | 3 +++ drivers/mtd/spi-nor/spi-nor.c | 10 ++++++++++ include/linux/mtd/spi-nor.h | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.txt index 548d6306ebca..da1fbff5a24c 100644 --- a/Documentation/mtd/spi-nor.txt +++ b/Documentation/mtd/spi-nor.txt @@ -60,3 +60,6 @@ The main API is spi_nor_scan(). Before you call the hook, a driver should initialize the necessary fields for spi_nor{}. Please see drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c when you want to write a new driver for a SPI NOR controller. +Another API is spi_nor_restore(), this is used to restore the status of SPI +flash chip such as addressing mode. Call it whenever detach the driver from +device or reboot the system. diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 1e4b4dfe26b5..9178139a39d0 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2740,6 +2740,16 @@ static void spi_nor_resume(struct mtd_info *mtd) dev_err(dev, "resume() failed\n"); } +void spi_nor_restore(struct spi_nor *nor) +{ + /* restore the addressing mode */ + if ((nor->addr_width == 4) && + (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) && + !(nor->info->flags & SPI_NOR_4B_OPCODES)) + set_4byte(nor, nor->info, 0); +} +EXPORT_SYMBOL_GPL(spi_nor_restore); + int spi_nor_scan(struct spi_nor *nor, const char *name, const struct spi_nor_hwcaps *hwcaps) { diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index c0836cca5280..de36969eb359 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -403,4 +403,10 @@ struct spi_nor_hwcaps { int spi_nor_scan(struct spi_nor *nor, const char *name, const struct spi_nor_hwcaps *hwcaps); +/** + * spi_nor_restore_addr_mode() - restore the status of SPI NOR + * @nor: the spi_nor structure + */ +void spi_nor_restore(struct spi_nor *nor); + #endif From 59b356ffd0b00ed986c0aa1b401dd9b466ee619d Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Wed, 6 Dec 2017 10:53:42 +0800 Subject: [PATCH 06/15] mtd: m25p80: restore the status of SPI flash when exiting Restore the status to be compatible with legacy devices. Take Freescale eSPI boot for example, it copies (in 3 Byte addressing mode) the RCW and bootloader images from SPI flash without firing a reset signal previously, so the reboot command will fail without resetting the addressing mode of SPI flash. This patch implements .shutdown function to restore the status in reboot process, and add the same operation to the .remove function. Signed-off-by: Hou Zhiqiang Signed-off-by: Cyrille Pitchen --- drivers/mtd/devices/m25p80.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index dbe6a1de2bb8..a4e18f6aaa33 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -307,10 +307,18 @@ static int m25p_remove(struct spi_device *spi) { struct m25p *flash = spi_get_drvdata(spi); + spi_nor_restore(&flash->spi_nor); + /* Clean up MTD stuff. */ return mtd_device_unregister(&flash->spi_nor.mtd); } +static void m25p_shutdown(struct spi_device *spi) +{ + struct m25p *flash = spi_get_drvdata(spi); + + spi_nor_restore(&flash->spi_nor); +} /* * Do NOT add to this array without reading the following: * @@ -386,6 +394,7 @@ static struct spi_driver m25p80_driver = { .id_table = m25p_ids, .probe = m25p_probe, .remove = m25p_remove, + .shutdown = m25p_shutdown, /* REVISIT: many of these chips have deep power-down modes, which * should clearly be entered on suspend() to minimize power use. From ded8a0447f49d7ec1778a79de433c281c64bf814 Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Fri, 15 Dec 2017 08:33:31 +0100 Subject: [PATCH 07/15] mtd: spi-nor: add support for is25lq040b Signed-off-by: Sean Nyekjaer Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 9178139a39d0..f7676aa50ce6 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1046,6 +1046,8 @@ static const struct flash_info spi_nor_ids[] = { /* ISSI */ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, + { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ) }, From 29d6b29f5040d3385510bd9766f5f7823537b26a Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Fri, 15 Dec 2017 08:33:32 +0100 Subject: [PATCH 08/15] mtd: spi-nor: indent issi section Signed-off-by: Sean Nyekjaer Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index f7676aa50ce6..8bafd462f0ae 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1045,10 +1045,10 @@ static const struct flash_info spi_nor_ids[] = { { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, /* ISSI */ - { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, - { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8, + { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, + { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, + { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ) }, /* Macronix */ From 0074a8f3b30302383ce59867299975fbf37a4061 Mon Sep 17 00:00:00 2001 From: Rafael Gago Date: Thu, 21 Dec 2017 13:27:30 +0100 Subject: [PATCH 09/15] mtd: spi-nor: Add support for s25fl128l and s25fl256l They are exactly the same as the s25fl064l but bigger. Signed-off-by: Rafael Gago Castano Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 8bafd462f0ae..79c598425352 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1094,7 +1094,7 @@ static const struct flash_info spi_nor_ids[] = { { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) }, - /* Spansion -- single (large) sector size only, at least + /* Spansion/Cypress -- single (large) sector size only, at least * for the chips listed here (without boot sectors). */ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, @@ -1123,6 +1123,8 @@ static const struct flash_info spi_nor_ids[] = { { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) }, { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) }, { "s25fl064l", INFO(0x016017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, /* SST -- large erase sizes are "overlays", "sectors" are 4K */ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, From 17407ec3354d291541099b2a7cd71545d9402e14 Mon Sep 17 00:00:00 2001 From: Romain Porte Date: Thu, 28 Dec 2017 11:03:24 +0100 Subject: [PATCH 10/15] mtd: spi-nor: Add ISSI is25lp080d support Add support for a new ISSI 1MB SPI NOR chip that was tested in our lab. Datasheet is available at: http://www.issi.com/WW/pdf/25LP-WP080D.pdf Testing was done only without the SPI_NOR_{DUAL,QUAD}_READ flags that were added later, according to the datasheet. Tested-by: Pascal Fabreges Reviewed-by: Alexander Sverdlin Signed-off-by: Romain Porte Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 79c598425352..d445a4d3b770 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1048,6 +1048,8 @@ static const struct flash_info spi_nor_ids[] = { { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "is25lp080d", INFO(0x9d6014, 0, 64 * 1024, 16, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ) }, From e4b580bc04af6b3408a99113d2d69f9dd268eafa Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Fri, 29 Dec 2017 14:41:02 +0530 Subject: [PATCH 11/15] mtd: spi-nor: cadence-quadspi: Refactor indirect read/write sequence. Move configuring of indirect read/write start address to cqspi_indirect_*_execute() function and rename cqspi_indirect_*_setup() function. This will help to reuse cqspi_indirect_*_setup() function for supporting direct access mode. Signed-off-by: Vignesh R Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/cadence-quadspi.c | 28 ++++++++++++--------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 75a2bc447a99..c7bf4d523f9c 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -450,8 +450,7 @@ static int cqspi_command_write_addr(struct spi_nor *nor, return cqspi_exec_flash_cmd(cqspi, reg); } -static int cqspi_indirect_read_setup(struct spi_nor *nor, - const unsigned int from_addr) +static int cqspi_read_setup(struct spi_nor *nor) { struct cqspi_flash_pdata *f_pdata = nor->priv; struct cqspi_st *cqspi = f_pdata->cqspi; @@ -459,8 +458,6 @@ static int cqspi_indirect_read_setup(struct spi_nor *nor, unsigned int dummy_clk = 0; unsigned int reg; - writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR); - reg = nor->read_opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB; reg |= cqspi_calc_rdreg(nor, nor->read_opcode); @@ -493,8 +490,8 @@ static int cqspi_indirect_read_setup(struct spi_nor *nor, return 0; } -static int cqspi_indirect_read_execute(struct spi_nor *nor, - u8 *rxbuf, const unsigned n_rx) +static int cqspi_indirect_read_execute(struct spi_nor *nor, u8 *rxbuf, + loff_t from_addr, const size_t n_rx) { struct cqspi_flash_pdata *f_pdata = nor->priv; struct cqspi_st *cqspi = f_pdata->cqspi; @@ -504,6 +501,7 @@ static int cqspi_indirect_read_execute(struct spi_nor *nor, unsigned int bytes_to_read = 0; int ret = 0; + writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR); writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES); /* Clear all interrupts. */ @@ -570,8 +568,7 @@ failrd: return ret; } -static int cqspi_indirect_write_setup(struct spi_nor *nor, - const unsigned int to_addr) +static int cqspi_write_setup(struct spi_nor *nor) { unsigned int reg; struct cqspi_flash_pdata *f_pdata = nor->priv; @@ -584,8 +581,6 @@ static int cqspi_indirect_write_setup(struct spi_nor *nor, reg = cqspi_calc_rdreg(nor, nor->program_opcode); writel(reg, reg_base + CQSPI_REG_RD_INSTR); - writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR); - reg = readl(reg_base + CQSPI_REG_SIZE); reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; reg |= (nor->addr_width - 1); @@ -593,8 +588,8 @@ static int cqspi_indirect_write_setup(struct spi_nor *nor, return 0; } -static int cqspi_indirect_write_execute(struct spi_nor *nor, - const u8 *txbuf, const unsigned n_tx) +static int cqspi_indirect_write_execute(struct spi_nor *nor, loff_t to_addr, + const u8 *txbuf, const size_t n_tx) { const unsigned int page_size = nor->page_size; struct cqspi_flash_pdata *f_pdata = nor->priv; @@ -604,6 +599,7 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor, unsigned int write_bytes; int ret; + writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR); writel(remaining, reg_base + CQSPI_REG_INDIRECTWRBYTES); /* Clear all interrupts. */ @@ -900,11 +896,11 @@ static ssize_t cqspi_write(struct spi_nor *nor, loff_t to, if (ret) return ret; - ret = cqspi_indirect_write_setup(nor, to); + ret = cqspi_write_setup(nor); if (ret) return ret; - ret = cqspi_indirect_write_execute(nor, buf, len); + ret = cqspi_indirect_write_execute(nor, to, buf, len); if (ret) return ret; @@ -920,11 +916,11 @@ static ssize_t cqspi_read(struct spi_nor *nor, loff_t from, if (ret) return ret; - ret = cqspi_indirect_read_setup(nor, from); + ret = cqspi_read_setup(nor); if (ret) return ret; - ret = cqspi_indirect_read_execute(nor, buf, len); + ret = cqspi_indirect_read_execute(nor, buf, from, len); if (ret) return ret; From a27f2eaf2b275758d269ba519833df53c6181878 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Fri, 29 Dec 2017 14:41:03 +0530 Subject: [PATCH 12/15] mtd: spi-nor: cadence-quadspi: Add support for direct access mode Cadence QSPI controller provides direct access mode through which flash can be accessed in a memory-mapped IO mode. This enables read/write to flash using memcpy*() functions. This mode provides higher throughput for both read/write operations when compared to current indirect mode of operation. This patch therefore adds support to use QSPI in direct mode. If the window reserved in SoC's memory map for MMIO access is less that of flash size(like on most SoCFPGA variants), then the driver falls back to indirect mode of operation. On TI's 66AK2G SoC, with ARM running at 600MHz and QSPI at 96MHz switching to direct mode improves read throughput from 3MB/s to 8MB/s. Signed-off-by: Vignesh R Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/cadence-quadspi.c | 31 +++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index c7bf4d523f9c..4b8e9183489a 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -58,6 +58,7 @@ struct cqspi_flash_pdata { u8 data_width; u8 cs; bool registered; + bool use_direct_mode; }; struct cqspi_st { @@ -68,6 +69,7 @@ struct cqspi_st { void __iomem *iobase; void __iomem *ahb_base; + resource_size_t ahb_size; struct completion transfer_complete; struct mutex bus_mutex; @@ -103,6 +105,7 @@ struct cqspi_st { /* Register map */ #define CQSPI_REG_CONFIG 0x00 #define CQSPI_REG_CONFIG_ENABLE_MASK BIT(0) +#define CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL BIT(7) #define CQSPI_REG_CONFIG_DECODE_MASK BIT(9) #define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10 #define CQSPI_REG_CONFIG_DMA_MASK BIT(15) @@ -890,6 +893,8 @@ static int cqspi_set_protocol(struct spi_nor *nor, const int read) static ssize_t cqspi_write(struct spi_nor *nor, loff_t to, size_t len, const u_char *buf) { + struct cqspi_flash_pdata *f_pdata = nor->priv; + struct cqspi_st *cqspi = f_pdata->cqspi; int ret; ret = cqspi_set_protocol(nor, 0); @@ -900,7 +905,10 @@ static ssize_t cqspi_write(struct spi_nor *nor, loff_t to, if (ret) return ret; - ret = cqspi_indirect_write_execute(nor, to, buf, len); + if (f_pdata->use_direct_mode) + memcpy_toio(cqspi->ahb_base + to, buf, len); + else + ret = cqspi_indirect_write_execute(nor, to, buf, len); if (ret) return ret; @@ -910,6 +918,8 @@ static ssize_t cqspi_write(struct spi_nor *nor, loff_t to, static ssize_t cqspi_read(struct spi_nor *nor, loff_t from, size_t len, u_char *buf) { + struct cqspi_flash_pdata *f_pdata = nor->priv; + struct cqspi_st *cqspi = f_pdata->cqspi; int ret; ret = cqspi_set_protocol(nor, 1); @@ -920,7 +930,10 @@ static ssize_t cqspi_read(struct spi_nor *nor, loff_t from, if (ret) return ret; - ret = cqspi_indirect_read_execute(nor, buf, from, len); + if (f_pdata->use_direct_mode) + memcpy_fromio(buf, cqspi->ahb_base + from, len); + else + ret = cqspi_indirect_read_execute(nor, buf, from, len); if (ret) return ret; @@ -1055,6 +1068,8 @@ static int cqspi_of_get_pdata(struct platform_device *pdev) static void cqspi_controller_init(struct cqspi_st *cqspi) { + u32 reg; + cqspi_controller_enable(cqspi, 0); /* Configure the remap address register, no remap */ @@ -1077,6 +1092,11 @@ static void cqspi_controller_init(struct cqspi_st *cqspi) writel(cqspi->fifo_depth * cqspi->fifo_width / 8, cqspi->iobase + CQSPI_REG_INDIRECTWRWATERMARK); + /* Enable Direct Access Controller */ + reg = readl(cqspi->iobase + CQSPI_REG_CONFIG); + reg |= CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL; + writel(reg, cqspi->iobase + CQSPI_REG_CONFIG); + cqspi_controller_enable(cqspi, 1); } @@ -1152,6 +1172,12 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np) goto err; f_pdata->registered = true; + + if (mtd->size <= cqspi->ahb_size) { + f_pdata->use_direct_mode = true; + dev_dbg(nor->dev, "using direct mode for %s\n", + mtd->name); + } } return 0; @@ -1211,6 +1237,7 @@ static int cqspi_probe(struct platform_device *pdev) dev_err(dev, "Cannot remap AHB address.\n"); return PTR_ERR(cqspi->ahb_base); } + cqspi->ahb_size = resource_size(res_ahb); init_completion(&cqspi->transfer_complete); From 2167d6d7a96a35614be64769f4d36d6eddc1860f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 2 Jan 2018 14:28:05 +0100 Subject: [PATCH 13/15] mtd: fsl-quadspi: account for const type of of_device_id.data This driver creates a number of const structures that it stores in the data field of an of_device_id array. The data field of an of_device_id structure has type const void *, so there is no need for a const-discarding cast when putting const values into such a structure. Done using Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/fsl-quadspi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index f17d22435bfc..2901c7bd9e30 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -801,10 +801,10 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) } static const struct of_device_id fsl_qspi_dt_ids[] = { - { .compatible = "fsl,vf610-qspi", .data = (void *)&vybrid_data, }, - { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, }, - { .compatible = "fsl,imx7d-qspi", .data = (void *)&imx7d_data, }, - { .compatible = "fsl,imx6ul-qspi", .data = (void *)&imx6ul_data, }, + { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, }, + { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, }, + { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, }, + { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, }, { .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, }, { /* sentinel */ } }; From a6e4836d6991b86736ed00835ffac94cc2ec5158 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 4 Jan 2018 12:07:44 +0300 Subject: [PATCH 14/15] spi-nor: intel-spi: Remove unused preopcodes field This field is not used in the driver anymore so remove it. Signed-off-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index ef034d898a23..699951523179 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -138,7 +138,6 @@ * @erase_64k: 64k erase supported * @opcodes: Opcodes which are supported. This are programmed by BIOS * before it locks down the controller. - * @preopcodes: Preopcodes which are supported. */ struct intel_spi { struct device *dev; @@ -155,7 +154,6 @@ struct intel_spi { bool swseq_erase; bool erase_64k; u8 opcodes[8]; - u8 preopcodes[2]; }; static bool writeable; @@ -400,10 +398,6 @@ static int intel_spi_init(struct intel_spi *ispi) ispi->opcodes[i] = opmenu0 >> i * 8; ispi->opcodes[i + 4] = opmenu1 >> i * 8; } - - val = readl(ispi->sregs + PREOP_OPTYPE); - ispi->preopcodes[0] = val; - ispi->preopcodes[1] = val >> 8; } } From 23bae78e8a57f0249ed9e3f9c3f40fc1499ce0d4 Mon Sep 17 00:00:00 2001 From: Guochun Mao Date: Mon, 18 Dec 2017 09:47:35 +0800 Subject: [PATCH 15/15] mtd: mtk-nor: modify functions' name more generally Since more and more Mediatek's SoC can use this driver to control spi-nor flash, functions' name with "mt8173_" is no longer properly. Replacing "mt8173_" with "mtk_" will be more accurate to describe these functions' usable scope. Signed-off-by: Guochun Mao Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/mtk-quadspi.c | 240 +++++++++++++++--------------- 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c index abe455ccd68b..5442993b71ff 100644 --- a/drivers/mtd/spi-nor/mtk-quadspi.c +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -110,7 +110,7 @@ #define MTK_NOR_PRG_REG(n) (MTK_NOR_PRGDATA0_REG + 4 * (n)) #define MTK_NOR_SHREG(n) (MTK_NOR_SHREG0_REG + 4 * (n)) -struct mt8173_nor { +struct mtk_nor { struct spi_nor nor; struct device *dev; void __iomem *base; /* nor flash base address */ @@ -118,48 +118,48 @@ struct mt8173_nor { struct clk *nor_clk; }; -static void mt8173_nor_set_read_mode(struct mt8173_nor *mt8173_nor) +static void mtk_nor_set_read_mode(struct mtk_nor *mtk_nor) { - struct spi_nor *nor = &mt8173_nor->nor; + struct spi_nor *nor = &mtk_nor->nor; switch (nor->read_proto) { case SNOR_PROTO_1_1_1: - writeb(nor->read_opcode, mt8173_nor->base + + writeb(nor->read_opcode, mtk_nor->base + MTK_NOR_PRGDATA3_REG); - writeb(MTK_NOR_FAST_READ, mt8173_nor->base + + writeb(MTK_NOR_FAST_READ, mtk_nor->base + MTK_NOR_CFG1_REG); break; case SNOR_PROTO_1_1_2: - writeb(nor->read_opcode, mt8173_nor->base + + writeb(nor->read_opcode, mtk_nor->base + MTK_NOR_PRGDATA3_REG); - writeb(MTK_NOR_DUAL_READ_EN, mt8173_nor->base + + writeb(MTK_NOR_DUAL_READ_EN, mtk_nor->base + MTK_NOR_DUAL_REG); break; case SNOR_PROTO_1_1_4: - writeb(nor->read_opcode, mt8173_nor->base + + writeb(nor->read_opcode, mtk_nor->base + MTK_NOR_PRGDATA4_REG); - writeb(MTK_NOR_QUAD_READ_EN, mt8173_nor->base + + writeb(MTK_NOR_QUAD_READ_EN, mtk_nor->base + MTK_NOR_DUAL_REG); break; default: - writeb(MTK_NOR_DUAL_DISABLE, mt8173_nor->base + + writeb(MTK_NOR_DUAL_DISABLE, mtk_nor->base + MTK_NOR_DUAL_REG); break; } } -static int mt8173_nor_execute_cmd(struct mt8173_nor *mt8173_nor, u8 cmdval) +static int mtk_nor_execute_cmd(struct mtk_nor *mtk_nor, u8 cmdval) { int reg; u8 val = cmdval & 0x1f; - writeb(cmdval, mt8173_nor->base + MTK_NOR_CMD_REG); - return readl_poll_timeout(mt8173_nor->base + MTK_NOR_CMD_REG, reg, + writeb(cmdval, mtk_nor->base + MTK_NOR_CMD_REG); + return readl_poll_timeout(mtk_nor->base + MTK_NOR_CMD_REG, reg, !(reg & val), 100, 10000); } -static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op, - u8 *tx, int txlen, u8 *rx, int rxlen) +static int mtk_nor_do_tx_rx(struct mtk_nor *mtk_nor, u8 op, + u8 *tx, int txlen, u8 *rx, int rxlen) { int len = 1 + txlen + rxlen; int i, ret, idx; @@ -167,26 +167,26 @@ static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op, if (len > MTK_NOR_MAX_SHIFT) return -EINVAL; - writeb(len * 8, mt8173_nor->base + MTK_NOR_CNT_REG); + writeb(len * 8, mtk_nor->base + MTK_NOR_CNT_REG); /* start at PRGDATA5, go down to PRGDATA0 */ idx = MTK_NOR_MAX_RX_TX_SHIFT - 1; /* opcode */ - writeb(op, mt8173_nor->base + MTK_NOR_PRG_REG(idx)); + writeb(op, mtk_nor->base + MTK_NOR_PRG_REG(idx)); idx--; /* program TX data */ for (i = 0; i < txlen; i++, idx--) - writeb(tx[i], mt8173_nor->base + MTK_NOR_PRG_REG(idx)); + writeb(tx[i], mtk_nor->base + MTK_NOR_PRG_REG(idx)); /* clear out rest of TX registers */ while (idx >= 0) { - writeb(0, mt8173_nor->base + MTK_NOR_PRG_REG(idx)); + writeb(0, mtk_nor->base + MTK_NOR_PRG_REG(idx)); idx--; } - ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PRG_CMD); + ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PRG_CMD); if (ret) return ret; @@ -195,20 +195,20 @@ static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op, /* read out RX data */ for (i = 0; i < rxlen; i++, idx--) - rx[i] = readb(mt8173_nor->base + MTK_NOR_SHREG(idx)); + rx[i] = readb(mtk_nor->base + MTK_NOR_SHREG(idx)); return 0; } /* Do a WRSR (Write Status Register) command */ -static int mt8173_nor_wr_sr(struct mt8173_nor *mt8173_nor, u8 sr) +static int mtk_nor_wr_sr(struct mtk_nor *mtk_nor, u8 sr) { - writeb(sr, mt8173_nor->base + MTK_NOR_PRGDATA5_REG); - writeb(8, mt8173_nor->base + MTK_NOR_CNT_REG); - return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WRSR_CMD); + writeb(sr, mtk_nor->base + MTK_NOR_PRGDATA5_REG); + writeb(8, mtk_nor->base + MTK_NOR_CNT_REG); + return mtk_nor_execute_cmd(mtk_nor, MTK_NOR_WRSR_CMD); } -static int mt8173_nor_write_buffer_enable(struct mt8173_nor *mt8173_nor) +static int mtk_nor_write_buffer_enable(struct mtk_nor *mtk_nor) { u8 reg; @@ -216,27 +216,27 @@ static int mt8173_nor_write_buffer_enable(struct mt8173_nor *mt8173_nor) * 0: pre-fetch buffer use for read * 1: pre-fetch buffer use for page program */ - writel(MTK_NOR_WR_BUF_ENABLE, mt8173_nor->base + MTK_NOR_CFG2_REG); - return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg, + writel(MTK_NOR_WR_BUF_ENABLE, mtk_nor->base + MTK_NOR_CFG2_REG); + return readb_poll_timeout(mtk_nor->base + MTK_NOR_CFG2_REG, reg, 0x01 == (reg & 0x01), 100, 10000); } -static int mt8173_nor_write_buffer_disable(struct mt8173_nor *mt8173_nor) +static int mtk_nor_write_buffer_disable(struct mtk_nor *mtk_nor) { u8 reg; - writel(MTK_NOR_WR_BUF_DISABLE, mt8173_nor->base + MTK_NOR_CFG2_REG); - return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg, + writel(MTK_NOR_WR_BUF_DISABLE, mtk_nor->base + MTK_NOR_CFG2_REG); + return readb_poll_timeout(mtk_nor->base + MTK_NOR_CFG2_REG, reg, MTK_NOR_WR_BUF_DISABLE == (reg & 0x1), 100, 10000); } -static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor) +static void mtk_nor_set_addr_width(struct mtk_nor *mtk_nor) { u8 val; - struct spi_nor *nor = &mt8173_nor->nor; + struct spi_nor *nor = &mtk_nor->nor; - val = readb(mt8173_nor->base + MTK_NOR_DUAL_REG); + val = readb(mtk_nor->base + MTK_NOR_DUAL_REG); switch (nor->addr_width) { case 3: @@ -246,115 +246,115 @@ static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor) val |= MTK_NOR_4B_ADDR_EN; break; default: - dev_warn(mt8173_nor->dev, "Unexpected address width %u.\n", + dev_warn(mtk_nor->dev, "Unexpected address width %u.\n", nor->addr_width); break; } - writeb(val, mt8173_nor->base + MTK_NOR_DUAL_REG); + writeb(val, mtk_nor->base + MTK_NOR_DUAL_REG); } -static void mt8173_nor_set_addr(struct mt8173_nor *mt8173_nor, u32 addr) +static void mtk_nor_set_addr(struct mtk_nor *mtk_nor, u32 addr) { int i; - mt8173_nor_set_addr_width(mt8173_nor); + mtk_nor_set_addr_width(mtk_nor); for (i = 0; i < 3; i++) { - writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR0_REG + i * 4); + writeb(addr & 0xff, mtk_nor->base + MTK_NOR_RADR0_REG + i * 4); addr >>= 8; } /* Last register is non-contiguous */ - writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR3_REG); + writeb(addr & 0xff, mtk_nor->base + MTK_NOR_RADR3_REG); } -static ssize_t mt8173_nor_read(struct spi_nor *nor, loff_t from, size_t length, - u_char *buffer) +static ssize_t mtk_nor_read(struct spi_nor *nor, loff_t from, size_t length, + u_char *buffer) { int i, ret; int addr = (int)from; u8 *buf = (u8 *)buffer; - struct mt8173_nor *mt8173_nor = nor->priv; + struct mtk_nor *mtk_nor = nor->priv; /* set mode for fast read mode ,dual mode or quad mode */ - mt8173_nor_set_read_mode(mt8173_nor); - mt8173_nor_set_addr(mt8173_nor, addr); + mtk_nor_set_read_mode(mtk_nor); + mtk_nor_set_addr(mtk_nor, addr); for (i = 0; i < length; i++) { - ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_READ_CMD); + ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PIO_READ_CMD); if (ret < 0) return ret; - buf[i] = readb(mt8173_nor->base + MTK_NOR_RDATA_REG); + buf[i] = readb(mtk_nor->base + MTK_NOR_RDATA_REG); } return length; } -static int mt8173_nor_write_single_byte(struct mt8173_nor *mt8173_nor, - int addr, int length, u8 *data) +static int mtk_nor_write_single_byte(struct mtk_nor *mtk_nor, + int addr, int length, u8 *data) { int i, ret; - mt8173_nor_set_addr(mt8173_nor, addr); + mtk_nor_set_addr(mtk_nor, addr); for (i = 0; i < length; i++) { - writeb(*data++, mt8173_nor->base + MTK_NOR_WDATA_REG); - ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_WR_CMD); + writeb(*data++, mtk_nor->base + MTK_NOR_WDATA_REG); + ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PIO_WR_CMD); if (ret < 0) return ret; } return 0; } -static int mt8173_nor_write_buffer(struct mt8173_nor *mt8173_nor, int addr, - const u8 *buf) +static int mtk_nor_write_buffer(struct mtk_nor *mtk_nor, int addr, + const u8 *buf) { int i, bufidx, data; - mt8173_nor_set_addr(mt8173_nor, addr); + mtk_nor_set_addr(mtk_nor, addr); bufidx = 0; for (i = 0; i < SFLASH_WRBUF_SIZE; i += 4) { data = buf[bufidx + 3]<<24 | buf[bufidx + 2]<<16 | buf[bufidx + 1]<<8 | buf[bufidx]; bufidx += 4; - writel(data, mt8173_nor->base + MTK_NOR_PP_DATA_REG); + writel(data, mtk_nor->base + MTK_NOR_PP_DATA_REG); } - return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WR_CMD); + return mtk_nor_execute_cmd(mtk_nor, MTK_NOR_WR_CMD); } -static ssize_t mt8173_nor_write(struct spi_nor *nor, loff_t to, size_t len, - const u_char *buf) +static ssize_t mtk_nor_write(struct spi_nor *nor, loff_t to, size_t len, + const u_char *buf) { int ret; - struct mt8173_nor *mt8173_nor = nor->priv; + struct mtk_nor *mtk_nor = nor->priv; size_t i; - ret = mt8173_nor_write_buffer_enable(mt8173_nor); + ret = mtk_nor_write_buffer_enable(mtk_nor); if (ret < 0) { - dev_warn(mt8173_nor->dev, "write buffer enable failed!\n"); + dev_warn(mtk_nor->dev, "write buffer enable failed!\n"); return ret; } for (i = 0; i + SFLASH_WRBUF_SIZE <= len; i += SFLASH_WRBUF_SIZE) { - ret = mt8173_nor_write_buffer(mt8173_nor, to, buf); + ret = mtk_nor_write_buffer(mtk_nor, to, buf); if (ret < 0) { - dev_err(mt8173_nor->dev, "write buffer failed!\n"); + dev_err(mtk_nor->dev, "write buffer failed!\n"); return ret; } to += SFLASH_WRBUF_SIZE; buf += SFLASH_WRBUF_SIZE; } - ret = mt8173_nor_write_buffer_disable(mt8173_nor); + ret = mtk_nor_write_buffer_disable(mtk_nor); if (ret < 0) { - dev_warn(mt8173_nor->dev, "write buffer disable failed!\n"); + dev_warn(mtk_nor->dev, "write buffer disable failed!\n"); return ret; } if (i < len) { - ret = mt8173_nor_write_single_byte(mt8173_nor, to, - (int)(len - i), (u8 *)buf); + ret = mtk_nor_write_single_byte(mtk_nor, to, + (int)(len - i), (u8 *)buf); if (ret < 0) { - dev_err(mt8173_nor->dev, "write single byte failed!\n"); + dev_err(mtk_nor->dev, "write single byte failed!\n"); return ret; } } @@ -362,72 +362,72 @@ static ssize_t mt8173_nor_write(struct spi_nor *nor, loff_t to, size_t len, return len; } -static int mt8173_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) +static int mtk_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) { int ret; - struct mt8173_nor *mt8173_nor = nor->priv; + struct mtk_nor *mtk_nor = nor->priv; switch (opcode) { case SPINOR_OP_RDSR: - ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_RDSR_CMD); + ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_RDSR_CMD); if (ret < 0) return ret; if (len == 1) - *buf = readb(mt8173_nor->base + MTK_NOR_RDSR_REG); + *buf = readb(mtk_nor->base + MTK_NOR_RDSR_REG); else - dev_err(mt8173_nor->dev, "len should be 1 for read status!\n"); + dev_err(mtk_nor->dev, "len should be 1 for read status!\n"); break; default: - ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, NULL, 0, buf, len); + ret = mtk_nor_do_tx_rx(mtk_nor, opcode, NULL, 0, buf, len); break; } return ret; } -static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, - int len) +static int mtk_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, + int len) { int ret; - struct mt8173_nor *mt8173_nor = nor->priv; + struct mtk_nor *mtk_nor = nor->priv; switch (opcode) { case SPINOR_OP_WRSR: /* We only handle 1 byte */ - ret = mt8173_nor_wr_sr(mt8173_nor, *buf); + ret = mtk_nor_wr_sr(mtk_nor, *buf); break; default: - ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, buf, len, NULL, 0); + ret = mtk_nor_do_tx_rx(mtk_nor, opcode, buf, len, NULL, 0); if (ret) - dev_warn(mt8173_nor->dev, "write reg failure!\n"); + dev_warn(mtk_nor->dev, "write reg failure!\n"); break; } return ret; } -static void mt8173_nor_disable_clk(struct mt8173_nor *mt8173_nor) +static void mtk_nor_disable_clk(struct mtk_nor *mtk_nor) { - clk_disable_unprepare(mt8173_nor->spi_clk); - clk_disable_unprepare(mt8173_nor->nor_clk); + clk_disable_unprepare(mtk_nor->spi_clk); + clk_disable_unprepare(mtk_nor->nor_clk); } -static int mt8173_nor_enable_clk(struct mt8173_nor *mt8173_nor) +static int mtk_nor_enable_clk(struct mtk_nor *mtk_nor) { int ret; - ret = clk_prepare_enable(mt8173_nor->spi_clk); + ret = clk_prepare_enable(mtk_nor->spi_clk); if (ret) return ret; - ret = clk_prepare_enable(mt8173_nor->nor_clk); + ret = clk_prepare_enable(mtk_nor->nor_clk); if (ret) { - clk_disable_unprepare(mt8173_nor->spi_clk); + clk_disable_unprepare(mtk_nor->spi_clk); return ret; } return 0; } -static int mtk_nor_init(struct mt8173_nor *mt8173_nor, +static int mtk_nor_init(struct mtk_nor *mtk_nor, struct device_node *flash_node) { const struct spi_nor_hwcaps hwcaps = { @@ -439,18 +439,18 @@ static int mtk_nor_init(struct mt8173_nor *mt8173_nor, struct spi_nor *nor; /* initialize controller to accept commands */ - writel(MTK_NOR_ENABLE_SF_CMD, mt8173_nor->base + MTK_NOR_WRPROT_REG); + writel(MTK_NOR_ENABLE_SF_CMD, mtk_nor->base + MTK_NOR_WRPROT_REG); - nor = &mt8173_nor->nor; - nor->dev = mt8173_nor->dev; - nor->priv = mt8173_nor; + nor = &mtk_nor->nor; + nor->dev = mtk_nor->dev; + nor->priv = mtk_nor; spi_nor_set_flash_node(nor, flash_node); /* fill the hooks to spi nor */ - nor->read = mt8173_nor_read; - nor->read_reg = mt8173_nor_read_reg; - nor->write = mt8173_nor_write; - nor->write_reg = mt8173_nor_write_reg; + nor->read = mtk_nor_read; + nor->read_reg = mtk_nor_read_reg; + nor->write = mtk_nor_write; + nor->write_reg = mtk_nor_write_reg; nor->mtd.name = "mtk_nor"; /* initialized with NULL */ ret = spi_nor_scan(nor, NULL, &hwcaps); @@ -465,34 +465,34 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) struct device_node *flash_np; struct resource *res; int ret; - struct mt8173_nor *mt8173_nor; + struct mtk_nor *mtk_nor; if (!pdev->dev.of_node) { dev_err(&pdev->dev, "No DT found\n"); return -EINVAL; } - mt8173_nor = devm_kzalloc(&pdev->dev, sizeof(*mt8173_nor), GFP_KERNEL); - if (!mt8173_nor) + mtk_nor = devm_kzalloc(&pdev->dev, sizeof(*mtk_nor), GFP_KERNEL); + if (!mtk_nor) return -ENOMEM; - platform_set_drvdata(pdev, mt8173_nor); + platform_set_drvdata(pdev, mtk_nor); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mt8173_nor->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mt8173_nor->base)) - return PTR_ERR(mt8173_nor->base); + mtk_nor->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mtk_nor->base)) + return PTR_ERR(mtk_nor->base); - mt8173_nor->spi_clk = devm_clk_get(&pdev->dev, "spi"); - if (IS_ERR(mt8173_nor->spi_clk)) - return PTR_ERR(mt8173_nor->spi_clk); + mtk_nor->spi_clk = devm_clk_get(&pdev->dev, "spi"); + if (IS_ERR(mtk_nor->spi_clk)) + return PTR_ERR(mtk_nor->spi_clk); - mt8173_nor->nor_clk = devm_clk_get(&pdev->dev, "sf"); - if (IS_ERR(mt8173_nor->nor_clk)) - return PTR_ERR(mt8173_nor->nor_clk); + mtk_nor->nor_clk = devm_clk_get(&pdev->dev, "sf"); + if (IS_ERR(mtk_nor->nor_clk)) + return PTR_ERR(mtk_nor->nor_clk); - mt8173_nor->dev = &pdev->dev; + mtk_nor->dev = &pdev->dev; - ret = mt8173_nor_enable_clk(mt8173_nor); + ret = mtk_nor_enable_clk(mtk_nor); if (ret) return ret; @@ -503,20 +503,20 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) ret = -ENODEV; goto nor_free; } - ret = mtk_nor_init(mt8173_nor, flash_np); + ret = mtk_nor_init(mtk_nor, flash_np); nor_free: if (ret) - mt8173_nor_disable_clk(mt8173_nor); + mtk_nor_disable_clk(mtk_nor); return ret; } static int mtk_nor_drv_remove(struct platform_device *pdev) { - struct mt8173_nor *mt8173_nor = platform_get_drvdata(pdev); + struct mtk_nor *mtk_nor = platform_get_drvdata(pdev); - mt8173_nor_disable_clk(mt8173_nor); + mtk_nor_disable_clk(mtk_nor); return 0; } @@ -524,18 +524,18 @@ static int mtk_nor_drv_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int mtk_nor_suspend(struct device *dev) { - struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); + struct mtk_nor *mtk_nor = dev_get_drvdata(dev); - mt8173_nor_disable_clk(mt8173_nor); + mtk_nor_disable_clk(mtk_nor); return 0; } static int mtk_nor_resume(struct device *dev) { - struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); + struct mtk_nor *mtk_nor = dev_get_drvdata(dev); - return mt8173_nor_enable_clk(mt8173_nor); + return mtk_nor_enable_clk(mtk_nor); } static const struct dev_pm_ops mtk_nor_dev_pm_ops = {