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
next prev 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