[RFC PATCH 09/13] spi: dw: Add XIP and XIP_CONCURRENT caps
Sean Anderson
seanga2 at gmail.com
Fri Feb 5 05:39:19 CET 2021
Both DW SSI APB and DWC SSI devices have an optional XIP mode. When the
xip_en signal is asserted, reads (and writes if SSIC_XIP_WRITE_REG_EN is
set) are mapped to SPI transfers.
If SSIC_CONCURRENT_XIP_EN is disabled, then XIP transfers are controlled
using SPI_CTRLR0. However, if SSIC_CONCURRENT_XIP_EN is enabled, then XIP
transfers can occur concurrently (first-come-first-serve) with non-XIP
transfers. To facilitate this, a separate XIP_CTRL register is used for
configuration which would otherwise by done using CTRLR0 and SPI_CTRLR0.
Signed-off-by: Sean Anderson <seanga2 at gmail.com>
---
drivers/spi/designware_spi.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index d7510646e7..c41c5b4982 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -202,6 +202,7 @@
struct dw_spi_plat {
s32 frequency; /* Default clock frequency, -1 for none */
void __iomem *regs;
+ fdt_size_t regs_size;
};
struct dw_spi_priv {
@@ -210,12 +211,15 @@ struct dw_spi_priv {
struct gpio_desc cs_gpio; /* External chip-select gpio */
void __iomem *regs;
+ fdt_size_t regs_size;
/* DW SPI capabilities */
#define DW_SPI_CAP_CS_OVERRIDE BIT(0) /* Unimplemented */
#define DW_SPI_CAP_KEEMBAY_MST BIT(1) /* Unimplemented */
#define DW_SPI_CAP_DWC_SSI BIT(2)
#define DW_SPI_CAP_DFS32 BIT(3)
#define DW_SPI_CAP_ENHANCED BIT(4)
+#define DW_SPI_CAP_XIP BIT(5)
+#define DW_SPI_CAP_XIP_CONCURRENT BIT(6)
unsigned long caps;
unsigned long bus_clk_rate;
unsigned int freq; /* Default frequency */
@@ -322,11 +326,13 @@ static int request_gpio_cs(struct udevice *bus)
static int dw_spi_of_to_plat(struct udevice *bus)
{
+ fdt_addr_t regs;
struct dw_spi_plat *plat = dev_get_plat(bus);
- plat->regs = dev_read_addr_ptr(bus);
- if (!plat->regs)
+ regs = dev_read_addr_size_index(bus, 0, &plat->regs_size);
+ if (regs == FDT_ADDR_T_NONE)
return -EINVAL;
+ plat->regs = (void *)regs;
/* Use 500KHz as a suitable default */
plat->frequency = dev_read_u32_default(bus, "spi-max-frequency",
@@ -375,6 +381,19 @@ static void spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
priv->caps |= DW_SPI_CAP_ENHANCED;
}
+ /*
+ * DWC_SPI always has this register with SSIC_XIP_EN. There is no way
+ * to detect XIP for DW APB SSI
+ */
+ dw_write(priv, DW_SPI_XIP_INCR_INST, 0xffffffff);
+ if (dw_read(priv, DW_SPI_XIP_INCR_INST))
+ priv->caps |= DW_SPI_CAP_XIP;
+
+ /* Exists with SSIC_CONCURRENT_XIP_EN */
+ dw_write(priv, DW_SPI_XIP_CTRL, 0xffffffff);
+ if (dw_read(priv, DW_SPI_XIP_CTRL))
+ priv->caps |= DW_SPI_CAP_XIP_CONCURRENT;
+
dw_write(priv, DW_SPI_SSIENR, 1);
/*
@@ -469,6 +488,7 @@ static int dw_spi_probe(struct udevice *bus)
u32 version;
priv->regs = plat->regs;
+ priv->regs_size = plat->regs_size;
priv->freq = plat->frequency;
ret = dw_spi_get_clk(bus, &priv->bus_clk_rate);
@@ -1022,7 +1042,10 @@ static const struct udevice_id dw_spi_ids[] = {
*/
{ .compatible = "altr,socfpga-spi" },
{ .compatible = "altr,socfpga-arria10-spi" },
- { .compatible = "canaan,kendryte-k210-spi" },
+ {
+ .compatible = "canaan,kendryte-k210-spi",
+ .data = DW_SPI_CAP_XIP,
+ },
{
.compatible = "canaan,kendryte-k210-ssi",
.data = DW_SPI_CAP_DWC_SSI,
--
2.29.2
More information about the U-Boot
mailing list