linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [cadence-spi] daisy chain
@ 2020-06-12 16:25 Adrian Fiergolski
  2020-06-13  7:33 ` Geert Uytterhoeven
  0 siblings, 1 reply; 13+ messages in thread
From: Adrian Fiergolski @ 2020-06-12 16:25 UTC (permalink / raw)
  To: linux-spi

Hi,

I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
connected to a single chip select of the cadence-spi master. I have the
impression such a configuration is supported by none of those two
drivers. I could try to extend both, however, I haven't found any other
SPI driver, where I could find implementation inspiration. Is it
supported by kernel?

The documentation mentions only about the common 'daisy-chained-devices'
property (devicetree/bindings/common-properties.txt). However, in order
to try to implement it in the master driver, IMHO, the spi subsystem
would need to have a call 'no-operation' to other nodes on the
daisy-chain, which are not addressed by the given SPI access. Is there
any recommended approach to address this case?

Regards,

Adrian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-12 16:25 [cadence-spi] daisy chain Adrian Fiergolski
@ 2020-06-13  7:33 ` Geert Uytterhoeven
  2020-06-15 13:01   ` Adrian Fiergolski
  0 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2020-06-13  7:33 UTC (permalink / raw)
  To: Adrian Fiergolski; +Cc: linux-spi, Lukas Wunner

Hi Adrian,

CC Lukas for #daisy-chained-devices

On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
<adrian.fiergolski@fastree3d.com> wrote:
> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
> connected to a single chip select of the cadence-spi master. I have the
> impression such a configuration is supported by none of those two
> drivers. I could try to extend both, however, I haven't found any other
> SPI driver, where I could find implementation inspiration. Is it
> supported by kernel?

drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
drivers/gpio/gpio-74x164.c supports multiple shift registers through the
"registers-number" DT property.

So both drivers handle this in their SPI slave drivers.

Of course this does not handle the mixed case, i.e. daisy-chaining
different types of devices.

> The documentation mentions only about the common 'daisy-chained-devices'
> property (devicetree/bindings/common-properties.txt). However, in order
> to try to implement it in the master driver, IMHO, the spi subsystem
> would need to have a call 'no-operation' to other nodes on the
> daisy-chain, which are not addressed by the given SPI access. Is there
> any recommended approach to address this case?

Supporting this in a generic way would indeed be nice, as it would mean
individual SPI slave drivers no longer have to care about it.
However, that may be difficult, as the master needs to known which
dummy (no-op) data is safe to shift through the non-addresses SPI slaves.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-13  7:33 ` Geert Uytterhoeven
@ 2020-06-15 13:01   ` Adrian Fiergolski
  2020-06-15 13:07     ` Geert Uytterhoeven
  0 siblings, 1 reply; 13+ messages in thread
From: Adrian Fiergolski @ 2020-06-15 13:01 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: linux-spi, Lukas Wunner

Hi Geert,

Thank you for the update.

In fact, the ultimate solution would be to have it solved at the level
of the spi subsystem:

  * /spi_device struct/ would contain extra callback which returns msg
    to be sent for no operation.
  * spi_device struct would contain a pointer to the list describing the
    given daisy chain (list of spi_devices on the chain)
  * /spi_device struct /would contain extra u8 daisy_chain_msg_length
    indicating length of a command of the addressed device if it's on
    the daisy chain
    For example, in case of the ltc2634 device, the regular message
    consists of 24 bits, but when device is a part of a daisy chain, the
    messages are 32 bits. This 32 would be stored in
    /daisy_chain_msg_length./
  * When /spi_write/ was called (include/linux/spi/spi.h), the
    /spi_message_init_with_transfer/ would create a msg of length equal
    to a sum of /daisy_chain_msg_length/ of all devices on the chain.
    Afterwards, in /spi_message_init_with_transfers/, the actual message
    would be filled with the command of the addressed device on the
    chain and no_operation content for all other devices on the chain
    not being addressed
  * I think in such a case, the /daisy-chained-devices /property would
    be not used, as chains would be build basing on the assigned
    chipselect (reg property).

If you agree with the above description, I could try to implement it. Of
course any suggestion are welcome, however, I would like to have a
working solution until end of this week, so I would appreciate an active
feedback. As my SoC works with kernel v4.19, I would implement it for
it, test it, and move it afterwards to the master version (I hope, there
were no big changes in the SPI subsystem, right?).

Regards,

Adrian

On 13.06.2020 09:33, Geert Uytterhoeven wrote:
> Hi Adrian,
>
> CC Lukas for #daisy-chained-devices
>
> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
> <adrian.fiergolski@fastree3d.com> wrote:
>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
>> connected to a single chip select of the cadence-spi master. I have the
>> impression such a configuration is supported by none of those two
>> drivers. I could try to extend both, however, I haven't found any other
>> SPI driver, where I could find implementation inspiration. Is it
>> supported by kernel?
> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
> "registers-number" DT property.
>
> So both drivers handle this in their SPI slave drivers.
>
> Of course this does not handle the mixed case, i.e. daisy-chaining
> different types of devices.
>
>> The documentation mentions only about the common 'daisy-chained-devices'
>> property (devicetree/bindings/common-properties.txt). However, in order
>> to try to implement it in the master driver, IMHO, the spi subsystem
>> would need to have a call 'no-operation' to other nodes on the
>> daisy-chain, which are not addressed by the given SPI access. Is there
>> any recommended approach to address this case?
> Supporting this in a generic way would indeed be nice, as it would mean
> individual SPI slave drivers no longer have to care about it.
> However, that may be difficult, as the master needs to known which
> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>
> Gr{oetje,eeting}s,
>
>                         Geert
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 13:01   ` Adrian Fiergolski
@ 2020-06-15 13:07     ` Geert Uytterhoeven
  2020-06-15 13:57       ` Adrian Fiergolski
  0 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2020-06-15 13:07 UTC (permalink / raw)
  To: Adrian Fiergolski
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Adrian,

CC devicetree

On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
<adrian.fiergolski@fastree3d.com> wrote:
> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
> > On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
> > <adrian.fiergolski@fastree3d.com> wrote:
> > I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
> > connected to a single chip select of the cadence-spi master. I have the
> > impression such a configuration is supported by none of those two
> > drivers. I could try to extend both, however, I haven't found any other
> > SPI driver, where I could find implementation inspiration. Is it
> > supported by kernel?
> >
> > drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
> > drivers/gpio/gpio-74x164.c supports multiple shift registers through the
> > "registers-number" DT property.
> >
> > So both drivers handle this in their SPI slave drivers.
> >
> > Of course this does not handle the mixed case, i.e. daisy-chaining
> > different types of devices.
> >
> > The documentation mentions only about the common 'daisy-chained-devices'
> > property (devicetree/bindings/common-properties.txt). However, in order
> > to try to implement it in the master driver, IMHO, the spi subsystem
> > would need to have a call 'no-operation' to other nodes on the
> > daisy-chain, which are not addressed by the given SPI access. Is there
> > any recommended approach to address this case?
> >
> > Supporting this in a generic way would indeed be nice, as it would mean
> > individual SPI slave drivers no longer have to care about it.
> > However, that may be difficult, as the master needs to known which
> > dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>
> In fact, the ultimate solution would be to have it solved at the level
> of the spi subsystem:
>
>   * /spi_device struct/ would contain extra callback which returns msg
>     to be sent for no operation.
>   * spi_device struct would contain a pointer to the list describing the
>     given daisy chain (list of spi_devices on the chain)
>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
>     indicating length of a command of the addressed device if it's on
>     the daisy chain
>     For example, in case of the ltc2634 device, the regular message
>     consists of 24 bits, but when device is a part of a daisy chain, the
>     messages are 32 bits. This 32 would be stored in
>     /daisy_chain_msg_length./
>   * When /spi_write/ was called (include/linux/spi/spi.h), the
>     /spi_message_init_with_transfer/ would create a msg of length equal
>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
>     Afterwards, in /spi_message_init_with_transfers/, the actual message
>     would be filled with the command of the addressed device on the
>     chain and no_operation content for all other devices on the chain
>     not being addressed

Sounds good to me.

>   * I think in such a case, the /daisy-chained-devices /property would
>     be not used, as chains would be build basing on the assigned
>     chipselect (reg property).

So you still have to describe the chain in DT in some way.
As there can be only a single sub node with the same unit address
(= chip select), you probably need a container with that address, which
would contain all devices in the chain, in order (unit addresses 0, 1, ...).

> If you agree with the above description, I could try to implement it. Of
> course any suggestion are welcome, however, I would like to have a
> working solution until end of this week, so I would appreciate an active
> feedback. As my SoC works with kernel v4.19, I would implement it for
> it, test it, and move it afterwards to the master version (I hope, there
> were no big changes in the SPI subsystem, right?).

Having something that works by the end of the week sounds doable to.
Getting it in shape for upstreaming is a different thing...

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 13:07     ` Geert Uytterhoeven
@ 2020-06-15 13:57       ` Adrian Fiergolski
  2020-06-15 14:06         ` Adrian Fiergolski
  0 siblings, 1 reply; 13+ messages in thread
From: Adrian Fiergolski @ 2020-06-15 13:57 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Geert,

Thank you for the quick reply.

On 15.06.2020 15:07, Geert Uytterhoeven wrote:
> Hi Adrian,
>
> CC devicetree
>
> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
> <adrian.fiergolski@fastree3d.com> wrote:
>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
>>> <adrian.fiergolski@fastree3d.com> wrote:
>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
>>> connected to a single chip select of the cadence-spi master. I have the
>>> impression such a configuration is supported by none of those two
>>> drivers. I could try to extend both, however, I haven't found any other
>>> SPI driver, where I could find implementation inspiration. Is it
>>> supported by kernel?
>>>
>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
>>> "registers-number" DT property.
>>>
>>> So both drivers handle this in their SPI slave drivers.
>>>
>>> Of course this does not handle the mixed case, i.e. daisy-chaining
>>> different types of devices.
>>>
>>> The documentation mentions only about the common 'daisy-chained-devices'
>>> property (devicetree/bindings/common-properties.txt). However, in order
>>> to try to implement it in the master driver, IMHO, the spi subsystem
>>> would need to have a call 'no-operation' to other nodes on the
>>> daisy-chain, which are not addressed by the given SPI access. Is there
>>> any recommended approach to address this case?
>>>
>>> Supporting this in a generic way would indeed be nice, as it would mean
>>> individual SPI slave drivers no longer have to care about it.
>>> However, that may be difficult, as the master needs to known which
>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>> In fact, the ultimate solution would be to have it solved at the level
>> of the spi subsystem:
>>
>>   * /spi_device struct/ would contain extra callback which returns msg
>>     to be sent for no operation.
>>   * spi_device struct would contain a pointer to the list describing the
>>     given daisy chain (list of spi_devices on the chain)
>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
>>     indicating length of a command of the addressed device if it's on
>>     the daisy chain
>>     For example, in case of the ltc2634 device, the regular message
>>     consists of 24 bits, but when device is a part of a daisy chain, the
>>     messages are 32 bits. This 32 would be stored in
>>     /daisy_chain_msg_length./
>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
>>     /spi_message_init_with_transfer/ would create a msg of length equal
>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
>>     would be filled with the command of the addressed device on the
>>     chain and no_operation content for all other devices on the chain
>>     not being addressed
> Sounds good to me.
>
>>   * I think in such a case, the /daisy-chained-devices /property would
>>     be not used, as chains would be build basing on the assigned
>>     chipselect (reg property).
> So you still have to describe the chain in DT in some way.
> As there can be only a single sub node with the same unit address
> (= chip select), you probably need a container with that address, which
> would contain all devices in the chain, in order (unit addresses 0, 1, ...).

Good point. So maybe at the level of the device tree, it could be
described like that (based on the spi-cadence example):

        spi0: spi@ff040000 {
            compatible = "cdns,spi-r1p6";
            status = "disabled";
            interrupt-parent = <&gic>;
            interrupts = <0 19 4>;
            reg = <0x0 0xff040000 0x0 0x1000>;
            clock-names = "ref_clk", "pclk";
            #address-cells = <1>;
            #size-cells = <0>;
            power-domains = <&zynqmp_firmware PD_SPI_0>;
            daisy-chain0 : daisy_chain@0 {
               #address-cells = <1>;
               #size-cells = <0>;
               reg = <0>;
               daisy-chained-devices = 2;

               dac0: ltc2632@0 {
                   compatible = "lltc,ltc2634-l12";
                   reg = <0>;
                   spi-max-frequency = <1000000>;
               };
               dac1: ltc2632@1 {
                   compatible = "lltc,ltc2634-l12";
                   reg = <1>;
                   spi-max-frequency = <2000000>;
               };
           };
        };

Once a node has daisy-chanied-devices property defined,
of_register_spi_device (spi.c) will interpret it as a daisy chain. I
will assume, that for the given chain the lowest frequency of the whole
chain should be used. When it comes to the mode, as in case of
incompatibility no much can be done anyway, the mode of the addressed
spi device will be used.

>
>> If you agree with the above description, I could try to implement it. Of
>> course any suggestion are welcome, however, I would like to have a
>> working solution until end of this week, so I would appreciate an active
>> feedback. As my SoC works with kernel v4.19, I would implement it for
>> it, test it, and move it afterwards to the master version (I hope, there
>> were no big changes in the SPI subsystem, right?).
> Having something that works by the end of the week sounds doable to.
> Getting it in shape for upstreaming is a different thing...

Let's try then. As I wrote earlier, I will try to implement it and test
it with 4.19. Afterwards, I will share it with you for a general concept
review. Once no comments, I will try to move it to the master and we can
start from there the upstreaming process.

Regards,

Adrian



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 13:57       ` Adrian Fiergolski
@ 2020-06-15 14:06         ` Adrian Fiergolski
  2020-06-15 14:40           ` Geert Uytterhoeven
  0 siblings, 1 reply; 13+ messages in thread
From: Adrian Fiergolski @ 2020-06-15 14:06 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Sorry for the typo in the example device tree:

On 15.06.2020 15:57, Adrian Fiergolski wrote:
> Hi Geert,
>
> Thank you for the quick reply.
>
> On 15.06.2020 15:07, Geert Uytterhoeven wrote:
>> Hi Adrian,
>>
>> CC devicetree
>>
>> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
>> <adrian.fiergolski@fastree3d.com> wrote:
>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
>>>> connected to a single chip select of the cadence-spi master. I have the
>>>> impression such a configuration is supported by none of those two
>>>> drivers. I could try to extend both, however, I haven't found any other
>>>> SPI driver, where I could find implementation inspiration. Is it
>>>> supported by kernel?
>>>>
>>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
>>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
>>>> "registers-number" DT property.
>>>>
>>>> So both drivers handle this in their SPI slave drivers.
>>>>
>>>> Of course this does not handle the mixed case, i.e. daisy-chaining
>>>> different types of devices.
>>>>
>>>> The documentation mentions only about the common 'daisy-chained-devices'
>>>> property (devicetree/bindings/common-properties.txt). However, in order
>>>> to try to implement it in the master driver, IMHO, the spi subsystem
>>>> would need to have a call 'no-operation' to other nodes on the
>>>> daisy-chain, which are not addressed by the given SPI access. Is there
>>>> any recommended approach to address this case?
>>>>
>>>> Supporting this in a generic way would indeed be nice, as it would mean
>>>> individual SPI slave drivers no longer have to care about it.
>>>> However, that may be difficult, as the master needs to known which
>>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>>> In fact, the ultimate solution would be to have it solved at the level
>>> of the spi subsystem:
>>>
>>>   * /spi_device struct/ would contain extra callback which returns msg
>>>     to be sent for no operation.
>>>   * spi_device struct would contain a pointer to the list describing the
>>>     given daisy chain (list of spi_devices on the chain)
>>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
>>>     indicating length of a command of the addressed device if it's on
>>>     the daisy chain
>>>     For example, in case of the ltc2634 device, the regular message
>>>     consists of 24 bits, but when device is a part of a daisy chain, the
>>>     messages are 32 bits. This 32 would be stored in
>>>     /daisy_chain_msg_length./
>>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
>>>     /spi_message_init_with_transfer/ would create a msg of length equal
>>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
>>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
>>>     would be filled with the command of the addressed device on the
>>>     chain and no_operation content for all other devices on the chain
>>>     not being addressed
>> Sounds good to me.
>>
>>>   * I think in such a case, the /daisy-chained-devices /property would
>>>     be not used, as chains would be build basing on the assigned
>>>     chipselect (reg property).
>> So you still have to describe the chain in DT in some way.
>> As there can be only a single sub node with the same unit address
>> (= chip select), you probably need a container with that address, which
>> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
> Good point. So maybe at the level of the device tree, it could be
> described like that (based on the spi-cadence example):
>
>         spi0: spi@ff040000 {
>             compatible = "cdns,spi-r1p6";
>             status = "disabled";
>             interrupt-parent = <&gic>;
>             interrupts = <0 19 4>;
>             reg = <0x0 0xff040000 0x0 0x1000>;
>             clock-names = "ref_clk", "pclk";
>             #address-cells = <1>;
>             #size-cells = <0>;
>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>             daisy-chain0 : daisy_chain@0 {
>                #address-cells = <1>;
>                #size-cells = <0>;
>                reg = <0>;
>                daisy-chained-devices = 2;
>
>                dac0: ltc2632@0 {
>                    compatible = "lltc,ltc2634-l12";
>                    reg = <0>;
>                    spi-max-frequency = <1000000>;
>                };
>                dac1: ltc2632@1 {
>                    compatible = "lltc,ltc2634-l12";
>                    reg = <1>;
>                    spi-max-frequency = <2000000>;
>                };
>            };
>         };

        spi0: spi@ff040000 {
            compatible = "cdns,spi-r1p6";
            status = "disabled";
            interrupt-parent = <&gic>;
            interrupts = <0 19 4>;
            reg = <0x0 0xff040000 0x0 0x1000>;
            clock-names = "ref_clk", "pclk";
            #address-cells = <1>;
            #size-cells = <0>;
            power-domains = <&zynqmp_firmware PD_SPI_0>;
            daisy-chain0 : daisy_chain@0 {
               #address-cells = <1>;
               #size-cells = <0>;
               #daisy-chained-devices = <2>;

               reg = <0>;
               
               dac0: ltc2632@0 {
                   compatible = "lltc,ltc2634-l12";
                   reg = <0>;
                   spi-max-frequency = <1000000>;
               };
               dac1: ltc2632@1 {
                   compatible = "lltc,ltc2634-l12";
                   reg = <1>;
                   spi-max-frequency = <2000000>;
               };
           };
        };

>
> Once a node has daisy-chanied-devices property defined,
> of_register_spi_device (spi.c) will interpret it as a daisy chain. I
> will assume, that for the given chain the lowest frequency of the whole
> chain should be used. When it comes to the mode, as in case of
> incompatibility no much can be done anyway, the mode of the addressed
> spi device will be used.
>
>>> If you agree with the above description, I could try to implement it. Of
>>> course any suggestion are welcome, however, I would like to have a
>>> working solution until end of this week, so I would appreciate an active
>>> feedback. As my SoC works with kernel v4.19, I would implement it for
>>> it, test it, and move it afterwards to the master version (I hope, there
>>> were no big changes in the SPI subsystem, right?).
>> Having something that works by the end of the week sounds doable to.
>> Getting it in shape for upstreaming is a different thing...
> Let's try then. As I wrote earlier, I will try to implement it and test
> it with 4.19. Afterwards, I will share it with you for a general concept
> review. Once no comments, I will try to move it to the master and we can
> start from there the upstreaming process.
>
> Regards,
>
> Adrian
>
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 14:06         ` Adrian Fiergolski
@ 2020-06-15 14:40           ` Geert Uytterhoeven
  2020-06-15 16:05             ` Adrian Fiergolski
  0 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2020-06-15 14:40 UTC (permalink / raw)
  To: Adrian Fiergolski
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Adrian,

On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
<adrian.fiergolski@fastree3d.com> wrote:
> Sorry for the typo in the example device tree:
>
> On 15.06.2020 15:57, Adrian Fiergolski wrote:
> > On 15.06.2020 15:07, Geert Uytterhoeven wrote:
> >> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
> >> <adrian.fiergolski@fastree3d.com> wrote:
> >>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
> >>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
> >>>> <adrian.fiergolski@fastree3d.com> wrote:
> >>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
> >>>> connected to a single chip select of the cadence-spi master. I have the
> >>>> impression such a configuration is supported by none of those two
> >>>> drivers. I could try to extend both, however, I haven't found any other
> >>>> SPI driver, where I could find implementation inspiration. Is it
> >>>> supported by kernel?
> >>>>
> >>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
> >>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
> >>>> "registers-number" DT property.
> >>>>
> >>>> So both drivers handle this in their SPI slave drivers.
> >>>>
> >>>> Of course this does not handle the mixed case, i.e. daisy-chaining
> >>>> different types of devices.
> >>>>
> >>>> The documentation mentions only about the common 'daisy-chained-devices'
> >>>> property (devicetree/bindings/common-properties.txt). However, in order
> >>>> to try to implement it in the master driver, IMHO, the spi subsystem
> >>>> would need to have a call 'no-operation' to other nodes on the
> >>>> daisy-chain, which are not addressed by the given SPI access. Is there
> >>>> any recommended approach to address this case?
> >>>>
> >>>> Supporting this in a generic way would indeed be nice, as it would mean
> >>>> individual SPI slave drivers no longer have to care about it.
> >>>> However, that may be difficult, as the master needs to known which
> >>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
> >>> In fact, the ultimate solution would be to have it solved at the level
> >>> of the spi subsystem:
> >>>
> >>>   * /spi_device struct/ would contain extra callback which returns msg
> >>>     to be sent for no operation.
> >>>   * spi_device struct would contain a pointer to the list describing the
> >>>     given daisy chain (list of spi_devices on the chain)
> >>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
> >>>     indicating length of a command of the addressed device if it's on
> >>>     the daisy chain
> >>>     For example, in case of the ltc2634 device, the regular message
> >>>     consists of 24 bits, but when device is a part of a daisy chain, the
> >>>     messages are 32 bits. This 32 would be stored in
> >>>     /daisy_chain_msg_length./
> >>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
> >>>     /spi_message_init_with_transfer/ would create a msg of length equal
> >>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
> >>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
> >>>     would be filled with the command of the addressed device on the
> >>>     chain and no_operation content for all other devices on the chain
> >>>     not being addressed
> >> Sounds good to me.
> >>
> >>>   * I think in such a case, the /daisy-chained-devices /property would
> >>>     be not used, as chains would be build basing on the assigned
> >>>     chipselect (reg property).
> >> So you still have to describe the chain in DT in some way.
> >> As there can be only a single sub node with the same unit address
> >> (= chip select), you probably need a container with that address, which
> >> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
> > Good point. So maybe at the level of the device tree, it could be
> > described like that (based on the spi-cadence example):
> >
> >         spi0: spi@ff040000 {
> >             compatible = "cdns,spi-r1p6";
> >             status = "disabled";
> >             interrupt-parent = <&gic>;
> >             interrupts = <0 19 4>;
> >             reg = <0x0 0xff040000 0x0 0x1000>;
> >             clock-names = "ref_clk", "pclk";
> >             #address-cells = <1>;
> >             #size-cells = <0>;
> >             power-domains = <&zynqmp_firmware PD_SPI_0>;
> >             daisy-chain0 : daisy_chain@0 {
> >                #address-cells = <1>;
> >                #size-cells = <0>;
> >                reg = <0>;
> >                daisy-chained-devices = 2;
> >
> >                dac0: ltc2632@0 {
> >                    compatible = "lltc,ltc2634-l12";
> >                    reg = <0>;
> >                    spi-max-frequency = <1000000>;
> >                };
> >                dac1: ltc2632@1 {
> >                    compatible = "lltc,ltc2634-l12";
> >                    reg = <1>;
> >                    spi-max-frequency = <2000000>;
> >                };
> >            };
> >         };
>
>         spi0: spi@ff040000 {
>             compatible = "cdns,spi-r1p6";
>             status = "disabled";
>             interrupt-parent = <&gic>;
>             interrupts = <0 19 4>;
>             reg = <0x0 0xff040000 0x0 0x1000>;
>             clock-names = "ref_clk", "pclk";
>             #address-cells = <1>;
>             #size-cells = <0>;
>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>             daisy-chain0 : daisy_chain@0 {
>                #address-cells = <1>;
>                #size-cells = <0>;
>                #daisy-chained-devices = <2>;

You probably want a proper "compatible" value here instead.
I don't think "#daisy-chained-devices" is needed, it can be derived
from the number of subnodes.

>
>                reg = <0>;
>
>                dac0: ltc2632@0 {
>                    compatible = "lltc,ltc2634-l12";
>                    reg = <0>;
>                    spi-max-frequency = <1000000>;
>                };
>                dac1: ltc2632@1 {
>                    compatible = "lltc,ltc2634-l12";
>                    reg = <1>;
>                    spi-max-frequency = <2000000>;
>                };
>            };
>         };
>
> >
> > Once a node has daisy-chanied-devices property defined,
> > of_register_spi_device (spi.c) will interpret it as a daisy chain. I
> > will assume, that for the given chain the lowest frequency of the whole
> > chain should be used. When it comes to the mode, as in case of
> > incompatibility no much can be done anyway, the mode of the addressed
> > spi device will be used.

Don't the modes have to agree, too?
Else the dummy command may be interpreted differently than intended.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 14:40           ` Geert Uytterhoeven
@ 2020-06-15 16:05             ` Adrian Fiergolski
  2020-06-15 21:30               ` Geert Uytterhoeven
  0 siblings, 1 reply; 13+ messages in thread
From: Adrian Fiergolski @ 2020-06-15 16:05 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Geert,

On 15.06.2020 16:40, Geert Uytterhoeven wrote:
> Hi Adrian,
>
> On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
> <adrian.fiergolski@fastree3d.com> wrote:
>> Sorry for the typo in the example device tree:
>>
>> On 15.06.2020 15:57, Adrian Fiergolski wrote:
>>> On 15.06.2020 15:07, Geert Uytterhoeven wrote:
>>>> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
>>>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
>>>>>> connected to a single chip select of the cadence-spi master. I have the
>>>>>> impression such a configuration is supported by none of those two
>>>>>> drivers. I could try to extend both, however, I haven't found any other
>>>>>> SPI driver, where I could find implementation inspiration. Is it
>>>>>> supported by kernel?
>>>>>>
>>>>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
>>>>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
>>>>>> "registers-number" DT property.
>>>>>>
>>>>>> So both drivers handle this in their SPI slave drivers.
>>>>>>
>>>>>> Of course this does not handle the mixed case, i.e. daisy-chaining
>>>>>> different types of devices.
>>>>>>
>>>>>> The documentation mentions only about the common 'daisy-chained-devices'
>>>>>> property (devicetree/bindings/common-properties.txt). However, in order
>>>>>> to try to implement it in the master driver, IMHO, the spi subsystem
>>>>>> would need to have a call 'no-operation' to other nodes on the
>>>>>> daisy-chain, which are not addressed by the given SPI access. Is there
>>>>>> any recommended approach to address this case?
>>>>>>
>>>>>> Supporting this in a generic way would indeed be nice, as it would mean
>>>>>> individual SPI slave drivers no longer have to care about it.
>>>>>> However, that may be difficult, as the master needs to known which
>>>>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>>>>> In fact, the ultimate solution would be to have it solved at the level
>>>>> of the spi subsystem:
>>>>>
>>>>>   * /spi_device struct/ would contain extra callback which returns msg
>>>>>     to be sent for no operation.
>>>>>   * spi_device struct would contain a pointer to the list describing the
>>>>>     given daisy chain (list of spi_devices on the chain)
>>>>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
>>>>>     indicating length of a command of the addressed device if it's on
>>>>>     the daisy chain
>>>>>     For example, in case of the ltc2634 device, the regular message
>>>>>     consists of 24 bits, but when device is a part of a daisy chain, the
>>>>>     messages are 32 bits. This 32 would be stored in
>>>>>     /daisy_chain_msg_length./
>>>>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
>>>>>     /spi_message_init_with_transfer/ would create a msg of length equal
>>>>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
>>>>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
>>>>>     would be filled with the command of the addressed device on the
>>>>>     chain and no_operation content for all other devices on the chain
>>>>>     not being addressed
>>>> Sounds good to me.
>>>>
>>>>>   * I think in such a case, the /daisy-chained-devices /property would
>>>>>     be not used, as chains would be build basing on the assigned
>>>>>     chipselect (reg property).
>>>> So you still have to describe the chain in DT in some way.
>>>> As there can be only a single sub node with the same unit address
>>>> (= chip select), you probably need a container with that address, which
>>>> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
>>> Good point. So maybe at the level of the device tree, it could be
>>> described like that (based on the spi-cadence example):
>>>
>>>         spi0: spi@ff040000 {
>>>             compatible = "cdns,spi-r1p6";
>>>             status = "disabled";
>>>             interrupt-parent = <&gic>;
>>>             interrupts = <0 19 4>;
>>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>>             clock-names = "ref_clk", "pclk";
>>>             #address-cells = <1>;
>>>             #size-cells = <0>;
>>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>>             daisy-chain0 : daisy_chain@0 {
>>>                #address-cells = <1>;
>>>                #size-cells = <0>;
>>>                reg = <0>;
>>>                daisy-chained-devices = 2;
>>>
>>>                dac0: ltc2632@0 {
>>>                    compatible = "lltc,ltc2634-l12";
>>>                    reg = <0>;
>>>                    spi-max-frequency = <1000000>;
>>>                };
>>>                dac1: ltc2632@1 {
>>>                    compatible = "lltc,ltc2634-l12";
>>>                    reg = <1>;
>>>                    spi-max-frequency = <2000000>;
>>>                };
>>>            };
>>>         };
>>         spi0: spi@ff040000 {
>>             compatible = "cdns,spi-r1p6";
>>             status = "disabled";
>>             interrupt-parent = <&gic>;
>>             interrupts = <0 19 4>;
>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>             clock-names = "ref_clk", "pclk";
>>             #address-cells = <1>;
>>             #size-cells = <0>;
>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>             daisy-chain0 : daisy_chain@0 {
>>                #address-cells = <1>;
>>                #size-cells = <0>;
>>                #daisy-chained-devices = <2>;
> You probably want a proper "compatible" value here instead.
> I don't think "#daisy-chained-devices" is needed, it can be derived
> from the number of subnodes.
compatible = "daisy_chain" or compatible ="simple-bus" would be better?
Both could be caught by of_register_spi_devices to populate the daisy
chain. Do you agree that at that level the chip select could be defined?
The reg properties from the sub-nodes (defining actual spi devices)
would be ignored, thus not even needed to be defined.
>
>>                reg = <0>;
>>
>>                dac0: ltc2632@0 {
>>                    compatible = "lltc,ltc2634-l12";
>>                    reg = <0>;
>>                    spi-max-frequency = <1000000>;
>>                };
>>                dac1: ltc2632@1 {
>>                    compatible = "lltc,ltc2634-l12";
>>                    reg = <1>;
>>                    spi-max-frequency = <2000000>;
>>                };
>>            };
>>         };
>>
>>> Once a node has daisy-chanied-devices property defined,
>>> of_register_spi_device (spi.c) will interpret it as a daisy chain. I
>>> will assume, that for the given chain the lowest frequency of the whole
>>> chain should be used. When it comes to the mode, as in case of
>>> incompatibility no much can be done anyway, the mode of the addressed
>>> spi device will be used.
> Don't the modes have to agree, too?
> Else the dummy command may be interpreted differently than intended.

So, in case of incompatible mode, let's throw an error and remove
devices of the whole daisy chain, maybe?

Regards,

Adrian



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 16:05             ` Adrian Fiergolski
@ 2020-06-15 21:30               ` Geert Uytterhoeven
  2020-06-15 22:22                 ` Rob Herring
  0 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2020-06-15 21:30 UTC (permalink / raw)
  To: Adrian Fiergolski
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Adrian,

On Mon, Jun 15, 2020 at 6:05 PM Adrian Fiergolski
<adrian.fiergolski@fastree3d.com> wrote:
> On 15.06.2020 16:40, Geert Uytterhoeven wrote:
> > On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
> > <adrian.fiergolski@fastree3d.com> wrote:
> >> Sorry for the typo in the example device tree:
> >>
> >> On 15.06.2020 15:57, Adrian Fiergolski wrote:
> >>> On 15.06.2020 15:07, Geert Uytterhoeven wrote:
> >>>> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
> >>>> <adrian.fiergolski@fastree3d.com> wrote:
> >>>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
> >>>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
> >>>>>> <adrian.fiergolski@fastree3d.com> wrote:
> >>>>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
> >>>>>> connected to a single chip select of the cadence-spi master. I have the
> >>>>>> impression such a configuration is supported by none of those two
> >>>>>> drivers. I could try to extend both, however, I haven't found any other
> >>>>>> SPI driver, where I could find implementation inspiration. Is it
> >>>>>> supported by kernel?
> >>>>>>
> >>>>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
> >>>>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
> >>>>>> "registers-number" DT property.
> >>>>>>
> >>>>>> So both drivers handle this in their SPI slave drivers.
> >>>>>>
> >>>>>> Of course this does not handle the mixed case, i.e. daisy-chaining
> >>>>>> different types of devices.
> >>>>>>
> >>>>>> The documentation mentions only about the common 'daisy-chained-devices'
> >>>>>> property (devicetree/bindings/common-properties.txt). However, in order
> >>>>>> to try to implement it in the master driver, IMHO, the spi subsystem
> >>>>>> would need to have a call 'no-operation' to other nodes on the
> >>>>>> daisy-chain, which are not addressed by the given SPI access. Is there
> >>>>>> any recommended approach to address this case?
> >>>>>>
> >>>>>> Supporting this in a generic way would indeed be nice, as it would mean
> >>>>>> individual SPI slave drivers no longer have to care about it.
> >>>>>> However, that may be difficult, as the master needs to known which
> >>>>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
> >>>>> In fact, the ultimate solution would be to have it solved at the level
> >>>>> of the spi subsystem:
> >>>>>
> >>>>>   * /spi_device struct/ would contain extra callback which returns msg
> >>>>>     to be sent for no operation.
> >>>>>   * spi_device struct would contain a pointer to the list describing the
> >>>>>     given daisy chain (list of spi_devices on the chain)
> >>>>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
> >>>>>     indicating length of a command of the addressed device if it's on
> >>>>>     the daisy chain
> >>>>>     For example, in case of the ltc2634 device, the regular message
> >>>>>     consists of 24 bits, but when device is a part of a daisy chain, the
> >>>>>     messages are 32 bits. This 32 would be stored in
> >>>>>     /daisy_chain_msg_length./
> >>>>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
> >>>>>     /spi_message_init_with_transfer/ would create a msg of length equal
> >>>>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
> >>>>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
> >>>>>     would be filled with the command of the addressed device on the
> >>>>>     chain and no_operation content for all other devices on the chain
> >>>>>     not being addressed
> >>>> Sounds good to me.
> >>>>
> >>>>>   * I think in such a case, the /daisy-chained-devices /property would
> >>>>>     be not used, as chains would be build basing on the assigned
> >>>>>     chipselect (reg property).
> >>>> So you still have to describe the chain in DT in some way.
> >>>> As there can be only a single sub node with the same unit address
> >>>> (= chip select), you probably need a container with that address, which
> >>>> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
> >>> Good point. So maybe at the level of the device tree, it could be
> >>> described like that (based on the spi-cadence example):
> >>>
> >>>         spi0: spi@ff040000 {
> >>>             compatible = "cdns,spi-r1p6";
> >>>             status = "disabled";
> >>>             interrupt-parent = <&gic>;
> >>>             interrupts = <0 19 4>;
> >>>             reg = <0x0 0xff040000 0x0 0x1000>;
> >>>             clock-names = "ref_clk", "pclk";
> >>>             #address-cells = <1>;
> >>>             #size-cells = <0>;
> >>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
> >>>             daisy-chain0 : daisy_chain@0 {
> >>>                #address-cells = <1>;
> >>>                #size-cells = <0>;
> >>>                reg = <0>;
> >>>                daisy-chained-devices = 2;
> >>>
> >>>                dac0: ltc2632@0 {
> >>>                    compatible = "lltc,ltc2634-l12";
> >>>                    reg = <0>;
> >>>                    spi-max-frequency = <1000000>;
> >>>                };
> >>>                dac1: ltc2632@1 {
> >>>                    compatible = "lltc,ltc2634-l12";
> >>>                    reg = <1>;
> >>>                    spi-max-frequency = <2000000>;
> >>>                };
> >>>            };
> >>>         };
> >>         spi0: spi@ff040000 {
> >>             compatible = "cdns,spi-r1p6";
> >>             status = "disabled";
> >>             interrupt-parent = <&gic>;
> >>             interrupts = <0 19 4>;
> >>             reg = <0x0 0xff040000 0x0 0x1000>;
> >>             clock-names = "ref_clk", "pclk";
> >>             #address-cells = <1>;
> >>             #size-cells = <0>;
> >>             power-domains = <&zynqmp_firmware PD_SPI_0>;
> >>             daisy-chain0 : daisy_chain@0 {
> >>                #address-cells = <1>;
> >>                #size-cells = <0>;
> >>                #daisy-chained-devices = <2>;
> >
> > You probably want a proper "compatible" value here instead.
> > I don't think "#daisy-chained-devices" is needed, it can be derived
> > from the number of subnodes.
> >
> compatible = "daisy_chain" or compatible ="simple-bus" would be better?

Not "simple-bus", as this is not a simple memory-mapped bus.
I'd use something like "spi,daisy-chain", to be validated by RobH.

> Both could be caught by of_register_spi_devices to populate the daisy
> chain. Do you agree that at that level the chip select could be defined?

Or by a separate SPI device driver that matches against "spi,daisy-chain",
and parse the subnodes.

> The reg properties from the sub-nodes (defining actual spi devices)
> would be ignored, thus not even needed to be defined.

They are needed to determine the order in the chain.

> >
> >>                reg = <0>;
> >>
> >>                dac0: ltc2632@0 {
> >>                    compatible = "lltc,ltc2634-l12";
> >>                    reg = <0>;
> >>                    spi-max-frequency = <1000000>;
> >>                };
> >>                dac1: ltc2632@1 {
> >>                    compatible = "lltc,ltc2634-l12";
> >>                    reg = <1>;
> >>                    spi-max-frequency = <2000000>;
> >>                };
> >>            };
> >>         };
> >>
> >>> Once a node has daisy-chanied-devices property defined,
> >>> of_register_spi_device (spi.c) will interpret it as a daisy chain. I
> >>> will assume, that for the given chain the lowest frequency of the whole
> >>> chain should be used. When it comes to the mode, as in case of
> >>> incompatibility no much can be done anyway, the mode of the addressed
> >>> spi device will be used.
> > Don't the modes have to agree, too?
> > Else the dummy command may be interpreted differently than intended.
>
> So, in case of incompatible mode, let's throw an error and remove
> devices of the whole daisy chain, maybe?

Yep.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 21:30               ` Geert Uytterhoeven
@ 2020-06-15 22:22                 ` Rob Herring
  2020-06-16 10:25                   ` Adrian Fiergolski
  0 siblings, 1 reply; 13+ messages in thread
From: Rob Herring @ 2020-06-15 22:22 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Adrian Fiergolski, linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Mon, Jun 15, 2020 at 3:30 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>
> Hi Adrian,
>
> On Mon, Jun 15, 2020 at 6:05 PM Adrian Fiergolski
> <adrian.fiergolski@fastree3d.com> wrote:
> > On 15.06.2020 16:40, Geert Uytterhoeven wrote:
> > > On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
> > > <adrian.fiergolski@fastree3d.com> wrote:
> > >> Sorry for the typo in the example device tree:
> > >>
> > >> On 15.06.2020 15:57, Adrian Fiergolski wrote:
> > >>> On 15.06.2020 15:07, Geert Uytterhoeven wrote:
> > >>>> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
> > >>>> <adrian.fiergolski@fastree3d.com> wrote:
> > >>>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
> > >>>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
> > >>>>>> <adrian.fiergolski@fastree3d.com> wrote:
> > >>>>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
> > >>>>>> connected to a single chip select of the cadence-spi master. I have the
> > >>>>>> impression such a configuration is supported by none of those two
> > >>>>>> drivers. I could try to extend both, however, I haven't found any other
> > >>>>>> SPI driver, where I could find implementation inspiration. Is it
> > >>>>>> supported by kernel?
> > >>>>>>
> > >>>>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
> > >>>>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
> > >>>>>> "registers-number" DT property.
> > >>>>>>
> > >>>>>> So both drivers handle this in their SPI slave drivers.
> > >>>>>>
> > >>>>>> Of course this does not handle the mixed case, i.e. daisy-chaining
> > >>>>>> different types of devices.
> > >>>>>>
> > >>>>>> The documentation mentions only about the common 'daisy-chained-devices'
> > >>>>>> property (devicetree/bindings/common-properties.txt). However, in order
> > >>>>>> to try to implement it in the master driver, IMHO, the spi subsystem
> > >>>>>> would need to have a call 'no-operation' to other nodes on the
> > >>>>>> daisy-chain, which are not addressed by the given SPI access. Is there
> > >>>>>> any recommended approach to address this case?
> > >>>>>>
> > >>>>>> Supporting this in a generic way would indeed be nice, as it would mean
> > >>>>>> individual SPI slave drivers no longer have to care about it.
> > >>>>>> However, that may be difficult, as the master needs to known which
> > >>>>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
> > >>>>> In fact, the ultimate solution would be to have it solved at the level
> > >>>>> of the spi subsystem:
> > >>>>>
> > >>>>>   * /spi_device struct/ would contain extra callback which returns msg
> > >>>>>     to be sent for no operation.
> > >>>>>   * spi_device struct would contain a pointer to the list describing the
> > >>>>>     given daisy chain (list of spi_devices on the chain)
> > >>>>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
> > >>>>>     indicating length of a command of the addressed device if it's on
> > >>>>>     the daisy chain
> > >>>>>     For example, in case of the ltc2634 device, the regular message
> > >>>>>     consists of 24 bits, but when device is a part of a daisy chain, the
> > >>>>>     messages are 32 bits. This 32 would be stored in
> > >>>>>     /daisy_chain_msg_length./
> > >>>>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
> > >>>>>     /spi_message_init_with_transfer/ would create a msg of length equal
> > >>>>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
> > >>>>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
> > >>>>>     would be filled with the command of the addressed device on the
> > >>>>>     chain and no_operation content for all other devices on the chain
> > >>>>>     not being addressed
> > >>>> Sounds good to me.
> > >>>>
> > >>>>>   * I think in such a case, the /daisy-chained-devices /property would
> > >>>>>     be not used, as chains would be build basing on the assigned
> > >>>>>     chipselect (reg property).
> > >>>> So you still have to describe the chain in DT in some way.
> > >>>> As there can be only a single sub node with the same unit address
> > >>>> (= chip select), you probably need a container with that address, which
> > >>>> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
> > >>> Good point. So maybe at the level of the device tree, it could be
> > >>> described like that (based on the spi-cadence example):
> > >>>
> > >>>         spi0: spi@ff040000 {
> > >>>             compatible = "cdns,spi-r1p6";
> > >>>             status = "disabled";
> > >>>             interrupt-parent = <&gic>;
> > >>>             interrupts = <0 19 4>;
> > >>>             reg = <0x0 0xff040000 0x0 0x1000>;
> > >>>             clock-names = "ref_clk", "pclk";
> > >>>             #address-cells = <1>;
> > >>>             #size-cells = <0>;
> > >>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
> > >>>             daisy-chain0 : daisy_chain@0 {
> > >>>                #address-cells = <1>;
> > >>>                #size-cells = <0>;
> > >>>                reg = <0>;
> > >>>                daisy-chained-devices = 2;
> > >>>
> > >>>                dac0: ltc2632@0 {
> > >>>                    compatible = "lltc,ltc2634-l12";
> > >>>                    reg = <0>;
> > >>>                    spi-max-frequency = <1000000>;
> > >>>                };
> > >>>                dac1: ltc2632@1 {
> > >>>                    compatible = "lltc,ltc2634-l12";
> > >>>                    reg = <1>;
> > >>>                    spi-max-frequency = <2000000>;
> > >>>                };
> > >>>            };
> > >>>         };
> > >>         spi0: spi@ff040000 {
> > >>             compatible = "cdns,spi-r1p6";
> > >>             status = "disabled";
> > >>             interrupt-parent = <&gic>;
> > >>             interrupts = <0 19 4>;
> > >>             reg = <0x0 0xff040000 0x0 0x1000>;
> > >>             clock-names = "ref_clk", "pclk";
> > >>             #address-cells = <1>;
> > >>             #size-cells = <0>;
> > >>             power-domains = <&zynqmp_firmware PD_SPI_0>;
> > >>             daisy-chain0 : daisy_chain@0 {
> > >>                #address-cells = <1>;
> > >>                #size-cells = <0>;
> > >>                #daisy-chained-devices = <2>;
> > >
> > > You probably want a proper "compatible" value here instead.
> > > I don't think "#daisy-chained-devices" is needed, it can be derived
> > > from the number of subnodes.

This is not how '#daisy-chained-devices' works either. The chained
devices are represented as a single node and a single driver instance
handles multiple physical devices.

The above looks like mux'ed access rather than creating a 'super'
device. Would you want to program all N chips in one SPI transfer or
it's one device at a time? (We should be careful with the bindings
that we're not encoding that into the binding as that could evolve
with the OS.)


> > compatible = "daisy_chain" or compatible ="simple-bus" would be better?
>
> Not "simple-bus", as this is not a simple memory-mapped bus.
> I'd use something like "spi,daisy-chain", to be validated by RobH.

Okay, but what makes it generic?

What happens with power control of the child devices? While I'd think
the only sane design is shared supplies, resets, clocks, etc. (and
daisy-chained-devices certainly assumes that), it's certainly possible
some cross device control is needed.

> > Both could be caught by of_register_spi_devices to populate the daisy
> > chain. Do you agree that at that level the chip select could be defined?
>
> Or by a separate SPI device driver that matches against "spi,daisy-chain",
> and parse the subnodes.
>
> > The reg properties from the sub-nodes (defining actual spi devices)
> > would be ignored, thus not even needed to be defined.
>
> They are needed to determine the order in the chain.

Agreed, you need something to address a device. A better address might
be the bit position of the device in the chain. Then this could work
for any mixture of devices that support chaining (though you'd need to
know what's a nop for each device).

Rob

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-15 22:22                 ` Rob Herring
@ 2020-06-16 10:25                   ` Adrian Fiergolski
  2020-06-17 12:33                     ` Adrian Fiergolski
  0 siblings, 1 reply; 13+ messages in thread
From: Adrian Fiergolski @ 2020-06-16 10:25 UTC (permalink / raw)
  To: Rob Herring, Geert Uytterhoeven
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Geert and Rob,

Thank you for your comments.

On 16.06.2020 00:22, Rob Herring wrote:
> On Mon, Jun 15, 2020 at 3:30 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>> Hi Adrian,
>>
>> On Mon, Jun 15, 2020 at 6:05 PM Adrian Fiergolski
>> <adrian.fiergolski@fastree3d.com> wrote:
>>> On 15.06.2020 16:40, Geert Uytterhoeven wrote:
>>>> On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>> Sorry for the typo in the example device tree:
>>>>>
>>>>> On 15.06.2020 15:57, Adrian Fiergolski wrote:
>>>>>> On 15.06.2020 15:07, Geert Uytterhoeven wrote:
>>>>>>> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
>>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
>>>>>>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
>>>>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>>>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
>>>>>>>>> connected to a single chip select of the cadence-spi master. I have the
>>>>>>>>> impression such a configuration is supported by none of those two
>>>>>>>>> drivers. I could try to extend both, however, I haven't found any other
>>>>>>>>> SPI driver, where I could find implementation inspiration. Is it
>>>>>>>>> supported by kernel?
>>>>>>>>>
>>>>>>>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
>>>>>>>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
>>>>>>>>> "registers-number" DT property.
>>>>>>>>>
>>>>>>>>> So both drivers handle this in their SPI slave drivers.
>>>>>>>>>
>>>>>>>>> Of course this does not handle the mixed case, i.e. daisy-chaining
>>>>>>>>> different types of devices.
>>>>>>>>>
>>>>>>>>> The documentation mentions only about the common 'daisy-chained-devices'
>>>>>>>>> property (devicetree/bindings/common-properties.txt). However, in order
>>>>>>>>> to try to implement it in the master driver, IMHO, the spi subsystem
>>>>>>>>> would need to have a call 'no-operation' to other nodes on the
>>>>>>>>> daisy-chain, which are not addressed by the given SPI access. Is there
>>>>>>>>> any recommended approach to address this case?
>>>>>>>>>
>>>>>>>>> Supporting this in a generic way would indeed be nice, as it would mean
>>>>>>>>> individual SPI slave drivers no longer have to care about it.
>>>>>>>>> However, that may be difficult, as the master needs to known which
>>>>>>>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>>>>>>>> In fact, the ultimate solution would be to have it solved at the level
>>>>>>>> of the spi subsystem:
>>>>>>>>
>>>>>>>>   * /spi_device struct/ would contain extra callback which returns msg
>>>>>>>>     to be sent for no operation.
>>>>>>>>   * spi_device struct would contain a pointer to the list describing the
>>>>>>>>     given daisy chain (list of spi_devices on the chain)
>>>>>>>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
>>>>>>>>     indicating length of a command of the addressed device if it's on
>>>>>>>>     the daisy chain
>>>>>>>>     For example, in case of the ltc2634 device, the regular message
>>>>>>>>     consists of 24 bits, but when device is a part of a daisy chain, the
>>>>>>>>     messages are 32 bits. This 32 would be stored in
>>>>>>>>     /daisy_chain_msg_length./
>>>>>>>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
>>>>>>>>     /spi_message_init_with_transfer/ would create a msg of length equal
>>>>>>>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
>>>>>>>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
>>>>>>>>     would be filled with the command of the addressed device on the
>>>>>>>>     chain and no_operation content for all other devices on the chain
>>>>>>>>     not being addressed
>>>>>>> Sounds good to me.
>>>>>>>
>>>>>>>>   * I think in such a case, the /daisy-chained-devices /property would
>>>>>>>>     be not used, as chains would be build basing on the assigned
>>>>>>>>     chipselect (reg property).
>>>>>>> So you still have to describe the chain in DT in some way.
>>>>>>> As there can be only a single sub node with the same unit address
>>>>>>> (= chip select), you probably need a container with that address, which
>>>>>>> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
>>>>>> Good point. So maybe at the level of the device tree, it could be
>>>>>> described like that (based on the spi-cadence example):
>>>>>>
>>>>>>         spi0: spi@ff040000 {
>>>>>>             compatible = "cdns,spi-r1p6";
>>>>>>             status = "disabled";
>>>>>>             interrupt-parent = <&gic>;
>>>>>>             interrupts = <0 19 4>;
>>>>>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>>>>>             clock-names = "ref_clk", "pclk";
>>>>>>             #address-cells = <1>;
>>>>>>             #size-cells = <0>;
>>>>>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>>>>>             daisy-chain0 : daisy_chain@0 {
>>>>>>                #address-cells = <1>;
>>>>>>                #size-cells = <0>;
>>>>>>                reg = <0>;
>>>>>>                daisy-chained-devices = 2;
>>>>>>
>>>>>>                dac0: ltc2632@0 {
>>>>>>                    compatible = "lltc,ltc2634-l12";
>>>>>>                    reg = <0>;
>>>>>>                    spi-max-frequency = <1000000>;
>>>>>>                };
>>>>>>                dac1: ltc2632@1 {
>>>>>>                    compatible = "lltc,ltc2634-l12";
>>>>>>                    reg = <1>;
>>>>>>                    spi-max-frequency = <2000000>;
>>>>>>                };
>>>>>>            };
>>>>>>         };
>>>>>         spi0: spi@ff040000 {
>>>>>             compatible = "cdns,spi-r1p6";
>>>>>             status = "disabled";
>>>>>             interrupt-parent = <&gic>;
>>>>>             interrupts = <0 19 4>;
>>>>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>>>>             clock-names = "ref_clk", "pclk";
>>>>>             #address-cells = <1>;
>>>>>             #size-cells = <0>;
>>>>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>>>>             daisy-chain0 : daisy_chain@0 {
>>>>>                #address-cells = <1>;
>>>>>                #size-cells = <0>;
>>>>>                #daisy-chained-devices = <2>;
>>>> You probably want a proper "compatible" value here instead.
>>>> I don't think "#daisy-chained-devices" is needed, it can be derived
>>>> from the number of subnodes.
> This is not how '#daisy-chained-devices' works either. The chained
> devices are represented as a single node and a single driver instance
> handles multiple physical devices.
>
> The above looks like mux'ed access rather than creating a 'super'
> device. Would you want to program all N chips in one SPI transfer or
> it's one device at a time? (We should be careful with the bindings
> that we're not encoding that into the binding as that could evolve
> with the OS.)

Well, I think the described concept of the daisy chain doesn't apply
here then. In principle, we can have different SPI devices, where each
is served by a different driver. Together, they create a long register
through which data is shifted. IMHO, the fact that the given device is
on the daisy chain with other devices should be transparent for its SPI
device driver and handled at the level of the SPI subsystem: at SPI
write/read stage, the SPI subsystem would combine message of a addressed
device with the specific no-operation pattern of all other devices being
present on the chain (each device may have its specific no-operation
pattern).

At the moment, I wouldn't try to address a few SPI devices in a single
access.

As you can see, it's no really a mux access like in case of e.g. I2C:
there, we have a physical device performing multiplexing. Once the I2C
bus is switched, no extra effort is required in communication between
the I2C master and I2C device (slave).

>>> compatible = "daisy_chain" or compatible ="simple-bus" would be better?
>> Not "simple-bus", as this is not a simple memory-mapped bus.
>> I'd use something like "spi,daisy-chain", to be validated by RobH.
> Okay, but what makes it generic?
>
> What happens with power control of the child devices? While I'd think
> the only sane design is shared supplies, resets, clocks, etc. (and
> daisy-chained-devices certainly assumes that), it's certainly possible
> some cross device control is needed.
>
>>> Both could be caught by of_register_spi_devices to populate the daisy
>>> chain. Do you agree that at that level the chip select could be defined?
>> Or by a separate SPI device driver that matches against "spi,daisy-chain",
>> and parse the subnodes.

I have been thinking about it and came to a similar idea. However, I
didn't find a straightforward way to associate the SPI devices with the
abstract daisy-chain device which would then eventually be linked with
the SPI controller. It would a simple and clean implementation then: SPI
devices at write/read would call daisy-chain device which would create a
full message and pass it to SPI controller. The issue is that the SPI
device requires for all calls SPI controller. It implies that SPI
daisy-chain would need to be SPI controller as well. However, I think
currently the SPI concept in the kernel is fixed: SPI controller <-> SPI
device and there is no place to implement SPI controller <-> SPI
controller (daisy-chain device) <-> SPI device. Any suggestions on how
to address it?

>>> The reg properties from the sub-nodes (defining actual spi devices)
>>> would be ignored, thus not even needed to be defined.
>> They are needed to determine the order in the chain.
> Agreed, you need something to address a device. A better address might
> be the bit position of the device in the chain. Then this could work
> for any mixture of devices that support chaining (though you'd need to
> know what's a nop for each device).

Well, the idea was that the daisy chain will be populated basing on all
sub-nodes and their order in the device tree. If we go for a reg
numbering the device in the chain, I think we need then
'#daisy-chained-devices' as well, such kernel knows a priori the length
of the chain and can issue an error in case some reg values are missing
on a given chain.

Regards,

Adrian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [cadence-spi] daisy chain
  2020-06-16 10:25                   ` Adrian Fiergolski
@ 2020-06-17 12:33                     ` Adrian Fiergolski
  2020-07-01 13:47                       ` SPI daisy chain support Adrian Fiergolski
  0 siblings, 1 reply; 13+ messages in thread
From: Adrian Fiergolski @ 2020-06-17 12:33 UTC (permalink / raw)
  To: Rob Herring, Geert Uytterhoeven
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi All,

A quick update: I have started implementation taking into account most
of the points from our discussion (a separate spi,daisy-chain spi
device, single device addressed at once, etc.). I have realized that the
daisy-chain device doesn't need to be a SPI controller and information
about the chain can be stored in the spi_device struct and then handled
by the SPI subsystem. Once I have a working implementation, I will share
it with you for a review.

Regards,

Adrian

On 16.06.2020 12:25, Adrian Fiergolski wrote:
> Hi Geert and Rob,
>
> Thank you for your comments.
>
> On 16.06.2020 00:22, Rob Herring wrote:
>> On Mon, Jun 15, 2020 at 3:30 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>>> Hi Adrian,
>>>
>>> On Mon, Jun 15, 2020 at 6:05 PM Adrian Fiergolski
>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>> On 15.06.2020 16:40, Geert Uytterhoeven wrote:
>>>>> On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>> Sorry for the typo in the example device tree:
>>>>>>
>>>>>> On 15.06.2020 15:57, Adrian Fiergolski wrote:
>>>>>>> On 15.06.2020 15:07, Geert Uytterhoeven wrote:
>>>>>>>> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
>>>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>>>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
>>>>>>>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
>>>>>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>>>>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
>>>>>>>>>> connected to a single chip select of the cadence-spi master. I have the
>>>>>>>>>> impression such a configuration is supported by none of those two
>>>>>>>>>> drivers. I could try to extend both, however, I haven't found any other
>>>>>>>>>> SPI driver, where I could find implementation inspiration. Is it
>>>>>>>>>> supported by kernel?
>>>>>>>>>>
>>>>>>>>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
>>>>>>>>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
>>>>>>>>>> "registers-number" DT property.
>>>>>>>>>>
>>>>>>>>>> So both drivers handle this in their SPI slave drivers.
>>>>>>>>>>
>>>>>>>>>> Of course this does not handle the mixed case, i.e. daisy-chaining
>>>>>>>>>> different types of devices.
>>>>>>>>>>
>>>>>>>>>> The documentation mentions only about the common 'daisy-chained-devices'
>>>>>>>>>> property (devicetree/bindings/common-properties.txt). However, in order
>>>>>>>>>> to try to implement it in the master driver, IMHO, the spi subsystem
>>>>>>>>>> would need to have a call 'no-operation' to other nodes on the
>>>>>>>>>> daisy-chain, which are not addressed by the given SPI access. Is there
>>>>>>>>>> any recommended approach to address this case?
>>>>>>>>>>
>>>>>>>>>> Supporting this in a generic way would indeed be nice, as it would mean
>>>>>>>>>> individual SPI slave drivers no longer have to care about it.
>>>>>>>>>> However, that may be difficult, as the master needs to known which
>>>>>>>>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>>>>>>>>> In fact, the ultimate solution would be to have it solved at the level
>>>>>>>>> of the spi subsystem:
>>>>>>>>>
>>>>>>>>>   * /spi_device struct/ would contain extra callback which returns msg
>>>>>>>>>     to be sent for no operation.
>>>>>>>>>   * spi_device struct would contain a pointer to the list describing the
>>>>>>>>>     given daisy chain (list of spi_devices on the chain)
>>>>>>>>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
>>>>>>>>>     indicating length of a command of the addressed device if it's on
>>>>>>>>>     the daisy chain
>>>>>>>>>     For example, in case of the ltc2634 device, the regular message
>>>>>>>>>     consists of 24 bits, but when device is a part of a daisy chain, the
>>>>>>>>>     messages are 32 bits. This 32 would be stored in
>>>>>>>>>     /daisy_chain_msg_length./
>>>>>>>>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
>>>>>>>>>     /spi_message_init_with_transfer/ would create a msg of length equal
>>>>>>>>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
>>>>>>>>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
>>>>>>>>>     would be filled with the command of the addressed device on the
>>>>>>>>>     chain and no_operation content for all other devices on the chain
>>>>>>>>>     not being addressed
>>>>>>>> Sounds good to me.
>>>>>>>>
>>>>>>>>>   * I think in such a case, the /daisy-chained-devices /property would
>>>>>>>>>     be not used, as chains would be build basing on the assigned
>>>>>>>>>     chipselect (reg property).
>>>>>>>> So you still have to describe the chain in DT in some way.
>>>>>>>> As there can be only a single sub node with the same unit address
>>>>>>>> (= chip select), you probably need a container with that address, which
>>>>>>>> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
>>>>>>> Good point. So maybe at the level of the device tree, it could be
>>>>>>> described like that (based on the spi-cadence example):
>>>>>>>
>>>>>>>         spi0: spi@ff040000 {
>>>>>>>             compatible = "cdns,spi-r1p6";
>>>>>>>             status = "disabled";
>>>>>>>             interrupt-parent = <&gic>;
>>>>>>>             interrupts = <0 19 4>;
>>>>>>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>>>>>>             clock-names = "ref_clk", "pclk";
>>>>>>>             #address-cells = <1>;
>>>>>>>             #size-cells = <0>;
>>>>>>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>>>>>>             daisy-chain0 : daisy_chain@0 {
>>>>>>>                #address-cells = <1>;
>>>>>>>                #size-cells = <0>;
>>>>>>>                reg = <0>;
>>>>>>>                daisy-chained-devices = 2;
>>>>>>>
>>>>>>>                dac0: ltc2632@0 {
>>>>>>>                    compatible = "lltc,ltc2634-l12";
>>>>>>>                    reg = <0>;
>>>>>>>                    spi-max-frequency = <1000000>;
>>>>>>>                };
>>>>>>>                dac1: ltc2632@1 {
>>>>>>>                    compatible = "lltc,ltc2634-l12";
>>>>>>>                    reg = <1>;
>>>>>>>                    spi-max-frequency = <2000000>;
>>>>>>>                };
>>>>>>>            };
>>>>>>>         };
>>>>>>         spi0: spi@ff040000 {
>>>>>>             compatible = "cdns,spi-r1p6";
>>>>>>             status = "disabled";
>>>>>>             interrupt-parent = <&gic>;
>>>>>>             interrupts = <0 19 4>;
>>>>>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>>>>>             clock-names = "ref_clk", "pclk";
>>>>>>             #address-cells = <1>;
>>>>>>             #size-cells = <0>;
>>>>>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>>>>>             daisy-chain0 : daisy_chain@0 {
>>>>>>                #address-cells = <1>;
>>>>>>                #size-cells = <0>;
>>>>>>                #daisy-chained-devices = <2>;
>>>>> You probably want a proper "compatible" value here instead.
>>>>> I don't think "#daisy-chained-devices" is needed, it can be derived
>>>>> from the number of subnodes.
>> This is not how '#daisy-chained-devices' works either. The chained
>> devices are represented as a single node and a single driver instance
>> handles multiple physical devices.
>>
>> The above looks like mux'ed access rather than creating a 'super'
>> device. Would you want to program all N chips in one SPI transfer or
>> it's one device at a time? (We should be careful with the bindings
>> that we're not encoding that into the binding as that could evolve
>> with the OS.)
> Well, I think the described concept of the daisy chain doesn't apply
> here then. In principle, we can have different SPI devices, where each
> is served by a different driver. Together, they create a long register
> through which data is shifted. IMHO, the fact that the given device is
> on the daisy chain with other devices should be transparent for its SPI
> device driver and handled at the level of the SPI subsystem: at SPI
> write/read stage, the SPI subsystem would combine message of a addressed
> device with the specific no-operation pattern of all other devices being
> present on the chain (each device may have its specific no-operation
> pattern).
>
> At the moment, I wouldn't try to address a few SPI devices in a single
> access.
>
> As you can see, it's no really a mux access like in case of e.g. I2C:
> there, we have a physical device performing multiplexing. Once the I2C
> bus is switched, no extra effort is required in communication between
> the I2C master and I2C device (slave).
>
>>>> compatible = "daisy_chain" or compatible ="simple-bus" would be better?
>>> Not "simple-bus", as this is not a simple memory-mapped bus.
>>> I'd use something like "spi,daisy-chain", to be validated by RobH.
>> Okay, but what makes it generic?
>>
>> What happens with power control of the child devices? While I'd think
>> the only sane design is shared supplies, resets, clocks, etc. (and
>> daisy-chained-devices certainly assumes that), it's certainly possible
>> some cross device control is needed.
>>
>>>> Both could be caught by of_register_spi_devices to populate the daisy
>>>> chain. Do you agree that at that level the chip select could be defined?
>>> Or by a separate SPI device driver that matches against "spi,daisy-chain",
>>> and parse the subnodes.
> I have been thinking about it and came to a similar idea. However, I
> didn't find a straightforward way to associate the SPI devices with the
> abstract daisy-chain device which would then eventually be linked with
> the SPI controller. It would a simple and clean implementation then: SPI
> devices at write/read would call daisy-chain device which would create a
> full message and pass it to SPI controller. The issue is that the SPI
> device requires for all calls SPI controller. It implies that SPI
> daisy-chain would need to be SPI controller as well. However, I think
> currently the SPI concept in the kernel is fixed: SPI controller <-> SPI
> device and there is no place to implement SPI controller <-> SPI
> controller (daisy-chain device) <-> SPI device. Any suggestions on how
> to address it?
>
>>>> The reg properties from the sub-nodes (defining actual spi devices)
>>>> would be ignored, thus not even needed to be defined.
>>> They are needed to determine the order in the chain.
>> Agreed, you need something to address a device. A better address might
>> be the bit position of the device in the chain. Then this could work
>> for any mixture of devices that support chaining (though you'd need to
>> know what's a nop for each device).
> Well, the idea was that the daisy chain will be populated basing on all
> sub-nodes and their order in the device tree. If we go for a reg
> numbering the device in the chain, I think we need then
> '#daisy-chained-devices' as well, such kernel knows a priori the length
> of the chain and can issue an error in case some reg values are missing
> on a given chain.
>
> Regards,
>
> Adrian
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: SPI daisy chain support
  2020-06-17 12:33                     ` Adrian Fiergolski
@ 2020-07-01 13:47                       ` Adrian Fiergolski
  0 siblings, 0 replies; 13+ messages in thread
From: Adrian Fiergolski @ 2020-07-01 13:47 UTC (permalink / raw)
  To: Rob Herring, Geert Uytterhoeven
  Cc: linux-spi, Lukas Wunner,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

[-- Attachment #1: Type: text/plain, Size: 12124 bytes --]

Hi All,

I have implemented the SPI daisy chain support for kernel 4.19. I am
enclosing the patch.

The implementation is transparent for the SPI devices and doesn't
require their modifications. It is based on a virtual SPI device
(spi-daisy_chain) and defines two required device tree properties
('spi-daisy-chain-len' and 'spi-daisy-chain-noop') and one optional
('spi-daisy-chain-bits_per_word'). It has been tested on hardware with a
chain of three ltc2694 devices. I am able to successfully control them.
Unfortunately, I can't confirm that readout works properly

If you agree with this daisy-chain concept, in order to upstream this
feature, I am willing to merge it with the master (could you navigate me
to branch, repository against which I should do it?).

Regards,

Adrian

On 17.06.2020 14:33, Adrian Fiergolski wrote:
> Hi All,
>
> A quick update: I have started implementation taking into account most
> of the points from our discussion (a separate spi,daisy-chain spi
> device, single device addressed at once, etc.). I have realized that the
> daisy-chain device doesn't need to be a SPI controller and information
> about the chain can be stored in the spi_device struct and then handled
> by the SPI subsystem. Once I have a working implementation, I will share
> it with you for a review.
>
> Regards,
>
> Adrian
>
> On 16.06.2020 12:25, Adrian Fiergolski wrote:
>> Hi Geert and Rob,
>>
>> Thank you for your comments.
>>
>> On 16.06.2020 00:22, Rob Herring wrote:
>>> On Mon, Jun 15, 2020 at 3:30 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>>>> Hi Adrian,
>>>>
>>>> On Mon, Jun 15, 2020 at 6:05 PM Adrian Fiergolski
>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>> On 15.06.2020 16:40, Geert Uytterhoeven wrote:
>>>>>> On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>>> Sorry for the typo in the example device tree:
>>>>>>>
>>>>>>> On 15.06.2020 15:57, Adrian Fiergolski wrote:
>>>>>>>> On 15.06.2020 15:07, Geert Uytterhoeven wrote:
>>>>>>>>> On Mon, Jun 15, 2020 at 3:01 PM Adrian Fiergolski
>>>>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>>>>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
>>>>>>>>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
>>>>>>>>>>> <adrian.fiergolski@fastree3d.com> wrote:
>>>>>>>>>>> I have a daisy chain of three ltc2634 slaves (iio/dac/ltc2632.c)
>>>>>>>>>>> connected to a single chip select of the cadence-spi master. I have the
>>>>>>>>>>> impression such a configuration is supported by none of those two
>>>>>>>>>>> drivers. I could try to extend both, however, I haven't found any other
>>>>>>>>>>> SPI driver, where I could find implementation inspiration. Is it
>>>>>>>>>>> supported by kernel?
>>>>>>>>>>>
>>>>>>>>>>> drivers/gpio/gpio-max3191x.c supports "#daisy-chained-devices".
>>>>>>>>>>> drivers/gpio/gpio-74x164.c supports multiple shift registers through the
>>>>>>>>>>> "registers-number" DT property.
>>>>>>>>>>>
>>>>>>>>>>> So both drivers handle this in their SPI slave drivers.
>>>>>>>>>>>
>>>>>>>>>>> Of course this does not handle the mixed case, i.e. daisy-chaining
>>>>>>>>>>> different types of devices.
>>>>>>>>>>>
>>>>>>>>>>> The documentation mentions only about the common 'daisy-chained-devices'
>>>>>>>>>>> property (devicetree/bindings/common-properties.txt). However, in order
>>>>>>>>>>> to try to implement it in the master driver, IMHO, the spi subsystem
>>>>>>>>>>> would need to have a call 'no-operation' to other nodes on the
>>>>>>>>>>> daisy-chain, which are not addressed by the given SPI access. Is there
>>>>>>>>>>> any recommended approach to address this case?
>>>>>>>>>>>
>>>>>>>>>>> Supporting this in a generic way would indeed be nice, as it would mean
>>>>>>>>>>> individual SPI slave drivers no longer have to care about it.
>>>>>>>>>>> However, that may be difficult, as the master needs to known which
>>>>>>>>>>> dummy (no-op) data is safe to shift through the non-addresses SPI slaves.
>>>>>>>>>> In fact, the ultimate solution would be to have it solved at the level
>>>>>>>>>> of the spi subsystem:
>>>>>>>>>>
>>>>>>>>>>   * /spi_device struct/ would contain extra callback which returns msg
>>>>>>>>>>     to be sent for no operation.
>>>>>>>>>>   * spi_device struct would contain a pointer to the list describing the
>>>>>>>>>>     given daisy chain (list of spi_devices on the chain)
>>>>>>>>>>   * /spi_device struct /would contain extra u8 daisy_chain_msg_length
>>>>>>>>>>     indicating length of a command of the addressed device if it's on
>>>>>>>>>>     the daisy chain
>>>>>>>>>>     For example, in case of the ltc2634 device, the regular message
>>>>>>>>>>     consists of 24 bits, but when device is a part of a daisy chain, the
>>>>>>>>>>     messages are 32 bits. This 32 would be stored in
>>>>>>>>>>     /daisy_chain_msg_length./
>>>>>>>>>>   * When /spi_write/ was called (include/linux/spi/spi.h), the
>>>>>>>>>>     /spi_message_init_with_transfer/ would create a msg of length equal
>>>>>>>>>>     to a sum of /daisy_chain_msg_length/ of all devices on the chain.
>>>>>>>>>>     Afterwards, in /spi_message_init_with_transfers/, the actual message
>>>>>>>>>>     would be filled with the command of the addressed device on the
>>>>>>>>>>     chain and no_operation content for all other devices on the chain
>>>>>>>>>>     not being addressed
>>>>>>>>> Sounds good to me.
>>>>>>>>>
>>>>>>>>>>   * I think in such a case, the /daisy-chained-devices /property would
>>>>>>>>>>     be not used, as chains would be build basing on the assigned
>>>>>>>>>>     chipselect (reg property).
>>>>>>>>> So you still have to describe the chain in DT in some way.
>>>>>>>>> As there can be only a single sub node with the same unit address
>>>>>>>>> (= chip select), you probably need a container with that address, which
>>>>>>>>> would contain all devices in the chain, in order (unit addresses 0, 1, ...).
>>>>>>>> Good point. So maybe at the level of the device tree, it could be
>>>>>>>> described like that (based on the spi-cadence example):
>>>>>>>>
>>>>>>>>         spi0: spi@ff040000 {
>>>>>>>>             compatible = "cdns,spi-r1p6";
>>>>>>>>             status = "disabled";
>>>>>>>>             interrupt-parent = <&gic>;
>>>>>>>>             interrupts = <0 19 4>;
>>>>>>>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>>>>>>>             clock-names = "ref_clk", "pclk";
>>>>>>>>             #address-cells = <1>;
>>>>>>>>             #size-cells = <0>;
>>>>>>>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>>>>>>>             daisy-chain0 : daisy_chain@0 {
>>>>>>>>                #address-cells = <1>;
>>>>>>>>                #size-cells = <0>;
>>>>>>>>                reg = <0>;
>>>>>>>>                daisy-chained-devices = 2;
>>>>>>>>
>>>>>>>>                dac0: ltc2632@0 {
>>>>>>>>                    compatible = "lltc,ltc2634-l12";
>>>>>>>>                    reg = <0>;
>>>>>>>>                    spi-max-frequency = <1000000>;
>>>>>>>>                };
>>>>>>>>                dac1: ltc2632@1 {
>>>>>>>>                    compatible = "lltc,ltc2634-l12";
>>>>>>>>                    reg = <1>;
>>>>>>>>                    spi-max-frequency = <2000000>;
>>>>>>>>                };
>>>>>>>>            };
>>>>>>>>         };
>>>>>>>         spi0: spi@ff040000 {
>>>>>>>             compatible = "cdns,spi-r1p6";
>>>>>>>             status = "disabled";
>>>>>>>             interrupt-parent = <&gic>;
>>>>>>>             interrupts = <0 19 4>;
>>>>>>>             reg = <0x0 0xff040000 0x0 0x1000>;
>>>>>>>             clock-names = "ref_clk", "pclk";
>>>>>>>             #address-cells = <1>;
>>>>>>>             #size-cells = <0>;
>>>>>>>             power-domains = <&zynqmp_firmware PD_SPI_0>;
>>>>>>>             daisy-chain0 : daisy_chain@0 {
>>>>>>>                #address-cells = <1>;
>>>>>>>                #size-cells = <0>;
>>>>>>>                #daisy-chained-devices = <2>;
>>>>>> You probably want a proper "compatible" value here instead.
>>>>>> I don't think "#daisy-chained-devices" is needed, it can be derived
>>>>>> from the number of subnodes.
>>> This is not how '#daisy-chained-devices' works either. The chained
>>> devices are represented as a single node and a single driver instance
>>> handles multiple physical devices.
>>>
>>> The above looks like mux'ed access rather than creating a 'super'
>>> device. Would you want to program all N chips in one SPI transfer or
>>> it's one device at a time? (We should be careful with the bindings
>>> that we're not encoding that into the binding as that could evolve
>>> with the OS.)
>> Well, I think the described concept of the daisy chain doesn't apply
>> here then. In principle, we can have different SPI devices, where each
>> is served by a different driver. Together, they create a long register
>> through which data is shifted. IMHO, the fact that the given device is
>> on the daisy chain with other devices should be transparent for its SPI
>> device driver and handled at the level of the SPI subsystem: at SPI
>> write/read stage, the SPI subsystem would combine message of a addressed
>> device with the specific no-operation pattern of all other devices being
>> present on the chain (each device may have its specific no-operation
>> pattern).
>>
>> At the moment, I wouldn't try to address a few SPI devices in a single
>> access.
>>
>> As you can see, it's no really a mux access like in case of e.g. I2C:
>> there, we have a physical device performing multiplexing. Once the I2C
>> bus is switched, no extra effort is required in communication between
>> the I2C master and I2C device (slave).
>>
>>>>> compatible = "daisy_chain" or compatible ="simple-bus" would be better?
>>>> Not "simple-bus", as this is not a simple memory-mapped bus.
>>>> I'd use something like "spi,daisy-chain", to be validated by RobH.
>>> Okay, but what makes it generic?
>>>
>>> What happens with power control of the child devices? While I'd think
>>> the only sane design is shared supplies, resets, clocks, etc. (and
>>> daisy-chained-devices certainly assumes that), it's certainly possible
>>> some cross device control is needed.
>>>
>>>>> Both could be caught by of_register_spi_devices to populate the daisy
>>>>> chain. Do you agree that at that level the chip select could be defined?
>>>> Or by a separate SPI device driver that matches against "spi,daisy-chain",
>>>> and parse the subnodes.
>> I have been thinking about it and came to a similar idea. However, I
>> didn't find a straightforward way to associate the SPI devices with the
>> abstract daisy-chain device which would then eventually be linked with
>> the SPI controller. It would a simple and clean implementation then: SPI
>> devices at write/read would call daisy-chain device which would create a
>> full message and pass it to SPI controller. The issue is that the SPI
>> device requires for all calls SPI controller. It implies that SPI
>> daisy-chain would need to be SPI controller as well. However, I think
>> currently the SPI concept in the kernel is fixed: SPI controller <-> SPI
>> device and there is no place to implement SPI controller <-> SPI
>> controller (daisy-chain device) <-> SPI device. Any suggestions on how
>> to address it?
>>
>>>>> The reg properties from the sub-nodes (defining actual spi devices)
>>>>> would be ignored, thus not even needed to be defined.
>>>> They are needed to determine the order in the chain.
>>> Agreed, you need something to address a device. A better address might
>>> be the bit position of the device in the chain. Then this could work
>>> for any mixture of devices that support chaining (though you'd need to
>>> know what's a nop for each device).
>> Well, the idea was that the daisy chain will be populated basing on all
>> sub-nodes and their order in the device tree. If we go for a reg
>> numbering the device in the chain, I think we need then
>> '#daisy-chained-devices' as well, such kernel knows a priori the length
>> of the chain and can issue an error in case some reg values are missing
>> on a given chain.
>>
>> Regards,
>>
>> Adrian
>>

[-- Attachment #2: 0001-Add-SPI-daisy-chain-support.patch --]
[-- Type: text/x-patch, Size: 23497 bytes --]

From d0af2938bafc81ca2d56a92db7647e1e5a454205 Mon Sep 17 00:00:00 2001
From: Adrian Fiergolski <adrian.fiergolski@fastree3d.com>
Date: Fri, 19 Jun 2020 17:10:21 +0200
Subject: [PATCH] Add SPI daisy chain support.

Signed-off-by: Adrian Fiergolski <adrian.fiergolski@fastree3d.com>
---
 .../bindings/spi/spi-daisy_chain.txt          |  62 +++
 Documentation/spi/00-INDEX                    |   2 +
 drivers/spi/Kconfig                           |   5 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/spi-daisy_chain.c                 | 419 ++++++++++++++++++
 drivers/spi/spi.c                             |  65 ++-
 include/linux/spi/spi-daisy_chain.h           |  32 ++
 include/linux/spi/spi.h                       |  15 +
 10 files changed, 620 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-daisy_chain.txt
 create mode 100644 drivers/spi/spi-daisy_chain.c
 create mode 100644 include/linux/spi/spi-daisy_chain.h

diff --git a/Documentation/devicetree/bindings/spi/spi-daisy_chain.txt b/Documentation/devicetree/bindings/spi/spi-daisy_chain.txt
new file mode 100644
index 000000000000..26e1d2dc4992
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-daisy_chain.txt
@@ -0,0 +1,62 @@
+spi-daisy_chain : The driver handling SPI daisy chains
+
+Required properties for the daisy chain virtual device:
+- compatible		: Should be "spi,daisy_chain"
+- reg			: Chip select assigned to the chain
+
+Required properties for the SPI devices on a common SPI chain (nodes of
+daisy_chain):
+- spi-daisy-chain-len  : Length (in bytes) of the SPI transfer,
+  		         when the SPI device is part of a device chain.
+- spi-daisy-chain-noop : Byte string of no-operation command which should
+  		         be send when device is not addressed during the
+			 given SPI transfer
+
+Optional properties for the SPI devices on a common SPI chain (nodes of
+daisy_chain):
+- spi-daisy-chain-bits_per_word : no-operation transfers involve
+                                  one or more words; word sizes like
+				  eight or 12 bits are common.
+				  In-memory wordsizes are powers of two
+				  bytes (e.g. 20 bit samples use 32 bits).
+				  If not defined, it is assumed to be 8.
+
+Example:
+
+&spi0 {
+	status = "okay";
+	num-cs = <2>;
+	is-decoded-cs = <0>;
+	
+	daisy_chain0: daisy_chain@0 {
+	        compatible = "spi,daisy_chain";
+		spi-max-frequency = <10000000>;
+		reg = <0>;
+
+		dac0: ltc2632@0 {
+	              compatible = "lltc,ltc2634-l12";
+		      spi-daisy-chain-len = <4>;
+		      spi-daisy-chain-noop = [00 F0 00 00];
+		};
+		dac1: ltc2632@1 {
+	              compatible = "lltc,ltc2634-l12";
+		      spi-daisy-chain-len = <4>;
+		      spi-daisy-chain-noop = [00 F0 00 00];
+		};
+		dac2: ltc2632@2 {
+	              compatible = "lltc,ltc2634-l12";
+		      spi-daisy-chain-len = <4>;
+		      spi-daisy-chain-noop = [00 F0 00 00];
+		};
+	};
+};
+
+The virtual daisy chain device is represented as a regular SPI device. Its nodes
+define physical devices available on the chain. The order of the nodes defines
+the order of the physical devices on the chain: MOSI pin of a device represented
+by first node is the last one on the MOSI daisy chain. The daisy-chain
+functionality is transparent to the drivers of physical devices on the
+chain. All nodes share SPI mode, chip select and max speed of the virtual daisy
+chain device. Once one of the physical device is accessed, the spi-daisy_chain
+driver combines this data with no-operation commands of all other devices on the
+chain.
diff --git a/Documentation/spi/00-INDEX b/Documentation/spi/00-INDEX
index 8e4bb17d70eb..457aec3e68ec 100644
--- a/Documentation/spi/00-INDEX
+++ b/Documentation/spi/00-INDEX
@@ -12,5 +12,7 @@ spi-lm70llp
 	- Connecting an LM70-LLP sensor to the kernel via the SPI subsys.
 spi-sc18is602
 	- NXP SC18IS602/603 I2C-bus to SPI bridge
+spi-daisy_chain
+	- Daisy chain driver
 spi-summary
 	- (Linux) SPI overview. If unsure about SPI or SPI in Linux, start here.
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2608d941ee03..0d3ea783f305 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -54,6 +54,11 @@ config SPI_MEM
 	  This extension is meant to simplify interaction with SPI memories
 	  by providing a high-level interface to send memory-like commands.
 
+config SPI_DAISY_CHAIN
+	bool "SPI daisy chain support"
+	help
+	  Enable this option if you want to enable the SPI daist chain support.
+
 comment "SPI Master Controller Drivers"
 
 config SPI_ALTERA
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c991bb287567..c4a93b5ae4cb 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -9,6 +9,7 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
 # config declarations into driver model code
 obj-$(CONFIG_SPI_MASTER)		+= spi.o
 obj-$(CONFIG_SPI_MEM)			+= spi-mem.o
+obj-$(CONFIG_SPI_DAISY_CHAIN)		+= spi-daisy_chain.o
 obj-$(CONFIG_SPI_SPIDEV)		+= spidev.o
 obj-$(CONFIG_SPI_LOOPBACK_TEST)		+= spi-loopback-test.o
 
diff --git a/drivers/spi/spi-daisy_chain.c b/drivers/spi/spi-daisy_chain.c
new file mode 100644
index 000000000000..ded27deb3c0d
--- /dev/null
+++ b/drivers/spi/spi-daisy_chain.c
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * A driver taking care of handling SPI daisy chaines.
+ *
+ * Copyright (C) 2020 Fastree3D
+ *	Adrian Fiergolski <Adrian.Fiergolski@fastree3d.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+
+#include <linux/spi/spi-daisy_chain.h>
+
+/**
+  * spi_daisy_chain_message_pre - generate SPI daisy chain message
+  * @spi: device with which data will be exchanged
+  * @message: describes the data transfers
+  *
+  * The call checks if the SPI device is part of daisy chain. If so, it
+  * generates a message containg no-operation codes
+  * of unaddressed device of a given daisy chain.
+  **/
+
+int spi_daisy_chain_message_pre(struct spi_device *spi,
+				struct spi_message *message)
+{
+	struct spi_transfer *tr, *ntr;
+	struct spi_daisy_chain_device *spi_chain_dev;
+	int rc;
+
+	//the device is not part of a daisy-chain
+	if (spi->daisy_chain_devs == NULL)
+		return 0;
+
+	if (message->is_dma_mapped) {
+		dev_err(&spi->dev,
+			"DMA mapped transfer is not support when on daisy chain");
+		return -EINVAL;
+	}
+
+	if (!list_is_singular(&message->transfers)) {
+		dev_err(&spi->dev,
+			"Mutliple transfer segments are not support when on daisy chain");
+		return -EINVAL;
+	}
+
+	message->daisy_chain_transfers = message->transfers;
+	INIT_LIST_HEAD(&message->transfers);
+
+	list_for_each_entry (spi_chain_dev, spi->daisy_chain_devs, devices) {
+		if (spi_chain_dev->spi == spi) {
+			tr = list_first_entry(&message->daisy_chain_transfers,
+					      struct spi_transfer,
+					      transfer_list);
+
+			//check if mode is not beeing changed
+			if (tr->tx_nbits)
+				switch (spi->mode &
+					(SPI_TX_DUAL | SPI_TX_QUAD)) {
+				case 0:
+					if (tr->tx_nbits & SPI_NBITS_SINGLE)
+						break;
+				case SPI_TX_DUAL:
+					if (tr->tx_nbits & SPI_NBITS_DUAL)
+						break;
+				case SPI_TX_QUAD:
+					if (tr->tx_nbits & SPI_NBITS_QUAD)
+						break;
+				default:
+					dev_err(&spi->dev,
+						"Unsupported tx mode on daisy chain");
+					return -EINVAL;
+				}
+
+			if (tr->rx_nbits)
+				switch (spi->mode &
+					(SPI_RX_DUAL | SPI_RX_QUAD)) {
+				case 0:
+					if (tr->rx_nbits & SPI_NBITS_SINGLE)
+						break;
+				case SPI_RX_DUAL:
+					if (tr->rx_nbits & SPI_NBITS_DUAL)
+						break;
+				case SPI_RX_QUAD:
+					if (tr->rx_nbits & SPI_NBITS_QUAD)
+						break;
+				default:
+					dev_err(&spi->dev,
+						"Unsupported rx mode on daisy chain");
+					return -EINVAL;
+				}
+
+			//check if frequency is not being changed
+			if (tr->speed_hz && tr->speed_hz != spi->max_speed_hz) {
+				dev_err(&spi->dev,
+					"Change of SPI frequency not supported when on daisy chain");
+				return -EINVAL;
+			}
+
+			//daisy chain operations has a regular length
+			if (tr->len == spi_chain_dev->no_operation.len) {
+				tr->bits_per_word = spi_chain_dev->no_operation
+							    .bits_per_word;
+				tr->cs_change = 0;
+
+				list_add_tail(&tr->transfer_list,
+					      &message->transfers);
+			}
+			//daisy chain operation has different than regular length
+			else {
+				if (tr->len > spi_chain_dev->no_operation.len) {
+					dev_err(&spi->dev,
+						"Transmission not supported");
+					return -EINVAL;
+				}
+
+				ntr = kzalloc(sizeof(*ntr), GFP_KERNEL);
+
+				if (!ntr)
+					return -ENOMEM;
+
+				message->daisy_chain_new_transfer = ntr;
+
+				ntr->len = spi_chain_dev->no_operation.len;
+				ntr->bits_per_word = spi_chain_dev->no_operation
+							     .bits_per_word;
+
+				//copy tx buffer
+				if (tr->tx_buf) {
+					ntr->tx_buf =
+						kmalloc(ntr->len, GFP_KERNEL);
+					if (!ntr->tx_buf) {
+						rc = -ENOMEM;
+						goto err_out;
+					}
+
+					//The daisy-chain padding is assumed to be right-justified,
+					//so unused tx bits are transferred first
+					memcpy((void *)((char *)ntr->tx_buf +
+							ntr->len - tr->len),
+					       tr->tx_buf, tr->len);
+				}
+
+				//allocate rx buffer
+				if (tr->rx_buf) {
+					ntr->rx_buf =
+						kmalloc(ntr->len, GFP_KERNEL);
+					if (!ntr->rx_buf) {
+						rc = -ENOMEM;
+						goto err_out;
+					}
+				}
+
+				list_add_tail(&ntr->transfer_list,
+					      &message->transfers);
+			}
+		} else
+			list_add_tail(
+				&spi_chain_dev->no_operation.transfer_list,
+				&message->transfers);
+	}
+
+	return 0;
+
+err_out:
+	if (ntr->tx_buf)
+		kfree(ntr->tx_buf);
+	if (ntr->rx_buf)
+		kfree(ntr->rx_buf);
+	kfree(ntr);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(spi_daisy_chain_message_pre);
+
+/**
+  * spi_daisy_chain_message_post - generate SPI daisy chain message
+  * @spi: device with which data will be exchanged
+  * @message: describes the data transfers
+  *
+  * The call checks if the SPI device is part of daisy chain. If so, it 
+  * removes no-operation codes of unaddressd device of a given chain.
+  **/
+
+void spi_daisy_chain_message_post(struct spi_device *spi,
+				  struct spi_message *message)
+{
+	struct spi_transfer *tr;
+
+	//the device is not part of a daisy-chain
+	if (spi->daisy_chain_devs == NULL)
+		return;
+
+	if (message->daisy_chain_new_transfer) {
+		tr = list_first_entry(&message->daisy_chain_transfers,
+				      struct spi_transfer, transfer_list);
+		if (tr->rx_buf)
+			//The daisy-chain padding is assumed to be right-justified,
+			//so unused rx bits were received first and can be skipped
+			memcpy((void *)tr->rx_buf,
+			       (char *)message->daisy_chain_new_transfer->rx_buf +
+				       message->daisy_chain_new_transfer->len -
+				       tr->len,
+			       tr->len);
+
+		if (message->daisy_chain_new_transfer->tx_buf)
+			kfree(message->daisy_chain_new_transfer->tx_buf);
+
+		if (message->daisy_chain_new_transfer->rx_buf)
+			kfree(message->daisy_chain_new_transfer->rx_buf);
+
+		kfree(message->daisy_chain_new_transfer);
+	}
+
+	list_del(&message->transfers);
+
+	message->transfers = message->daisy_chain_transfers;
+}
+EXPORT_SYMBOL_GPL(spi_daisy_chain_message_post);
+
+void spi_daisy_chain_clean(struct list_head *daisy_chain_devs)
+{
+	struct spi_device *spi_dev;
+	struct spi_daisy_chain_device *spi_chain_dev;
+
+	list_for_each_entry (spi_chain_dev, daisy_chain_devs, devices) {
+		spi_dev = spi_chain_dev->spi;
+		spi_dev_put(spi_dev);
+		kfree(spi_chain_dev->no_operation.tx_buf);
+		kfree(spi_chain_dev);
+	}
+	list_del(daisy_chain_devs);
+	kfree(daisy_chain_devs);
+}
+
+static int spi_daisy_chain_driver_probe(struct spi_device *spi)
+{
+	struct device_node *nc;
+	struct spi_device *spi_dev;
+	struct spi_daisy_chain_device *spi_chain_dev;
+	struct spi_transfer *no_operation;
+	int w_size;
+	int rc;
+
+	//Initialise the SPI daisy-chain queue
+	spi->daisy_chain_devs =
+		kzalloc(sizeof(*spi->daisy_chain_devs), GFP_KERNEL);
+	if (!spi->daisy_chain_devs) {
+		return -ENOMEM;
+	}
+	INIT_LIST_HEAD(spi->daisy_chain_devs);
+
+	for_each_available_child_of_node (spi->dev.of_node, nc) {
+		if (of_node_test_and_set_flag(nc, OF_POPULATED))
+			continue;
+
+		spi_chain_dev = kzalloc(sizeof(*spi_chain_dev), GFP_KERNEL);
+		if (!spi_chain_dev) {
+			rc = -ENOMEM;
+			goto err_out;
+		}
+
+		////////////////////////////////////////////////////////////
+		//extract daisy-chain no-operation command from devicetree
+		////////////////////////////////////////////////////////////
+		no_operation = &spi_chain_dev->no_operation;
+		if (of_property_read_u8(nc, "spi-daisy-chain-bits_per_word",
+					&no_operation->bits_per_word)) {
+			no_operation->bits_per_word = 8;
+		}
+
+		if (no_operation->bits_per_word > 32) {
+			dev_err(&spi->dev,
+				"device %pOF: 'spi-daisy-chain-bits_per_word' property can't by higher than 32",
+				nc);
+			rc = -EINVAL;
+			goto err_out_spi_chain;
+		}
+
+		if (of_property_read_u32(nc, "spi-daisy-chain-len",
+					 &no_operation->len)) {
+			dev_err(&spi->dev,
+				"device %pOF doesn't define 'spi-daisy-chain-len' property",
+				nc);
+			rc = -EINVAL;
+			goto err_out_spi_chain;
+		}
+
+		// SPI transfer length should be multiple of SPI word size
+		// where SPI word size should be power-of-two multiple
+		if (no_operation->bits_per_word <= 8)
+			w_size = 1;
+		else if (no_operation->bits_per_word <= 16)
+			w_size = 2;
+		else
+			w_size = 4;
+
+		/* No partial transfers accepted */
+		if (no_operation->len % w_size) {
+			rc = -EINVAL;
+			dev_err(&spi->dev,
+				"no partial transfers accepted (propeties 'spi-daisy-chain-len' and  spi-daisy-chain-bits_per_word of device %pOF",
+				nc);
+			rc = -EINVAL;
+			goto err_out_spi_chain;
+		}
+
+		no_operation->tx_buf = kmalloc(no_operation->len, GFP_KERNEL);
+		if (!no_operation->tx_buf) {
+			rc = -ENOMEM;
+			goto err_out_spi_chain;
+		}
+
+		if (of_property_read_u8_array(nc, "spi-daisy-chain-noop",
+					      (void *)no_operation->tx_buf,
+					      no_operation->len)) {
+			dev_err(&spi->dev,
+				"device %pOF doesn't define 'spi-daisy-chain-noop' property",
+				nc);
+			rc = -EINVAL;
+			goto err_out_tx_buf;
+		}
+
+		////////////////////////////
+		//allocate a new SPI device
+		////////////////////////////
+		spi_dev = spi_alloc_device(spi->controller);
+		if (!spi_dev) {
+			dev_err(&spi->dev, "spi_device alloc error for %pOF\n",
+				nc);
+			rc = -ENOMEM;
+			goto err_out_tx_buf;
+		}
+		spi_chain_dev->spi = spi_dev;
+		spi_dev->daisy_chain_devs = spi->daisy_chain_devs;
+
+		//select device driver
+		rc = of_modalias_node(nc, spi_dev->modalias,
+				      sizeof(spi_dev->modalias));
+		if (rc < 0) {
+			dev_err(&spi->dev, "cannot find modalias for %pOF\n",
+				nc);
+			goto err_out_spi_dev;
+		}
+
+		//store a pointer to the node in the device structure
+		of_node_get(nc);
+		spi_dev->dev.of_node = nc;
+
+		//add the SPI device to the chain
+		list_add_tail(&spi_chain_dev->devices, spi->daisy_chain_devs);
+	}
+
+	//////////////////////
+	//add all SPI devices
+	//////////////////////
+	list_for_each_entry (spi_chain_dev, spi->daisy_chain_devs, devices) {
+		spi_dev = spi_chain_dev->spi;
+
+		//All devices on the chain share settings of the daisy-chain node
+		//The individual settings of the SPI nodes are ignored
+		spi_dev->mode = spi->mode;
+		spi_dev->chip_select = spi->chip_select;
+		spi_dev->max_speed_hz = spi->max_speed_hz;
+
+		//Register the new device
+		rc = spi_add_device(spi_dev);
+		if (rc) {
+			dev_err(&spi->dev,
+				"spi_device register error on daisy chain %pOF\n",
+				spi_dev->dev.of_node);
+			of_node_put(nc);
+			goto err_out;
+		}
+	}
+
+	return 0;
+
+err_out_spi_dev:
+	spi_dev_put(spi_chain_dev->spi);
+err_out_tx_buf:
+	kfree(spi_chain_dev->no_operation.tx_buf);
+err_out_spi_chain:
+	kfree(spi_chain_dev);
+err_out:
+	spi_daisy_chain_clean(spi->daisy_chain_devs);
+	return rc;
+}
+
+static int spi_daisy_chain_driver_remove(struct spi_device *spi)
+{
+	spi_daisy_chain_clean(spi->daisy_chain_devs);
+	return 0;
+}
+
+static const struct of_device_id spi_daisy_chain_of_match[] = {
+	{
+		.compatible = "spi,daisy_chain",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, spi_daisy_chain_of_match);
+
+static struct spi_driver spi_daisy_chain_driver = {
+	.probe = spi_daisy_chain_driver_probe,
+	.remove = spi_daisy_chain_driver_remove,
+	.driver =
+		{
+			.name = "daisy_chain",
+			.of_match_table = spi_daisy_chain_of_match,
+		},
+};
+module_spi_driver(spi_daisy_chain_driver);
+
+MODULE_AUTHOR("Adrian Fiergolski <Adrian.Fiergolski@fastree3d.com>");
+MODULE_DESCRIPTION("Driver handling SPI daisy chain");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:daisy_chain");
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index fd3f1aa79f26..4f32456f8cd0 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -29,6 +29,9 @@
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi-mem.h>
+#ifdef	CONFIG_SPI_DAISY_CHAIN
+#include <linux/spi/spi-daisy_chain.h>
+#endif
 #include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_domain.h>
@@ -478,14 +481,33 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
 static void spi_dev_set_name(struct spi_device *spi)
 {
 	struct acpi_device *adev = ACPI_COMPANION(&spi->dev);
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	struct spi_daisy_chain_device *spi_chain_dev;
+	int spi_dev_index;
+#endif
 
 	if (adev) {
 		dev_set_name(&spi->dev, "spi-%s", acpi_dev_name(adev));
 		return;
 	}
 
-	dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->controller->dev),
-		     spi->chip_select);
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	if (spi->daisy_chain_devs != NULL) {
+		spi_dev_index = 0;
+		list_for_each_entry (spi_chain_dev, spi->daisy_chain_devs,
+				     devices)
+			if (spi_chain_dev->spi == spi)
+				break;
+			else
+				spi_dev_index++;
+		dev_set_name(&spi->dev, "%s.%u.%u",
+			     dev_name(&spi->controller->dev), spi->chip_select,
+			     spi_dev_index);
+
+	} else
+#endif
+		dev_set_name(&spi->dev, "%s.%u",
+			     dev_name(&spi->controller->dev), spi->chip_select);
 }
 
 static int spi_dev_check(struct device *dev, void *data)
@@ -529,14 +551,27 @@ int spi_add_device(struct spi_device *spi)
 	 * chipselect **BEFORE** we call setup(), else we'll trash
 	 * its configuration.  Lock against concurrent add() calls.
 	 */
-	mutex_lock(&spi_add_lock);
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	/* Do not lock the controller when registering the daisy_chain driver
+	 * as the last one wouldn't be able to register its subnodes
+	 */
+	if (strcmp((const char *)spi->dev.of_node->name, "daisy_chain") == 0)
+#endif
+		mutex_lock(&spi_add_lock);
 
-	status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
-	if (status) {
-		dev_err(dev, "chipselect %d already in use\n",
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	if (spi->daisy_chain_devs == NULL) {
+#endif
+		status = bus_for_each_dev(&spi_bus_type, NULL, spi,
+					  spi_dev_check);
+		if (status) {
+			dev_err(dev, "chipselect %d already in use\n",
 				spi->chip_select);
-		goto done;
+			goto done;
+		}
+#ifdef CONFIG_SPI_DAISY_CHAIN
 	}
+#endif
 
 	if (ctlr->cs_gpios)
 		spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];
@@ -561,7 +596,10 @@ int spi_add_device(struct spi_device *spi)
 		dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
 
 done:
-	mutex_unlock(&spi_add_lock);
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	if (strcmp((const char *)spi->dev.of_node->name, "daisy_chain") == 0)
+#endif
+		mutex_unlock(&spi_add_lock);
 	return status;
 }
 EXPORT_SYMBOL_GPL(spi_add_device);
@@ -3116,6 +3154,12 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
 	SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, spi_sync);
 	SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync);
 
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	status = spi_daisy_chain_message_pre(spi, message);
+	if (status < 0)
+		return status;
+#endif
+
 	/* If we're not using the legacy transfer method then we will
 	 * try to transfer in the calling context so special case.
 	 * This code would be less tricky if we could remove the
@@ -3149,6 +3193,11 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
 		status = message->status;
 	}
 	message->context = NULL;
+
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	spi_daisy_chain_message_post(spi, message);
+#endif
+
 	return status;
 }
 
diff --git a/include/linux/spi/spi-daisy_chain.h b/include/linux/spi/spi-daisy_chain.h
new file mode 100644
index 000000000000..beb409b0be2e
--- /dev/null
+++ b/include/linux/spi/spi-daisy_chain.h
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * A driver taking care of handling daisy chaines.
+ *
+ * Copyright (C) 2020 Fastree3D
+ *	Adrian Fiergolski <Adrian.Fiergolski@fastree3d.com>
+ */
+
+#ifndef __LINUX_SPI_DAISY_CHAIN_H
+#define __LINUX_SPI_DAISY_CHAIN_H
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+/**
+ * struct spi_daisy_chain - interface to a SPI device on a daisy chain
+ * @spi: SPI device on the daisy chain
+ * @no_operation: no-opeartion SPI message for the given device
+ * @devices: list of SPI devices sharing the given daisy chain
+ **/
+struct spi_daisy_chain_device {
+	struct spi_device *spi;
+	struct spi_transfer no_operation;
+	struct list_head devices;
+};
+
+extern int spi_daisy_chain_message_pre(struct spi_device *spi,
+				       struct spi_message *message);
+extern void spi_daisy_chain_message_post(struct spi_device *spi,
+					 struct spi_message *message);
+
+#endif /* __LINUX_SPI_DAISY_CHAIN_H */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index b5c84c1507cd..c247d1e2cfb9 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -102,6 +102,9 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
  * @dev: Driver model representation of the device.
  * @controller: SPI controller used with the device.
  * @master: Copy of controller, for backwards compatibility.
+ * @daisy_chain_devs: list of all SPI devices on the daisy chain
+ *      used by the given SPI device.
+ *      Handled by the SPI daisy chain driver.
  * @max_speed_hz: Maximum clock rate to be used with this chip
  *	(on this board); may be changed by the device's driver.
  *	The spi_transfer.speed_hz can override this for each transfer.
@@ -144,6 +147,9 @@ struct spi_device {
 	struct device		dev;
 	struct spi_controller	*controller;
 	struct spi_controller	*master;	/* compatibility layer */
+#ifdef CONFIG_SPI_DAISY_CHAIN
+	struct list_head        *daisy_chain_devs;
+#endif
 	u32			max_speed_hz;
 	u8			chip_select;
 	u8			bits_per_word;
@@ -821,6 +827,11 @@ struct spi_transfer {
 /**
  * struct spi_message - one multi-segment SPI transaction
  * @transfers: list of transfer segments in this transaction
+ * @daisy_chain_transfers: head of the original transfers queue.
+ *      Handled by the SPI daisy chain driver.
+ * @daisy_chain_new_transfer: pointer to an extra SPI transfer,
+ *      in case it had to be created.
+ *      Handled by the SPI daisy chain driver.
  * @spi: SPI device to which the transaction is queued
  * @is_dma_mapped: if true, the caller provided both dma and cpu virtual
  *	addresses for each transfer buffer
@@ -851,6 +862,10 @@ struct spi_transfer {
 struct spi_message {
 	struct list_head	transfers;
 
+#ifdef	CONFIG_SPI_DAISY_CHAIN
+	struct list_head	daisy_chain_transfers;
+        struct spi_transfer     *daisy_chain_new_transfer;
+#endif
 	struct spi_device	*spi;
 
 	unsigned		is_dma_mapped:1;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-07-01 13:47 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-12 16:25 [cadence-spi] daisy chain Adrian Fiergolski
2020-06-13  7:33 ` Geert Uytterhoeven
2020-06-15 13:01   ` Adrian Fiergolski
2020-06-15 13:07     ` Geert Uytterhoeven
2020-06-15 13:57       ` Adrian Fiergolski
2020-06-15 14:06         ` Adrian Fiergolski
2020-06-15 14:40           ` Geert Uytterhoeven
2020-06-15 16:05             ` Adrian Fiergolski
2020-06-15 21:30               ` Geert Uytterhoeven
2020-06-15 22:22                 ` Rob Herring
2020-06-16 10:25                   ` Adrian Fiergolski
2020-06-17 12:33                     ` Adrian Fiergolski
2020-07-01 13:47                       ` SPI daisy chain support Adrian Fiergolski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).