[PATCH v7 1/3] mtd: spi-nor: spansion: Add support for Read/Write Any Register

Takahiro Kuwano tkuw584924 at gmail.com
Tue Feb 1 23:39:23 PST 2022


Hi Tudor,

Thank you for your suggestions.
I will revise the series

Best Regards,
Takahiro

On 2/1/2022 4:40 PM, Tudor.Ambarus at microchip.com wrote:
> On 2/1/22 09:37, Tudor Ambarus - M18064 wrote:
>> On 1/31/22 13:10, Takahiro Kuwano wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> On 1/31/2022 4:50 PM, Tudor.Ambarus at microchip.com wrote:
>>>> On 1/28/22 18:20, Pratyush Yadav wrote:
>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>
>>>>> On 28/01/22 09:43AM, Tudor.Ambarus at microchip.com wrote:
>>>>>> On 7/19/21 11:03, tkuw584924 at gmail.com wrote:
>>>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>>>
>>>>>>> From: Takahiro Kuwano <Takahiro.Kuwano at infineon.com>
>>>>>>>
>>>>>>> Some of Spansion/Cypress chips support Read/Write Any Register commands.
>>>>>>> These commands are mainly used to write volatile registers.
>>>>>>>
>>>>>>> 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 at infineon.com>
>>>>>>> ---
>>>>>>> Changes in v7:
>>>>>>>   - No change
>>>>>>>
>>>>>>> Changes in v6:
>>>>>>>   - Add helper functions for controller_ops
>>>>>>>   - Add 'reg_addr_width' parameter to spansion_read/write_any_reg()
>>>>>>>   - Remove spi_nor_write_enable() from spansion_write_any_reg() and modified
>>>>>>>     function header comment
>>>>>>>
>>>>>>> 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 | 142 +++++++++++++++++++++++++++++++++
>>>>>>>  1 file changed, 142 insertions(+)
>>>>>>>
>>>>>>> +/**
>>>>>>> + * spansion_read_any_reg() - Read Any Register.
>>>>>>> + * @nor:               pointer to a 'struct spi_nor'
>>>>>>> + * @reg_addr:          register address
>>>>>>> + * @reg_addr_width:    number of address bytes
>>>>>>> + * @reg_dummy:         number of dummy cycles for register read
>>>>>>> + * @reg_val:           pointer to a buffer where the register value is copied
>>>>>>> + *
>>>>>>> + * Return: 0 on success, -errno otherwise.
>>>>>>> + */
>>>>>>> +static int spansion_read_any_reg(struct spi_nor *nor, u32 reg_addr,
>>>>>>> +                                u8 reg_addr_width, u8 reg_dummy, u8 *reg_val)
>>>>>>
>>>>>> how about making this a generic core method? I'm sure there are other SPI NOR
>>>>>> vendors that use registers indexed by address. How about introducing:
>>>>>>
>>>>>> struct spi_nor_reg {
>>>>>>       u32 addr;
>>>>>>       u8 addr_width;
>>>>>>       u8 dummy;
>>>>>>       u8 opcode;
>>>>>>       u8 val;
>>>>>> };
>>>>>>
>>>>>> and passing a pointer to this struct as argument.
>>>>>
>>>>> Wouldn't it be simpler if they fill it in a struct spi_mem_op, and then
>>>>> just pass that in as a "template"?
>>>>>
>>>> sure, sounds fine. I would like a generic method with less function parameters,
>>>> if possible. Let's see what Takahiro will propose.
>>>
>>> So, I would propose...
>>> In core, spi_nor_spimem_{read,write}_reg(struct spi_nor *, struct spi_mem_op *)
>>> that calls spi_nor_spimem_setup() and spi_mem_exec_op().
>>> In vendor specific, spi_mem_op is filled and passed to the core method.
>>>
>>
>> how about the following?
>>
>> static ssize_t spi_nor_spimem_read_reg(struct spi_nor *nor, struct spi_mem_op *op)                    
>> {                                                                                  
>>         bool usebouncebuf;                                                      
>>         ssize_t nbytes;                                                         
>>         int error;      
> s/error/ret
>                                                         
>>                                                                                 
>>         spi_nor_spimem_setup_op(nor, &op, nor->read_proto);
> s/&op/op
>                     
>>                                                                                 
>>         /* convert the dummy cycles to the number of bytes */                   
>>         op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;   
> 
> op->dummy.nbytes and op->dummy.buswidth
>          
>>         if (spi_nor_protocol_is_dtr(nor->read_proto))                           
>>                 op.dummy.nbytes *= 2;   
> op->dummy.nbytes
>                                         
>>                                                                                 
>>         usebouncebuf = spi_nor_spimem_bounce(nor, &op); 
> s/&op/op
>                         
>>                                                                                                                                           
>>         ret = spi_nor_spimem_exec_op(nor, &op);    
> s/&op/op
>                    
>>         if (ret)                                                      
>>                return ret;                                           
>>         nbytes = op.data.nbytes;
> op->data.nbytes
>                                                                                                 
>>                                                                                
>>         if (usebouncebuf && nbytes > 0)                                         
>>                 memcpy(buf, op.data.buf.in, nbytes);    
> op->data.buf.in
>                         
>>                                                                                 
>>         return nbytes;                                                          
>> }  
>>
>> ssize_t spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op)
>> {                                                                               
>>         if (nor->spimem)                                                        
>>                 return spi_nor_spimem_read_reg(nor, from, len, buf);           
>>                                                                                 
>>         return -EOPNOTSUPP;                  
>> } 
> 



More information about the linux-mtd mailing list