diff mbox series

spi: Update speed/mode on change

Message ID 20210225205212.728105-1-marex@denx.de
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series spi: Update speed/mode on change | expand

Commit Message

Marek Vasut Feb. 25, 2021, 8:52 p.m. UTC
The spi_get_bus_and_cs() may be called on the same bus and chipselect
with different frequency or mode. This is valid usecase, but the code
fails to notify the controller of such a configuration change. Call
spi_set_speed_mode() in case bus frequency or bus mode changed to let
the controller update the configuration.

The problem can easily be triggered using the sspi command:
=> sspi 0:0@1000
=> sspi 0:0@2000
Without this patch, both transfers happen at 1000 Hz. With this patch,
the later transfer happens correctly at 2000 Hz.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Jagan Teki <jagan@amarulasolutions.com>
Cc: Patrick Delaunay <patrick.delaunay@st.com>
---
 drivers/spi/spi-uclass.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Patrick Delaunay Feb. 26, 2021, 1:07 p.m. UTC | #1
Hi Marek,

On 2/25/21 9:52 PM, Marek Vasut wrote:
> The spi_get_bus_and_cs() may be called on the same bus and chipselect
> with different frequency or mode. This is valid usecase, but the code
> fails to notify the controller of such a configuration change. Call
> spi_set_speed_mode() in case bus frequency or bus mode changed to let
> the controller update the configuration.
>
> The problem can easily be triggered using the sspi command:
> => sspi 0:0@1000
> => sspi 0:0@2000
> Without this patch, both transfers happen at 1000 Hz. With this patch,
> the later transfer happens correctly at 2000 Hz.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Jagan Teki <jagan@amarulasolutions.com>
> Cc: Patrick Delaunay <patrick.delaunay@st.com>
> ---
>   drivers/spi/spi-uclass.c | 10 ++++++++++
>   1 file changed, 10 insertions(+)
>
> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> index 7155d4aebd6..96c9a83e761 100644
> --- a/drivers/spi/spi-uclass.c
> +++ b/drivers/spi/spi-uclass.c
> @@ -405,12 +405,22 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
>   			goto err;
>   	}
>   
> +	/* In case bus frequency or mode changed, update it. */
> +	if ((speed && slave->speed && slave->speed != speed) ||
> +	    (plat->mode != mode)) {
> +		ret = spi_set_speed_mode(bus, speed, mode);
> +		if (ret)
> +			goto err_speed_mode;
> +	}
> +

We compare bus (with lastest configured value ) or slave (value 
requested) here ?

in dm_spi_claim_bus() it is compared with bus :

spi->speed and spi->mode and spi = dev_get_uclass_priv(bus);

+	/* In case bus frequency or mode changed, update it. */
+	if ((speed && bus->speed != speed) || (bus->mode != mode)) {
+		ret = spi_set_speed_mode(bus, speed, mode);
+		if (ret)
+			goto err_speed_mode;
+		bus->speed = speed;
+		bus->mode = mode;
+	}

NB: bus->speed can't be 0 here after previous spi_claim_bus()

PS: the update of spi->speed and spi->mode can be done in 
spi_set_speed_mode() function


>   	*busp = bus;
>   	*devp = slave;
>   	log_debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp);
>   
>   	return 0;
>   
> +err_speed_mode:
> +	spi_claim_bus(slave);


here I think it is:

spi_release_bus(slave);

called after previous spi_claim_bus().

>   err:
>   	log_debug("%s: Error path, created=%d, device '%s'\n", __func__,
>   		  created, dev->name);

Regards

Patrick
Marek Vasut Feb. 26, 2021, 1:52 p.m. UTC | #2
On 2/26/21 2:07 PM, Patrick DELAUNAY wrote:
> Hi Marek,
> 
> On 2/25/21 9:52 PM, Marek Vasut wrote:
>> The spi_get_bus_and_cs() may be called on the same bus and chipselect
>> with different frequency or mode. This is valid usecase, but the code
>> fails to notify the controller of such a configuration change. Call
>> spi_set_speed_mode() in case bus frequency or bus mode changed to let
>> the controller update the configuration.
>>
>> The problem can easily be triggered using the sspi command:
>> => sspi 0:0@1000
>> => sspi 0:0@2000
>> Without this patch, both transfers happen at 1000 Hz. With this patch,
>> the later transfer happens correctly at 2000 Hz.
>>
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> Cc: Jagan Teki <jagan@amarulasolutions.com>
>> Cc: Patrick Delaunay <patrick.delaunay@st.com>
>> ---
>>   drivers/spi/spi-uclass.c | 10 ++++++++++
>>   1 file changed, 10 insertions(+)
>>
>> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
>> index 7155d4aebd6..96c9a83e761 100644
>> --- a/drivers/spi/spi-uclass.c
>> +++ b/drivers/spi/spi-uclass.c
>> @@ -405,12 +405,22 @@ int spi_get_bus_and_cs(int busnum, int cs, int 
>> speed, int mode,
>>               goto err;
>>       }
>> +    /* In case bus frequency or mode changed, update it. */
>> +    if ((speed && slave->speed && slave->speed != speed) ||
>> +        (plat->mode != mode)) {
>> +        ret = spi_set_speed_mode(bus, speed, mode);
>> +        if (ret)
>> +            goto err_speed_mode;
>> +    }
>> +
> 
> We compare bus (with lastest configured value ) or slave (value 
> requested) here ?

Argh, this should in fact be bus_data->speed , it seems I sent 
un-rebased patches.

> in dm_spi_claim_bus() it is compared with bus :
> 
> spi->speed and spi->mode and spi = dev_get_uclass_priv(bus);
> 
> +    /* In case bus frequency or mode changed, update it. */
> +    if ((speed && bus->speed != speed) || (bus->mode != mode)) {
> +        ret = spi_set_speed_mode(bus, speed, mode);
> +        if (ret)
> +            goto err_speed_mode;
> +        bus->speed = speed;
> +        bus->mode = mode;
> +    }
> 
> NB: bus->speed can't be 0 here after previous spi_claim_bus()
> 
> PS: the update of spi->speed and spi->mode can be done in 
> spi_set_speed_mode() function

I don't think you want to do this every time you call dm_spi_claim_bus()

>>       *busp = bus;
>>       *devp = slave;
>>       log_debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp);
>>       return 0;
>> +err_speed_mode:
>> +    spi_claim_bus(slave);
> 
> 
> here I think it is:
> 
> spi_release_bus(slave);
> 
> called after previous spi_claim_bus().

Right
diff mbox series

Patch

diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 7155d4aebd6..96c9a83e761 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -405,12 +405,22 @@  int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 			goto err;
 	}
 
+	/* In case bus frequency or mode changed, update it. */
+	if ((speed && slave->speed && slave->speed != speed) ||
+	    (plat->mode != mode)) {
+		ret = spi_set_speed_mode(bus, speed, mode);
+		if (ret)
+			goto err_speed_mode;
+	}
+
 	*busp = bus;
 	*devp = slave;
 	log_debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp);
 
 	return 0;
 
+err_speed_mode:
+	spi_claim_bus(slave);
 err:
 	log_debug("%s: Error path, created=%d, device '%s'\n", __func__,
 		  created, dev->name);