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,