qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support
@ 2021-02-06 14:38 Bin Meng
  2021-02-06 14:38 ` [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues Bin Meng
  2021-02-06 14:38 ` [PATCH 2/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support Bin Meng
  0 siblings, 2 replies; 7+ messages in thread
From: Bin Meng @ 2021-02-06 14:38 UTC (permalink / raw)
  To: Alistair Francis, Edgar E . Iglesias, Peter Maydell, qemu-arm,
	qemu-devel
  Cc: Bin Meng

From: Bin Meng <bin.meng@windriver.com>

ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
crash. This is observed when testing VxWorks 7.

Add a basic implementation of QSPI DMA functionality.


Xuzhou Cheng (2):
  hw/ssi: xilinx_spips: Clean up coding convention issues
  hw/ssi: xilinx_spips: Implement basic QSPI DMA support

 hw/ssi/xilinx_spips.c | 211 +++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 183 insertions(+), 28 deletions(-)

-- 
2.7.4



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues
  2021-02-06 14:38 [PATCH 0/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support Bin Meng
@ 2021-02-06 14:38 ` Bin Meng
  2021-02-06 15:18   ` Peter Maydell
  2021-02-06 17:01   ` Philippe Mathieu-Daudé
  2021-02-06 14:38 ` [PATCH 2/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support Bin Meng
  1 sibling, 2 replies; 7+ messages in thread
From: Bin Meng @ 2021-02-06 14:38 UTC (permalink / raw)
  To: Alistair Francis, Edgar E . Iglesias, Peter Maydell, qemu-arm,
	qemu-devel
  Cc: Xuzhou Cheng, Bin Meng

From: Xuzhou Cheng <xuzhou.cheng@windriver.com>

There are some coding convention warnings in xilinx_spips.c,
as reported by:

  $ ./scripts/checkpatch.pl hw/ssi/xilinx_spips.c

Let's clean them up.

Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>
---

 hw/ssi/xilinx_spips.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index a897034..8a0cc22 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -176,7 +176,8 @@
     FIELD(GQSPI_FIFO_CTRL, GENERIC_FIFO_RESET, 0, 1)
 #define R_GQSPI_GFIFO_THRESH    (0x150 / 4)
 #define R_GQSPI_DATA_STS (0x15c / 4)
-/* We use the snapshot register to hold the core state for the currently
+/*
+ * We use the snapshot register to hold the core state for the currently
  * or most recently executed command. So the generic fifo format is defined
  * for the snapshot register
  */
@@ -424,7 +425,8 @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
     xlnx_zynqmp_qspips_update_ixr(s);
 }
 
-/* N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
+/*
+ * N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
  * column wise (from element 0 to N-1). num is the length of x, and dir
  * reverses the direction of the transform. Best illustrated by example:
  * Each digit in the below array is a single bit (num == 3):
@@ -637,8 +639,10 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
                 tx_rx[i] = tx;
             }
         } else {
-            /* Extract a dummy byte and generate dummy cycles according to the
-             * link state */
+            /*
+             * Extract a dummy byte and generate dummy cycles according to the
+             * link state
+             */
             tx = fifo8_pop(&s->tx_fifo);
             dummy_cycles = 8 / s->link_state;
         }
@@ -721,8 +725,9 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
             }
             break;
         case (SNOOP_ADDR):
-            /* Address has been transmitted, transmit dummy cycles now if
-             * needed */
+            /*
+             * Address has been transmitted, transmit dummy cycles now if needed
+             */
             if (s->cmd_dummies < 0) {
                 s->snoop_state = SNOOP_NONE;
             } else {
@@ -876,7 +881,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
 }
 
 static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
-                                                        unsigned size)
+                                  unsigned size)
 {
     XilinxSPIPS *s = opaque;
     uint32_t mask = ~0;
@@ -970,7 +975,7 @@ static uint64_t xlnx_zynqmp_qspips_read(void *opaque,
 }
 
 static void xilinx_spips_write(void *opaque, hwaddr addr,
-                                        uint64_t value, unsigned size)
+                               uint64_t value, unsigned size)
 {
     int mask = ~0;
     XilinxSPIPS *s = opaque;
@@ -1072,7 +1077,7 @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
 }
 
 static void xlnx_zynqmp_qspips_write(void *opaque, hwaddr addr,
-                                        uint64_t value, unsigned size)
+                                     uint64_t value, unsigned size)
 {
     XlnxZynqMPQSPIPS *s = XLNX_ZYNQMP_QSPIPS(opaque);
     uint32_t reg = addr / 4;
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support
  2021-02-06 14:38 [PATCH 0/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support Bin Meng
  2021-02-06 14:38 ` [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues Bin Meng
@ 2021-02-06 14:38 ` Bin Meng
  2021-02-06 15:28   ` Peter Maydell
  1 sibling, 1 reply; 7+ messages in thread
From: Bin Meng @ 2021-02-06 14:38 UTC (permalink / raw)
  To: Alistair Francis, Edgar E . Iglesias, Peter Maydell, qemu-arm,
	qemu-devel
  Cc: Xuzhou Cheng, Bin Meng

From: Xuzhou Cheng <xuzhou.cheng@windriver.com>

ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
crash. This is observed when testing VxWorks 7.

Add a basic implementation of QSPI DMA functionality.

Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>

---

 hw/ssi/xilinx_spips.c | 188 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 169 insertions(+), 19 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 8a0cc22..57ab9a3 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -195,12 +195,72 @@
 #define R_GQSPI_MOD_ID        (0x1fc / 4)
 #define R_GQSPI_MOD_ID_RESET  (0x10a0000)
 
-#define R_QSPIDMA_DST_CTRL         (0x80c / 4)
-#define R_QSPIDMA_DST_CTRL_RESET   (0x803ffa00)
-#define R_QSPIDMA_DST_I_MASK       (0x820 / 4)
-#define R_QSPIDMA_DST_I_MASK_RESET (0xfe)
-#define R_QSPIDMA_DST_CTRL2        (0x824 / 4)
-#define R_QSPIDMA_DST_CTRL2_RESET  (0x081bfff8)
+#define GQSPI_CNFG_MODE_EN_IO  (0)
+#define GQSPI_CNFG_MODE_EN_DMA (2)
+
+/*
+ * Ref: UG1087 (v1.7) February 8, 2019
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
+ */
+REG32(GQSPI_DMA_ADDR, 0x800)
+    FIELD(GQSPI_DMA_ADDR,   ADDR, 2, 30)
+REG32(GQSPI_DMA_SIZE, 0x804)
+    FIELD(GQSPI_DMA_SIZE,   SIZE, 2, 27)
+REG32(GQSPI_DMA_STS, 0x808)
+    FIELD(GQSPI_DMA_STS, DONE_CNT, 13, 3)
+    FIELD(GQSPI_DMA_STS, BUSY, 0, 1)
+REG32(GQSPI_DMA_CTRL, 0x80c)
+    FIELD(GQSPI_DMA_CTRL,   FIFO_LVL_HIT_THRESH, 25, 7)
+    FIELD(GQSPI_DMA_CTRL,   APB_ERR_RESP, 24, 1)
+    FIELD(GQSPI_DMA_CTRL,   ENDIANNESS, 23, 1)
+    FIELD(GQSPI_DMA_CTRL,   AXI_BRST_TYPE, 22, 1)
+    FIELD(GQSPI_DMA_CTRL,   TIMEOUT_VAL, 10, 12)
+    FIELD(GQSPI_DMA_CTRL,   FIFO_THRESH, 2, 8)
+    FIELD(GQSPI_DMA_CTRL,   PAUSE_STRM, 1, 1)
+    FIELD(GQSPI_DMA_CTRL,   PAUSE_MEM, 0, 1)
+REG32(GQSPI_DMA_I_STS, 0x814)
+    FIELD(GQSPI_DMA_I_STS, FIFO_OVERFLOW, 7, 1)
+    FIELD(GQSPI_DMA_I_STS, INVALID_APB, 6, 1)
+    FIELD(GQSPI_DMA_I_STS, THRESH_HIT, 5, 1)
+    FIELD(GQSPI_DMA_I_STS, TIMEOUT_MEM, 4, 1)
+    FIELD(GQSPI_DMA_I_STS, TIMEOUT_STRM, 3, 1)
+    FIELD(GQSPI_DMA_I_STS, AXI_BRESP_ERR, 2, 1)
+    FIELD(GQSPI_DMA_I_STS, DONE, 1, 1)
+REG32(GQSPI_DMA_I_EN, 0x818)
+    FIELD(GQSPI_DMA_I_EN, FIFO_OVERFLOW, 7, 1)
+    FIELD(GQSPI_DMA_I_EN, INVALID_APB, 6, 1)
+    FIELD(GQSPI_DMA_I_EN, THRESH_HIT, 5, 1)
+    FIELD(GQSPI_DMA_I_EN, TIMEOUT_MEM, 4, 1)
+    FIELD(GQSPI_DMA_I_EN, TIMEOUT_STRM, 3, 1)
+    FIELD(GQSPI_DMA_I_EN, AXI_BRESP_ERR, 2, 1)
+    FIELD(GQSPI_DMA_I_EN, DONE, 1, 1)
+REG32(GQSPI_DMA_I_DIS, 0x81c)
+    FIELD(GQSPI_DMA_I_DIS, FIFO_OVERFLOW, 7, 1)
+    FIELD(GQSPI_DMA_I_DIS, INVALID_APB, 6, 1)
+    FIELD(GQSPI_DMA_I_DIS, THRESH_HIT, 5, 1)
+    FIELD(GQSPI_DMA_I_DIS, TIMEOUT_MEM, 4, 1)
+    FIELD(GQSPI_DMA_I_DIS, TIMEOUT_STRM, 3, 1)
+    FIELD(GQSPI_DMA_I_DIS, AXI_BRESP_ERR, 2, 1)
+    FIELD(GQSPI_DMA_I_DIS, DONE, 1, 1)
+REG32(GQSPI_DMA_I_MASK, 0x820)
+    FIELD(GQSPI_DMA_I_MASK, FIFO_OVERFLOW, 7, 1)
+    FIELD(GQSPI_DMA_I_MASK, INVALID_APB, 6, 1)
+    FIELD(GQSPI_DMA_I_MASK, THRESH_HIT, 5, 1)
+    FIELD(GQSPI_DMA_I_MASK, TIMEOUT_MEM, 4, 1)
+    FIELD(GQSPI_DMA_I_MASK, TIMEOUT_STRM, 3, 1)
+    FIELD(GQSPI_DMA_I_MASK, AXI_BRESP_ERR, 2, 1)
+    FIELD(GQSPI_DMA_I_MASK, DONE, 1, 1)
+REG32(GQSPI_DMA_CTRL2, 0x824)
+    FIELD(GQSPI_DMA_CTRL2, ARCACHE, 24, 3)
+    FIELD(GQSPI_DMA_CTRL2, TIMEOUT_EN, 22, 1)
+    FIELD(GQSPI_DMA_CTRL2, TIMEOUT_PRE, 4, 12)
+    FIELD(GQSPI_DMA_CTRL2, MAX_OUTS_CMDS, 0, 4)
+REG32(GQSPI_DMA_ADDR_MSB, 0x828)
+    FIELD(GQSPI_DMA_ADDR_MSB, ADDR_MSB, 0, 12)
+
+#define R_GQSPI_DMA_CTRL_RESET    (0x803ffa00)
+#define R_GQSPI_DMA_INT_MASK      (0xfe)
+#define R_GQSPI_DMA_CTRL2_RESET   (0x081bfff8)
 
 /* size of TXRX FIFOs */
 #define RXFF_A          (128)
@@ -341,6 +401,7 @@ static void xilinx_spips_update_ixr(XilinxSPIPS *s)
 static void xlnx_zynqmp_qspips_update_ixr(XlnxZynqMPQSPIPS *s)
 {
     uint32_t gqspi_int;
+    uint32_t mode;
     int new_irqline;
 
     s->regs[R_GQSPI_ISR] &= ~IXR_SELF_CLEAR;
@@ -359,13 +420,20 @@ static void xlnx_zynqmp_qspips_update_ixr(XlnxZynqMPQSPIPS *s)
                                     IXR_TX_FIFO_NOT_FULL : 0);
 
     /* GQSPI Interrupt Trigger Status */
-    gqspi_int = (~s->regs[R_GQSPI_IMR]) & s->regs[R_GQSPI_ISR] & GQSPI_IXR_MASK;
-    new_irqline = !!(gqspi_int & IXR_ALL);
-
-    /* drive external interrupt pin */
-    if (new_irqline != s->gqspi_irqline) {
-        s->gqspi_irqline = new_irqline;
-        qemu_set_irq(XILINX_SPIPS(s)->irq, s->gqspi_irqline);
+    mode = ARRAY_FIELD_EX32(s->regs, GQSPI_CNFG, MODE_EN);
+    if (mode == GQSPI_CNFG_MODE_EN_IO) {
+        gqspi_int = (~s->regs[R_GQSPI_IMR]) & s->regs[R_GQSPI_ISR] \
+                                            & GQSPI_IXR_MASK;
+        new_irqline = !!(gqspi_int & IXR_ALL);
+
+        /* drive external interrupt pin */
+        if (new_irqline != s->gqspi_irqline) {
+            s->gqspi_irqline = new_irqline;
+            qemu_set_irq(XILINX_SPIPS(s)->irq, s->gqspi_irqline);
+        }
+    } else if (mode == GQSPI_CNFG_MODE_EN_DMA) {
+        new_irqline = s->regs[R_GQSPI_DMA_I_STS] & ~s->regs[R_GQSPI_DMA_I_MASK];
+        qemu_set_irq(XILINX_SPIPS(s)->irq, !!new_irqline);
     }
 }
 
@@ -417,9 +485,9 @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
     s->regs[R_GQSPI_GPIO] = 1;
     s->regs[R_GQSPI_LPBK_DLY_ADJ] = R_GQSPI_LPBK_DLY_ADJ_RESET;
     s->regs[R_GQSPI_MOD_ID] = R_GQSPI_MOD_ID_RESET;
-    s->regs[R_QSPIDMA_DST_CTRL] = R_QSPIDMA_DST_CTRL_RESET;
-    s->regs[R_QSPIDMA_DST_I_MASK] = R_QSPIDMA_DST_I_MASK_RESET;
-    s->regs[R_QSPIDMA_DST_CTRL2] = R_QSPIDMA_DST_CTRL2_RESET;
+    s->regs[R_GQSPI_DMA_CTRL] = R_GQSPI_DMA_CTRL_RESET;
+    s->regs[R_GQSPI_DMA_I_MASK] = R_GQSPI_DMA_INT_MASK;
+    s->regs[R_GQSPI_DMA_CTRL2] = R_GQSPI_DMA_CTRL2_RESET;
     s->man_start_com_g = false;
     s->gqspi_irqline = 0;
     xlnx_zynqmp_qspips_update_ixr(s);
@@ -843,6 +911,62 @@ static const void *pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num)
     return ret;
 }
 
+static void xlnx_zynqmp_gspips_dma_done(XlnxZynqMPQSPIPS *s)
+{
+    int cnt;
+
+    s->regs[R_GQSPI_DMA_STS] &= ~R_GQSPI_DMA_STS_BUSY_MASK;
+    s->regs[R_GQSPI_DMA_I_STS] |= R_GQSPI_DMA_I_STS_DONE_MASK;
+
+    cnt = ARRAY_FIELD_EX32(s->regs, GQSPI_DMA_STS, DONE_CNT) + 1;
+    ARRAY_FIELD_DP32(s->regs, GQSPI_DMA_STS, DONE_CNT, cnt);
+
+}
+
+static uint32_t xlnx_zynqmp_gspips_dma_advance(XlnxZynqMPQSPIPS *s,
+                                               uint32_t len, hwaddr dst)
+{
+    uint32_t size = s->regs[R_GQSPI_DMA_SIZE];
+
+    size -= len;
+    size &= R_GQSPI_DMA_SIZE_SIZE_MASK;
+    dst += len;
+
+    s->regs[R_GQSPI_DMA_SIZE] = size;
+    s->regs[R_GQSPI_DMA_ADDR] = (uint32_t) dst;
+    s->regs[R_GQSPI_DMA_ADDR_MSB] = dst >> 32;
+
+    return size;
+}
+
+static size_t xlnx_zynqmp_gspips_dma_push(XlnxZynqMPQSPIPS *s,
+                                          uint8_t *buf, size_t len, bool eop)
+{
+    hwaddr dst = (hwaddr)s->regs[R_GQSPI_DMA_ADDR_MSB] << 32
+                 | s->regs[R_GQSPI_DMA_ADDR];
+    uint32_t size = s->regs[R_GQSPI_DMA_SIZE];
+    uint32_t mlen = MIN(size, len) & (~3); /* Size is word aligned */
+
+    if (size == 0 || len <= 0) {
+        return 0;
+    }
+
+    cpu_physical_memory_write(dst, buf, mlen);
+    size = xlnx_zynqmp_gspips_dma_advance(s, mlen, dst);
+
+    if (size == 0) {
+        xlnx_zynqmp_gspips_dma_done(s);
+        xlnx_zynqmp_qspips_update_ixr(s);
+    }
+
+   return mlen;
+}
+
+static bool xlnx_zynqmp_gspips_dma_can_push(XlnxZynqMPQSPIPS *s)
+{
+    return s->regs[R_GQSPI_DMA_SIZE] ? true : false;
+}
+
 static void xlnx_zynqmp_qspips_notify(void *opaque)
 {
     XlnxZynqMPQSPIPS *rq = XLNX_ZYNQMP_QSPIPS(opaque);
@@ -850,7 +974,8 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
     Fifo8 *recv_fifo;
 
     if (ARRAY_FIELD_EX32(rq->regs, GQSPI_SELECT, GENERIC_QSPI_EN)) {
-        if (!(ARRAY_FIELD_EX32(rq->regs, GQSPI_CNFG, MODE_EN) == 2)) {
+        if (ARRAY_FIELD_EX32(rq->regs, GQSPI_CNFG, MODE_EN)
+            != GQSPI_CNFG_MODE_EN_DMA) {
             return;
         }
         recv_fifo = &rq->rx_fifo_g;
@@ -861,7 +986,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
         recv_fifo = &s->rx_fifo;
     }
     while (recv_fifo->num >= 4
-           && stream_can_push(rq->dma, xlnx_zynqmp_qspips_notify, rq))
+           && xlnx_zynqmp_gspips_dma_can_push(rq))
     {
         size_t ret;
         uint32_t num;
@@ -874,7 +999,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
 
         memcpy(rq->dma_buf, rxd, num);
 
-        ret = stream_push(rq->dma, rq->dma_buf, num, false);
+        ret = xlnx_zynqmp_gspips_dma_push(rq, rq->dma_buf, num, false);
         assert(ret == num);
         xlnx_zynqmp_qspips_check_flush(rq);
     }
@@ -1127,6 +1252,31 @@ static void xlnx_zynqmp_qspips_write(void *opaque, hwaddr addr,
         case R_GQSPI_GF_SNAPSHOT:
         case R_GQSPI_MOD_ID:
             break;
+        case R_GQSPI_DMA_ADDR:
+            s->regs[R_GQSPI_DMA_ADDR] = value & R_GQSPI_DMA_ADDR_ADDR_MASK;
+            break;
+        case R_GQSPI_DMA_SIZE:
+            s->regs[R_GQSPI_DMA_SIZE] = value & R_GQSPI_DMA_SIZE_SIZE_MASK;
+            break;
+        case R_GQSPI_DMA_STS:
+            s->regs[R_GQSPI_DMA_STS] &= ~(value &
+                                          R_GQSPI_DMA_STS_DONE_CNT_MASK);
+            break;
+        case R_GQSPI_DMA_I_EN:
+            s->regs[R_GQSPI_DMA_I_EN]    = value & R_GQSPI_DMA_INT_MASK;
+            s->regs[R_GQSPI_DMA_I_MASK] &= ~s->regs[R_GQSPI_DMA_I_EN];
+            s->regs[R_GQSPI_DMA_I_DIS]  &= ~s->regs[R_GQSPI_DMA_I_EN];
+            break;
+        case R_GQSPI_DMA_I_DIS:
+            s->regs[R_GQSPI_DMA_I_DIS]  |= value & R_GQSPI_DMA_INT_MASK;
+            s->regs[R_GQSPI_DMA_I_MASK] |= s->regs[R_GQSPI_DMA_I_DIS];
+            s->regs[R_GQSPI_DMA_I_EN]   &= ~s->regs[R_GQSPI_DMA_I_DIS];
+            s->regs[R_GQSPI_DMA_STS] &= 0;
+            break;
+        case R_GQSPI_DMA_ADDR_MSB:
+            s->regs[R_GQSPI_DMA_ADDR_MSB] = value &
+                                            R_GQSPI_DMA_ADDR_MSB_ADDR_MSB_MASK;
+            break;
         default:
             s->regs[reg] = value;
             break;
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues
  2021-02-06 14:38 ` [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues Bin Meng
@ 2021-02-06 15:18   ` Peter Maydell
  2021-02-06 17:01   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 7+ messages in thread
From: Peter Maydell @ 2021-02-06 15:18 UTC (permalink / raw)
  To: Bin Meng
  Cc: Xuzhou Cheng, Bin Meng, QEMU Developers, qemu-arm,
	Alistair Francis, Edgar E . Iglesias

On Sat, 6 Feb 2021 at 14:38, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
>
> There are some coding convention warnings in xilinx_spips.c,
> as reported by:
>
>   $ ./scripts/checkpatch.pl hw/ssi/xilinx_spips.c
>
> Let's clean them up.
>
> Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
> Signed-off-by: Bin Meng <bin.meng@windriver.com>
> ---

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support
  2021-02-06 14:38 ` [PATCH 2/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support Bin Meng
@ 2021-02-06 15:28   ` Peter Maydell
  2021-02-07 15:46     ` Bin Meng
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Maydell @ 2021-02-06 15:28 UTC (permalink / raw)
  To: Bin Meng
  Cc: Xuzhou Cheng, Bin Meng, QEMU Developers, qemu-arm,
	Alistair Francis, Edgar E . Iglesias

On Sat, 6 Feb 2021 at 14:38, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
>
> ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
> is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
> crash. This is observed when testing VxWorks 7.
>
> Add a basic implementation of QSPI DMA functionality.
>
> Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
> Signed-off-by: Bin Meng <bin.meng@windriver.com>

> +static size_t xlnx_zynqmp_gspips_dma_push(XlnxZynqMPQSPIPS *s,
> +                                          uint8_t *buf, size_t len, bool eop)
> +{
> +    hwaddr dst = (hwaddr)s->regs[R_GQSPI_DMA_ADDR_MSB] << 32
> +                 | s->regs[R_GQSPI_DMA_ADDR];
> +    uint32_t size = s->regs[R_GQSPI_DMA_SIZE];
> +    uint32_t mlen = MIN(size, len) & (~3); /* Size is word aligned */
> +
> +    if (size == 0 || len <= 0) {
> +        return 0;
> +    }
> +
> +    cpu_physical_memory_write(dst, buf, mlen);
> +    size = xlnx_zynqmp_gspips_dma_advance(s, mlen, dst);
> +
> +    if (size == 0) {
> +        xlnx_zynqmp_gspips_dma_done(s);
> +        xlnx_zynqmp_qspips_update_ixr(s);
> +    }
> +
> +   return mlen;
> +}

> @@ -861,7 +986,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
>          recv_fifo = &s->rx_fifo;
>      }
>      while (recv_fifo->num >= 4
> -           && stream_can_push(rq->dma, xlnx_zynqmp_qspips_notify, rq))
> +           && xlnx_zynqmp_gspips_dma_can_push(rq))
>      {
>          size_t ret;
>          uint32_t num;
> @@ -874,7 +999,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
>
>          memcpy(rq->dma_buf, rxd, num);
>
> -        ret = stream_push(rq->dma, rq->dma_buf, num, false);
> +        ret = xlnx_zynqmp_gspips_dma_push(rq, rq->dma_buf, num, false);
>          assert(ret == num);
>          xlnx_zynqmp_qspips_check_flush(rq);
>      }

This seems to be removing the existing handling of DMA to the
TYPE_STREAM_SINK via the stream_* functions -- that doesn't look
right. I don't know any of the details of this device, but if it
has two different modes of DMA then we need to support both of them,
surely ?

If the device really should be doing its own DMA memory
accesses, please don't use cpu_physical_memory_write() for
this. The device should take a TYPE_MEMORY_REGION link property,
and the board code should set this to tell the device what
its view of the world that it is doing DMA to is. Then the
device in its realize method calls address_space_init() to create
an AddressSpace for this MemoryRegion, and does memory accesses
using functions like address_space_read()/address_space_write()/
address_space_ld*()/etc. (Examples in hw/dma, eg pl080.c.)
Note that the address_space* functions have a return value
indicating whether the access failed, which you should handle.
(The pl080 code doesn't do that, but that's because it's older code.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues
  2021-02-06 14:38 ` [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues Bin Meng
  2021-02-06 15:18   ` Peter Maydell
@ 2021-02-06 17:01   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-06 17:01 UTC (permalink / raw)
  To: Bin Meng, Alistair Francis, Edgar E . Iglesias, Peter Maydell,
	qemu-arm, qemu-devel
  Cc: Xuzhou Cheng, Bin Meng

On 2/6/21 3:38 PM, Bin Meng wrote:
> From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
> 
> There are some coding convention warnings in xilinx_spips.c,
> as reported by:
> 
>   $ ./scripts/checkpatch.pl hw/ssi/xilinx_spips.c
> 
> Let's clean them up.
> 
> Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
> Signed-off-by: Bin Meng <bin.meng@windriver.com>
> ---
> 
>  hw/ssi/xilinx_spips.c | 23 ++++++++++++++---------
>  1 file changed, 14 insertions(+), 9 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support
  2021-02-06 15:28   ` Peter Maydell
@ 2021-02-07 15:46     ` Bin Meng
  0 siblings, 0 replies; 7+ messages in thread
From: Bin Meng @ 2021-02-07 15:46 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Xuzhou Cheng, Bin Meng, QEMU Developers, qemu-arm,
	Alistair Francis, Edgar E . Iglesias

Hi Peter,

On Sat, Feb 6, 2021 at 11:28 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Sat, 6 Feb 2021 at 14:38, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
> >
> > ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
> > is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
> > crash. This is observed when testing VxWorks 7.
> >
> > Add a basic implementation of QSPI DMA functionality.
> >
> > Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
> > Signed-off-by: Bin Meng <bin.meng@windriver.com>
>
> > +static size_t xlnx_zynqmp_gspips_dma_push(XlnxZynqMPQSPIPS *s,
> > +                                          uint8_t *buf, size_t len, bool eop)
> > +{
> > +    hwaddr dst = (hwaddr)s->regs[R_GQSPI_DMA_ADDR_MSB] << 32
> > +                 | s->regs[R_GQSPI_DMA_ADDR];
> > +    uint32_t size = s->regs[R_GQSPI_DMA_SIZE];
> > +    uint32_t mlen = MIN(size, len) & (~3); /* Size is word aligned */
> > +
> > +    if (size == 0 || len <= 0) {
> > +        return 0;
> > +    }
> > +
> > +    cpu_physical_memory_write(dst, buf, mlen);
> > +    size = xlnx_zynqmp_gspips_dma_advance(s, mlen, dst);
> > +
> > +    if (size == 0) {
> > +        xlnx_zynqmp_gspips_dma_done(s);
> > +        xlnx_zynqmp_qspips_update_ixr(s);
> > +    }
> > +
> > +   return mlen;
> > +}
>
> > @@ -861,7 +986,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
> >          recv_fifo = &s->rx_fifo;
> >      }
> >      while (recv_fifo->num >= 4
> > -           && stream_can_push(rq->dma, xlnx_zynqmp_qspips_notify, rq))
> > +           && xlnx_zynqmp_gspips_dma_can_push(rq))
> >      {
> >          size_t ret;
> >          uint32_t num;
> > @@ -874,7 +999,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
> >
> >          memcpy(rq->dma_buf, rxd, num);
> >
> > -        ret = stream_push(rq->dma, rq->dma_buf, num, false);
> > +        ret = xlnx_zynqmp_gspips_dma_push(rq, rq->dma_buf, num, false);
> >          assert(ret == num);
> >          xlnx_zynqmp_qspips_check_flush(rq);
> >      }
>
> This seems to be removing the existing handling of DMA to the
> TYPE_STREAM_SINK via the stream_* functions -- that doesn't look
> right. I don't know any of the details of this device, but if it
> has two different modes of DMA then we need to support both of them,
> surely ?

This DMA engine is a built-in engine dedicated for QSPI so I think
there is no need to use the stream_* functions.

> If the device really should be doing its own DMA memory
> accesses, please don't use cpu_physical_memory_write() for
> this. The device should take a TYPE_MEMORY_REGION link property,
> and the board code should set this to tell the device what
> its view of the world that it is doing DMA to is. Then the
> device in its realize method calls address_space_init() to create
> an AddressSpace for this MemoryRegion, and does memory accesses
> using functions like address_space_read()/address_space_write()/
> address_space_ld*()/etc. (Examples in hw/dma, eg pl080.c.)
> Note that the address_space* functions have a return value
> indicating whether the access failed, which you should handle.
> (The pl080 code doesn't do that, but that's because it's older code.)

Sure will switch to use DMA AddressSpace in v2.

Regards,
Bin


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-02-07 15:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-02-06 14:38 [PATCH 0/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support Bin Meng
2021-02-06 14:38 ` [PATCH 1/2] hw/ssi: xilinx_spips: Clean up coding convention issues Bin Meng
2021-02-06 15:18   ` Peter Maydell
2021-02-06 17:01   ` Philippe Mathieu-Daudé
2021-02-06 14:38 ` [PATCH 2/2] hw/ssi: xilinx_spips: Implement basic QSPI DMA support Bin Meng
2021-02-06 15:28   ` Peter Maydell
2021-02-07 15:46     ` Bin Meng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).