This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: An indirect write completion error occurred in the linux OSPI driver

Part Number: TDA4VM


Hi,

We are developing a custom board with TDA4VM. The OSPI nor flash chip part namber is mt35xu256aba. The SDK version is PROCESSOR-SDK-LINUX-J721E_07.02.00.07.

While running a CNN application, we use flashcp to test OSPI flash. After a period of testing, the kernel will output error log information.

Test code:

for i in {0..20000}; do
    echo test cnt ${i} $(date)
    flashcp -v mtd14.bin /dev/mtd14
    if [ $? != 0 ]; then
        echo flashcp error.
    fi
done

Kernel error log:

[ 172.248463] cadence-qspi 47040000.spi: Indirect write completion error (-110)
[ 172.255604] spi-nor spi0.0: operation failed with -110

dts configuration:

&ospi0 {
        pinctrl-names = "default";
        pinctrl-0 = <&mcu_fss0_ospi0_pins_default>;
​
        flash@0{
                compatible = "jedec,spi-nor";
                reg = <0x0>;
                spi-tx-bus-width = <8>;
                spi-rx-bus-width = <8>;
                spi-max-frequency = <25000000>;
                cdns,tshsl-ns = <60>;
                cdns,tsd2d-ns = <60>;
                cdns,tchsh-ns = <60>;
                cdns,tslch-ns = <60>;
                cdns,read-delay = <0>;
                cdns,phy-mode;
                #address-cells = <1>;
                #size-cells = <1>;
                partition@1fe0000 {
                        label = "ospi.phypattern";
                        reg = <0x1fe0000 0x20000>;
                };
        };
};

We modified “spi-max-frequency = <5000000> ”of ospi0 in the device tree and performed PHY calibration. The test results showed that the problem was not improved.

We see a section like "Some delay is required for the above bit to be internally synchronized by the QSPI module." in the "driver/ /spi/cadence_qspi_apb.c" of uboot.


static int
cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
                                        unsigned int n_tx, const u8 *txbuf)
{
		...

        /* Configure the indirect read transfer bytes */
        writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);

        /* Start the indirect write transfer */
        writel(CQSPI_REG_INDIRECTWR_START,
               plat->regbase + CQSPI_REG_INDIRECTWR);

        /*
         * Some delay is required for the above bit to be internally
         * synchronized by the QSPI module.
         */
        ndelay(plat->wr_delay);

        while (remaining > 0) {
			...
        }

        /* Check indirect done status */
        ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR,
                                CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
        if (ret) {
                printf("Indirect write completion error (%i)\n", ret);
                goto failwr;
        }

        /* Clear indirect completion status */
        writel(CQSPI_REG_INDIRECTWR_DONE,
               plat->regbase + CQSPI_REG_INDIRECTWR);
        if (bounce_buf)
                free(bounce_buf);
        return 0;

failwr:
        /* Cancel the indirect write */
        writel(CQSPI_REG_INDIRECTWR_CANCEL,
               plat->regbase + CQSPI_REG_INDIRECTWR);
        if (bounce_buf)
                free(bounce_buf);
        return ret;
}

When we try to make the following modifications to spi-cadence-quadspi.c, the problem no longer occurs.

--- a/board-support/linux-5.4.74+gitAUTOINC+9574bba32a-g9574bba32a/drivers/spi/spi-cadence-quadspi.c
+++ b/board-support/linux-5.4.74+gitAUTOINC+9574bba32a-g9574bba32a/drivers/spi/spi-cadence-quadspi.c
@@ -2343,7 +2363,7 @@ static int cqspi_probe(struct platform_device *pdev)
        ddata  = of_device_get_match_data(dev);
        if (ddata) {
                if (ddata->quirks & CQSPI_NEEDS_WR_DELAY)
-                       cqspi->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC,
+                       cqspi->wr_delay = 400 * DIV_ROUND_UP(NSEC_PER_SEC,
                                                cqspi->master_ref_clk_hz);
                if (ddata->hwcaps_mask & CQSPI_SUPPORTS_OCTAL)
                        master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL;
​

Is our method correct?

Is the setting of delay value appropriate?

What is the effective basis for the current modification?

Thanks,

Chen Zongsheng