Re: [PATCH] spi: xilinx: Add DT support for selecting transfer word width

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

 



Hi Alvaro,

On Tue, Oct 22, 2019 at 4:01 PM Alvaro Gamez Machado
<alvaro.gamez@xxxxxxxxxx> wrote:
> On Tue, Oct 22, 2019 at 03:03:18PM +0200, Geert Uytterhoeven wrote:
> > On Tue, Oct 22, 2019 at 12:38 PM Alvaro Gamez Machado
> > <alvaro.gamez@xxxxxxxxxx> wrote:
> > > On Tue, Oct 22, 2019 at 11:20:07AM +0100, Mark Brown wrote:
> > > > On Tue, Oct 22, 2019 at 11:00:07AM +0200, Alvaro Gamez Machado wrote:
> > > >
> > > > >             of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits",
> > > > >                                       &num_cs);
> > > > > +           ret = of_property_read_u32(pdev->dev.of_node,
> > > > > +                                      "xlnx,num-transfer-bits",
> > > > > +                                      &bits_per_word);
> > > > > +           if (ret)
> > > > > +                   bits_per_word = 8;
> > > >
> > > > Any new DT property needs documentation adding but in any case this
> > >
> > > Oh, ok. If this patch is of any interest, then I should provide changes to
> > > the appropriate file under Documentation/, is that right?
> > >
> > > I was preparing and testing a second patch to add "spi-bits-per-word"
> > > property to children of the SPI driver, similar to the spi-max-frequency
> > > property and others alike, to fully support AXI Quad SPI core with different
> > > word widths. This also modifies the DT, so I guess it'd be better to send a
> > > single patch that comprises all these changes alongside the DT
> > > documentation. Would that be correct procedure?
> >
> > Is this "spi-bits-per-word" a property of the SPI slave device?
> > If yes, it may be better to hardcode it in the SPI slave device driver,
> > as it is fixed for that type of SPI slave.
> >
> > If not, perhaps I'm misunderstanding the purpose.
>
> Ok, this is a bit confusing and my patch didn't really explain a lot. I'll
> try to explain myself and not make a lot of mistakes.
>
> Most, if not all SPI slaves, have a fixed word width, which is typically 8
> bits, but there exist some devices for which this value is 16, 32 or who
> knows what.
>
> On the other hand, master SPI devices may have the possibility to use word
> widths of 8, 16, 32 or whatever, and some of them may be able to switch its
> word width on demand.

OK.

> The specific case of AXI Quad SPI core is that you choose this value upon
> instantiation and you cannot modify it via software. This means that you
> could instantiate an 8 bit IP core to talk to a 32 wordwidth slave, and
> you'd get no useful communication, that's the harwdare designer
> responsibility: both devices must match in its wordwidth.
>
> More over, it seems that linux needs to know this information to build the
> messages it needs to send to the SPI master.

You also have to configure this in spi_controller.bits_per_word_mask.
Typical values are:
    - SPI_BPW_RANGE_MASK(8, 32),
    - SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32),
    - SPI_BPW_MASK(8).

So you have to use SPI_BPW_MASK(8)[*] resp. SPI_BPW_MASK(32).

[*] This could actually be relaxed to 8/16/24/32, as the last three can be
    emulated using 8.

> For something this simple, I believe the best approach is a DT property, as
> I've proposed in my not-very-clearly-explained patch. So, this means a DT
> property for the SPI master, although a different compatible string could be
> used as you suggested. See below for my comments on this idea.

OK.

> Any way, afer this, assuming we have a way of setting this master driver
> with the correct wordwidth, and given that there may be SPI masters that are
> able to switch it on demand, it seems feasible to connect two or more slaves
> with different wordwidth to the same SPI master.

Sure, but only if the master supports all bits_per_word values needed
by the slaves.

> It's true that this value could be hardcoded in each slave device driver
> code, but currently the SPI infrastructure sets this value to 8 by

Slave drivers for slaves using a different value should fill in a different
value.

> default. What's wrong with this? The problem lies on userspace drivers.
>
> For SPI slaves that do not have an in kernel code, we can add a compatible
> string to spidev_dt_ids, which will provide a /dev/spidevX.Y node which can
> be used from userspace, from the set of properties that we write on the DT.
>
> Using this spidev node one would expect to be able to set this slave in
> particular to a different datawidth using SPI user interface, with ioctl
> SPI_IOC_WR_BITS_PER_WORD, basically the same as what we'd do in the kernel.
>
> What happens, however, is that on boot a wordwidth of 8 is assigned by
> default, and so there occurs this discrepancy between what the master is
> capable of and what the slave requires. The patch I sent before makes the
> master know it can work with something different to 8, in my case that's 32.
> But when trying to initialize /dev/spidev devices, the following happens:
>
> xilinx_spi 44a10000.spi: can't setup spi1.0, status -22
> spi_master spi1: spi_device register error /amba_pl/spi@44a10000/spidev@0
> spi_master spi1: Failed to create SPI device for /amba_pl/spi@44a10000/spidev@0
>
> So now there's no way for me to open /dev/spidev1.0 and change its
> bits-per-word parameter, because /dev/spidev1.0 does not exist and it's
> trying to link an 8 bit wordwidth slave with a 32 bit wordwidth master.

OK, so that's a bug in the SPI core, or in spidev.

> So, in fact here below is the full patch that will serve my purpose of
>
> a) Configuring my up-to-now unconfigurable SPI master driver to support
>    16 or 32 wordwidth.

OK.

> b) Allow its slaves to be visible from userspace without the need of a
>    kernel driver
>
> diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
> index 92ea22fedb33..46bb103ef30e 100644
> --- a/drivers/spi/spi-xilinx.c
> +++ b/drivers/spi/spi-xilinx.c
> @@ -380,7 +380,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
>         struct xilinx_spi *xspi;
>         struct xspi_platform_data *pdata;
>         struct resource *res;
> -       int ret, num_cs = 0, bits_per_word = 8;
> +       int ret, num_cs = 0, bits_per_word;
>         struct spi_master *master;
>         u32 tmp;
>         u8 i;
> @@ -392,6 +392,11 @@ static int xilinx_spi_probe(struct platform_device *pdev)
>         } else {
>                 of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits",
>                                           &num_cs);
> +               ret = of_property_read_u32(pdev->dev.of_node,
> +                                          "xlnx,num-transfer-bits",
> +                                          &bits_per_word);
> +               if (ret)
> +                       bits_per_word = 8;
>         }
>
>         if (!num_cs) {

Looks good to me.

> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index f9502dbbb5c1..06424b7b0d73 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -1792,6 +1792,10 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
>         }
>         spi->max_speed_hz = value;
>
> +       /* Bits per word */
> +       if (!of_property_read_u32(nc, "spi-bits-per-word", &value))
> +               spi->bits_per_word = value;
> +
>         return 0;
>  }

Probably this should be fixed in spidev instead, to use a value that
conforms to spi_controller.bits_per_word_mask.
That would remove the need for specifying this in DT.
Once the spidev is instantiated, userspace can still change it using
SPI_IOC_WR_BITS_PER_WORD.

> > > > shouldn't be set in DT, it should be set by the client driver - it's
> > > > going to be a fixed property of the device, not something that varies
> > > > per system.
> > >
> > > But this is in fact something that changes per system. When instantiating an
> > > AXI Quad SPI core in a HDL design that's exactly one of the options you can
> > > provide. In fact, in the board I'm working with right now, I'm instantiating
> > > two SPI cores, one of them with 8 bits per word but the other one requires
> > > 32 bits per word, as the devices it's going to talk to have this
> > > requirement.
> >
> > So you're instantiating two variants of the same "xlnx,axi-quad-spi-1.00.a"
> > controller, with different options?
> > While you could add an "xlnx,foo" DT property for that, an alternative could
> > be to introduce a new compatible value.
> > It all depends on how many options there are when instantiating such a
> > controller.
> >
>
> Regardless of which SPI slave will be connected to the SPI master, there's
> the need to indicate in the DT how is this master configured. Now, you could
> definitely add another compatible value, but then I'd need to introduce a
> compatible value for 8 bits, another one for 16 and a last one for 32. I
> don't think this is easier nor powerful enough, and I think the use of the
> DT property matches very well with other drivers I've read, such as
> axi-ethernet and others (most of them from the Xilinx IP core set), but I
> surely can be in the wrong about this, I'm pretty noob on kernel code as you
> can see.

Yes, using a DT property for this is fine.  It just needs to be documented
in Documentation/devicetree/bindings/spi/spi-xilinx.txt (or its yaml
counterpart).

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx

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



[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux