Unverified Commit 4b50e6cc authored by Mark Brown's avatar Mark Brown
Browse files

spi: microchip core-qspi gpio-cs fixes + cleanup

Conor Dooley <conor@kernel.org> says:

v3 with the review comment about the core handing CS_HIGH dealt with.
I noticed that in the same function there was a "raw" BIT(1), which I
replaced with a macro that the patch was already adding for use in the
setup function...
parents 5b33b756 0b2eb1f8
Loading
Loading
Loading
Loading
+79 −20
Original line number Diff line number Diff line
@@ -74,6 +74,13 @@
#define STATUS_FLAGSX4		BIT(8)
#define STATUS_MASK		GENMASK(8, 0)

/*
 * QSPI Direct Access register defines
 */
#define DIRECT_ACCESS_EN_SSEL		BIT(0)
#define DIRECT_ACCESS_OP_SSEL		BIT(1)
#define DIRECT_ACCESS_OP_SSEL_SHIFT	1

#define BYTESUPPER_MASK		GENMASK(31, 16)
#define BYTESLOWER_MASK		GENMASK(15, 0)

@@ -158,7 +165,39 @@ static int mchp_coreqspi_set_mode(struct mchp_coreqspi *qspi, const struct spi_m
	return 0;
}

static inline void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
static void mchp_coreqspi_set_cs(struct spi_device *spi, bool enable)
{
	struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller);
	u32 val;

	val = readl(qspi->regs + REG_DIRECT_ACCESS);

	val &= ~DIRECT_ACCESS_OP_SSEL;
	val |= !enable << DIRECT_ACCESS_OP_SSEL_SHIFT;

	writel(val, qspi->regs + REG_DIRECT_ACCESS);
}

static int mchp_coreqspi_setup(struct spi_device *spi)
{
	struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller);
	u32 val;

	/*
	 * Active low devices need to be specifically set to their inactive
	 * states during probe.
	 */
	if (spi->mode & SPI_CS_HIGH)
		return 0;

	val = readl(qspi->regs + REG_DIRECT_ACCESS);
	val |= DIRECT_ACCESS_OP_SSEL;
	writel(val, qspi->regs + REG_DIRECT_ACCESS);

	return 0;
}

static void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
{
	u32 control, data;

@@ -194,7 +233,7 @@ static inline void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
	}
}

static inline void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi)
static void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi)
{
	u32 control, data;

@@ -222,7 +261,7 @@ static inline void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi)
	}
}

static inline void mchp_coreqspi_write_read_op(struct mchp_coreqspi *qspi)
static void mchp_coreqspi_write_read_op(struct mchp_coreqspi *qspi)
{
	u32 control, data;

@@ -380,20 +419,7 @@ static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_devi
	return 0;
}

static int mchp_coreqspi_setup_op(struct spi_device *spi_dev)
{
	struct spi_controller *ctlr = spi_dev->controller;
	struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
	u32 control = readl_relaxed(qspi->regs + REG_CONTROL);

	control |= (CONTROL_MASTER | CONTROL_ENABLE);
	control &= ~CONTROL_CLKIDLE;
	writel_relaxed(control, qspi->regs + REG_CONTROL);

	return 0;
}

static inline void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
static void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
{
	u32 idle_cycles = 0;
	int total_bytes, cmd_bytes, frames, ctrl;
@@ -483,6 +509,7 @@ static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o

	reinit_completion(&qspi->data_completion);
	mchp_coreqspi_config_op(qspi, op);
	mchp_coreqspi_set_cs(mem->spi, true);
	if (op->cmd.opcode) {
		qspi->txbuf = &opcode;
		qspi->rxbuf = NULL;
@@ -523,6 +550,7 @@ static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
		err = -ETIMEDOUT;

error:
	mchp_coreqspi_set_cs(mem->spi, false);
	mutex_unlock(&qspi->op_lock);
	mchp_coreqspi_disable_ints(qspi);

@@ -662,18 +690,28 @@ static int mchp_coreqspi_transfer_one(struct spi_controller *ctlr, struct spi_de
				      struct spi_transfer *t)
{
	struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
	bool dual_quad = false;

	qspi->tx_len = t->len;

	if (t->tx_nbits == SPI_NBITS_QUAD || t->rx_nbits == SPI_NBITS_QUAD ||
			t->tx_nbits == SPI_NBITS_DUAL ||
			t->rx_nbits == SPI_NBITS_DUAL)
		dual_quad = true;

	if (t->tx_buf)
		qspi->txbuf = (u8 *)t->tx_buf;

	if (!t->rx_buf) {
		mchp_coreqspi_write_op(qspi);
	} else {
	} else if (!dual_quad) {
		qspi->rxbuf = (u8 *)t->rx_buf;
		qspi->rx_len = t->len;
		mchp_coreqspi_write_read_op(qspi);
	} else {
		qspi->rxbuf = (u8 *)t->rx_buf;
		qspi->rx_len = t->len;
		mchp_coreqspi_read_op(qspi);
	}

	return 0;
@@ -686,6 +724,7 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	int ret;
	u32 num_cs, val;

	ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*qspi));
	if (!ctlr)
@@ -718,10 +757,18 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
		return ret;
	}

	/*
	 * The IP core only has a single CS, any more have to be provided via
	 * gpios
	 */
	if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs))
		num_cs = 1;

	ctlr->num_chipselect = num_cs;

	ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
	ctlr->mem_ops = &mchp_coreqspi_mem_ops;
	ctlr->mem_caps = &mchp_coreqspi_mem_caps;
	ctlr->setup = mchp_coreqspi_setup_op;
	ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
			  SPI_TX_DUAL | SPI_TX_QUAD;
	ctlr->dev.of_node = np;
@@ -729,9 +776,21 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
	ctlr->prepare_message = mchp_coreqspi_prepare_message;
	ctlr->unprepare_message = mchp_coreqspi_unprepare_message;
	ctlr->transfer_one = mchp_coreqspi_transfer_one;
	ctlr->num_chipselect = 2;
	ctlr->setup = mchp_coreqspi_setup;
	ctlr->set_cs = mchp_coreqspi_set_cs;
	ctlr->use_gpio_descriptors = true;

	val = readl_relaxed(qspi->regs + REG_CONTROL);
	val |= (CONTROL_MASTER | CONTROL_ENABLE);
	writel_relaxed(val, qspi->regs + REG_CONTROL);

	/*
	 * Put cs into software controlled mode
	 */
	val = readl_relaxed(qspi->regs + REG_DIRECT_ACCESS);
	val |= DIRECT_ACCESS_EN_SSEL;
	writel(val, qspi->regs + REG_DIRECT_ACCESS);

	ret = spi_register_controller(ctlr);
	if (ret)
		return dev_err_probe(&pdev->dev, ret,