Unverified Commit 97e4827d authored by Matthias Schiffer's avatar Matthias Schiffer Committed by Mark Brown
Browse files

spi: cadence-quadspi: fix protocol setup for non-1-1-X operations



cqspi_set_protocol() only set the data width, but ignored the command
and address width (except for 8-8-8 DTR ops), leading to corruption of
all transfers using 1-X-X or X-X-X ops. Fix by setting the other two
widths as well.

While we're at it, simplify the code a bit by replacing the
CQSPI_INST_TYPE_* constants with ilog2().

Tested on a TI AM64x with a Macronix MX25U51245G QSPI flash with 1-4-4
read and write operations.

Signed-off-by: default avatarMatthias Schiffer <matthias.schiffer@ew.tq-group.com>
Link: https://lore.kernel.org/r/20220331110819.133392-1-matthias.schiffer@ew.tq-group.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 409543ce
Loading
Loading
Loading
Loading
+12 −34
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/iopoll.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
@@ -102,12 +103,6 @@ struct cqspi_driver_platdata {
#define CQSPI_TIMEOUT_MS			500
#define CQSPI_READ_TIMEOUT_MS			10

/* Instruction type */
#define CQSPI_INST_TYPE_SINGLE			0
#define CQSPI_INST_TYPE_DUAL			1
#define CQSPI_INST_TYPE_QUAD			2
#define CQSPI_INST_TYPE_OCTAL			3

#define CQSPI_DUMMY_CLKS_PER_BYTE		8
#define CQSPI_DUMMY_BYTES_MAX			4
#define CQSPI_DUMMY_CLKS_MAX			31
@@ -376,10 +371,6 @@ static unsigned int cqspi_calc_dummy(const struct spi_mem_op *op, bool dtr)
static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
			      const struct spi_mem_op *op)
{
	f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE;
	f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE;
	f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;

	/*
	 * For an op to be DTR, cmd phase along with every other non-empty
	 * phase should have dtr field set to 1. If an op phase has zero
@@ -389,32 +380,23 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
		       (!op->addr.nbytes || op->addr.dtr) &&
		       (!op->data.nbytes || op->data.dtr);

	switch (op->data.buswidth) {
	case 0:
		break;
	case 1:
		f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;
		break;
	case 2:
		f_pdata->data_width = CQSPI_INST_TYPE_DUAL;
		break;
	case 4:
		f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
		break;
	case 8:
		f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
		break;
	default:
		return -EINVAL;
	}
	f_pdata->inst_width = 0;
	if (op->cmd.buswidth)
		f_pdata->inst_width = ilog2(op->cmd.buswidth);

	f_pdata->addr_width = 0;
	if (op->addr.buswidth)
		f_pdata->addr_width = ilog2(op->addr.buswidth);

	f_pdata->data_width = 0;
	if (op->data.buswidth)
		f_pdata->data_width = ilog2(op->data.buswidth);

	/* Right now we only support 8-8-8 DTR mode. */
	if (f_pdata->dtr) {
		switch (op->cmd.buswidth) {
		case 0:
			break;
		case 8:
			f_pdata->inst_width = CQSPI_INST_TYPE_OCTAL;
			break;
		default:
			return -EINVAL;
@@ -422,9 +404,7 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,

		switch (op->addr.buswidth) {
		case 0:
			break;
		case 8:
			f_pdata->addr_width = CQSPI_INST_TYPE_OCTAL;
			break;
		default:
			return -EINVAL;
@@ -432,9 +412,7 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,

		switch (op->data.buswidth) {
		case 0:
			break;
		case 8:
			f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
			break;
		default:
			return -EINVAL;