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 <siva...@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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to