public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Sean Anderson <seanga2@gmail.com>
To: u-boot@lists.denx.de
Subject: [RFC PATCH 11/13] spi: dw: Add support for DIRMAP
Date: Thu,  4 Feb 2021 23:39:21 -0500	[thread overview]
Message-ID: <20210205043924.149504-12-seanga2@gmail.com> (raw)
In-Reply-To: <20210205043924.149504-1-seanga2@gmail.com>

This adds support for XIP mode. It is not actually any faster than QPI
(yet), but it serves as a good starting point for using XIP mode for other
purposes (such as actual eXecuting In Place).

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---

 drivers/spi/designware_spi.c | 131 +++++++++++++++++++++++++++++++++++
 1 file changed, 131 insertions(+)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 6f74a471e3..cb7a28c3bf 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -1056,10 +1056,141 @@ static int dw_spi_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op)
 	return 0;
 }
 
+#if CONFIG_IS_ENABLED(SPI_DIRMAP)
+static int dw_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
+{
+	struct dw_spi_priv *priv = dev_get_priv(desc->slave->dev->parent);
+
+	/*
+	 * Currently only DWC XIP is supported. DW APB SSI XIP exists, but
+	 * cannot send an instruction before the address, so it is left for when
+	 * U-Boot supports 0-X-X instructions. In addition, we only support
+	 * concurrent XIP (since I have no non-condcurrent XIP hardware to test
+	 * with)
+	 */
+	if (!(priv->caps & (DW_SPI_CAP_XIP)) ||
+	    !(priv->caps & (DW_SPI_CAP_DWC_SSI)) ||
+	    !(priv->caps & (DW_SPI_CAP_XIP_CONCURRENT)))
+		return -ENOTSUPP;
+
+	if (!spi_mem_supports_op(desc->slave, &desc->info.op_tmpl))
+		return -ENOTSUPP;
+
+	/*
+	 * Make sure the requested region doesn't go out of the physically
+	 * mapped flash memory bounds and the operation is read-only.
+	 */
+	if (desc->info.offset + desc->info.length > priv->regs_size ||
+	    desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
+		return -ENOTSUPP;
+
+	/* XIP only supports enhanced SPI modes */
+	if (desc->info.op_tmpl.data.buswidth == 1)
+		return -ENOTSUPP;
+
+	return 0;
+}
+
+static u32 dw_spi_update_xip_cr(const struct spi_mem_op *op, uint frf)
+{
+	uint trans_type, wait_cycles;
+
+	/* This assumes support_op has filtered invalid types */
+	if (op->addr.buswidth == 1)
+		trans_type = TRANS_TYPE_1_1_X;
+	else if (op->cmd.buswidth == 1)
+		trans_type = TRANS_TYPE_1_X_X;
+	else
+		trans_type = TRANS_TYPE_X_X_X;
+
+	if (op->dummy.buswidth)
+		wait_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
+	else
+		wait_cycles = 0;
+
+	return FIELD_PREP(XIP_CTRL_FRF, frf)
+	       | FIELD_PREP(XIP_CTRL_TRANS_TYPE_MASK, trans_type)
+	       | FIELD_PREP(XIP_CTRL_ADDR_L_MASK, op->addr.nbytes * 2)
+	       | FIELD_PREP(XIP_CTRL_INST_L_MASK, INST_L_8)
+	       | FIELD_PREP(XIP_CTRL_WAIT_CYCLES_MASK, wait_cycles)
+	       //| XIP_CTRL_DFS_HC
+	       | XIP_CTRL_INST_EN
+	       | XIP_CTRL_CONT_XFER_EN
+	       | XIP_CTRL_PREFETCH_EN;
+}
+
+static ssize_t dw_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs,
+				  size_t len, void *buf)
+{
+	int ret;
+	size_t count = len;
+	struct spi_slave *slave = desc->slave;
+	struct udevice *bus = slave->dev->parent;
+	struct dw_spi_priv *priv = dev_get_priv(bus);
+	struct spi_mem_op *op = &desc->info.op_tmpl;
+	u8 *from, *to;
+
+	switch (op->data.buswidth) {
+	case 2:
+		priv->spi_frf = CTRLR0_SPI_FRF_DUAL;
+		break;
+	case 4:
+		priv->spi_frf = CTRLR0_SPI_FRF_QUAD;
+		break;
+	case 8:
+		priv->spi_frf = CTRLR0_SPI_FRF_OCTAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = dw_spi_mux_ctrl(bus);
+	if (ret)
+		return ret;
+
+	dw_write(priv, DW_SPI_SSIENR, 0);
+	//dw_write(priv, DW_SPI_CTRLR0, dw_spi_update_cr0(priv));
+	dw_write(priv, DW_SPI_XIP_CTRL, dw_spi_update_xip_cr(op, priv->spi_frf));
+	dw_write(priv, DW_SPI_XIP_INCR_INST, op->cmd.opcode);
+	/*
+	 * FIXME: U-Boot doesn't currently support wrap instructions, but we
+	 * can't control what the AHB master does. Just write 0 to get something
+	 * obviously bogus.
+	 */
+	dw_write(priv, DW_SPI_XIP_WRAP_INST, 0);
+	dw_write(priv, DW_SPI_XIP_SER, 1 << spi_chip_select(slave->dev));
+	dw_write(priv, DW_SPI_SSIENR, 1);
+
+	dw_spi_mux_deselect(bus);
+
+	external_cs_manage(slave->dev, true);
+
+	ret = dw_spi_mux_xip(bus);
+	if (ret)
+		return ret;
+
+	//memcpy(buf, priv->regs + offs, len);
+	from = priv->regs + offs;
+	to = buf;
+	while (count--)
+		*to++ = *from++;
+
+	dw_spi_mux_deselect(bus);
+
+	external_cs_manage(slave->dev, false);
+
+	return len;
+}
+#endif /* CONFIG_SPI_DIRMAP */
+
 static const struct spi_controller_mem_ops dw_spi_mem_ops = {
 	.exec_op = dw_spi_exec_op,
 	.supports_op = dw_spi_supports_op,
 	.adjust_op_size = dw_spi_adjust_op_size,
+#if CONFIG_IS_ENABLED(SPI_DIRMAP)
+	.dirmap_create = dw_spi_dirmap_create,
+	.dirmap_read = dw_spi_dirmap_read,
+#endif
 };
 
 static int dw_spi_set_speed(struct udevice *bus, uint speed)
-- 
2.29.2

  parent reply	other threads:[~2021-02-05  4:39 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-05  4:39 [RFC PATCH 00/13] spi: dw: Add support for XIP mode Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 01/13] linux err: Synchronize with Linux 5.10 Sean Anderson
2021-02-07 14:37   ` Simon Glass
2021-02-05  4:39 ` [RFC PATCH 02/13] spi-mem: Add dirmap API from Linux Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 03/13] mtd: spi-nor: use spi-mem dirmap API Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 04/13] core: ofnode: Fix inconsistent returns of *_read_u32_array Sean Anderson
2021-02-07 14:37   ` Simon Glass
2021-02-05  4:39 ` [RFC PATCH 05/13] mux: Inline mux functions when CONFIG_MUX is disabled Sean Anderson
2021-02-05  7:32   ` Pratyush Yadav
2021-02-05  4:39 ` [RFC PATCH 06/13] mux: Define a stub for mux_get_by_index if " Sean Anderson
2021-02-05 10:53   ` Pratyush Yadav
2021-02-05  4:39 ` [RFC PATCH 07/13] mux: mmio: Only complain about idle-states if it is malformed Sean Anderson
2021-02-05 11:06   ` Pratyush Yadav
2021-02-05 13:28     ` Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 08/13] spi: dw: Define XIP registers Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 09/13] spi: dw: Add XIP and XIP_CONCURRENT caps Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 10/13] spi: dw: Use a mux to access registers Sean Anderson
2021-02-05  4:39 ` Sean Anderson [this message]
2021-02-05  4:39 ` [RFC PATCH 12/13] riscv: k210: Increase SPI3 bus clock to CPU speed Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 13/13] riscv: k210: Add bindings for SPI XIP Sean Anderson
2021-02-05  4:43 ` [RFC PATCH 00/13] spi: dw: Add support for XIP mode Sean Anderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210205043924.149504-12-seanga2@gmail.com \
    --to=seanga2@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox