diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-13 15:42:44 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-13 15:42:44 -0700 |
| commit | 3f06962273e73c5f7a651726b191d531cadef788 (patch) | |
| tree | 370219bd166ac6dda105901dd316a54c2f9ac3d0 | |
| parent | 2260840592fbed5be98ca03c97eb8172941f27ac (diff) | |
| parent | 46ce10df799fb0647a9c0e3f793e66463a8d6773 (diff) | |
| download | linux-3f06962273e73c5f7a651726b191d531cadef788.tar.gz linux-3f06962273e73c5f7a651726b191d531cadef788.tar.bz2 linux-3f06962273e73c5f7a651726b191d531cadef788.zip | |
Merge tag 'mtd/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull MTD updates from Miquel Raynal:
"This contains the following changes for MTD:
MTD core changes:
- New Hyperbus framework
- New _is_locked (concat) implementation
- Various cleanups
NAND core changes:
- use longest matching pattern in ->exec_op() default parser
- export NAND operation tracer
- add flag to indicate panic_write in MTD
- use kzalloc() instead of kmalloc() and memset()
Raw NAND controller drivers changes:
- brcmnand:
- fix BCH ECC layout for large page NAND parts
- fallback to detected ecc-strength, ecc-step-size
- when oops in progress use pio and interrupt polling
- code refactor code to introduce helper functions
- add support for v7.3 controller
- FSMC:
- use nand_op_trace for operation tracing
- GPMI:
- move all driver code into single file
- various cleanups (including dmaengine changes)
- use runtime PM to manage clocks
- implement exec_op
- MTK:
- correct low level time calculation of r/w cycle
- improve data sampling timing for read cycle
- add validity check for CE# pin setting
- fix wrongly assigned OOB buffer pointer issue
- re-license MTK NAND driver as Dual MIT/GPL
- STM32:
- manage the get_irq error case
- increase DMA completion timeouts
Raw NAND chips drivers changes:
- Macronix: add read-retry support
Onenand driver changes:
- add support for 8Gb datasize chips
- avoid fall-through warnings
SPI-NAND changes:
- define macros for page-read ops with three-byte addresses
- add support for two-byte device IDs and then for GigaDevice
GD5F1GQ4UFxxG
- add initial support for Paragon PN26G0xA
- handle the case where the last page read has bitflips
SPI-NOR core changes:
- add support for the mt25ql02g and w25q16jv flashes
- print error in case of jedec read id fails
- is25lp256: add post BFPT fix to correct the addr_width
SPI NOR controller drivers changes:
- intel-spi: Add support for Intel Elkhart Lake SPI serial flash
- smt32: remove the driver as the driver was replaced by spi-stm32-qspi.c
- cadence-quadspi: add reset control"
* tag 'mtd/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (60 commits)
mtd: concat: implement _is_locked mtd operation
mtd: concat: refactor concat_lock/concat_unlock
mtd: abi: do not use C++ style comments in uapi header
mtd: afs: remove unneeded NULL check
mtd: rawnand: stm32_fmc2: increase DMA completion timeouts
mtd: rawnand: Use kzalloc() instead of kmalloc() and memset()
mtd: hyperbus: Add driver for TI's HyperBus memory controller
mtd: spinand: read returns badly if the last page has bitflips
mtd: spinand: Add initial support for Paragon PN26G0xA
mtd: rawnand: mtk: Re-license MTK NAND driver as Dual MIT/GPL
mtd: rawnand: gpmi: remove double assignment to block_size
dt-bindings: mtd: brcmnand: Add brcmnand, brcmnand-v7.3 support
mtd: rawnand: brcmnand: Add support for v7.3 controller
mtd: rawnand: brcmnand: Refactored code to introduce helper functions
mtd: rawnand: brcmnand: When oops in progress use pio and interrupt polling
mtd: Add flag to indicate panic_write
mtd: rawnand: Add Macronix NAND read retry support
mtd: onenand: Avoid fall-through warnings
mtd: spinand: Add support for GigaDevice GD5F1GQ4UFxxG
mtd: spinand: Add support for two-byte device IDs
...
49 files changed, 2624 insertions, 2490 deletions
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt index 0b7c3738b66c..82156dc8f304 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt @@ -28,6 +28,7 @@ Required properties: brcm,brcmnand-v7.0 brcm,brcmnand-v7.1 brcm,brcmnand-v7.2 + brcm,brcmnand-v7.3 brcm,brcmnand - reg : the register start and length for NAND register region. (optional) Flash DMA register range (if present) @@ -101,10 +102,10 @@ Required properties: number (e.g., 0, 1, 2, etc.) - #address-cells : see partition.txt - #size-cells : see partition.txt -- nand-ecc-strength : see nand-controller.yaml -- nand-ecc-step-size : must be 512 or 1024. See nand-controller.yaml Optional properties: +- nand-ecc-strength : see nand-controller.yaml +- nand-ecc-step-size : must be 512 or 1024. See nand-controller.yaml - nand-on-flash-bbt : boolean, to enable the on-flash BBT for this chip-select. See nand-controller.yaml - brcm,nand-oob-sector-size : integer, to denote the spare area sector size diff --git a/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt b/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt index 4345c3a6f530..945be7d5b236 100644 --- a/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt @@ -35,6 +35,9 @@ custom properties: (qspi_n_ss_out). - cdns,tslch-ns : Delay in nanoseconds between setting qspi_n_ss_out low and first bit transfer. +- resets : Must contain an entry for each entry in reset-names. + See ../reset/reset.txt for details. +- reset-names : Must include either "qspi" and/or "qspi-ocp". Example: @@ -50,6 +53,8 @@ Example: cdns,fifo-depth = <128>; cdns,fifo-width = <4>; cdns,trigger-address = <0x00000000>; + resets = <&rst QSPI_RESET>, <&rst QSPI_OCP_RESET>; + reset-names = "qspi", "qspi-ocp"; flash0: n25q00@0 { ... 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>; + }; diff --git a/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt b/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt deleted file mode 100644 index ddd18c135148..000000000000 --- a/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt +++ /dev/null @@ -1,43 +0,0 @@ -* STMicroelectronics Quad Serial Peripheral Interface(QuadSPI) - -Required properties: -- compatible: should be "st,stm32f469-qspi" -- reg: the first contains the register location and length. - the second contains the memory mapping address and length -- reg-names: should contain the reg names "qspi" "qspi_mm" -- interrupts: should contain the interrupt for the device -- clocks: the phandle of the clock needed by the QSPI controller -- A pinctrl must be defined to set pins in mode of operation for QSPI transfer - -Optional properties: -- resets: must contain the phandle to the reset controller. - -A spi flash must be a child of the nor_flash node and could have some -properties. Also see jedec,spi-nor.txt. - -Required properties: -- reg: chip-Select number (QSPI controller may connect 2 nor flashes) -- spi-max-frequency: max frequency of spi bus - -Optional property: -- spi-rx-bus-width: see ../spi/spi-bus.txt for the description - -Example: - -qspi: spi@a0001000 { - compatible = "st,stm32f469-qspi"; - reg = <0xa0001000 0x1000>, <0x90000000 0x10000000>; - reg-names = "qspi", "qspi_mm"; - interrupts = <91>; - resets = <&rcc STM32F4_AHB3_RESET(QSPI)>; - clocks = <&rcc 0 STM32F4_AHB3_CLOCK(QSPI)>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_qspi0>; - - flash@0 { - reg = <0>; - spi-rx-bus-width = <4>; - spi-max-frequency = <108000000>; - ... - }; -}; 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..faa81c2e5da6 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt @@ -0,0 +1,51 @@ +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 32bb6280c219..211ea3a199bd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7435,6 +7435,14 @@ 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 +F: Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt + HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@lists.ozlabs.org S: Odd Fixes diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 22cc7f68ef6e..20a9cb7cb6d3 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -24,6 +24,7 @@ #include <linux/of_device.h> #include <linux/of_dma.h> #include <linux/list.h> +#include <linux/dma/mxs-dma.h> #include <asm/irq.h> @@ -77,6 +78,7 @@ #define BM_CCW_COMMAND (3 << 0) #define CCW_CHAIN (1 << 2) #define CCW_IRQ (1 << 3) +#define CCW_WAIT4RDY (1 << 5) #define CCW_DEC_SEM (1 << 6) #define CCW_WAIT4END (1 << 7) #define CCW_HALT_ON_TERM (1 << 8) @@ -477,16 +479,16 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan) * ...... * ->device_prep_slave_sg(0); * ...... - * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + * ->device_prep_slave_sg(DMA_CTRL_ACK); * ...... * [3] If there are more than two DMA commands in the DMA chain, the code * should be: * ...... * ->device_prep_slave_sg(0); // First * ...... - * ->device_prep_slave_sg(DMA_PREP_INTERRUPT [| DMA_CTRL_ACK]); + * ->device_prep_slave_sg(DMA_CTRL_ACK]); * ...... - * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); // Last + * ->device_prep_slave_sg(DMA_CTRL_ACK); // Last * ...... */ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( @@ -500,13 +502,12 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( struct scatterlist *sg; u32 i, j; u32 *pio; - bool append = flags & DMA_PREP_INTERRUPT; - int idx = append ? mxs_chan->desc_count : 0; + int idx = 0; - if (mxs_chan->status == DMA_IN_PROGRESS && !append) - return NULL; + if (mxs_chan->status == DMA_IN_PROGRESS) + idx = mxs_chan->desc_count; - if (sg_len + (append ? idx : 0) > NUM_CCW) { + if (sg_len + idx > NUM_CCW) { dev_err(mxs_dma->dma_device.dev, "maximum number of sg exceeded: %d > %d\n", sg_len, NUM_CCW); @@ -520,7 +521,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( * If the sg is prepared with append flag set, the sg * will be appended to the last prepared sg. */ - if (append) { + if (idx) { BUG_ON(idx < 1); ccw = &mxs_chan->ccw[idx - 1]; ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx; @@ -541,12 +542,14 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( ccw->bits = 0; ccw->bits |= CCW_IRQ; ccw->bits |= CCW_DEC_SEM; - if (flags & DMA_CTRL_ACK) + if (flags & MXS_DMA_CTRL_WAIT4END) ccw->bits |= CCW_WAIT4END; ccw->bits |= CCW_HALT_ON_TERM; ccw->bits |= CCW_TERM_FLUSH; ccw->bits |= BF_CCW(sg_len, PIO_NUM); ccw->bits |= BF_CCW(MXS_DMA_CMD_NO_XFER, COMMAND); + if (flags & MXS_DMA_CTRL_WAIT4RDY) + ccw->bits |= CCW_WAIT4RDY; } else { for_each_sg(sgl, sg, sg_len, i) { if (sg_dma_len(sg) > MAX_XFER_BYTES) { @@ -573,7 +576,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( ccw->bits &= ~CCW_CHAIN; ccw->bits |= CCW_IRQ; ccw->bits |= CCW_DEC_SEM; - if (flags & DMA_CTRL_ACK) + if (flags & MXS_DMA_CTRL_WAIT4END) ccw->bits |= CCW_WAIT4END; } } 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/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c8fa5906bdf9..f4da7bd552e9 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,50 @@ 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; + u8 poll_mask = CFI_POLL_STATUS_REG | CFI_POLL_DQ; + + return extp->MinorVersion >= '5' && + (extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG; +} + +static void cfi_check_err_status(struct map_info *map, struct flchip *chip, + 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, chip->start, 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 */ @@ -742,10 +796,25 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) * correctly and is therefore not done (particularly with interleaved chips * as each chip must be checked independently of the others). */ -static int __xipram chip_ready(struct map_info *map, unsigned long addr) +static int __xipram chip_ready(struct map_info *map, struct flchip *chip, + 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, chip->start, 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); @@ -767,10 +836,30 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) * as each chip must be checked independently of the others). * */ -static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) +static int __xipram chip_good(struct map_info *map, struct flchip *chip, + 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, chip->start, 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); @@ -792,7 +881,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr case FL_STATUS: for (;;) { - if (chip_ready(map, adr)) + if (chip_ready(map, chip, adr)) break; if (time_after(jiffies, timeo)) { @@ -830,7 +919,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr chip->state = FL_ERASE_SUSPENDING; chip->erase_suspended = 1; for (;;) { - if (chip_ready(map, adr)) + if (chip_ready(map, chip, adr)) break; if (time_after(jiffies, timeo)) { @@ -1362,7 +1451,7 @@ static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr, /* wait for chip to become ready */ timeo = jiffies + msecs_to_jiffies(2); for (;;) { - if (chip_ready(map, adr)) + if (chip_ready(map, chip, adr)) break; if (time_after(jiffies, timeo)) { @@ -1628,22 +1717,24 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, continue; } - if (time_after(jiffies, timeo) && !chip_ready(map, adr)){ + if (time_after(jiffies, timeo) && + !chip_ready(map, chip, adr)) { xip_enable(map, chip, adr); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); xip_disable(map, chip, adr); break; } - if (chip_ready(map, adr)) + if (chip_ready(map, chip, adr)) break; /* Latency issues. Drop the lock, wait a while and retry */ UDELAY(map, chip, adr, 1); } /* Did we succeed? */ - if (!chip_good(map, adr, datum)) { + if (!chip_good(map, chip, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, chip, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -1881,10 +1972,11 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, * We check "time_after" and "!chip_good" before checking "chip_good" to avoid * the failure due to scheduling. */ - if (time_after(jiffies, timeo) && !chip_good(map, adr, datum)) + if (time_after(jiffies, timeo) && + !chip_good(map, chip, adr, datum)) break; - if (chip_good(map, adr, datum)) { + if (chip_good(map, chip, adr, datum)) { xip_enable(map, chip, adr); goto op_done; } @@ -1901,6 +1993,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, chip, 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, @@ -2018,7 +2111,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip, * If the driver thinks the chip is idle, and no toggle bits * are changing, then the chip is actually idle for sure. */ - if (chip->state == FL_READY && chip_ready(map, adr)) + if (chip->state == FL_READY && chip_ready(map, chip, adr)) return 0; /* @@ -2035,7 +2128,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip, /* wait for the chip to become ready */ for (i = 0; i < jiffies_to_usecs(timeo); i++) { - if (chip_ready(map, adr)) + if (chip_ready(map, chip, adr)) return 0; udelay(1); @@ -2099,14 +2192,15 @@ retry: map_write(map, datum, adr); for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) { - if (chip_ready(map, adr)) + if (chip_ready(map, chip, adr)) break; udelay(1); } - if (!chip_good(map, adr, datum)) { + if (!chip_good(map, chip, adr, datum)) { /* reset on all failures. */ + cfi_check_err_status(map, chip, adr); map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ @@ -2300,7 +2394,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) chip->erase_suspended = 0; } - if (chip_good(map, adr, map_word_ff(map))) + if (chip_good(map, chip, adr, map_word_ff(map))) break; if (time_after(jiffies, timeo)) { @@ -2316,6 +2410,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip |
