From: Takahiro Kuwano <tkuw584924@gmail.com>
To: Vignesh Raghavendra <vigneshr@ti.com>, linux-mtd@lists.infradead.org
Cc: tudor.ambarus@microchip.com, miquel.raynal@bootlin.com,
richard@nod.at, p.yadav@ti.com, Bacem.Daassi@infineon.com,
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Subject: Re: [PATCH v5 3/6] mtd: spi-nor: spansion: Add support for Read/Write Any Register
Date: Tue, 1 Jun 2021 16:53:44 +0900 [thread overview]
Message-ID: <e65ca95f-0f10-eef3-2f08-07a09ac080e4@gmail.com> (raw)
In-Reply-To: <a5736c3f-d49e-2130-44e5-7dd8b4db21f4@ti.com>
Hi Vignesh,
On 5/27/2021 8:06 PM, Vignesh Raghavendra wrote:
> Hi,
>
> On 4/27/21 12:38 PM, tkuw584924@gmail.com wrote:
>> From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>
>> Some of Spansion/Cypress chips support Read/Write Any Register commands.
>> These commands are mainly used to write volatile registers and access to
>> the registers in second and subsequent die for multi-die package parts.
>>
>> The Read Any Register instruction (65h) is followed by register address
>> and dummy cycles, then the selected register byte is returned.
>>
>> The Write Any Register instruction (71h) is followed by register address
>> and register byte to write.
>>
>> Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>> ---
>> Changes in v5:
>> - Fix 'if (ret == 1)' to 'if (ret < 0)' in spansion_read_any_reg()
>>
>> Changes in v4:
>> - Fix dummy cycle calculation in spansion_read_any_reg()
>> - Modify comment for spansion_write_any_reg()
>>
>> Changes in v3:
>> - Cleanup implementation
>>
>> drivers/mtd/spi-nor/spansion.c | 106 +++++++++++++++++++++++++++++++++
>> 1 file changed, 106 insertions(+)
>>
>> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
>> index b0c5521c1e27..436db8933dcf 100644
>> --- a/drivers/mtd/spi-nor/spansion.c
>> +++ b/drivers/mtd/spi-nor/spansion.c
>> @@ -19,6 +19,112 @@
>> #define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS 0
>> #define SPINOR_OP_CYPRESS_RD_FAST 0xee
>>
>> +/**
>> + * spansion_read_any_reg() - Read Any Register.
>> + * @nor: pointer to a 'struct spi_nor'
>> + * @reg_addr: register address
>> + * @reg_dummy: number of dummy cycles for register read
>> + * @reg_val: pointer to a buffer where the register value is copied into
>> + *
>> + * Return: 0 on success, -errno otherwise.
>> + */
>> +static int spansion_read_any_reg(struct spi_nor *nor, u32 reg_addr,
>> + u8 reg_dummy, u8 *reg_val)
>> +{
>> + ssize_t ret;
>> +
>> + if (nor->spimem) {
>> + struct spi_mem_op op =
>> + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0),
>> + SPI_MEM_OP_ADDR(nor->addr_width, reg_addr, 0),
>> + SPI_MEM_OP_DUMMY(reg_dummy, 0),
>> + SPI_MEM_OP_DATA_IN(1, reg_val, 0));
>
> This isn't compatible with DDR mode. We should able to use
> spansion_read_any_reg() helper in place of some of the open coding being
> done today in spi_nor_cypress_octal_dtr_enable(). Same applies for
> spansion_write_any_reg().
>
I don't see why this isn't compatible with DDR mode.
The spi_nor_spimem_setup_op() and dummy adjustment take care of DDR.
To use this helper in spi_nor_cypress_octal_dtr_enable(), addr_width needs
to be passed by parameter instead of using 'nor->addr_width'. Please let
me know if any other changes are required.
>> +
>> + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
>> +
>
>
>> + op.dummy.nbytes = (reg_dummy * op.dummy.buswidth) / 8;
>> + if (spi_nor_protocol_is_dtr(nor->reg_proto))
>> + op.dummy.nbytes *= 2;
>
> spi_nor_spimem_setup_op() should care of above right?
>
This is same as spi_nor_spimem_read_data() in core.c. We need to convert
the dummy 'cycles' to the dummy 'bytes' after spi_nor_spimem_setup_op().
I will add a comment about it.
>> +
>> + ret = spi_mem_exec_op(nor->spimem, &op);
>
> return spi_mem_exec_op(nor->spimem, &op);
>
> Thus avoid extra level indentation below.
>
>> + } else {
>> + enum spi_nor_protocol proto = nor->read_proto;
>> + u8 opcode = nor->read_opcode;
>> + u8 dummy = nor->read_dummy;
>> +
>> + nor->read_opcode = SPINOR_OP_RD_ANY_REG;
>> + nor->read_dummy = reg_dummy;
>> + nor->read_proto = nor->reg_proto;
>> +
>> + ret = nor->controller_ops->read(nor, reg_addr, 1, reg_val);
>> +
>> + nor->read_opcode = opcode;
>> + nor->read_dummy = dummy;
>> + nor->read_proto = proto;
>> +
>> + if (ret < 0)
>> + return ret;
>> + if (ret != 1)
>> + return -EIO;
>> +
>
>
>> + ret = 0;
>
> return 0;
>
For better readability, how about adding a helper of controller ops?
if (nor->spimem) {
[...]
return spi_mem_exec_op(nor->spimem, &op);
}
return spansion_controller_ops_read_any_reg(nor, reg_addr, reg_dummy, reg_val);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +/**
>> + * spansion_write_any_reg() - Write Any Register.
>> + * @nor: pointer to a 'struct spi_nor'
>> + * @reg_addr: register address (should be a volatile register)
>
>
> To be safe, lets explicitly reject writes to non-volatile register
> addresses.
>
OK.
>> + * @reg_val: register value to be written
>> + *
>> + * Volatile register write will be effective immediately after the operation so
>> + * this function does not poll the status.
>> + *
>> + * Return: 0 on success, -errno otherwise.
>> + */
>> +static int spansion_write_any_reg(struct spi_nor *nor, u32 reg_addr, u8 reg_val)
>> +{
>> + ssize_t ret;
>> +
>> + ret = spi_nor_write_enable(nor);
>> + if (ret)
>> + return ret;
>
>
> Hmm, I don't see spi_nor_write_disable().
>
> Either both spi_nor_write_enable() and spi_nor_write_disable() should be
> responsibility of caller or both needs to be taken care of here.
>
> And the same needs to be documented in the function description
>
OK. I will call both from outside.
>> +
>> + if (nor->spimem) {
>> + struct spi_mem_op op =
>> + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0),
>> + SPI_MEM_OP_ADDR(nor->addr_width, reg_addr, 0),
>> + SPI_MEM_OP_NO_DUMMY,
>> + SPI_MEM_OP_DATA_OUT(1, ®_val, 0));
>> +
>> + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
>> +
>> + ret = spi_mem_exec_op(nor->spimem, &op);
>> + } else {
>> + enum spi_nor_protocol proto = nor->write_proto;
>> + u8 opcode = nor->program_opcode;
>> +
>> + nor->program_opcode = SPINOR_OP_WR_ANY_REG;
>> + nor->write_proto = nor->reg_proto;
>> +
>> + ret = nor->controller_ops->write(nor, reg_addr, 1, ®_val);
>> +
>> + nor->program_opcode = opcode;
>> + nor->write_proto = proto;
>> +
>> + if (ret < 0)
>> + return ret;
>> + if (ret != 1)
>> + return -EIO;
>> +
>> + ret = 0;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> /**
>> * spi_nor_cypress_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
>> * @nor: pointer to a 'struct spi_nor'
>>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2021-06-01 7:54 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-27 7:08 [PATCH v5 0/6] mtd: spi-nor: Add support for Cypress s25hl-t/s25hs-t tkuw584924
2021-04-27 7:08 ` [PATCH v5 1/6] mtd: spi-nor: core: Add the ->ready() hook tkuw584924
2021-04-27 7:08 ` [PATCH v5 2/6] mtd: spi-nor: core: Expose spi_nor_clear_sr() to manufacturer drivers tkuw584924
2021-04-27 7:08 ` [PATCH v5 3/6] mtd: spi-nor: spansion: Add support for Read/Write Any Register tkuw584924
2021-05-27 11:06 ` Vignesh Raghavendra
2021-06-01 7:53 ` Takahiro Kuwano [this message]
2021-04-27 7:08 ` [PATCH v5 4/6] mtd: spi-nor: spansion: Add support for volatile QE bit tkuw584924
2021-04-27 7:09 ` [PATCH v5 5/6] mtd: spi-nor: spansion: Add status check for multi-die parts tkuw584924
2021-04-27 7:09 ` [PATCH v5 6/6] mtd: spi-nor: spansion: Add s25hl-t/s25hs-t IDs and fixups tkuw584924
2021-05-27 13:20 ` Vignesh Raghavendra
2021-06-01 8:09 ` Takahiro Kuwano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e65ca95f-0f10-eef3-2f08-07a09ac080e4@gmail.com \
--to=tkuw584924@gmail.com \
--cc=Bacem.Daassi@infineon.com \
--cc=Takahiro.Kuwano@infineon.com \
--cc=linux-mtd@lists.infradead.org \
--cc=miquel.raynal@bootlin.com \
--cc=p.yadav@ti.com \
--cc=richard@nod.at \
--cc=tudor.ambarus@microchip.com \
--cc=vigneshr@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.