[PATCH v9 08/18] spi: cadence-quadspi: add PHY tuning support

Santhosh Kumar K s-k6 at ti.com
Wed Sep 2 02:45:24 PDT 2026


Hello Mark,

On 27/08/26 03:13, Mark Brown wrote:
> On Tue, Aug 25, 2026 at 10:47:27PM +0530, Santhosh Kumar K wrote:
>> The Cadence QSPI controller supports a delay-line PHY for high-speed
>> operation. Without calibration the PHY is unused and read capture relies
>> on a fixed delay, limiting throughput at frequencies above the base
>> operating speed.
> 
>> Add an execute_tuning callback that performs delay-line calibration using
>> a known data pattern written to a dedicated flash region. The pattern is
>> either read from a NOR partition identified by the DT property
>> spi-phy-pattern-partition, or written to the NAND page cache before
>> each calibration read.
> 
>>   struct cqspi_flash_pdata {
> 
>> +	bool			use_dqs;
>> +	bool			use_tuned_phy;
> 
> The AM65x has a fun erratum i2189 which mentions that it requires
> disabling DQS for writes:
> 
>     https://www.ti.com.cn/lit/er/sprz452i/sprz452i.pdf
> 
> which suggests we might need separate controls for read and write
> operation.

Thanks for pointing this out.

The DQS bit in CQSPI_REG_READCAPTURE is used for read data capture and
it's not consulted during writes.

However, the actual i2189 issue was that cqspi_tune_phy()
unconditionally set both PHY_EN and PHY_PIPELINE on both read and write 
path - non-compliant with the erratum. So, I'll split the tune_phy()
into two separate paths for read and write.

Will respin the series with this fix and some sashiko-bot fixes.

> 
>> +static int cqspi_write_pattern_to_cache(struct cqspi_flash_pdata *f_pdata,
>> +					struct spi_mem *mem,
>> +					const struct spi_mem_op *write_op)
>> +{
>> +	struct spi_controller *ctlr = mem->spi->controller;
>> +	struct device *dev = &f_pdata->cqspi->pdev->dev;
>> +	struct spi_mem_op op = *write_op;
>> +	int ret;
>> +
>> +	op.max_freq = mem->spi->max_speed_hz;
>> +	op.data.nbytes = sizeof(phy_tuning_pattern);
>> +	op.data.buf.out = phy_tuning_pattern;
>> +
>> +	ret = ctlr->mem_ops->exec_op(mem, &op);
>> +	if (ret) {
>> +		dev_err(dev, "Failed to write PHY pattern to cache: %d\n", ret);
>> +		return ret;
>> +	}
>> +	dev_dbg(dev, "PHY pattern (%zu bytes) written to cache\n",
>> +		sizeof(phy_tuning_pattern));
>> +
>> +	return 0;
>> +}
> 
> spinand_write_page() has a multi-operation sequence, I've not checked if
> any fancy flashes with DQS support actually need that.  _read_page()
> looks more straightforward.

cqspi_write_pattern_to_cache() does a PROGRAM_LOAD only (no
PROGRAM_EXECUTE), and tuning reads the pattern back from cache - no cell
wear. True for all SPI NANDs we've tested; a DQS capable device needing
EXECUTE before readback would need separate handling, but haven't seen one.

Thanks,
Santhosh.




More information about the linux-mtd mailing list