[PATCH 10/14] spi: dw: Add DUAL/QUAD/OCTAL caps

Sean Anderson seanga2 at gmail.com
Mon Feb 1 01:34:32 CET 2021


These capabilities correspond to SSIC_SPI_MODE of 1, 2, or 3, respectively.
This doesn't do much yet, but it does add support for detection and for
disallowing unsupported modes.  Unfortunately, we cannot discriminate
between these modes (only that SSIC_SPI_MODE != 0), so we only assume DUAL
if something sticks to SPI_FRF.

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

 drivers/spi/designware_spi.c | 41 +++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 683394a5a4..1dd83e6ca6 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -129,6 +129,9 @@ struct dw_spi_priv {
 #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_DUAL			BIT(4)
+#define DW_SPI_CAP_QUAD			BIT(5)
+#define DW_SPI_CAP_OCTAL		BIT(5)
 	unsigned long caps;
 	unsigned long bus_clk_rate;
 	unsigned int freq;		/* Default frequency */
@@ -141,6 +144,7 @@ struct dw_spi_priv {
 	u8 cs;				/* chip select pin */
 	u8 tmode;			/* TR/TO/RO/EEPROM */
 	u8 type;			/* SPI/SSP/MicroWire */
+	u8 spi_frf;			/* BYTE/DUAL/QUAD/OCTAL */
 };
 
 static inline u32 dw_read(struct dw_spi_priv *priv, u32 offset)
@@ -267,7 +271,6 @@ static void spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
 		priv->fifo_len = (fifo == 1) ? 0 : fifo;
 		dw_write(priv, DW_SPI_TXFTLR, 0);
 	}
-	dev_dbg(bus, "fifo_len=%d\n", priv->fifo_len);
 }
 
 /*
@@ -351,22 +354,21 @@ static int dw_spi_probe(struct udevice *bus)
 	if (ret)
 		return ret;
 
-	priv->caps = dev_get_driver_data(bus);
-	dw_spi_detect_caps(bus, priv);
-
-	version = dw_read(priv, DW_SPI_VERSION);
-	dev_dbg(bus, "ssi_version_id=%c.%c%c%c ssi_max_xfer_size=%u\n",
-		version >> 24, version >> 16, version >> 8, version,
-		priv->caps & DW_SPI_CAP_DFS32 ? 32 : 16);
-
 	/* Currently only bits_per_word == 8 supported */
 	priv->bits_per_word = 8;
 
 	priv->tmode = 0; /* Tx & Rx */
 
 	/* Basic HW init */
+	priv->caps = dev_get_driver_data(bus);
 	spi_hw_init(bus, priv);
 
+	version = dw_read(priv, DW_SPI_VERSION);
+	dev_dbg(bus,
+		"ssi_version_id=%c.%c%c%c ssi_rx_fifo_depth=%u ssi_max_xfer_size=%u\n",
+		version >> 24, version >> 16, version >> 8, version,
+		priv->fifo_len, priv->caps & DW_SPI_CAP_DFS32 ? 32 : 16);
+
 	return 0;
 }
 
@@ -748,13 +750,25 @@ static int dw_spi_set_mode(struct udevice *bus, uint mode)
 {
 	struct dw_spi_priv *priv = dev_get_priv(bus);
 
+	if (!(priv->caps & DW_SPI_CAP_DUAL) &&
+	    (mode & (SPI_RX_DUAL | SPI_TX_DUAL)))
+		return -EINVAL;
+
+	if (!(priv->caps & DW_SPI_CAP_QUAD) &&
+	    (mode & (SPI_RX_QUAD | SPI_TX_QUAD)))
+		return -EINVAL;
+
+	if (!(priv->caps & DW_SPI_CAP_OCTAL) &&
+	    (mode & (SPI_RX_OCTAL | SPI_TX_OCTAL)))
+		return -EINVAL;
+
 	/*
 	 * Can't set mode yet. Since this depends on if rx, tx, or
 	 * rx & tx is requested. So we have to defer this to the
 	 * real transfer function.
 	 */
 	priv->mode = mode;
-	dev_dbg(bus, "mode=%d\n", priv->mode);
+	dev_dbg(bus, "mode=%x\n", mode);
 
 	return 0;
 }
@@ -813,10 +827,13 @@ 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_QUAD | DW_SPI_CAP_OCTAL,
+	},
 	{
 		.compatible = "canaan,kendryte-k210-ssi",
-		.data = DW_SPI_CAP_DWC_SSI,
+		.data = DW_SPI_CAP_DWC_SSI | DW_SPI_CAP_QUAD,
 	},
 	{ .compatible = "intel,stratix10-spi" },
 	{ .compatible = "intel,agilex-spi" },
-- 
2.29.2



More information about the U-Boot mailing list