diff options
Diffstat (limited to 'drivers/mtd/spi-nor/core.c')
-rw-r--r-- | drivers/mtd/spi-nor/core.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 0369d98b2d12..65eff4ce6ab1 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1907,15 +1907,16 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) } /** - * spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status - * Register 1. + * spi_nor_sr1_bit6_quad_enable() - Set/Unset the Quad Enable BIT(6) in the + * Status Register 1. * @nor: pointer to a 'struct spi_nor' + * @enable: true to enable Quad mode, false to disable Quad mode. * * Bit 6 of the Status Register 1 is the QE bit for Macronix like QSPI memories. * * Return: 0 on success, -errno otherwise. */ -int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor) +int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor, bool enable) { int ret; @@ -1923,45 +1924,56 @@ int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor) if (ret) return ret; - if (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6) + if ((enable && (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)) || + (!enable && !(nor->bouncebuf[0] & SR1_QUAD_EN_BIT6))) return 0; - nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6; + if (enable) + nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6; + else + nor->bouncebuf[0] &= ~SR1_QUAD_EN_BIT6; return spi_nor_write_sr1_and_check(nor, nor->bouncebuf[0]); } /** - * spi_nor_sr2_bit1_quad_enable() - set the Quad Enable BIT(1) in the Status - * Register 2. + * spi_nor_sr2_bit1_quad_enable() - set/unset the Quad Enable BIT(1) in the + * Status Register 2. * @nor: pointer to a 'struct spi_nor'. + * @enable: true to enable Quad mode, false to disable Quad mode. * * Bit 1 of the Status Register 2 is the QE bit for Spansion like QSPI memories. * * Return: 0 on success, -errno otherwise. */ -int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor) +int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor, bool enable) { int ret; if (nor->flags & SNOR_F_NO_READ_CR) - return spi_nor_write_16bit_cr_and_check(nor, SR2_QUAD_EN_BIT1); + return spi_nor_write_16bit_cr_and_check(nor, + enable ? SR2_QUAD_EN_BIT1 : 0); ret = spi_nor_read_cr(nor, nor->bouncebuf); if (ret) return ret; - if (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1) + if ((enable && (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)) || + (!enable && !(nor->bouncebuf[0] & SR2_QUAD_EN_BIT1))) return 0; - nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1; + if (enable) + nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1; + else + nor->bouncebuf[0] &= ~SR2_QUAD_EN_BIT1; return spi_nor_write_16bit_cr_and_check(nor, nor->bouncebuf[0]); } /** - * spi_nor_sr2_bit7_quad_enable() - set QE bit in Status Register 2. + * spi_nor_sr2_bit7_quad_enable() - set/unset QE bit in Status Register 2. * @nor: pointer to a 'struct spi_nor' + * @enable: true to enable Quad mode, false to disable Quad mode. * * Set the Quad Enable (QE) bit in the Status Register 2. * @@ -1971,7 +1983,7 @@ int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor) * * Return: 0 on success, -errno otherwise. */ -int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor) +int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor, bool enable) { u8 *sr2 = nor->bouncebuf; int ret; @@ -1981,11 +1993,15 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor) ret = spi_nor_read_sr2(nor, sr2); if (ret) return ret; - if (*sr2 & SR2_QUAD_EN_BIT7) + if ((enable && (*sr2 & SR2_QUAD_EN_BIT7)) || + (!enable && !(*sr2 & SR2_QUAD_EN_BIT7))) return 0; /* Update the Quad Enable bit. */ - *sr2 |= SR2_QUAD_EN_BIT7; + if (enable) + *sr2 |= SR2_QUAD_EN_BIT7; + else + *sr2 &= ~SR2_QUAD_EN_BIT7; ret = spi_nor_write_sr2(nor, sr2); if (ret) @@ -2898,12 +2914,13 @@ static int spi_nor_init_params(struct spi_nor *nor) } /** - * spi_nor_quad_enable() - enable Quad I/O if needed. + * spi_nor_quad_enable() - enable/disable Quad I/O if needed. * @nor: pointer to a 'struct spi_nor' + * @enable: true to enable Quad mode. false to disable Quad mode. * * Return: 0 on success, -errno otherwise. */ -static int spi_nor_quad_enable(struct spi_nor *nor) +static int spi_nor_quad_enable(struct spi_nor *nor, bool enable) { if (!nor->params->quad_enable) return 0; @@ -2912,7 +2929,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor) spi_nor_get_protocol_width(nor->write_proto) == 4)) return 0; - return nor->params->quad_enable(nor); + return nor->params->quad_enable(nor, enable); } /** @@ -2936,7 +2953,7 @@ static int spi_nor_init(struct spi_nor *nor) { int err; - err = spi_nor_quad_enable(nor); + err = spi_nor_quad_enable(nor, true); if (err) { dev_dbg(nor->dev, "quad mode not supported\n"); return err; @@ -2983,6 +3000,8 @@ void spi_nor_restore(struct spi_nor *nor) if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) && nor->flags & SNOR_F_BROKEN_RESET) nor->params->set_4byte_addr_mode(nor, false); + + spi_nor_quad_enable(nor, false); } EXPORT_SYMBOL_GPL(spi_nor_restore); |