Re: [cadence-spi] daisy chain

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxx> wrote:
>>> Hi Adrian,
>>>
>>> On Mon, Jun 15, 2020 at 6:05 PM Adrian Fiergolski
>>> <adrian.fiergolski@xxxxxxxxxxxxx> wrote:
>>>> On 15.06.2020 16:40, Geert Uytterhoeven wrote:
>>>>> On Mon, Jun 15, 2020 at 4:06 PM Adrian Fiergolski
>>>>> <adrian.fiergolski@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxx> wrote:
>>>>>>>>> On 13.06.2020 09:33, Geert Uytterhoeven wrote:
>>>>>>>>>> On Fri, Jun 12, 2020 at 6:26 PM Adrian Fiergolski
>>>>>>>>>> <adrian.fiergolski@xxxxxxxxxxxxx> 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
>



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux