CS on 40 pin SPI deasserts in Jetpack 6 versus 5 for IMU driver

I’m on an Orin Dev Kit - JP 6.2 and my device-tree and spi-tegra114.c have been updated to work in a single read/write fashion with drivers for the ADI IMU. The modifications to spi-tegra114.c are per the response from SPI bus chip select on Jetpack 6.2 with device-tree - #4 by jays

Running the IMU kernel space driver, I can see that it does work for a specific situation but when there is a need for a burst read - per the IMU datasheet here:


Notice the CS is always asserted between the MOSI (DIN) and then MISO (DOUT) lines respond but the CS must stay asserted during this time.

Looks like the following post has the exact same issue on the CS but didn’t notice that the burst read feature does not work.

You can see the difference between JP 5 and JP6 and clearly the CS deasserting is the problem.

It looks like cs_change doesn’t seem to be properly handled with this driver. There is no work around for this until spi-tegra114.c is asserting the CS line properly. From the oscope this is what it looks like now:

Red = CS
Yellow = CLK.

You can see the first 16 clocks, the CS is asserted and then immediately afterwards it is deasserted and then asserted again. That doesn’t match the requirement on the datasheet. Any updates to fix this issue? I know the response have been a fix in the up and coming JP however that’s been a few months.

I also know in user-space, the burst read does work.

Hi jays,

Do you mean that there’s still CS related issue even if you’ve applied the patch from your previous topic?

From the waveform you shared, it looks good to me as CS de-asserted when there’s no CLK output.

If you want it always asserted during several SCLK outputs, you may need to customize the driver for your use case.

Sorry that the recent JP6 releases are all minor updates, the previous fix should be included in next L4T r36.5.x release.

Yes the CS is the issue even with the application of the patches from prior topics.

The CS assertion must be held during all the SCLKs - regardless if there isn’t a SCLK because the part requires the CS to be asserted during the burst read. The first 16 clocks shown are the MOSI events while the remaining clocks are waiting for MISO to occur. MISO can’t occur because the parts wants CS to be asserted once the MOSI lines are done.

From what I can tell, it looks like the spi-tegra114.c driver doesn’t handle the .cs_change properly since the transaction in the driver has been modified to force cs_change = 0 and we see no difference in the CS waveform.

Even removing nvidia, enable_hw-based-cs in the device tree does nothing to change this around.

Could you try to combine write(MOSI) and read(MISO) to a single spi_message for spi_transfer in your use case?
For example, if you want to write 16 bytes and receive N bytes. Please specify 16+N as total length for your spi transaction. It could help your CS keeps asserted during this spi transaction.

The code that does this is here - Making sure you're not a bot!

You can see the transfers are all put together into one spi message already and this code hasn’t changed from Jetpack 5 to Jetpack 6. We do know this is working fine also on RPI too so it seems like a problem with how spi-tegra114.c is handling the CS now.

Could you help to check if it is single spi_transfer or multiple spi_transfer?
We would suggest using one spi message with single spi_transfer?

Have you tried porting SPI driver from JP5 to check it it could work with JP6?

You mean the Nvidia spi-tegra114.c driver? I no done so.

Yes, it worths to give a try to clarify if the issue may be caused from SPI driver.

It is another suggestion to send SPI data in only one spi_transfer through modifying your SPI appliction(adis_buffer.c - drivers/iio/imu/adis_buffer.c - Linux source code v5.15.148 - Bootlin Elixir Cross Referencer)

Reading around the port of JP 5 to JP6 spi driver is a massive change. We know it is the spi-tegra114 driver and even the prior links that are out there are partial hacks to address similar SPI handling to JP5. Those changes don’t really fix the CS problem.

The suggestion to send SPI data in only one single spi_transfer - that is done already in the code I pointed out in adis_buffer.c.

We’ve used the upstream spi driver since JP6. Porting the driver from JP5 could help to find out the potential issue in JP6 spi driver.

The following part indicates that it would create multiple spi transfer.

adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);

I see your point on the two transfers now. That is not possible with the IMU because you must do a TX to set up a burst read (it has to be written to the device) and then the 2nd transfer is really the read response. This portion of the IMU driver hasn’t changed from JP5 to JP6. This seems to be causing the CS to deassert too but again even with the changes per other threads, the CS deasserts while we know in JP5, it doesn’t do that.

it is as if the cs_change is ignored for some reason.

Could you try to remove nvidia,enable-hw-based-cs; and add cs-gpios in device tree to check if it could help for your case?

I want to clarify that if I use cs-gpios, I won’t be able to utiliize jetson-io. Next, since the part is connected to another board that attaches to the 40 pin header, the usage from SPI1-CS0 won’t work so thus it looks like I need to change the overlay to setup that specific pin (i.e. GPIO3_PZ.06). Do you have an example of that setup in the overlay then?

Jetson-IO is used to configure the pinmux while cs-gpios is the attribute in kernel device tree.

You can try adding the following line in your SPI node (i.e. spi@3230000)

cs-gpios = <&gpio TEGRA234_MAIN_GPIO(Z, 6) GPIO_ACTIVE_LOW>;

It didn’t seem to work per the changes that look like this in the device tree on the orin jetson.

      spi@3210000 {
            /* force the SPI clock so it can go down to 2 MHz - issue in JP 6 */
            assigned-clock-parents = <&bpmp TEGRA234_CLK_CLK_M>;
            cs-gpios = <&gpio TEGRA234_MAIN_GPIO(Z, 6) GPIO_ACTIVE_LOW>;
            compatible = "nvidia,tegra114-spi";
            status = "okay";
            spi@0 {
                    status = "okay";
                    compatible = "adi,adis16505-2";
                    adi,burst32-enable;
                    reg = <0x0>;
                    spi-cpha;
                    spi-cpol;
                    spi-max-frequency = <2000000>;
                    interrupt-parent = <&gpio>;
                    interrupts = < TEGRA234_MAIN_GPIO(AC , 6) IRQ_TYPE_EDGE_RISING >;
                    reset-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 6) GPIO_ACTIVE_LOW >;

                    controller-data {
                                    //nvidia,enable-hw-based-cs;
                                    cs-gpios;
                                    nvidia,rx-clk-tap-delay = <0x10>;
                                    nvidia,tx-clk-tap-delay = <0x0>;
                            };
                  };
              };
          };

The driver doesn’t see the part per the read on the product id so functionally the spi bus doesn’t seem to be operating right with those specific changes.

Please share the full dmesg with above configuration.

Post power cycle, the dmesg is good - no issues doing SPI bus single reads. However the burst read that are needed still has the exact same problem, where a CS must be continuously asserted through the entire transaction.

You can see the CLK is red, CS is yellow.

That CS should be always asserted low throughout the transaction.

Could you try about this to port SPI driver from JP5 to JP6?
You can simply overwrite the spi-tegra114.c and check if you can build it successfully.

Current behavior is expected for SPI driver but it seems not meeting for your requirement.
Have you also tried to control CS pin from your application manually?

It is a non trivial port from JP5 to JP6 - it actually doesn’t build either.

When we use /dev/spiX in userspace it works.