]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
spi: zynqmp_qspi: Changes to support QSPI driver model
authorSiva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
Thu, 6 Aug 2015 13:59:25 +0000 (19:29 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Mon, 10 Aug 2015 05:31:59 +0000 (07:31 +0200)
Changes to support QSPI driver model for zynqMP and enable QSPI again.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
configs/xilinx_zynqmp_ep_defconfig
configs/xilinx_zynqmp_mini_qspi_defconfig
drivers/spi/zynqmp_qspi.c

index 7205d58ff8ac10c9765a087b75212673b1b6f208..ea7d63562494c903f76a3aa1e99de20f68344dca 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ZYNQMP=y
+CONFIG_ZYNQMP_QSPI=y
 CONFIG_NAND_ARASAN=y
 CONFIG_ZYNQMP_USB=y
 CONFIG_SYS_TEXT_BASE=0x8000000
index 9efefa21152aa358a9d21b45c1c5dd974312b7dd..c2e58c799b90b2d7810d45bf4543c92ac309c07c 100644 (file)
@@ -2,6 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_TARGET_ZYNQMP_MINI=y
 CONFIG_SECURE_IOU=y
+CONFIG_ZYNQMP_QSPI=y
 CONFIG_SYS_TEXT_BASE=0xFFFC0000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108"
 CONFIG_FIT=y
index 2fdfdbab14bd21beba7d87df5441365ee6d50026..842ab666888cbef9617b61f70b5f4b6a4b68e484 100644 (file)
@@ -64,6 +64,7 @@
 #define ZYNQMP_QSPI_STRT_GEN_FIFO              (1 << 28)
 #define ZYNQMP_QSPI_GEN_FIFO_STRT_MOD  (1 << 29)
 #define ZYNQMP_QSPI_GFIFO_WP_HOLD              (1 << 19)
+#define ZYNQMP_QSPI_BAUD_DIV_MASK      (7 << 3)
 #define ZYNQMP_QSPI_DFLT_BAUD_RATE_DIV (1 << 3)
 #define ZYNQMP_QSPI_GFIFO_ALL_INT_MASK 0xFBE
 #define ZYNQMP_QSPI_DMA_DST_I_STS_DONE (1 << 1)
@@ -125,16 +126,21 @@ struct zynqmp_qspi_dma_regs {
        u32 dmadstmsb;  /* 0x28 */
 };
 
-#define zynqmp_qspi_base                               \
-                ((struct zynqmp_qspi_regs *)(ZYNQMP_QSPI_BASEADDR + 0x100))
-#define zynqmp_qspi_dma                                        \
-                ((struct zynqmp_qspi_dma_regs *)(ZYNQMP_QSPI_BASEADDR + 0x800))
-
-struct zynqmp_qspi {
-       u32 input_clk_hz;
+struct zynqmp_qspi_platdata {
+       struct zynqmp_qspi_regs *regs;
+       struct zynqmp_qspi_dma_regs *dma_regs;
+       u32 frequency;
        u32 speed_hz;
-       const void *txbuf;
-       void *rxbuf;
+};
+
+struct zynqmp_qspi_priv {
+       struct zynqmp_qspi_regs *regs;
+       struct zynqmp_qspi_dma_regs *dma_regs;
+       u8 mode;
+       u32 freq;
+       const void *tx_buf;
+       void *rx_buf;
+       unsigned len;
        int bytes_to_transfer;
        int bytes_to_receive;
        unsigned int is_inst;
@@ -142,75 +148,69 @@ struct zynqmp_qspi {
        unsigned int u_page;
        unsigned int bus;
        unsigned int stripe;
+       unsigned cs_change:1;
 };
 
-struct spi_device {
-       struct zynqmp_qspi master;
-       u32 max_speed_hz;
-       u8 chip_select;
-       u8 mode;
-};
+static u8 last_cmd;
 
-struct spi_transfer {
-       const void *tx_buf;
-       void *rx_buf;
-       unsigned len;
-       unsigned cs_change:1;
-       u16 delay_usecs;
-       u32 speed_hz;
-};
+static int zynqmp_qspi_ofdata_to_platdata(struct udevice *bus)
+{
+       struct zynqmp_qspi_platdata *plat = bus->platdata;
 
-struct zynqmp_qspi_slave {
-       struct spi_slave slave;
-       struct spi_device qspi;
-};
-#define to_zynqmp_qspi_slave(s) container_of(s, struct zynqmp_qspi_slave, slave)
+       debug("%s\n", __func__);
+       plat->regs = (struct zynqmp_qspi_regs *)(ZYNQMP_QSPI_BASEADDR + 0x100);
+       plat->dma_regs = (struct zynqmp_qspi_dma_regs *)(ZYNQMP_QSPI_BASEADDR +
+                                                        0x800);
+       plat->frequency = 166666666;
+       plat->speed_hz = plat->frequency / 2;
 
-static u8 last_cmd;
+       return 0;
+}
 
-static void zynqmp_qspi_init_hw(int is_dual, unsigned int cs)
+static void zynqmp_qspi_init_hw(struct zynqmp_qspi_priv *priv)
 {
        u32 config_reg;
+       struct zynqmp_qspi_regs *regs = priv->regs;
 
-       writel(ZYNQMP_QSPI_GFIFO_SELECT, &zynqmp_qspi_base->gqspisel);
-       writel(ZYNQMP_QSPI_GFIFO_ALL_INT_MASK, &zynqmp_qspi_base->idisr);
-       writel(ZYNQMP_QSPI_FIFO_THRESHOLD, &zynqmp_qspi_base->txftr);
-       writel(ZYNQMP_QSPI_FIFO_THRESHOLD, &zynqmp_qspi_base->rxftr);
-       writel(ZYNQMP_QSPI_GFIFO_ALL_INT_MASK, &zynqmp_qspi_base->isr);
+       writel(ZYNQMP_QSPI_GFIFO_SELECT, &regs->gqspisel);
+       writel(ZYNQMP_QSPI_GFIFO_ALL_INT_MASK, &regs->idisr);
+       writel(ZYNQMP_QSPI_FIFO_THRESHOLD, &regs->txftr);
+       writel(ZYNQMP_QSPI_FIFO_THRESHOLD, &regs->rxftr);
+       writel(ZYNQMP_QSPI_GFIFO_ALL_INT_MASK, &regs->isr);
 
-       config_reg = readl(&zynqmp_qspi_base->confr);
+       config_reg = readl(&regs->confr);
        config_reg &= ~(ZYNQMP_QSPI_GFIFO_STRT_MODE_MASK |
                        ZYNQMP_QSPI_CONFIG_MODE_EN_MASK);
        config_reg |= ZYNQMP_QSPI_CONFIG_DMA_MODE |
                      ZYNQMP_QSPI_GFIFO_WP_HOLD |
                      ZYNQMP_QSPI_DFLT_BAUD_RATE_DIV;
-       writel(config_reg, &zynqmp_qspi_base->confr);
+       writel(config_reg, &regs->confr);
 
-       writel(ZYNQMP_QSPI_ENABLE_ENABLE_MASK, &zynqmp_qspi_base->enbr);
+       writel(ZYNQMP_QSPI_ENABLE_ENABLE_MASK, &regs->enbr);
 }
 
-static u32 zynqmp_qspi_bus_select(struct spi_device *qspi)
+static u32 zynqmp_qspi_bus_select(struct zynqmp_qspi_priv *priv)
 {
        u32 gqspi_fifo_reg = 0;
 
-       if (qspi->master.is_dual == SF_DUAL_PARALLEL_FLASH) {
-               if (qspi->master.bus == SPI_XFER_ON_BOTH)
+       if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) {
+               if (priv->bus == SPI_XFER_ON_BOTH)
                        gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS |
                                         ZYNQMP_QSPI_GFIFO_UP_BUS |
                                         ZYNQMP_QSPI_GFIFO_CS_UPPER |
                                         ZYNQMP_QSPI_GFIFO_CS_LOWER;
-               else if (qspi->master.bus == SPI_XFER_ON_LOWER)
+               else if (priv->bus == SPI_XFER_ON_LOWER)
                        gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS |
                                         ZYNQMP_QSPI_GFIFO_CS_UPPER |
                                         ZYNQMP_QSPI_GFIFO_CS_LOWER;
-               else if (qspi->master.bus == SPI_XFER_ON_UPPER)
+               else if (priv->bus == SPI_XFER_ON_UPPER)
                        gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS |
                                         ZYNQMP_QSPI_GFIFO_CS_LOWER |
                                         ZYNQMP_QSPI_GFIFO_CS_UPPER;
                else
-                       printf("Wrong Bus selection:0x%x\n", qspi->master.bus);
+                       debug("Wrong Bus selection:0x%x\n", priv->bus);
        } else {
-               if (qspi->master.u_page)
+               if (priv->u_page)
                        gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS |
                                         ZYNQMP_QSPI_GFIFO_CS_UPPER;
                else
@@ -220,19 +220,20 @@ static u32 zynqmp_qspi_bus_select(struct spi_device *qspi)
        return gqspi_fifo_reg;
 }
 
-static void zynqmp_qspi_chipselect(struct spi_device *qspi, int is_on)
+static void zynqmp_qspi_chipselect(struct zynqmp_qspi_priv *priv, int is_on)
 {
        u32 gqspi_fifo_reg = 0;
+       struct zynqmp_qspi_regs *regs = priv->regs;
 
        if (is_on) {
-               gqspi_fifo_reg = zynqmp_qspi_bus_select(qspi);
+               gqspi_fifo_reg = zynqmp_qspi_bus_select(priv);
                gqspi_fifo_reg |= ZYNQMP_QSPI_SPI_MODE_SPI |
                                  ZYNQMP_QSPI_IMD_DATA_CS_ASSERT;
        } else {
-               if (qspi->master.is_dual == SF_DUAL_PARALLEL_FLASH)
+               if (priv->is_dual == SF_DUAL_PARALLEL_FLASH)
                        gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS |
                                         ZYNQMP_QSPI_GFIFO_LOW_BUS;
-               else if (qspi->master.u_page)
+               else if (priv->u_page)
                        gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS;
                else
                        gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS;
@@ -241,46 +242,141 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, int is_on)
 
        debug("GFIFO_CMD_CS: 0x%x\n", gqspi_fifo_reg);
 
-       writel(gqspi_fifo_reg, &zynqmp_qspi_base->genfifo);
+       writel(gqspi_fifo_reg, &regs->genfifo);
 }
 
-static int zynqmp_qspi_setup_transfer(struct spi_device *qspi,
-               struct spi_transfer *transfer)
+static int zynqmp_qspi_set_speed(struct udevice *bus, uint speed)
 {
-       u32 config_reg;
+       struct zynqmp_qspi_platdata *plat = bus->platdata;
+       struct zynqmp_qspi_priv *priv = dev_get_priv(bus);
+       struct zynqmp_qspi_regs *regs = priv->regs;
+       uint32_t confr;
+       u8 baud_rate_val = 0;
+
+       debug("%s\n", __func__);
+       if (speed > plat->frequency)
+               speed = plat->frequency;
+
+       /* Set the clock frequency */
+       confr = readl(&regs->confr);
+       if (speed == 0) {
+               /* Set baudrate x8, if the freq is 0 */
+               baud_rate_val = 0x2;
+       } else if (plat->speed_hz != speed) {
+               while ((baud_rate_val < 8) &&
+                      ((plat->frequency /
+                      (2 << baud_rate_val)) > speed))
+                       baud_rate_val++;
+
+               plat->speed_hz = speed / (2 << baud_rate_val);
+       }
+       confr &= ~ZYNQMP_QSPI_BAUD_DIV_MASK;
+       confr |= (baud_rate_val << 3);
+
+       priv->freq = speed;
+
+       debug("regs=%p, mode=%d\n", priv->regs, priv->freq);
+
+       return 0;
+}
 
-       if (qspi->mode & ~MODEBITS) {
-               printf("%s: Unsupported mode bits %x\n",
-                      __func__, qspi->mode & ~MODEBITS);
+static int zynqmp_qspi_child_pre_probe(struct udevice *bus)
+{
+       struct spi_slave *slave = dev_get_parentdata(bus);
+       struct zynqmp_qspi_priv *priv = dev_get_priv(bus->parent);
+
+       slave->option = priv->is_dual;
+       slave->op_mode_rx = SPI_OPM_RX_QOF;
+       slave->op_mode_tx = SPI_OPM_TX_QPP;
+
+       return 0;
+}
+
+static void zynqmp_qspi_check_is_dual_flash(struct zynqmp_qspi_priv *priv)
+{
+       int is_dual = -1;
+       int lower_mio = 0, upper_mio = 0, upper_mio_cs1 = 0;
+
+       lower_mio = zynq_slcr_get_mio_pin_status("qspi0");
+       if (lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0)
+               priv->is_dual = SF_SINGLE_FLASH;
+
+       upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs");
+       if ((lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0) &&
+           (upper_mio_cs1 == ZYNQMP_QSPI_MIO_NUM_QSPI1_CS))
+               priv->is_dual = SF_DUAL_STACKED_FLASH;
+
+       upper_mio = zynq_slcr_get_mio_pin_status("qspi1");
+       if ((lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0) &&
+           (upper_mio_cs1 == ZYNQMP_QSPI_MIO_NUM_QSPI1_CS) &&
+           (upper_mio == ZYNQMP_QSPI_MIO_NUM_QSPI1))
+               priv->is_dual = SF_DUAL_PARALLEL_FLASH;
+}
+
+static int zynqmp_qspi_probe(struct udevice *bus)
+{
+       struct zynqmp_qspi_platdata *plat = dev_get_platdata(bus);
+       struct zynqmp_qspi_priv *priv = dev_get_priv(bus);
+
+       debug("zynqmp_qspi_probe:  bus:%p, priv:%p \n", bus, priv);
+
+       priv->regs = plat->regs;
+       priv->dma_regs = plat->dma_regs;
+       zynqmp_qspi_check_is_dual_flash(priv);
+
+       if (priv->is_dual == -1) {
+               debug("%s: No QSPI device detected based on MIO settings\n",
+                     __func__);
                return -1;
        }
 
-       config_reg = readl(&zynqmp_qspi_base->confr);
+       /* init the zynq spi hw */
+       zynqmp_qspi_init_hw(priv);
+
+       return 0;
+}
+
+static int zynqmp_qspi_set_mode(struct udevice *bus, uint mode)
+{
+       struct zynqmp_qspi_priv *priv = dev_get_priv(bus);
+       struct zynqmp_qspi_regs *regs = priv->regs;
+       uint32_t confr;
+
+       debug("%s\n", __func__);
+       /* Set the SPI Clock phase and polarities */
+       confr = readl(&regs->confr);
+       confr &= ~(ZYNQMP_QSPI_CONFIG_CPHA_MASK |
+                  ZYNQMP_QSPI_CONFIG_CPOL_MASK);
+
+       if (priv->mode & SPI_CPHA)
+               confr |= ZYNQMP_QSPI_CONFIG_CPHA_MASK;
+       if (priv->mode & SPI_CPOL)
+               confr |= ZYNQMP_QSPI_CONFIG_CPOL_MASK;
+
+       //writel(confr, &regs->confr);
+       priv->mode = mode;
 
-       /* Set the QSPI clock phase and clock polarity */
-       config_reg &= (~ZYNQMP_QSPI_CONFIG_CPHA_MASK) &
-                               (~ZYNQMP_QSPI_CONFIG_CPOL_MASK);
-       if (qspi->mode & SPI_CPHA)
-               config_reg |= ZYNQMP_QSPI_CONFIG_CPHA_MASK;
-       if (qspi->mode & SPI_CPOL)
-               config_reg |= ZYNQMP_QSPI_CONFIG_CPOL_MASK;
+       debug("regs=%p, mode=%d\n", priv->regs, priv->mode);
 
        return 0;
 }
 
-static int zynqmp_qspi_fill_tx_fifo(u32 *buf, u32 size)
+
+static int zynqmp_qspi_fill_tx_fifo(struct zynqmp_qspi_priv *priv, u32 size)
 {
        u32 data;
        u32 timeout = 10000000;
+       struct zynqmp_qspi_regs *regs = priv->regs;
+       u32 *buf = (u32 *)priv->tx_buf;
 
-       debug("TxFIFO: 0x%x, size: 0x%x\n", readl(&zynqmp_qspi_base->isr),
+       debug("TxFIFO: 0x%x, size: 0x%x\n", readl(&regs->isr),
              size);
 
        while (size && timeout) {
-               if (readl(&zynqmp_qspi_base->isr) &
+               if (readl(&regs->isr) &
                        ZYNQMP_QSPI_IXR_TXNFULL_MASK) {
                        if (size >= 4) {
-                               writel(*buf, &zynqmp_qspi_base->txd0r);
+                               writel(*buf, &regs->txd0r);
                                buf++;
                                size -= 4;
                        } else {
@@ -303,7 +399,7 @@ static int zynqmp_qspi_fill_tx_fifo(u32 *buf, u32 size)
                                        data |= 0xFF000000;
                                        break;
                                }
-                               writel(data, &zynqmp_qspi_base->txd0r);
+                               writel(data, &regs->txd0r);
                                size = 0;
                        }
                } else {
@@ -311,80 +407,80 @@ static int zynqmp_qspi_fill_tx_fifo(u32 *buf, u32 size)
                }
        }
        if (!timeout) {
-               printf("zynqmp_qspi_fill_tx_fifo: Timeout\n");
+               debug("zynqmp_qspi_fill_tx_fifo: Timeout\n");
                return -1;
        }
 
        return 0;
 }
 
-static void zynqmp_qspi_genfifo_cmd(struct spi_device *qspi,
-                                   struct spi_transfer *transfer)
+static void zynqmp_qspi_genfifo_cmd(struct zynqmp_qspi_priv *priv)
 {
        u8 command = 1;
        u32 gen_fifo_cmd;
        u32 bytecount = 0;
+       struct zynqmp_qspi_regs *regs = priv->regs;
 
-       while (transfer->len) {
-               gen_fifo_cmd = zynqmp_qspi_bus_select(qspi);
+       while (priv->len) {
+               gen_fifo_cmd = zynqmp_qspi_bus_select(priv);
                gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_TX;
 
                if (command) {
                        command = 0;
-                       last_cmd = *(u8 *)transfer->tx_buf;
+                       last_cmd = *(u8 *)priv->tx_buf;
                }
 
                gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI;
-               gen_fifo_cmd |= *(u8 *)transfer->tx_buf;
+               gen_fifo_cmd |= *(u8 *)priv->tx_buf;
                bytecount++;
-               transfer->len--;
-               transfer->tx_buf = (u8 *)transfer->tx_buf + 1;
+               priv->len--;
+               priv->tx_buf = (u8 *)priv->tx_buf + 1;
 
                debug("GFIFO_CMD_Cmd = 0x%x\n", gen_fifo_cmd);
 
-               writel(gen_fifo_cmd, &zynqmp_qspi_base->genfifo);
+               writel(gen_fifo_cmd, &regs->genfifo);
        }
 }
 
-static u32 zynqmp_qspi_calc_exp(struct spi_transfer *transfer,
+static u32 zynqmp_qspi_calc_exp(struct zynqmp_qspi_priv *priv,
                                u32 *gen_fifo_cmd)
 {
        u32 expval = 8;
        u32 len;
 
        while (1) {
-               if (transfer->len > 255) {
-                       if (transfer->len & (1 << expval)) {
+               if (priv->len > 255) {
+                       if (priv->len & (1 << expval)) {
                                *gen_fifo_cmd &= ~ZYNQMP_QSPI_GFIFO_IMD_MASK;
                                *gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_EXP_MASK;
                                *gen_fifo_cmd |= expval;
-                               transfer->len -= (1 << expval);
+                               priv->len -= (1 << expval);
                                return expval;
                        }
                        expval++;
                } else {
                        *gen_fifo_cmd &= ~(ZYNQMP_QSPI_GFIFO_IMD_MASK |
                                          ZYNQMP_QSPI_GFIFO_EXP_MASK);
-                       *gen_fifo_cmd |= (u8)transfer->len;
-                       len = (u8)transfer->len;
-                       transfer->len  = 0;
+                       *gen_fifo_cmd |= (u8)priv->len;
+                       len = (u8)priv->len;
+                       priv->len  = 0;
                        return len;
                }
        }
 }
 
-static int zynqmp_qspi_genfifo_fill_tx(struct spi_device *qspi,
-                                       struct spi_transfer *transfer)
+static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv)
 {
        u32 gen_fifo_cmd;
        u32 len;
        int ret = 0;
+       struct zynqmp_qspi_regs *regs = priv->regs;
 
-       gen_fifo_cmd = zynqmp_qspi_bus_select(qspi);
+       gen_fifo_cmd = zynqmp_qspi_bus_select(priv);
        gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_TX |
                        ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK;
 
-       if (qspi->master.stripe)
+       if (priv->stripe)
                gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK;
 
        if (last_cmd == QUAD_PAGE_PROGRAM_CMD)
@@ -392,17 +488,17 @@ static int zynqmp_qspi_genfifo_fill_tx(struct spi_device *qspi,
        else
                gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI;
 
-       while (transfer->len) {
-               len = zynqmp_qspi_calc_exp(transfer, &gen_fifo_cmd);
-               writel(gen_fifo_cmd, &zynqmp_qspi_base->genfifo);
+       while (priv->len) {
+               len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
+               writel(gen_fifo_cmd, &regs->genfifo);
 
                debug("GFIFO_CMD_TX:0x%x\n", gen_fifo_cmd);
 
                if (gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK)
-                       ret = zynqmp_qspi_fill_tx_fifo((u32 *)transfer->tx_buf,
+                       ret = zynqmp_qspi_fill_tx_fifo(priv,
                                                       1 << len);
                else
-                       ret = zynqmp_qspi_fill_tx_fifo((u32 *)transfer->tx_buf,
+                       ret = zynqmp_qspi_fill_tx_fifo(priv,
                                                       len);
 
                if (ret)
@@ -411,17 +507,18 @@ static int zynqmp_qspi_genfifo_fill_tx(struct spi_device *qspi,
        return ret;
 }
 
-static int zynqmp_qspi_genfifo_fill_rx(struct spi_device *qspi,
-                                       struct spi_transfer *transfer)
+static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv)
 {
        u32 gen_fifo_cmd;
        u32 *buf;
        u32 addr;
        u32 size, len;
        u32 timeout = 10000000;
-       u32 actuallen = transfer->len;
+       u32 actuallen = priv->len;
+       struct zynqmp_qspi_regs *regs = priv->regs;
+       struct zynqmp_qspi_dma_regs *dma_regs = priv->dma_regs;
 
-       gen_fifo_cmd = zynqmp_qspi_bus_select(qspi);
+       gen_fifo_cmd = zynqmp_qspi_bus_select(priv);
        gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_RX |
                        ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK;
 
@@ -430,252 +527,151 @@ static int zynqmp_qspi_genfifo_fill_rx(struct spi_device *qspi,
        else
                gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI;
 
-       if (qspi->master.stripe)
+       if (priv->stripe)
                gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK;
 
-       if (!((u32)transfer->rx_buf & 0x3) && !(actuallen % 4)) {
-               buf = (u32 *)transfer->rx_buf;
+       if (!((u32)priv->rx_buf & 0x3) && !(actuallen % 4)) {
+               buf = (u32 *)priv->rx_buf;
        } else {
-               ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(transfer->len, 4));
+               ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, 4));
                buf = (u32 *)tmp;
        }
-       writel((u32)buf, &zynqmp_qspi_dma->dmadst);
-       writel(roundup(transfer->len, 4), &zynqmp_qspi_dma->dmasize);
-       writel(ZYNQMP_QSPI_DMA_DST_I_STS_MASK, &zynqmp_qspi_dma->dmaier);
+       writel((u32)buf, &dma_regs->dmadst);
+       writel(roundup(priv->len, 4), &dma_regs->dmasize);
+       writel(ZYNQMP_QSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier);
        addr = (u32)buf;
-       size = roundup(transfer->len, ARCH_DMA_MINALIGN);
+       size = roundup(priv->len, ARCH_DMA_MINALIGN);
        flush_dcache_range(addr, addr+size);
 
-       while (transfer->len) {
-               len = zynqmp_qspi_calc_exp(transfer, &gen_fifo_cmd);
+       while (priv->len) {
+               len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
                if (!(gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK) &&
                    (len % 4)) {
                        gen_fifo_cmd &= ~(0xFF);
                        gen_fifo_cmd |= (len/4 + 1) * 4;
                }
-               writel(gen_fifo_cmd, &zynqmp_qspi_base->genfifo);
+               writel(gen_fifo_cmd, &regs->genfifo);
 
                debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd);
        }
 
        while (timeout) {
-               if (readl(&zynqmp_qspi_dma->dmaisr) &
+               if (readl(&dma_regs->dmaisr) &
                    ZYNQMP_QSPI_DMA_DST_I_STS_DONE) {
                        writel(ZYNQMP_QSPI_DMA_DST_I_STS_DONE,
-                              &zynqmp_qspi_dma->dmaisr);
+                              &dma_regs->dmaisr);
                        break;
                }
                timeout--;
        }
 
-       debug("buf:0x%lx, txbuf:0x%lx, *buf:0x%x len: 0x%x\n",
-             (unsigned long)buf, (unsigned long)transfer->rx_buf, *buf,
+       debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n",
+             (unsigned long)buf, (unsigned long)priv->rx_buf, *buf,
              actuallen);
        if (!timeout) {
-               printf("DMA Timeout:0x%x\n", readl(&zynqmp_qspi_dma->dmaisr));
+               debug("DMA Timeout:0x%x\n", readl(&dma_regs->dmaisr));
                return -1;
        }
 
-       if (buf != transfer->rx_buf)
-               memcpy(transfer->rx_buf, buf, actuallen);
+       if (buf != priv->rx_buf)
+               memcpy(priv->rx_buf, buf, actuallen);
 
        return 0;
 }
 
-static int zynqmp_qspi_start_transfer(struct spi_device *qspi,
-                       struct spi_transfer *transfer)
+static int zynqmp_qspi_start_transfer(struct zynqmp_qspi_priv *priv)
 {
        int ret = 0;
 
-       if (qspi->master.is_inst) {
-               if (transfer->tx_buf)
-                       zynqmp_qspi_genfifo_cmd(qspi, transfer);
+       if (priv->is_inst) {
+               if (priv->tx_buf)
+                       zynqmp_qspi_genfifo_cmd(priv);
                else
                        ret = -1;
        } else {
-               if (transfer->tx_buf)
-                       ret = zynqmp_qspi_genfifo_fill_tx(qspi, transfer);
-               else if (transfer->rx_buf)
-                       ret = zynqmp_qspi_genfifo_fill_rx(qspi, transfer);
+               if (priv->tx_buf)
+                       ret = zynqmp_qspi_genfifo_fill_tx(priv);
+               else if (priv->rx_buf)
+                       ret = zynqmp_qspi_genfifo_fill_rx(priv);
                else
                        ret = -1;
        }
        return ret;
 }
 
-static int zynqmp_qspi_check_is_dual_flash(void)
-{
-       int is_dual = -1;
-       int lower_mio = 0, upper_mio = 0, upper_mio_cs1 = 0;
-
-       lower_mio = zynq_slcr_get_mio_pin_status("qspi0");
-       if (lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0)
-               is_dual = SF_SINGLE_FLASH;
-
-       upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs");
-       if ((lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0) &&
-           (upper_mio_cs1 == ZYNQMP_QSPI_MIO_NUM_QSPI1_CS))
-               is_dual = SF_DUAL_STACKED_FLASH;
-
-       upper_mio = zynq_slcr_get_mio_pin_status("qspi1");
-       if ((lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0) &&
-           (upper_mio_cs1 == ZYNQMP_QSPI_MIO_NUM_QSPI1_CS) &&
-           (upper_mio == ZYNQMP_QSPI_MIO_NUM_QSPI1))
-               is_dual = SF_DUAL_PARALLEL_FLASH;
-
-       return is_dual;
-}
-
-static int zynqmp_qspi_transfer(struct spi_device *qspi,
-               struct spi_transfer *transfer)
+static int zynqmp_qspi_transfer(struct zynqmp_qspi_priv *priv)
 {
-       struct zynqmp_qspi *zqspi = &qspi->master;
        static unsigned cs_change = 1;
        int status = 0;
 
        debug("%s\n", __func__);
 
        while (1) {
-               if (transfer->speed_hz) {
-                       status = zynqmp_qspi_setup_transfer(qspi, transfer);
-                       if (status < 0)
-                               break;
-               }
-
                /* Select the chip if required */
                if (cs_change)
-                       zynqmp_qspi_chipselect(qspi, 1);
+                       zynqmp_qspi_chipselect(priv, 1);
 
-               cs_change = transfer->cs_change;
+               cs_change = priv->cs_change;
 
-               if (!transfer->tx_buf && !transfer->rx_buf && transfer->len) {
+               if (!priv->tx_buf && !priv->rx_buf && priv->len) {
                        status = -1;
                        break;
                }
 
                /* Request the transfer */
-               if (transfer->len) {
-                       status = zynqmp_qspi_start_transfer(qspi, transfer);
-                       zqspi->is_inst = 0;
+               if (priv->len) {
+                       status = zynqmp_qspi_start_transfer(priv);
+                       priv->is_inst = 0;
                        if (status < 0)
                                break;
                }
 
-               if (transfer->delay_usecs)
-                       udelay(transfer->delay_usecs);
-
                if (cs_change)
                        /* Deselect the chip */
-                       zynqmp_qspi_chipselect(qspi, 0);
+                       zynqmp_qspi_chipselect(priv, 0);
                break;
        }
 
-       zynqmp_qspi_setup_transfer(qspi, NULL);
-
        return status;
 }
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-       /* 1 bus with 2 chipselect */
-       return bus == 0 && cs < 2;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
+static int zynqmp_qspi_claim_bus(struct udevice *dev)
 {
-       debug("%s: slave 0x%08lx\n", __func__, (unsigned long)slave);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-       debug("%s: slave 0x%08lx\n", __func__, (unsigned long)slave);
-}
+       struct udevice *bus = dev->parent;
+       struct zynqmp_qspi_priv *priv = dev_get_priv(bus);
+       struct zynqmp_qspi_regs *regs = priv->regs;
 
-void spi_init(void)
-{
        debug("%s\n", __func__);
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int mode)
-{
-       int is_dual = SF_SINGLE_FLASH;
-       struct zynqmp_qspi_slave *qspi;
-
-       debug("%s: bus: %d cs: %d max_hz: %d mode: %d\n",
-             __func__, bus, cs, max_hz, mode);
-
-       if (!spi_cs_is_valid(bus, cs))
-               return NULL;
-
-       is_dual = zynqmp_qspi_check_is_dual_flash();
-
-       if (is_dual == -1) {
-               printf("%s: No QSPI device detected based on MIO settings\n",
-                      __func__);
-               return NULL;
-       }
-
-       zynqmp_qspi_init_hw(is_dual, cs);
-
-       qspi = spi_alloc_slave(struct zynqmp_qspi_slave, bus, cs);
-       if (!qspi) {
-               printf("%s: Fail to allocate zynqmp_qspi_slave\n", __func__);
-               return NULL;
-       }
+       writel(ZYNQMP_QSPI_ENABLE_ENABLE_MASK, &regs->enbr);
 
-       debug("Defaulting to 200000000 Hz qspi clk");
-       qspi->qspi.master.input_clk_hz = 200000000;
-
-       qspi->slave.option = is_dual;
-       qspi->slave.op_mode_rx = SPI_OPM_RX_QOF;
-       qspi->slave.op_mode_tx = SPI_OPM_TX_QPP;
-       qspi->qspi.master.speed_hz = qspi->qspi.master.input_clk_hz / 2;
-       qspi->qspi.max_speed_hz = (max_hz < qspi->qspi.master.speed_hz) ?
-                                 max_hz : qspi->qspi.master.speed_hz;
-       qspi->qspi.master.is_dual = is_dual;
-       qspi->qspi.mode = mode;
-       qspi->qspi.chip_select = 0;
-       zynqmp_qspi_setup_transfer(&qspi->qspi, NULL);
-
-       return &qspi->slave;
+       return 0;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+static int zynqmp_qspi_release_bus(struct udevice *dev)
 {
-       struct zynqmp_qspi_slave *qspi;
-
-       debug("%s: slave: 0x%08lx\n", __func__, (unsigned long)slave);
+       struct udevice *bus = dev->parent;
+       struct zynqmp_qspi_priv *priv = dev_get_priv(bus);
+       struct zynqmp_qspi_regs *regs = priv->regs;
 
-       qspi = to_zynqmp_qspi_slave(slave);
-       free(qspi);
-}
+       debug("%s\n", __func__);
+       writel(~ZYNQMP_QSPI_ENABLE_ENABLE_MASK, &regs->enbr);
 
-int spi_claim_bus(struct spi_slave *slave)
-{
-       debug("%s: slave: 0x%08lx\n", __func__, (unsigned long)slave);
        return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
-{
-       debug("%s: slave: 0x%08lx\n", __func__, (unsigned long)slave);
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+int zynqmp_qspi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout,
                void *din, unsigned long flags)
 {
-       struct zynqmp_qspi_slave *qspi;
-       struct spi_transfer transfer;
+       struct udevice *bus = dev->parent;
+       struct zynqmp_qspi_priv *priv = dev_get_priv(bus);
 
-       debug("%s: slave: 0x%08lx bitlen: %d dout: 0x%08lx ", __func__,
-             (unsigned long)slave, bitlen, (unsigned long)dout);
+       debug("%s: priv: 0x%08lx bitlen: %d dout: 0x%08lx ", __func__,
+             (unsigned long)priv, bitlen, (unsigned long)dout);
        debug("din: 0x%08lx flags: 0x%lx\n", (unsigned long)din, flags);
 
-       qspi = (struct zynqmp_qspi_slave *)slave;
-       transfer.tx_buf = dout;
-       transfer.rx_buf = din;
-       transfer.len = bitlen / 8;
+       priv->tx_buf = dout;
+       priv->rx_buf = din;
+       priv->len = bitlen / 8;
 
        /*
         * Festering sore.
@@ -683,34 +679,56 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
         * transmit must contain a device command.
         */
        if (dout && flags & SPI_XFER_BEGIN)
-               qspi->qspi.master.is_inst = 1;
+               priv->is_inst = 1;
        else
-               qspi->qspi.master.is_inst = 0;
+               priv->is_inst = 0;
 
        if (flags & SPI_XFER_END)
-               transfer.cs_change = 1;
+               priv->cs_change = 1;
        else
-               transfer.cs_change = 0;
+               priv->cs_change = 0;
 
        if (flags & SPI_XFER_U_PAGE)
-               qspi->qspi.master.u_page = 1;
+               priv->u_page = 1;
        else
-               qspi->qspi.master.u_page = 0;
+               priv->u_page = 0;
 
-       qspi->qspi.master.stripe = 0;
-       qspi->qspi.master.bus = 0;
-       if (qspi->slave.option == SF_DUAL_PARALLEL_FLASH) {
-               qspi->qspi.master.is_dual = SF_DUAL_PARALLEL_FLASH;
+       priv->stripe = 0;
+       priv->bus = 0;
+
+       if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) {
                if (flags & SPI_XFER_MASK)
-                       qspi->qspi.master.bus = (flags & SPI_XFER_MASK) >> 8;
+                       priv->bus = (flags & SPI_XFER_MASK) >> 8;
                if (flags & SPI_XFER_STRIPE)
-                       qspi->qspi.master.stripe = 1;
+                       priv->stripe = 1;
        }
 
-       transfer.delay_usecs = 0;
-       transfer.speed_hz = qspi->qspi.max_speed_hz;
-
-       zynqmp_qspi_transfer(&qspi->qspi, &transfer);
+       zynqmp_qspi_transfer(priv);
 
        return 0;
 }
+
+static const struct dm_spi_ops zynqmp_qspi_ops = {
+       .claim_bus      = zynqmp_qspi_claim_bus,
+       .release_bus    = zynqmp_qspi_release_bus,
+       .xfer           = zynqmp_qspi_xfer,
+       .set_speed      = zynqmp_qspi_set_speed,
+       .set_mode       = zynqmp_qspi_set_mode,
+};
+
+static const struct udevice_id zynqmp_qspi_ids[] = {
+       { .compatible = "xlnx,zynqmp-qspi-1.0" },
+       { }
+};
+
+U_BOOT_DRIVER(zynqmp_qspi) = {
+       .name   = "zynqmp_qspi",
+       .id     = UCLASS_SPI,
+       .of_match = zynqmp_qspi_ids,
+       .ops    = &zynqmp_qspi_ops,
+       .ofdata_to_platdata = zynqmp_qspi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct zynqmp_qspi_platdata),
+       .priv_auto_alloc_size = sizeof(struct zynqmp_qspi_priv),
+       .probe  = zynqmp_qspi_probe,
+       .child_pre_probe = zynqmp_qspi_child_pre_probe,
+};