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>;
};
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); }
- 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)
@zyxhuo
did u solve the gap problem?
@ShaneCCC
did these patches fix the gap issues?
when test the gap, we must use hw cs?
if we dont use hw cs, what will happen?
tks~