iMX8X: max frequency of spidev

To enable the spidev I use this patch

diff --git a/arch/arm64/boot/dts/freescale/fsl-imx8qxp-colibri-eval-v3.dts b/arch/arm64/boot/dts/freescale/fsl-imx8qxp-colibri-eval-v3.dts
index bb565ab6ea76..dd384ffdaf28 100644
--- a/arch/arm64/boot/dts/freescale/fsl-imx8qxp-colibri-eval-v3.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-imx8qxp-colibri-eval-v3.dts
@@ -12,3 +12,14 @@
 	model = "Toradex Colibri iMX8QXP/DX on Colibri Evaluation Board V3";
 	compatible = "toradex,colibri-imx8qxp-eval-v3", "toradex,colibri-imx8qxp", "fsl,imx8qxp";
 };
+
+&lpspi2 {
+	mcp2515: can@0 {
+		status = "disabled";
+	};
+
+	spidev0: spidev@0 {
+		spi-max-frequency = <60000000>;
+		status = "okay";
+	};
+};

There I set ‘spi-max-frequency’ to ‘60000000’ since the SPI of the Colibri iMX8QXP supports this frequency.

The command

hexdump /sys/class/spi_master/spi0/of_node/spidev\@0/spi-max-frequency

gives me 0x03938700 in reverse byte order (that is 60000000 decimal).

With my test program (see this question: (link) I’m able to send data with up to 12 MHz.

But when I try to rise the frequency above that limit, I got an ‘Invalid argument’ error for the write() command.

What am I missing? Do I have to modify clock settings of the lpspi2 too? E.g. set the ‘assigned-clock-rates’ to a bigger value like ‘60000000’

I’ve found an answer by myself here.

But it has a weird behavior. I set ‘assigned-clock-rates’ to 120 MHz and ‘spi-max-frequency’ to 60 MHz. Now when I set the speed in the test program to 50 MHz I measure 58 MHz with my oszilloscope. And when I set the speed to 60 MHz I got the ‘Invalid argument’ error again.

The maximum spi frequency I can set in the test program is 58181818 Hz

HI @Mowlwurf

Which parent clock did you use?

Here is the fdtdump of my device tree: link.

From what I understand the spidev uses the lpspi2. For this the parent clock is defined in the file ‘fsl-imx8dx.dtsi’ as follows:

clocks = <&clk IMX8QXP_SPI2_CLK>,
          <&clk IMX8QXP_SPI2_IPG_CLK>;
clock-names = "per", "ipg";
assigned-clocks = <&clk IMX8QXP_SPI2_CLK>;

And IMX8QXP_SPI2_CLK is defined as 135 in’ /include/dt-bindings/clock/imx8qxp-clock.h’

HI

Thanks for the Information.
Could you check which Range of frequencies is not working well?

Additionally please share the Clock Tree when SPI is active:
cat /sys/kernel/debug/clk/clk_summary

Thanks and best regards,
Jaski

Here is the output of the clock tree: link. There the input clock for the spi is 116363636 MHz

I run the test program (link) with several settings for the max spi frequency and measure the frequency of the spi_clk pin with an MSO4104 from Tektronix:

 Program [MHz]    Measured [MHz]    divider for base clock
     60           Invalid argument          1 ?
     50              58,1                   2
     40              58,1                   2
     30              38,7                   3
     20              23,3                   5
     10              10,6                  11
      5               5,1                  23
      2               2,0                  58 ?
      1               1,0                 116 ?

I would expect the following:

 Program [MHz]    Measured [MHz]    divider for base clock
     60              58,1                   2
     50              38,8                   3
     40              38,8                   3
     30              29,1                   4
     20              19,4                   6
     10               9,7                  12
      5               4,8                  24
      2               2,0                  59
      1               1,0                 117

So for me it seems that there is an off-by-one-error in the calculation for the divider of the spi base clock.

HI @Mowlwurf

These dividers are set by the SPI driver. Note that smallest value for the driver is 2.

So for me it seems that there is an off-by-one-error in the calculation for the divider of the spi base clock.

Yes, that’s true.

We will internally look into this and come back to you. Do you have a deadline for the solution of this issue?

Best regards,
Jaski

No there is no deadline.

Can you give me a hint how I can set the spi base clock to exactly 100 or 120 MHz?

No, unfortunately not. As I said, we will look into this and come back to you.

Thank you for your detailed answer.

Hi @Mowlwurf,

According to the reference manual, “The LPSPI divides the functional clock by a prescaler; the resulting frequency must be at least 2 times faster than the SPI external clock frequency (LPSPI_SCK).”

I’m afraid it’s impossible to use LPSPI_CLK (freq on spi_clk pin in your terms) 60MHz with the input clock 116363636 Hz. The same rule is for other freqs.

Also, it is impossible to set LPSPI_SCK to 120000000. The source for the SPI clock is DIG_PLL0 with 1280MHz. The divider for this source is an integer, so you can set 128000000 (1280000000 / 10) or 116363636 (128000000 / 11).

So, to use SPI with 60000000 bps speed, you should set LPSPI_SCK to 128000000 or higher value.


&lpspi2 {
    ...
    assigned-clock-rates = <128000000>;
    ...
}

root@colibri-imx8x:~# cat /sys/kernel/debug/clk/clk_summary | grep spi2
     spi2_div                                 1            1  128000000           0 0  
        spi2_clk                              1            1  128000000           0 0  
        spi2_ipg_clk                          1            1   120000000          0 0  

I slightly changed your test program and got the following result with mentioned settings:

root@colibri-imx8x:~# ./spi-freq
SPI open: OK (3)
SPI set SPI_MODE_0 mode: OK
SPI set 32 bits per word: OK
Set speed 1000000...OK
Set speed 2000000...OK
Set speed 5000000...OK
Set speed 10000000...OK
Set speed 20000000...OK
Set speed 30000000...OK
Set speed 40000000...OK
Set speed 58181818...OK
Set speed 60000000...OK

Please, look at the patch I’ve attached to this answer.link text

@Mowlwurf could you let us know if the changing “assigned-clock-rates” solves your issue, please?

Changing the “assigned-clock rates” solves my initial issue that I can not transmit data with more then 12 MHz. I changed it to 120 MHz and can now transmit with up to 58,2 MHz.

The second issue with the off-by-one-error in the calculation of the base clock divider (mentioned above in comment on Feb 05) is still present but can be worked around.

Perfect that it works.

Thanks for your feedback.

Best regards,
Jaski