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

Tudor.Ambarus at microchip.com Tudor.Ambarus at microchip.com
Mon Jan 31 23:40:14 PST 2022


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