<snip>
> I have been using SPI on the Dragonboard 410c and found some issues.
> Specifically Hardware Chip Select is not working on the Debian kernel from
> Linaro (Build #202). It turns out that the SPI_IO_C_MX_CS_MODE bit in the
> SPI_IO_CONTROL register needs to be set. My 'patch' is very simplistic, and I
> certainly haven't tested it against all cases of DMA/non-DMA and various
> transfer lengths, but it does fix my one case.
Since the spi-qup driver used the generic spi transfer_one_message I would keep
the CS pin as a GPIO function rather than the blsp_spi5 function and let the
framework assert/deassert it.
> First I changed only the dtsi files to enable a spidev driver with hardware
> chip select (and set the drive strength correctly):
>
> diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> index f6d2bcb6dbd1..874150a412a2 100644
> --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> @@ -208,8 +208,14 @@
> /* On Low speed expansion */
> label = "LS-SPI0";
> +/* cs-gpios = <&msmgpio 18 0> */
> status = "okay";
> + spidev@0 {
> + compatible = "spidev";
> + spi-max-frequency = <100000>;
> + reg = <0>;
> + };
> };
>
> leds {
> diff --git a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
> b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
> index 899f2b28a9c9..1c22b4414edf 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
> @@ -208,7 +208,7 @@
> pins = "gpio16", "gpio17", "gpio19";
> };
> pinmux_cs {
> - function = "gpio";
> + function = "blsp_spi5";
> pins = "gpio18";
> };
> pinconf {
> @@ -218,7 +218,7 @@
> };
> pinconf_cs {
> pins = "gpio18";
> - drive-strength = <2>;
> + drive-strength = <12>;
> bias-disable;
> output-high;
> };
>
> Here is what my 3-byte transactions end up looking like (Yellow - Clock,
> Green – Data Out, Magenta- Chip Select) :
>
>
> As you can see the chip select is going high between each byte of data. This
> violates the SPI protocol and I am unable to transfer data from the device.
>
> Next I changed the SPI driver:
>
> diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
> index 68f95acf7971..aed71ef7e3fd 100644
> --- a/drivers/spi/spi-qup.c
> +++ b/drivers/spi/spi-qup.c
> @@ -580,6 +580,7 @@ static int spi_qup_io_config(struct spi_device *spi,
> struct spi_transfer *xfer)
> else
> control &= ~SPI_IO_C_CLK_IDLE_HIGH;
>
> + config |= SPI_IO_C_MX_CS_MODE;
> writel_relaxed(control, controller->base + SPI_IO_CONTROL);
>
> config = readl_relaxed(controller->base + SPI_CONFIG);
> @@ -928,7 +929,7 @@ static int spi_qup_probe(struct platform_device *pdev)
> base + QUP_ERROR_FLAGS_EN);
>
> writel_relaxed(0, base + SPI_CONFIG);
> - writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
> + writel_relaxed(SPI_IO_C_NO_TRI_STATE|SPI_IO_C_MX_CS_MODE, base +
> SPI_IO_CONTROL);
>
> ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
> IRQF_TRIGGER_HIGH, pdev->name, controller);
>
> This sets the SPI_IO_C_MX_MODE bit in the SPI_IO_CONTROL register. Once this
> is done the SPI transactions look like this:
>
>
>
> As you can see the Chip Select stays low for the entire transaction and the
> device successfully transfers data.
>
> I have NOT tested this change very carefully and I have not covered all of
> the possible cases (different processors, DMA vs non-DMA, etc). This ‘patch’
> is only known to work with MSM8916/APQ8016, and only with 3-byte transfers at
> 100kHz.
>
> Lawrence King
> Senior Staff Eng./mgr
> Qualcomm Canada Inc.
> Suite 100, 105 Commerce Valley Drive West
> Markham Ontario Canada L3T 7W3
> +1(905)482-5403 – office
> +1(416)627-7302 - cell
>
>
> -----Original Message-----
> From: Andy Gross [mailto:[email protected]]
> Sent: Tuesday, February 14, 2017 4:21 PM
> To: King, Lawrence <[email protected]>
> Cc: Fradkin, Alex <[email protected]>; [email protected];
> Bjorn Andersson <[email protected]>; Srinivas Kandagatla
> <[email protected]>; Elster, Constantine
> <[email protected]>; Sedlak Grinbaum, Anna Hanna
> <[email protected]>
> Subject: Re: SPI fix needed in kernel
>
> On 14 February 2017 at 14:37, King, Lawrence <[email protected]> wrote:
>> Dear All:
>>
>>
>>
>> I am back on the case of the SPI driver for the APQ8016. This time I
>> am using the 'latest' build #202 of Debian.
>>
>>
>>
>> In order to get the hardware Chip Select to operate correctly I tried
>> the same 'trick' I had been doing before, I added the line of code
>> that sets the SPI_IO_C_MX_CS_MODE bit in the SPI_IO_CONTROL register
>> in the function spi_qup_io_config(). But to my annoyance it didn't fix the
>> problem.
>
> Looking at the spi_qsd.c in 3.18, there is a pretty complex dance involved
> with deciding whether or not to set the MX_CS. Probably because of the weird
> transfer coalescing they do.
>
> In addition, they are doing a FORCE_CS when the spi core calls set_cs.
>
>>
>>
>> In order to get hardware CS control to work I also had to change the
>> SPI_IO_CONTROL in the function spi_qup_probe() from
>>
>> writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
>>
>> to
>>
>> writel_relaxed(SPI_IO_C_NO_TRI_STATE|SPI_IO_C_MX_CS_MODE, base +
>> SPI_IO_CONTROL);
>>
>>
>>
>> I would have thought that the spi_qup_io_config() ran after the
>> spi_qup_probe(), but this is apparently not the case.
>
> The spi_qup_io_config() is run every time there is a spi transaction.
> It is called from spi_qup_transfer_one().
>
>>
>>
>> Why is the SPI_IO_C_MX_CS_MODE bit still not set in the code? Without
>> this bit set hardware CS will never work properly. Now that you have
>> separated out the old controller from the new controller with the
>> qup_v1 flag it should be easy…
>
> I presume no one sent a patch to the mailing list for this. If you do,
> please CC linux-msm. But due to the details above, it might be a good idea
> to ask someone in Boulder about all the different states where you need some
> flags set and others not set if you want to use auto chip select. Sagar
> Dharia might be a good starting point.
>
>
> Regards,
>
> Andy