Message ID | 1612517808-10010-1-git-send-email-zhengxunli@mxic.com.tw |
---|---|
Headers | show |
Series | Add octal DTR support for Macronix flash | expand |
Hello, zhengxunli <zhengxunli@mxic.com.tw> wrote on Fri, 5 Feb 2021 17:36:47 +0800: > The ocatflash is an xSPI compliant octal DTR flash. Add support > for using it in octal DTR mode. > > Enable Octal DTR mode with 20 dummy cycles to allow running at the > maximum supported frequency of 200Mhz. > > Try to verify the flash ID to check whether the flash memory in octal > DTR mode is correct. When reading ID in OCTAL DTR mode, ID will appear > in a repeated manner. ex: ID[0] = 0xc2, ID[1] = 0xc2, ID[2] = 0x94, > ID[3] = 0x94... Rearrange the order so that the ID can pass. > > Signed-off-by: zhengxunli <zhengxunli@mxic.com.tw> > --- > drivers/mtd/spi-nor/macronix.c | 121 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 121 insertions(+) > > diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c > index 9203aba..7498978 100644 > --- a/drivers/mtd/spi-nor/macronix.c > +++ b/drivers/mtd/spi-nor/macronix.c > @@ -8,6 +8,16 @@ > > #include "core.h" > > +#define SPINOR_OP_RD_CR2 0x71 /* Read configuration register 2 */ > +#define SPINOR_OP_WR_CR2 0x72 /* Write configuration register 2 */ > +#define SPINOR_OP_MXIC_DTR_RD 0xee /* Fast Read opcode in DTR mode */ > +#define SPINOR_REG_MXIC_CR2_MODE 0x00000000 /* For setting octal DTR mode */ > +#define SPINOR_REG_MXIC_OPI_DTR_EN 0x2 /* Enable Octal DTR */ > +#define SPINOR_REG_MXIC_OPI_DTR_DIS 0x1 /* Disable Octal DTR */ > +#define SPINOR_REG_MXIC_CR2_DC 0x00000300 /* For setting dummy cycles */ > +#define SPINOR_REG_MXIC_DC_20 0x0 /* Setting dummy cycles to 20 */ > +#define MXIC_MAX_DC 20 /* Maximum value of dummy cycles */ > + > static int > mx25l25635_post_bfpt_fixups(struct spi_nor *nor, > const struct sfdp_parameter_header *bfpt_header, > @@ -33,6 +43,113 @@ > .post_bfpt = mx25l25635_post_bfpt_fixups, > }; > > +/** > + * spi_nor_macronix_octal_dtr_enable() - Enable octal DTR on Macronix flashes. > + * @nor: pointer to a 'struct spi_nor' > + * @enable: whether to enable or disable Octal DTR > + * > + * This also sets the memory access dummy cycles to 20 to allow the flash to > + * run at up to 200MHz. > + * > + * Return: 0 on success, -errno otherwise. > + */ > +static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor, bool enable) > +{ > + struct spi_mem_op op; > + u8 *buf = nor->bouncebuf, i; > + int ret; > + > + if (enable) { > + /* Use 20 dummy cycles for memory array reads. */ > + ret = spi_nor_write_enable(nor); > + if (ret) > + return ret; > + > + *buf = SPINOR_REG_MXIC_DC_20; > + op = (struct spi_mem_op) > + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1), > + SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_DC, 1), > + SPI_MEM_OP_NO_DUMMY, > + SPI_MEM_OP_DATA_OUT(1, buf, 1)); > + > + ret = spi_mem_exec_op(nor->spimem, &op); > + if (ret) > + return ret; > + > + ret = spi_nor_wait_till_ready(nor); > + if (ret) > + return ret; > + > + nor->read_dummy = MXIC_MAX_DC; I am still not convinced by this constant value. The rest looks good to me. Thanks, Miquèl
On 05/02/21 10:47AM, Miquel Raynal wrote: > Hello, > > zhengxunli <zhengxunli@mxic.com.tw> wrote on Fri, 5 Feb 2021 17:36:47 > +0800: > > > The ocatflash is an xSPI compliant octal DTR flash. Add support > > for using it in octal DTR mode. > > > > Enable Octal DTR mode with 20 dummy cycles to allow running at the > > maximum supported frequency of 200Mhz. > > > > Try to verify the flash ID to check whether the flash memory in octal > > DTR mode is correct. When reading ID in OCTAL DTR mode, ID will appear > > in a repeated manner. ex: ID[0] = 0xc2, ID[1] = 0xc2, ID[2] = 0x94, > > ID[3] = 0x94... Rearrange the order so that the ID can pass. > > > > Signed-off-by: zhengxunli <zhengxunli@mxic.com.tw> > > --- > > drivers/mtd/spi-nor/macronix.c | 121 +++++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 121 insertions(+) > > > > diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c > > index 9203aba..7498978 100644 > > --- a/drivers/mtd/spi-nor/macronix.c > > +++ b/drivers/mtd/spi-nor/macronix.c > > @@ -8,6 +8,16 @@ > > > > #include "core.h" > > > > +#define SPINOR_OP_RD_CR2 0x71 /* Read configuration register 2 */ > > +#define SPINOR_OP_WR_CR2 0x72 /* Write configuration register 2 */ > > +#define SPINOR_OP_MXIC_DTR_RD 0xee /* Fast Read opcode in DTR mode */ > > +#define SPINOR_REG_MXIC_CR2_MODE 0x00000000 /* For setting octal DTR mode */ > > +#define SPINOR_REG_MXIC_OPI_DTR_EN 0x2 /* Enable Octal DTR */ > > +#define SPINOR_REG_MXIC_OPI_DTR_DIS 0x1 /* Disable Octal DTR */ > > +#define SPINOR_REG_MXIC_CR2_DC 0x00000300 /* For setting dummy cycles */ > > +#define SPINOR_REG_MXIC_DC_20 0x0 /* Setting dummy cycles to 20 */ > > +#define MXIC_MAX_DC 20 /* Maximum value of dummy cycles */ > > + > > static int > > mx25l25635_post_bfpt_fixups(struct spi_nor *nor, > > const struct sfdp_parameter_header *bfpt_header, > > @@ -33,6 +43,113 @@ > > .post_bfpt = mx25l25635_post_bfpt_fixups, > > }; > > > > +/** > > + * spi_nor_macronix_octal_dtr_enable() - Enable octal DTR on Macronix flashes. > > + * @nor: pointer to a 'struct spi_nor' > > + * @enable: whether to enable or disable Octal DTR > > + * > > + * This also sets the memory access dummy cycles to 20 to allow the flash to > > + * run at up to 200MHz. > > + * > > + * Return: 0 on success, -errno otherwise. > > + */ > > +static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor, bool enable) > > +{ > > + struct spi_mem_op op; > > + u8 *buf = nor->bouncebuf, i; > > + int ret; > > + > > + if (enable) { > > + /* Use 20 dummy cycles for memory array reads. */ > > + ret = spi_nor_write_enable(nor); > > + if (ret) > > + return ret; > > + > > + *buf = SPINOR_REG_MXIC_DC_20; > > + op = (struct spi_mem_op) > > + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1), > > + SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_DC, 1), > > + SPI_MEM_OP_NO_DUMMY, > > + SPI_MEM_OP_DATA_OUT(1, buf, 1)); > > + > > + ret = spi_mem_exec_op(nor->spimem, &op); > > + if (ret) > > + return ret; > > + > > + ret = spi_nor_wait_till_ready(nor); > > + if (ret) > > + return ret; > > + > > + nor->read_dummy = MXIC_MAX_DC; > > I am still not convinced by this constant value. I think a constant value is fine. This dummy cycle value reflects how many cycles the master clock would go through before the flash starts emitting the data. If the master (aka the controller) is running at a lower frequency then those cycles go through slower, but the flash still waits for them to finish before emitting data. And since the master is driving the clock and the flash is just "reading" it, both remain in sync. The dummy cycles need to be set for the worst case scenario [0]. The flash usually needs a minimum amount of time before it is ready to emit the data. So for example if the master is at 25 MHz, the clock period is longer so 8 clock cycles [1] might be long enough to exceed that minimum time. But when the master is running at 200 MHz, the clock period is smaller so 8 cycles might not give the flash enough time to prepare. So we need to to wait at least 20 cycles [1] before emitting data. This is what my patches do for the Cypress S28 flash. I have tested it on both 25 MHz and 166 MHz with 22 dummy cycles. It is not the most efficient at 25 MHz since 5 dummy cycles is all that is needed for that speed, but its the best we can do right now. [0] Since SPI NOR has no way of knowing what speed the controller is running at, assume the fastest speed the flash can run at. [1] Hypothetical example. Don't know the actual values for this flash. > The rest looks good to me.
Hi Pratyush, Pratyush Yadav <p.yadav@ti.com> wrote on Fri, 5 Feb 2021 19:04:04 +0530: > On 05/02/21 10:47AM, Miquel Raynal wrote: > > Hello, > > > > zhengxunli <zhengxunli@mxic.com.tw> wrote on Fri, 5 Feb 2021 17:36:47 > > +0800: > > > > > The ocatflash is an xSPI compliant octal DTR flash. Add support > > > for using it in octal DTR mode. > > > > > > Enable Octal DTR mode with 20 dummy cycles to allow running at the > > > maximum supported frequency of 200Mhz. > > > > > > Try to verify the flash ID to check whether the flash memory in octal > > > DTR mode is correct. When reading ID in OCTAL DTR mode, ID will appear > > > in a repeated manner. ex: ID[0] = 0xc2, ID[1] = 0xc2, ID[2] = 0x94, > > > ID[3] = 0x94... Rearrange the order so that the ID can pass. > > > > > > Signed-off-by: zhengxunli <zhengxunli@mxic.com.tw> > > > --- > > > drivers/mtd/spi-nor/macronix.c | 121 +++++++++++++++++++++++++++++++++++++++++ > > > 1 file changed, 121 insertions(+) > > > > > > diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c > > > index 9203aba..7498978 100644 > > > --- a/drivers/mtd/spi-nor/macronix.c > > > +++ b/drivers/mtd/spi-nor/macronix.c > > > @@ -8,6 +8,16 @@ > > > > > > #include "core.h" > > > > > > +#define SPINOR_OP_RD_CR2 0x71 /* Read configuration register 2 */ > > > +#define SPINOR_OP_WR_CR2 0x72 /* Write configuration register 2 */ > > > +#define SPINOR_OP_MXIC_DTR_RD 0xee /* Fast Read opcode in DTR mode */ > > > +#define SPINOR_REG_MXIC_CR2_MODE 0x00000000 /* For setting octal DTR mode */ > > > +#define SPINOR_REG_MXIC_OPI_DTR_EN 0x2 /* Enable Octal DTR */ > > > +#define SPINOR_REG_MXIC_OPI_DTR_DIS 0x1 /* Disable Octal DTR */ > > > +#define SPINOR_REG_MXIC_CR2_DC 0x00000300 /* For setting dummy cycles */ > > > +#define SPINOR_REG_MXIC_DC_20 0x0 /* Setting dummy cycles to 20 */ > > > +#define MXIC_MAX_DC 20 /* Maximum value of dummy cycles */ > > > + > > > static int > > > mx25l25635_post_bfpt_fixups(struct spi_nor *nor, > > > const struct sfdp_parameter_header *bfpt_header, > > > @@ -33,6 +43,113 @@ > > > .post_bfpt = mx25l25635_post_bfpt_fixups, > > > }; > > > > > > +/** > > > + * spi_nor_macronix_octal_dtr_enable() - Enable octal DTR on Macronix flashes. > > > + * @nor: pointer to a 'struct spi_nor' > > > + * @enable: whether to enable or disable Octal DTR > > > + * > > > + * This also sets the memory access dummy cycles to 20 to allow the flash to > > > + * run at up to 200MHz. > > > + * > > > + * Return: 0 on success, -errno otherwise. > > > + */ > > > +static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor, bool enable) > > > +{ > > > + struct spi_mem_op op; > > > + u8 *buf = nor->bouncebuf, i; > > > + int ret; > > > + > > > + if (enable) { > > > + /* Use 20 dummy cycles for memory array reads. */ > > > + ret = spi_nor_write_enable(nor); > > > + if (ret) > > > + return ret; > > > + > > > + *buf = SPINOR_REG_MXIC_DC_20; > > > + op = (struct spi_mem_op) > > > + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1), > > > + SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_DC, 1), > > > + SPI_MEM_OP_NO_DUMMY, > > > + SPI_MEM_OP_DATA_OUT(1, buf, 1)); > > > + > > > + ret = spi_mem_exec_op(nor->spimem, &op); > > > + if (ret) > > > + return ret; > > > + > > > + ret = spi_nor_wait_till_ready(nor); > > > + if (ret) > > > + return ret; > > > + > > > + nor->read_dummy = MXIC_MAX_DC; > > > > I am still not convinced by this constant value. > > I think a constant value is fine. This dummy cycle value reflects how > many cycles the master clock would go through before the flash starts > emitting the data. If the master (aka the controller) is running at a > lower frequency then those cycles go through slower, but the flash still > waits for them to finish before emitting data. And since the master is > driving the clock and the flash is just "reading" it, both remain in > sync. > > The dummy cycles need to be set for the worst case scenario [0]. The > flash usually needs a minimum amount of time before it is ready to emit > the data. So for example if the master is at 25 MHz, the clock period is > longer so 8 clock cycles [1] might be long enough to exceed that minimum > time. But when the master is running at 200 MHz, the clock period is > smaller so 8 cycles might not give the flash enough time to prepare. So > we need to to wait at least 20 cycles [1] before emitting data. > > This is what my patches do for the Cypress S28 flash. I have tested it > on both 25 MHz and 166 MHz with 22 dummy cycles. It is not the most > efficient at 25 MHz since 5 dummy cycles is all that is needed for that > speed, but its the best we can do right now. > > [0] Since SPI NOR has no way of knowing what speed the controller is > running at, assume the fastest speed the flash can run at. Ok, I am not entirely clear about what is available/not available from the SPI core. If this is true then I guess we can't do better with the current code base and this can be improved in the future if needed. So I'm fine with the current implementation. > [1] Hypothetical example. Don't know the actual values for this flash. > > > The rest looks good to me. > Thanks, Miquèl
On Tue, Feb 23, 2021 at 02:13:44PM +0100, Miquel Raynal wrote: > Pratyush Yadav <p.yadav@ti.com> wrote on Fri, 5 Feb 2021 19:04:04 +0530: > > [0] Since SPI NOR has no way of knowing what speed the controller is > > running at, assume the fastest speed the flash can run at. > Ok, I am not entirely clear about what is available/not available from > the SPI core. > If this is true then I guess we can't do better with the current code > base and this can be improved in the future if needed. So I'm fine with > the current implementation. For normal SPI operations you can set the speed (really, top speed) on a per transfer basis.
On 23/02/21 01:36PM, Mark Brown wrote: > On Tue, Feb 23, 2021 at 02:13:44PM +0100, Miquel Raynal wrote: > > Pratyush Yadav <p.yadav@ti.com> wrote on Fri, 5 Feb 2021 19:04:04 +0530: > > > > [0] Since SPI NOR has no way of knowing what speed the controller is > > > running at, assume the fastest speed the flash can run at. > > > Ok, I am not entirely clear about what is available/not available from > > the SPI core. > > > If this is true then I guess we can't do better with the current code > > base and this can be improved in the future if needed. So I'm fine with > > the current implementation. > > For normal SPI operations you can set the speed (really, top speed) on a > per transfer basis. To select the optimal number of dummy cycles we need to know what speed the controller is running at, not the other way around. The flash would always set the top speed to its maximum (say 200 MHz). But if the controller is only capable of running at 50 MHz, you will end up wasting dummy cycles. I don't see any API to communicate speed from controller to flash.
On Tue, Feb 23, 2021 at 07:07:37PM +0100, Geert Uytterhoeven wrote: > On Tue, Feb 23, 2021 at 4:25 PM Pratyush Yadav <p.yadav@ti.com> wrote: > > To select the optimal number of dummy cycles we need to know what speed > > the controller is running at, not the other way around. The flash would > > always set the top speed to its maximum (say 200 MHz). But if the > > controller is only capable of running at 50 MHz, you will end up wasting > > dummy cycles. I don't see any API to communicate speed from controller > > to flash. > spi_transfer.effective_speed_hz? > If the driver has filled this in (after the first transfer), you can optimize > dummy cycles before doing the next transfer. Note that effective_speed_hz > might not always be the same, if e.g. the SPI controller shares its parent > clock with another component. Yes, that's what that's for, or just go with the speed set by the client on the basis that it should be safe even if potentially wasteful. You'd need to fall back to that anyway in the cases where the controller doesn't or can't report the effective speed.
On 3/29/21 9:35 AM, zhengxunli@mxic.com.tw wrote: > Hi Tudor, Hi, > > We are discussing flash dummy cycle and SPI speed settings, but there > are no new comments. Can you help comment on this series and provide > some suggestions? Sure, I'll probably be able to look at this next week. Cheers, ta
On Fri, 5 Feb 2021 17:36:46 +0800, zhengxunli wrote: > This series adds support for Octal DTR for Macronix flashes. The > first set of patches is add Macronix octaflash series octal dtr > mode support. The second set of patches add the Octal DTR mode > support for host driver. > > Changes in v2: > - Define with a generic name to describe the maximum dummy cycles. > > [...] Applied to https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next Thanks! [2/2] spi: mxic: patch for octal DTR mode support commit: d05aaa66ba3ca3fdc2b5cd774ff218deb238b352 All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark