How to decrease the delay between spi transfer and CS action?

The delay between between spi transfer and CS action is more than 100us(max up to 1ms), how to decease the delay time?
the device tree is below:
spi@7000d600 { /* SPI 2 to 40 pin header */
status = “okay”;
num-cs = <1>;
cs-gpios = <&gpio TEGRA_GPIO(B, 7) GPIO_ACTIVE_LOW>;
max3107spi@0 {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = “max3107_spi”;
status = “okay”;
reg = <0x0>;
spi-max-frequency = <25000000>;
controller-data {
nvidia,cs-setup-clk-count = <0>;
nvidia,cs-hold-clk-count = <0>;
nvidia,rx-clk-tap-delay = <0>;
nvidia,tx-clk-tap-delay = <0>;
// nvidia,clk-delay-between-packets = <1>;
};

Here is the figure:

use hardware and software method is the same, Yellow is CS, blue is CLK

Have a try to add below two property to the device tree to try.

  • nvidia,clk-delay-between-packets: Clock delay between packets by keeping
    CS active. For this, it is required to pass the Chip select
    as GPIO.
  • nvidia,chipselect-gpio: Chipselect GPIO number as per gpio binding.

How to add nvidia,chipselect-gpio? I have check tegra114.c not use this comments.
below is part of code in tegra114.c:
of_property_read_u32(data_np, “nvidia,cs-setup-clk-count”,
&cdata->cs_setup_clk_count);
of_property_read_u32(data_np, “nvidia,cs-hold-clk-count”,
&cdata->cs_hold_clk_count);
of_property_read_u32(data_np, “nvidia,rx-clk-tap-delay”,
&cdata->rx_clk_tap_delay);
of_property_read_u32(data_np, “nvidia,tx-clk-tap-delay”,
&cdata->tx_clk_tap_delay);
of_property_read_u32(data_np, “nvidia,cs-inactive-cycles”,
&cdata->cs_inactive_cycles);
of_property_read_u32(data_np, “nvidia,clk-delay-between-packets”,
&cdata->clk_delay_between_packets);

Have a reference to below to use GPIO as chipselect.

here is binded

As I showed in dts above, I have bind it,but the gap is still very large

Any change when increase the clk-delay-between-packets ?

spi@7000d600 { /* SPI 2 to 40 pin header */
status = “okay”;
num-cs = <1>;
cs-gpios = <&gpio TEGRA_GPIO(B, 7) GPIO_ACTIVE_LOW>;
nvidia,chipselect-gpio = <0>;
max3107spi@0 {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = “max3107_spi”;
status = “okay”;
reg = <0x0>;
spi-max-frequency = <25000000>;
controller-data {
nvidia,cs-setup-clk-count = <0>;
nvidia,cs-hold-clk-count = <0>;
nvidia,rx-clk-tap-delay = <0>;
nvidia,tx-clk-tap-delay = <0>;
nvidia,clk-delay-between-packets = <1>;
};

		max3107_gpio{
			rs_gpio = <&gpio TEGRA_GPIO(DD, 0) GPIO_ACTIVE_LOW>;
			irq_gpio = <&gpio TEGRA_GPIO(G, 2)  0>;
			interrupt-controller;
			interrupt-parent = <&gpio>;
			interrupts = <TEGRA_GPIO(G, 2) IRQ_TYPE_LEVEL_LOW>;
		};
	};
};

this is the dts, and the figure of two transfer in one message。I have also tried hardware cs, the results is still the same.
the figure of oscilloscope,yellow cs,blue clk:


the printk in tegra114 is the same:

  • printk in tegra114:
    ret = tegra_spi_start_transfer_one(spi, xfer, cmd1);
    if (ret < 0) {
    dev_err(tspi->dev,
    “spi can not start transfer, err %d\n”, ret);
    goto complete_xfer;
    }

      is_first_msg = false;
      if (tspi->polling_mode)
      {
      	printk("p");
      	timeleft = tegra_spi_status_poll(tspi);
      }
      else
      {
      	printk("m");
      	timeleft = wait_for_completion_timeout(
      			&tspi->xfer_completion,
      			SPI_DMA_TIMEOUT);
      }
      printk("6,timecost:%ld",SPI_DMA_TIMEOUT - timeleft);
    

*dmesg figure:

sometimes the gap is about 50us,sometimes the gap is near 1000us. I don’t know why change so large?

In addtion, there is a bug in spi-tegra114 when use software cs when use xfer->cs_change:
if (is_first_of_msg) {
tspi->status_reg = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
tegra_spi_clear_status(tspi);

	command1 = tspi->def_command1_reg;
	command1 |= SPI_BIT_LENGTH(bits_per_word - 1);

	command1 &= ~SPI_CONTROL_MODE_MASK;
	req_mode = spi->mode & 0x3;
	if (req_mode == SPI_MODE_0)
		command1 |= SPI_CONTROL_MODE_0;
	else if (req_mode == SPI_MODE_1)
		command1 |= SPI_CONTROL_MODE_1;
	else if (req_mode == SPI_MODE_2)
		command1 |= SPI_CONTROL_MODE_2;
	else if (req_mode == SPI_MODE_3)
		command1 |= SPI_CONTROL_MODE_3;

	if (spi->mode & SPI_LSBYTE_FIRST)
		command1 |= SPI_LSBYTE_FE;
	else
		command1 &= ~SPI_LSBYTE_FE;

	if (spi->mode & SPI_LSB_FIRST)
		command1 |= SPI_LSBIT_FE;
	else
		command1 &= ~SPI_LSBIT_FE;

	if (spi->mode & SPI_3WIRE)
		command1 |= SPI_BIDIROE;
	else
		command1 &= ~SPI_BIDIROE;

	if (tspi->cs_control) {
		if (tspi->cs_control != spi)
			tegra_spi_writel(tspi, command1, SPI_COMMAND1);
		tspi->cs_control = NULL;
	} else
		if (SPI_MODE_VAL(command1) !=
		    SPI_MODE_VAL(tspi->def_command1_reg))
			tegra_spi_writel(tspi, command1, SPI_COMMAND1);

	tspi->is_hw_based_cs = false;
	if (cdata && cdata->is_hw_based_cs && is_single_xfer &&
	    ((tspi->curr_dma_words * tspi->bytes_per_word) ==
	     (t->len - tspi->cur_pos))) {
		tegra_spi_set_timing1(spi);
		tspi->is_hw_based_cs = true;
	}

	tegra_spi_set_timing2(spi);

	if (!tspi->is_hw_based_cs) {
		command1 |= SPI_CS_SW_HW;
		if (spi->mode & SPI_CS_HIGH)
			command1 |= SPI_CS_SS_VAL;
		else
			command1 &= ~SPI_CS_SS_VAL;
	} else {
		command1 &= ~SPI_CS_SW_HW;
		command1 &= ~SPI_CS_SS_VAL;
	}

	if (cstate && cstate->cs_gpio_valid) {

		if (spi->mode & SPI_CS_HIGH)
			gval = 1;
		else
			gval = 0;

		gpio_set_value(spi->cs_gpio, gval);
		printk("cs1:%d",gval);
	}

	if (!tspi->prod_list)
		tegra_spi_set_cmd2(spi, speed);
	else
		tegra_spi_set_prod(tspi, spi->chip_select);
} else {
	command1 = tspi->command1_reg;
	command1 &= ~SPI_BIT_LENGTH(~0);
	command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
}
  • need to add in else condition:
    //bug: need to add
    if (cstate && cstate->cs_gpio_valid) {

      	if (spi->mode & SPI_CS_HIGH)
      		gval = 1;
      	else
      		gval = 0;
    
      	gpio_set_value(spi->cs_gpio, gval);
      	printk("cs1:%d",gval);
      }
    
  1. List item

HI All
Please help these patch to verify the problem.
0001-spi-tegra-fix-SPI-setup-and-hold-times.patch.txt (2.0 KB)
0002-spi-tegra-optimize-delay-between-packets.patch.txt (6.3 KB)