[U-Boot] [PATCH v2 2/9] spi: zynq_qspi: Add support of Dual parallel and Dual stacked modes

Siva Durga Prasad Paladugu siva.durga.paladugu at xilinx.com
Tue Jul 19 17:48:27 CEST 2016


Add Dual parallel and dual stacked supports for zynq
qspi driver. The is-dual property defines the dual
parallel mode and num-cs, numbere of chip selects
defines dual stacked mode if its value is 2

Signed-off-by: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
---
 drivers/spi/zynq_qspi.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c
index e636244..44057ba 100644
--- a/drivers/spi/zynq_qspi.c
+++ b/drivers/spi/zynq_qspi.c
@@ -52,6 +52,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #define CONFIG_SYS_ZYNQ_QSPI_WAIT	CONFIG_SYS_HZ/100	/* 10 ms */
 #endif
 
+#define ZYNQ_QSPI_LCR_TWO_MEM_MASK     BIT(30) /* QSPI Enable Bit Mask */
+#define ZYNQ_QSPI_LCR_SEP_BUS_MASK     BIT(29) /* QSPI Enable Bit Mask */
+#define ZYNQ_QSPI_LCR_U_PAGE           BIT(28) /* QSPI Upper memory set */
+
 /* zynq qspi register set */
 struct zynq_qspi_regs {
 	u32 cr;		/* 0x00 */
@@ -96,6 +100,8 @@ struct zynq_qspi_priv {
 	int bytes_to_transfer;
 	int bytes_to_receive;
 	unsigned int is_inst;
+	unsigned int is_dual;
+	unsigned int u_page;
 	unsigned cs_change:1;
 };
 
@@ -154,6 +160,14 @@ static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
 	confr &= ~ZYNQ_QSPI_LQSPICFG_LQMODE_MASK;
 	writel(confr, &regs->lqspicfg);
 
+	if (priv->is_dual == SF_DUAL_PARALLEL_FLASH)
+		writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK |
+			ZYNQ_QSPI_LCR_SEP_BUS_MASK,
+			&regs->lqspicfg);
+	else if (priv->is_dual == SF_DUAL_STACKED_FLASH)
+		writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK,
+		       &regs->lqspicfg);
+
 	/* Enable SPI */
 	writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
 }
@@ -161,7 +175,9 @@ static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
 static int zynq_qspi_child_pre_probe(struct udevice *bus)
 {
 	struct spi_slave *slave = dev_get_parent_priv(bus);
+	struct zynq_qspi_priv *priv = dev_get_priv(bus->parent);
 
+	slave->option = priv->is_dual;
 	slave->mode_rx = QUAD_OUTPUT_FAST;
 	slave->mode = SPI_TX_QUAD;
 	slave->no_all_quad = 1;
@@ -173,10 +189,23 @@ static int zynq_qspi_probe(struct udevice *bus)
 {
 	struct zynq_qspi_platdata *plat = dev_get_platdata(bus);
 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+	const void *blob = gd->fdt_blob;
+	int node = bus->of_offset;
+	u8 is_dual = 0;
+	u8 num_cs = 0;
 
 	priv->regs = plat->regs;
 	priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH;
 
+	is_dual = fdtdec_get_int(blob, node, "is-dual", 0);
+	if (is_dual) {
+		priv->is_dual = SF_DUAL_PARALLEL_FLASH;
+	} else {
+		num_cs = fdtdec_get_int(blob, node, "num-cs", 1);
+		if (num_cs == 2)
+			priv->is_dual = SF_DUAL_STACKED_FLASH;
+	}
+
 	/* init the zynq spi hw */
 	zynq_qspi_init_hw(priv);
 
@@ -437,6 +466,7 @@ static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv)
  */
 static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
 {
+	static u8 current_u_page;
 	u32 data = 0;
 	struct zynq_qspi_regs *regs = priv->regs;
 
@@ -446,6 +476,18 @@ static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
 	priv->bytes_to_transfer = priv->len;
 	priv->bytes_to_receive = priv->len;
 
+	if (priv->is_inst && (priv->is_dual == SF_DUAL_STACKED_FLASH) &&
+	    (current_u_page != priv->u_page)) {
+		if (priv->u_page)
+			writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK |
+				ZYNQ_QSPI_LCR_U_PAGE,
+				&regs->lqspicfg);
+		else
+			writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK,
+			       &regs->lqspicfg);
+		current_u_page = priv->u_page;
+	}
+
 	if (priv->len < 4)
 		zynq_qspi_fill_tx_fifo(priv, priv->len);
 	else
@@ -555,6 +597,11 @@ static int zynq_qspi_xfer(struct udevice *dev, unsigned int bitlen,
 	else
 		priv->cs_change = 0;
 
+	if (flags & SPI_XFER_U_PAGE)
+		priv->u_page = 1;
+	else
+		priv->u_page = 0;
+
 	zynq_qspi_transfer(priv);
 
 	return 0;
-- 
2.7.4



More information about the U-Boot mailing list