Dear, expers
The sf
test command we used is like below:
=> sf test 0 0x10000
SPI flash test:
0 erase: 206 ticks, 310 KiB/s 2.480 Mbps
1 check: 17 ticks, 3764 KiB/s 30.112 Mbps
2 write: 123 ticks, 520 KiB/s 4.160 Mbps
3 read: 18 ticks, 3555 KiB/s 28.440 Mbps
Test passed
0 erase: 206 ticks, 310 KiB/s 2.480 Mbps
1 check: 17 ticks, 3764 KiB/s 30.112 Mbps
2 write: 123 ticks, 520 KiB/s 4.160 Mbps
3 read: 18 ticks, 3555 KiB/s 28.440 Mbps
From above data, we can see the Nor Flash has poor read and write performance. Driving into the details of the code, we learned that the driver uses memcpy
when writing data to flash. So the write performance seems to be within the normal range.
int cadence_qspi_apb_write_execute(struct cadence_spi_platdata *plat,
const struct spi_mem_op *op)
{
u32 to = op->addr.val;
const void *buf = op->data.buf.out;
size_t len = op->data.nbytes;
/*
* Some flashes like the Cypress Semper flash expect a dummy 4-byte
* address (all 0s) with the read status register command in DTR mode.
* But this controller does not support sending dummy address bytes to
* the flash when it is polling the write completion register in DTR
* mode. So, we can not use direct mode when in DTR mode for writing
* data.
*/
if (!plat->dtr && plat->use_dac_mode && (to + len < plat->ahbsize)) {
memcpy_toio(plat->ahbbase + to, buf, len);
if (!cadence_qspi_wait_idle(plat->regbase))
return -EIO;
return 0;
}
return cadence_qspi_apb_indirect_write_execute(plat, len, buf);
}
dma_memcpy
to copy data from flash. So the read performance is very poor!!!!!
static int
cadence_qspi_apb_direct_read_execute(struct cadence_spi_platdata *plat,
const struct spi_mem_op *op)
{
......
if (!cadence_qspi_apb_use_phy(plat, op)) {
if (!op->data.dtr || dma_memcpy(buf, plat->ahbbase + from, len) < 0)
memcpy_fromio(buf, plat->ahbbase + from, len);
if (!cadence_qspi_wait_idle(plat->regbase))
return -EIO;
return 0;
}
......
}
The conditional judgment `if (!op->data.dtr || dma_memcpy(buf, plat->ahbbase + from, len) < 0)` is weird. The correct conditional judgment would look something like this: `if (!op->data.dtr && dma_memcpy(buf, plat->ahbbase + from, len) < 0)`. The test results are as follows:
=> sf test 0 0x10000
SPI flash test:
0 erase: 163 ticks, 392 KiB/s 3.136 Mbps
1 check: 5 ticks, 12800 KiB/s 102.400 Mbps
2 write: 110 ticks, 581 KiB/s 4.648 Mbps
3 read: 5 ticks, 12800 KiB/s 102.400 Mbps
Test passed
0 erase: 163 ticks, 392 KiB/s 3.136 Mbps
1 check: 5 ticks, 12800 KiB/s 102.400 Mbps
2 write: 110 ticks, 581 KiB/s 4.648 Mbps
3 read: 5 ticks, 12800 KiB/s 102.400 Mbps
THANKS
XA