Tool/software:
Hi all,
We are working on a hardware platform with a TI AM6412 SOC. We boot our firmware/software from a quad flash (macronix,mx25u51245g), which is connected to the OPSI interface.
The corresponding device tree entry is:
flash@0 { compatible = "macronix,mx25u51245g", "jedec,spi-nor"; reg = <0x0>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; cdns,tshsl-ns = <30>; cdns,tsd2d-ns = <3>; cdns,tchsh-ns = <3>; cdns,tslch-ns = <3>; cdns,read-delay = <3>; #address-cells = <1>; #size-cells = <1>;
The operating system, consisting of the Linux kernel and an initramfs (minimal rootfs, busybox), is loaded by U-Boot and then executed.
We are currently using the TI Kernel 6.1.83-rt28-ti-rt-g96b0ebd82722 from the latest meta-ti Yocto layer.
When we use busybox's flashcp to write arbitrary binary data of arbitrary size (e.g. /dev/random) to a 256k mtd partition, we face two problems:
- Data blobs smaller than 9 bytes are written properly to the flash, but the verification read in flashcp fails. We tried to debug the problem
and ended up in the Linux kernel in drivers/spi/spi-cadence-quadspi.c, function cqspi_mem_process. Applying the patchdiff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index b3f5a4e3577d..58247a9733ce 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -2151,11 +2151,20 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op) * Performing reads in DAC mode forces to read minimum 4 bytes * which is unsupported on some flash devices during register * reads, prefer STIG mode for such small reads. + * + * X + * X + * X + * X + * + * X + * X */ - if (!op->addr.nbytes || - op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX) + if (!op->addr.nbytes) { //} || + //op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX) return cqspi_command_read(f_pdata, op); - + } + return cqspi_read(f_pdata, op); }
as "workaround" seems to fix the issue. - When writing two data blobs with flashcp one after the other, the verification of the second blob fails.
Example:
dd if=/dev/random of=/tmp/data1 bs=1 count=192 && dd if=/dev/random of=/tmp/data2 bs=1 count=1872
flashcp -v /tmp/data1 /dev/mtd8 && flashcp -v /tmp/data2 /dev/mtd8
Adding debugging messages to flashcp shows, that starting at byte 192, 32 bytes with value 0 (wrong!) are read. From byte 223 the read values
are correct again. Further debugging ended up again in the Linux kernel in drivers/spi/spi-cadence-quadspi.c, now function cqspi_direct_read_execute.
Applying the patchdiff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 58247a9733ce..e6fdbabea8a6 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -2063,10 +2063,11 @@ static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata, u_char *buf = op->data.buf.in; int ret; - if (!cqspi->rx_chan || !virt_addr_valid(buf) || len <= 16) { + /* Workaround for read problems from userspace (e.g. flashcp verification) */ + //if (!cqspi->rx_chan || !virt_addr_valid(buf) || len <= 16) { cqspi_memcpy_fromio(op, buf, cqspi->ahb_base + from, len); return 0; - } + //} if (!cqspi_use_phy(f_pdata, op)) return cqspi_direct_read_dma(f_pdata, buf, from, len);
seems to "workaround" the problem.
The fixes for both problems are in the best case a workaround, but do not solve the problem itself.
Has anybody an idea, what the root cause is?