122cd0945SFrancisco Iglesias /*
222cd0945SFrancisco Iglesias * QEMU model of the ZynqMP generic DMA
322cd0945SFrancisco Iglesias *
422cd0945SFrancisco Iglesias * Copyright (c) 2014 Xilinx Inc.
522cd0945SFrancisco Iglesias * Copyright (c) 2018 FEIMTECH AB
622cd0945SFrancisco Iglesias *
722cd0945SFrancisco Iglesias * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>,
822cd0945SFrancisco Iglesias * Francisco Iglesias <francisco.iglesias@feimtech.se>
922cd0945SFrancisco Iglesias *
1022cd0945SFrancisco Iglesias * Permission is hereby granted, free of charge, to any person obtaining a copy
1122cd0945SFrancisco Iglesias * of this software and associated documentation files (the "Software"), to deal
1222cd0945SFrancisco Iglesias * in the Software without restriction, including without limitation the rights
1322cd0945SFrancisco Iglesias * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1422cd0945SFrancisco Iglesias * copies of the Software, and to permit persons to whom the Software is
1522cd0945SFrancisco Iglesias * furnished to do so, subject to the following conditions:
1622cd0945SFrancisco Iglesias *
1722cd0945SFrancisco Iglesias * The above copyright notice and this permission notice shall be included in
1822cd0945SFrancisco Iglesias * all copies or substantial portions of the Software.
1922cd0945SFrancisco Iglesias *
2022cd0945SFrancisco Iglesias * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2122cd0945SFrancisco Iglesias * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2222cd0945SFrancisco Iglesias * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2322cd0945SFrancisco Iglesias * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2422cd0945SFrancisco Iglesias * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2522cd0945SFrancisco Iglesias * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2622cd0945SFrancisco Iglesias * THE SOFTWARE.
2722cd0945SFrancisco Iglesias */
2822cd0945SFrancisco Iglesias
2922cd0945SFrancisco Iglesias #include "qemu/osdep.h"
3022cd0945SFrancisco Iglesias #include "hw/dma/xlnx-zdma.h"
3164552b6bSMarkus Armbruster #include "hw/irq.h"
32a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
33d6454270SMarkus Armbruster #include "migration/vmstate.h"
3422cd0945SFrancisco Iglesias #include "qemu/bitops.h"
3522cd0945SFrancisco Iglesias #include "qemu/log.h"
360b8fa32fSMarkus Armbruster #include "qemu/module.h"
3722cd0945SFrancisco Iglesias #include "qapi/error.h"
3822cd0945SFrancisco Iglesias
3922cd0945SFrancisco Iglesias #ifndef XLNX_ZDMA_ERR_DEBUG
4022cd0945SFrancisco Iglesias #define XLNX_ZDMA_ERR_DEBUG 0
4122cd0945SFrancisco Iglesias #endif
4222cd0945SFrancisco Iglesias
4322cd0945SFrancisco Iglesias REG32(ZDMA_ERR_CTRL, 0x0)
4422cd0945SFrancisco Iglesias FIELD(ZDMA_ERR_CTRL, APB_ERR_RES, 0, 1)
4522cd0945SFrancisco Iglesias REG32(ZDMA_CH_ISR, 0x100)
4622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, DMA_PAUSE, 11, 1)
4722cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, DMA_DONE, 10, 1)
4822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, AXI_WR_DATA, 9, 1)
4922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, AXI_RD_DATA, 8, 1)
5022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, AXI_RD_DST_DSCR, 7, 1)
5122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, AXI_RD_SRC_DSCR, 6, 1)
5222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, IRQ_DST_ACCT_ERR, 5, 1)
5322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, IRQ_SRC_ACCT_ERR, 4, 1)
5422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, BYTE_CNT_OVRFL, 3, 1)
5522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, DST_DSCR_DONE, 2, 1)
5622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, SRC_DSCR_DONE, 1, 1)
5722cd0945SFrancisco Iglesias FIELD(ZDMA_CH_ISR, INV_APB, 0, 1)
5822cd0945SFrancisco Iglesias REG32(ZDMA_CH_IMR, 0x104)
5922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, DMA_PAUSE, 11, 1)
6022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, DMA_DONE, 10, 1)
6122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, AXI_WR_DATA, 9, 1)
6222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, AXI_RD_DATA, 8, 1)
6322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, AXI_RD_DST_DSCR, 7, 1)
6422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, AXI_RD_SRC_DSCR, 6, 1)
6522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, IRQ_DST_ACCT_ERR, 5, 1)
6622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, IRQ_SRC_ACCT_ERR, 4, 1)
6722cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, BYTE_CNT_OVRFL, 3, 1)
6822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, DST_DSCR_DONE, 2, 1)
6922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, SRC_DSCR_DONE, 1, 1)
7022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IMR, INV_APB, 0, 1)
7122cd0945SFrancisco Iglesias REG32(ZDMA_CH_IEN, 0x108)
7222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, DMA_PAUSE, 11, 1)
7322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, DMA_DONE, 10, 1)
7422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, AXI_WR_DATA, 9, 1)
7522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, AXI_RD_DATA, 8, 1)
7622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, AXI_RD_DST_DSCR, 7, 1)
7722cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, AXI_RD_SRC_DSCR, 6, 1)
7822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, IRQ_DST_ACCT_ERR, 5, 1)
7922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, IRQ_SRC_ACCT_ERR, 4, 1)
8022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, BYTE_CNT_OVRFL, 3, 1)
8122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, DST_DSCR_DONE, 2, 1)
8222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, SRC_DSCR_DONE, 1, 1)
8322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IEN, INV_APB, 0, 1)
8422cd0945SFrancisco Iglesias REG32(ZDMA_CH_IDS, 0x10c)
8522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, DMA_PAUSE, 11, 1)
8622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, DMA_DONE, 10, 1)
8722cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, AXI_WR_DATA, 9, 1)
8822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, AXI_RD_DATA, 8, 1)
8922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, AXI_RD_DST_DSCR, 7, 1)
9022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, AXI_RD_SRC_DSCR, 6, 1)
9122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, IRQ_DST_ACCT_ERR, 5, 1)
9222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, IRQ_SRC_ACCT_ERR, 4, 1)
9322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, BYTE_CNT_OVRFL, 3, 1)
9422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, DST_DSCR_DONE, 2, 1)
9522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, SRC_DSCR_DONE, 1, 1)
9622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IDS, INV_APB, 0, 1)
9722cd0945SFrancisco Iglesias REG32(ZDMA_CH_CTRL0, 0x110)
9822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL0, OVR_FETCH, 7, 1)
9922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL0, POINT_TYPE, 6, 1)
10022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL0, MODE, 4, 2)
10122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL0, RATE_CTRL, 3, 1)
10222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL0, CONT_ADDR, 2, 1)
10322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL0, CONT, 1, 1)
10422cd0945SFrancisco Iglesias REG32(ZDMA_CH_CTRL1, 0x114)
10522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL1, DST_ISSUE, 5, 5)
10622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL1, SRC_ISSUE, 0, 5)
10722cd0945SFrancisco Iglesias REG32(ZDMA_CH_FCI, 0x118)
10822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_FCI, PROG_CELL_CNT, 2, 2)
10922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_FCI, SIDE, 1, 1)
11022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_FCI, EN, 0, 1)
11122cd0945SFrancisco Iglesias REG32(ZDMA_CH_STATUS, 0x11c)
11222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_STATUS, STATE, 0, 2)
11322cd0945SFrancisco Iglesias REG32(ZDMA_CH_DATA_ATTR, 0x120)
11422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, ARBURST, 26, 2)
11522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, ARCACHE, 22, 4)
11622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, ARQOS, 18, 4)
11722cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, ARLEN, 14, 4)
11822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, AWBURST, 12, 2)
11922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, AWCACHE, 8, 4)
12022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, AWQOS, 4, 4)
12122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DATA_ATTR, AWLEN, 0, 4)
12222cd0945SFrancisco Iglesias REG32(ZDMA_CH_DSCR_ATTR, 0x124)
12322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DSCR_ATTR, AXCOHRNT, 8, 1)
12422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DSCR_ATTR, AXCACHE, 4, 4)
12522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DSCR_ATTR, AXQOS, 0, 4)
12622cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_DSCR_WORD0, 0x128)
12722cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_DSCR_WORD1, 0x12c)
12822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_DSCR_WORD1, MSB, 0, 17)
12922cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_DSCR_WORD2, 0x130)
13022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_DSCR_WORD2, SIZE, 0, 30)
13122cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_DSCR_WORD3, 0x134)
13222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_DSCR_WORD3, CMD, 3, 2)
13322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_DSCR_WORD3, INTR, 2, 1)
13422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_DSCR_WORD3, TYPE, 1, 1)
13522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_DSCR_WORD3, COHRNT, 0, 1)
13622cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_DSCR_WORD0, 0x138)
13722cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_DSCR_WORD1, 0x13c)
13822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_DSCR_WORD1, MSB, 0, 17)
13922cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_DSCR_WORD2, 0x140)
14022cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_DSCR_WORD2, SIZE, 0, 30)
14122cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_DSCR_WORD3, 0x144)
14222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_DSCR_WORD3, INTR, 2, 1)
14322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_DSCR_WORD3, TYPE, 1, 1)
14422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_DSCR_WORD3, COHRNT, 0, 1)
14522cd0945SFrancisco Iglesias REG32(ZDMA_CH_WR_ONLY_WORD0, 0x148)
14622cd0945SFrancisco Iglesias REG32(ZDMA_CH_WR_ONLY_WORD1, 0x14c)
14722cd0945SFrancisco Iglesias REG32(ZDMA_CH_WR_ONLY_WORD2, 0x150)
14822cd0945SFrancisco Iglesias REG32(ZDMA_CH_WR_ONLY_WORD3, 0x154)
14922cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_START_LSB, 0x158)
15022cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_START_MSB, 0x15c)
15122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_START_MSB, ADDR, 0, 17)
15222cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_START_LSB, 0x160)
15322cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_START_MSB, 0x164)
15422cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_START_MSB, ADDR, 0, 17)
15522cd0945SFrancisco Iglesias REG32(ZDMA_CH_RATE_CTRL, 0x18c)
15622cd0945SFrancisco Iglesias FIELD(ZDMA_CH_RATE_CTRL, CNT, 0, 12)
15722cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_CUR_PYLD_LSB, 0x168)
15822cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_CUR_PYLD_MSB, 0x16c)
15922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_CUR_PYLD_MSB, ADDR, 0, 17)
16022cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_CUR_PYLD_LSB, 0x170)
16122cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_CUR_PYLD_MSB, 0x174)
16222cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_CUR_PYLD_MSB, ADDR, 0, 17)
16322cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_CUR_DSCR_LSB, 0x178)
16422cd0945SFrancisco Iglesias REG32(ZDMA_CH_SRC_CUR_DSCR_MSB, 0x17c)
16522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_SRC_CUR_DSCR_MSB, ADDR, 0, 17)
16622cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_CUR_DSCR_LSB, 0x180)
16722cd0945SFrancisco Iglesias REG32(ZDMA_CH_DST_CUR_DSCR_MSB, 0x184)
16822cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DST_CUR_DSCR_MSB, ADDR, 0, 17)
16922cd0945SFrancisco Iglesias REG32(ZDMA_CH_TOTAL_BYTE, 0x188)
17022cd0945SFrancisco Iglesias REG32(ZDMA_CH_RATE_CNTL, 0x18c)
17122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_RATE_CNTL, CNT, 0, 12)
17222cd0945SFrancisco Iglesias REG32(ZDMA_CH_IRQ_SRC_ACCT, 0x190)
17322cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IRQ_SRC_ACCT, CNT, 0, 8)
17422cd0945SFrancisco Iglesias REG32(ZDMA_CH_IRQ_DST_ACCT, 0x194)
17522cd0945SFrancisco Iglesias FIELD(ZDMA_CH_IRQ_DST_ACCT, CNT, 0, 8)
17622cd0945SFrancisco Iglesias REG32(ZDMA_CH_DBG0, 0x198)
17722cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DBG0, CMN_BUF_FREE, 0, 9)
17822cd0945SFrancisco Iglesias REG32(ZDMA_CH_DBG1, 0x19c)
17922cd0945SFrancisco Iglesias FIELD(ZDMA_CH_DBG1, CMN_BUF_OCC, 0, 9)
18022cd0945SFrancisco Iglesias REG32(ZDMA_CH_CTRL2, 0x200)
18122cd0945SFrancisco Iglesias FIELD(ZDMA_CH_CTRL2, EN, 0, 1)
18222cd0945SFrancisco Iglesias
18322cd0945SFrancisco Iglesias enum {
18422cd0945SFrancisco Iglesias PT_REG = 0,
18522cd0945SFrancisco Iglesias PT_MEM = 1,
18622cd0945SFrancisco Iglesias };
18722cd0945SFrancisco Iglesias
18822cd0945SFrancisco Iglesias enum {
18922cd0945SFrancisco Iglesias CMD_HALT = 1,
19022cd0945SFrancisco Iglesias CMD_STOP = 2,
19122cd0945SFrancisco Iglesias };
19222cd0945SFrancisco Iglesias
19322cd0945SFrancisco Iglesias enum {
19422cd0945SFrancisco Iglesias RW_MODE_RW = 0,
19522cd0945SFrancisco Iglesias RW_MODE_WO = 1,
19622cd0945SFrancisco Iglesias RW_MODE_RO = 2,
19722cd0945SFrancisco Iglesias };
19822cd0945SFrancisco Iglesias
19922cd0945SFrancisco Iglesias enum {
20022cd0945SFrancisco Iglesias DTYPE_LINEAR = 0,
20122cd0945SFrancisco Iglesias DTYPE_LINKED = 1,
20222cd0945SFrancisco Iglesias };
20322cd0945SFrancisco Iglesias
20422cd0945SFrancisco Iglesias enum {
20522cd0945SFrancisco Iglesias AXI_BURST_FIXED = 0,
20622cd0945SFrancisco Iglesias AXI_BURST_INCR = 1,
20722cd0945SFrancisco Iglesias };
20822cd0945SFrancisco Iglesias
zdma_ch_imr_update_irq(XlnxZDMA * s)20922cd0945SFrancisco Iglesias static void zdma_ch_imr_update_irq(XlnxZDMA *s)
21022cd0945SFrancisco Iglesias {
21122cd0945SFrancisco Iglesias bool pending;
21222cd0945SFrancisco Iglesias
21322cd0945SFrancisco Iglesias pending = s->regs[R_ZDMA_CH_ISR] & ~s->regs[R_ZDMA_CH_IMR];
21422cd0945SFrancisco Iglesias
21522cd0945SFrancisco Iglesias qemu_set_irq(s->irq_zdma_ch_imr, pending);
21622cd0945SFrancisco Iglesias }
21722cd0945SFrancisco Iglesias
zdma_ch_isr_postw(RegisterInfo * reg,uint64_t val64)21822cd0945SFrancisco Iglesias static void zdma_ch_isr_postw(RegisterInfo *reg, uint64_t val64)
21922cd0945SFrancisco Iglesias {
22022cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(reg->opaque);
22122cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
22222cd0945SFrancisco Iglesias }
22322cd0945SFrancisco Iglesias
zdma_ch_ien_prew(RegisterInfo * reg,uint64_t val64)22422cd0945SFrancisco Iglesias static uint64_t zdma_ch_ien_prew(RegisterInfo *reg, uint64_t val64)
22522cd0945SFrancisco Iglesias {
22622cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(reg->opaque);
22722cd0945SFrancisco Iglesias uint32_t val = val64;
22822cd0945SFrancisco Iglesias
22922cd0945SFrancisco Iglesias s->regs[R_ZDMA_CH_IMR] &= ~val;
23022cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
23122cd0945SFrancisco Iglesias return 0;
23222cd0945SFrancisco Iglesias }
23322cd0945SFrancisco Iglesias
zdma_ch_ids_prew(RegisterInfo * reg,uint64_t val64)23422cd0945SFrancisco Iglesias static uint64_t zdma_ch_ids_prew(RegisterInfo *reg, uint64_t val64)
23522cd0945SFrancisco Iglesias {
23622cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(reg->opaque);
23722cd0945SFrancisco Iglesias uint32_t val = val64;
23822cd0945SFrancisco Iglesias
23922cd0945SFrancisco Iglesias s->regs[R_ZDMA_CH_IMR] |= val;
24022cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
24122cd0945SFrancisco Iglesias return 0;
24222cd0945SFrancisco Iglesias }
24322cd0945SFrancisco Iglesias
zdma_set_state(XlnxZDMA * s,XlnxZDMAState state)24422cd0945SFrancisco Iglesias static void zdma_set_state(XlnxZDMA *s, XlnxZDMAState state)
24522cd0945SFrancisco Iglesias {
24622cd0945SFrancisco Iglesias s->state = state;
24722cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_STATUS, STATE, state);
24822cd0945SFrancisco Iglesias
24922cd0945SFrancisco Iglesias /* Signal error if we have an error condition. */
25022cd0945SFrancisco Iglesias if (s->error) {
25122cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_STATUS, STATE, 3);
25222cd0945SFrancisco Iglesias }
25322cd0945SFrancisco Iglesias }
25422cd0945SFrancisco Iglesias
zdma_src_done(XlnxZDMA * s)25522cd0945SFrancisco Iglesias static void zdma_src_done(XlnxZDMA *s)
25622cd0945SFrancisco Iglesias {
25722cd0945SFrancisco Iglesias unsigned int cnt;
25822cd0945SFrancisco Iglesias cnt = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_SRC_ACCT, CNT);
25922cd0945SFrancisco Iglesias cnt++;
26022cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_IRQ_SRC_ACCT, CNT, cnt);
26122cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, SRC_DSCR_DONE, true);
26222cd0945SFrancisco Iglesias
26322cd0945SFrancisco Iglesias /* Did we overflow? */
26422cd0945SFrancisco Iglesias if (cnt != ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_SRC_ACCT, CNT)) {
26522cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, IRQ_SRC_ACCT_ERR, true);
26622cd0945SFrancisco Iglesias }
26722cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
26822cd0945SFrancisco Iglesias }
26922cd0945SFrancisco Iglesias
zdma_dst_done(XlnxZDMA * s)27022cd0945SFrancisco Iglesias static void zdma_dst_done(XlnxZDMA *s)
27122cd0945SFrancisco Iglesias {
27222cd0945SFrancisco Iglesias unsigned int cnt;
27322cd0945SFrancisco Iglesias cnt = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_DST_ACCT, CNT);
27422cd0945SFrancisco Iglesias cnt++;
27522cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_IRQ_DST_ACCT, CNT, cnt);
27622cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, DST_DSCR_DONE, true);
27722cd0945SFrancisco Iglesias
27822cd0945SFrancisco Iglesias /* Did we overflow? */
27922cd0945SFrancisco Iglesias if (cnt != ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_DST_ACCT, CNT)) {
28022cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, IRQ_DST_ACCT_ERR, true);
28122cd0945SFrancisco Iglesias }
28222cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
28322cd0945SFrancisco Iglesias }
28422cd0945SFrancisco Iglesias
zdma_get_regaddr64(XlnxZDMA * s,unsigned int basereg)28522cd0945SFrancisco Iglesias static uint64_t zdma_get_regaddr64(XlnxZDMA *s, unsigned int basereg)
28622cd0945SFrancisco Iglesias {
28722cd0945SFrancisco Iglesias uint64_t addr;
28822cd0945SFrancisco Iglesias
28922cd0945SFrancisco Iglesias addr = s->regs[basereg + 1];
29022cd0945SFrancisco Iglesias addr <<= 32;
29122cd0945SFrancisco Iglesias addr |= s->regs[basereg];
29222cd0945SFrancisco Iglesias
29322cd0945SFrancisco Iglesias return addr;
29422cd0945SFrancisco Iglesias }
29522cd0945SFrancisco Iglesias
zdma_put_regaddr64(XlnxZDMA * s,unsigned int basereg,uint64_t addr)29622cd0945SFrancisco Iglesias static void zdma_put_regaddr64(XlnxZDMA *s, unsigned int basereg, uint64_t addr)
29722cd0945SFrancisco Iglesias {
29822cd0945SFrancisco Iglesias s->regs[basereg] = addr;
29922cd0945SFrancisco Iglesias s->regs[basereg + 1] = addr >> 32;
30022cd0945SFrancisco Iglesias }
30122cd0945SFrancisco Iglesias
zdma_load_descriptor_reg(XlnxZDMA * s,unsigned int reg,XlnxZDMADescr * descr)3021633ed1eSEdgar E. Iglesias static void zdma_load_descriptor_reg(XlnxZDMA *s, unsigned int reg,
3031633ed1eSEdgar E. Iglesias XlnxZDMADescr *descr)
3041633ed1eSEdgar E. Iglesias {
3051633ed1eSEdgar E. Iglesias descr->addr = zdma_get_regaddr64(s, reg);
3061633ed1eSEdgar E. Iglesias descr->size = s->regs[reg + 2];
3071633ed1eSEdgar E. Iglesias descr->attr = s->regs[reg + 3];
3081633ed1eSEdgar E. Iglesias }
3091633ed1eSEdgar E. Iglesias
zdma_load_descriptor(XlnxZDMA * s,uint64_t addr,XlnxZDMADescr * descr)310dac717daSEdgar E. Iglesias static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr,
311dac717daSEdgar E. Iglesias XlnxZDMADescr *descr)
31222cd0945SFrancisco Iglesias {
31322cd0945SFrancisco Iglesias /* ZDMA descriptors must be aligned to their own size. */
31422cd0945SFrancisco Iglesias if (addr % sizeof(XlnxZDMADescr)) {
31522cd0945SFrancisco Iglesias qemu_log_mask(LOG_GUEST_ERROR,
31622cd0945SFrancisco Iglesias "zdma: unaligned descriptor at %" PRIx64,
31722cd0945SFrancisco Iglesias addr);
318dac717daSEdgar E. Iglesias memset(descr, 0x0, sizeof(XlnxZDMADescr));
31922cd0945SFrancisco Iglesias s->error = true;
32022cd0945SFrancisco Iglesias return false;
32122cd0945SFrancisco Iglesias }
32222cd0945SFrancisco Iglesias
323783dbab1SPhilippe Mathieu-Daudé descr->addr = address_space_ldq_le(&s->dma_as, addr, s->attr, NULL);
324783dbab1SPhilippe Mathieu-Daudé descr->size = address_space_ldl_le(&s->dma_as, addr + 8, s->attr, NULL);
325783dbab1SPhilippe Mathieu-Daudé descr->attr = address_space_ldl_le(&s->dma_as, addr + 12, s->attr, NULL);
32622cd0945SFrancisco Iglesias return true;
32722cd0945SFrancisco Iglesias }
32822cd0945SFrancisco Iglesias
zdma_load_src_descriptor(XlnxZDMA * s)32922cd0945SFrancisco Iglesias static void zdma_load_src_descriptor(XlnxZDMA *s)
33022cd0945SFrancisco Iglesias {
33122cd0945SFrancisco Iglesias uint64_t src_addr;
33222cd0945SFrancisco Iglesias unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE);
33322cd0945SFrancisco Iglesias
33422cd0945SFrancisco Iglesias if (ptype == PT_REG) {
3351633ed1eSEdgar E. Iglesias zdma_load_descriptor_reg(s, R_ZDMA_CH_SRC_DSCR_WORD0, &s->dsc_src);
33622cd0945SFrancisco Iglesias return;
33722cd0945SFrancisco Iglesias }
33822cd0945SFrancisco Iglesias
33922cd0945SFrancisco Iglesias src_addr = zdma_get_regaddr64(s, R_ZDMA_CH_SRC_CUR_DSCR_LSB);
34022cd0945SFrancisco Iglesias
34122cd0945SFrancisco Iglesias if (!zdma_load_descriptor(s, src_addr, &s->dsc_src)) {
34222cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, AXI_RD_SRC_DSCR, true);
34322cd0945SFrancisco Iglesias }
34422cd0945SFrancisco Iglesias }
34522cd0945SFrancisco Iglesias
zdma_update_descr_addr(XlnxZDMA * s,bool type,unsigned int basereg)34688937909SEdgar E. Iglesias static void zdma_update_descr_addr(XlnxZDMA *s, bool type,
34788937909SEdgar E. Iglesias unsigned int basereg)
34888937909SEdgar E. Iglesias {
34988937909SEdgar E. Iglesias uint64_t addr, next;
35088937909SEdgar E. Iglesias
35188937909SEdgar E. Iglesias if (type == DTYPE_LINEAR) {
35288937909SEdgar E. Iglesias addr = zdma_get_regaddr64(s, basereg);
35388937909SEdgar E. Iglesias next = addr + sizeof(s->dsc_dst);
35488937909SEdgar E. Iglesias } else {
35588937909SEdgar E. Iglesias addr = zdma_get_regaddr64(s, basereg);
35688937909SEdgar E. Iglesias addr += sizeof(s->dsc_dst);
357783dbab1SPhilippe Mathieu-Daudé next = address_space_ldq_le(&s->dma_as, addr, s->attr, NULL);
35888937909SEdgar E. Iglesias }
35988937909SEdgar E. Iglesias
36088937909SEdgar E. Iglesias zdma_put_regaddr64(s, basereg, next);
36188937909SEdgar E. Iglesias }
36288937909SEdgar E. Iglesias
zdma_load_dst_descriptor(XlnxZDMA * s)36322cd0945SFrancisco Iglesias static void zdma_load_dst_descriptor(XlnxZDMA *s)
36422cd0945SFrancisco Iglesias {
36522cd0945SFrancisco Iglesias uint64_t dst_addr;
36622cd0945SFrancisco Iglesias unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE);
36788937909SEdgar E. Iglesias bool dst_type;
36822cd0945SFrancisco Iglesias
36922cd0945SFrancisco Iglesias if (ptype == PT_REG) {
3701633ed1eSEdgar E. Iglesias zdma_load_descriptor_reg(s, R_ZDMA_CH_DST_DSCR_WORD0, &s->dsc_dst);
37122cd0945SFrancisco Iglesias return;
37222cd0945SFrancisco Iglesias }
37322cd0945SFrancisco Iglesias
37422cd0945SFrancisco Iglesias dst_addr = zdma_get_regaddr64(s, R_ZDMA_CH_DST_CUR_DSCR_LSB);
37522cd0945SFrancisco Iglesias
37622cd0945SFrancisco Iglesias if (!zdma_load_descriptor(s, dst_addr, &s->dsc_dst)) {
37722cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, AXI_RD_DST_DSCR, true);
37822cd0945SFrancisco Iglesias }
37922cd0945SFrancisco Iglesias
38088937909SEdgar E. Iglesias /* Advance the descriptor pointer. */
38188937909SEdgar E. Iglesias dst_type = FIELD_EX32(s->dsc_dst.words[3], ZDMA_CH_DST_DSCR_WORD3, TYPE);
38288937909SEdgar E. Iglesias zdma_update_descr_addr(s, dst_type, R_ZDMA_CH_DST_CUR_DSCR_LSB);
38322cd0945SFrancisco Iglesias }
38422cd0945SFrancisco Iglesias
zdma_write_dst(XlnxZDMA * s,uint8_t * buf,uint32_t len)38522cd0945SFrancisco Iglesias static void zdma_write_dst(XlnxZDMA *s, uint8_t *buf, uint32_t len)
38622cd0945SFrancisco Iglesias {
38722cd0945SFrancisco Iglesias uint32_t dst_size, dlen;
388780c7dadSChen Qun bool dst_intr;
38922cd0945SFrancisco Iglesias unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE);
39022cd0945SFrancisco Iglesias unsigned int rw_mode = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, MODE);
39122cd0945SFrancisco Iglesias unsigned int burst_type = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_DATA_ATTR,
39222cd0945SFrancisco Iglesias AWBURST);
39322cd0945SFrancisco Iglesias
39422cd0945SFrancisco Iglesias /* FIXED burst types are only supported in simple dma mode. */
39522cd0945SFrancisco Iglesias if (ptype != PT_REG) {
39622cd0945SFrancisco Iglesias burst_type = AXI_BURST_INCR;
39722cd0945SFrancisco Iglesias }
39822cd0945SFrancisco Iglesias
39922cd0945SFrancisco Iglesias while (len) {
40022cd0945SFrancisco Iglesias dst_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2,
40122cd0945SFrancisco Iglesias SIZE);
40222cd0945SFrancisco Iglesias if (dst_size == 0 && ptype == PT_MEM) {
40388937909SEdgar E. Iglesias zdma_load_dst_descriptor(s);
40422cd0945SFrancisco Iglesias dst_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2,
40522cd0945SFrancisco Iglesias SIZE);
40622cd0945SFrancisco Iglesias }
40722cd0945SFrancisco Iglesias
40822cd0945SFrancisco Iglesias /* Match what hardware does by ignoring the dst_size and only using
40922cd0945SFrancisco Iglesias * the src size for Simple register mode. */
41022cd0945SFrancisco Iglesias if (ptype == PT_REG && rw_mode != RW_MODE_WO) {
41122cd0945SFrancisco Iglesias dst_size = len;
41222cd0945SFrancisco Iglesias }
41322cd0945SFrancisco Iglesias
41422cd0945SFrancisco Iglesias dst_intr = FIELD_EX32(s->dsc_dst.words[3], ZDMA_CH_DST_DSCR_WORD3,
41522cd0945SFrancisco Iglesias INTR);
41622cd0945SFrancisco Iglesias
41722cd0945SFrancisco Iglesias dlen = len > dst_size ? dst_size : len;
41822cd0945SFrancisco Iglesias if (burst_type == AXI_BURST_FIXED) {
41922cd0945SFrancisco Iglesias if (dlen > (s->cfg.bus_width / 8)) {
42022cd0945SFrancisco Iglesias dlen = s->cfg.bus_width / 8;
42122cd0945SFrancisco Iglesias }
42222cd0945SFrancisco Iglesias }
42322cd0945SFrancisco Iglesias
424783dbab1SPhilippe Mathieu-Daudé address_space_write(&s->dma_as, s->dsc_dst.addr, s->attr, buf, dlen);
42522cd0945SFrancisco Iglesias if (burst_type == AXI_BURST_INCR) {
42622cd0945SFrancisco Iglesias s->dsc_dst.addr += dlen;
42722cd0945SFrancisco Iglesias }
42822cd0945SFrancisco Iglesias dst_size -= dlen;
42922cd0945SFrancisco Iglesias buf += dlen;
43022cd0945SFrancisco Iglesias len -= dlen;
43122cd0945SFrancisco Iglesias
43222cd0945SFrancisco Iglesias if (dst_size == 0 && dst_intr) {
43322cd0945SFrancisco Iglesias zdma_dst_done(s);
43422cd0945SFrancisco Iglesias }
43522cd0945SFrancisco Iglesias
43622cd0945SFrancisco Iglesias /* Write back to buffered descriptor. */
43722cd0945SFrancisco Iglesias s->dsc_dst.words[2] = FIELD_DP32(s->dsc_dst.words[2],
43822cd0945SFrancisco Iglesias ZDMA_CH_DST_DSCR_WORD2,
43922cd0945SFrancisco Iglesias SIZE,
44022cd0945SFrancisco Iglesias dst_size);
44122cd0945SFrancisco Iglesias }
44222cd0945SFrancisco Iglesias }
44322cd0945SFrancisco Iglesias
zdma_process_descr(XlnxZDMA * s)44422cd0945SFrancisco Iglesias static void zdma_process_descr(XlnxZDMA *s)
44522cd0945SFrancisco Iglesias {
44622cd0945SFrancisco Iglesias uint64_t src_addr;
44722cd0945SFrancisco Iglesias uint32_t src_size, len;
44822cd0945SFrancisco Iglesias unsigned int src_cmd;
44922cd0945SFrancisco Iglesias bool src_intr, src_type;
45022cd0945SFrancisco Iglesias unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE);
45122cd0945SFrancisco Iglesias unsigned int rw_mode = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, MODE);
45222cd0945SFrancisco Iglesias unsigned int burst_type = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_DATA_ATTR,
45322cd0945SFrancisco Iglesias ARBURST);
45422cd0945SFrancisco Iglesias
45522cd0945SFrancisco Iglesias src_addr = s->dsc_src.addr;
45622cd0945SFrancisco Iglesias src_size = FIELD_EX32(s->dsc_src.words[2], ZDMA_CH_SRC_DSCR_WORD2, SIZE);
45722cd0945SFrancisco Iglesias src_cmd = FIELD_EX32(s->dsc_src.words[3], ZDMA_CH_SRC_DSCR_WORD3, CMD);
45822cd0945SFrancisco Iglesias src_type = FIELD_EX32(s->dsc_src.words[3], ZDMA_CH_SRC_DSCR_WORD3, TYPE);
45922cd0945SFrancisco Iglesias src_intr = FIELD_EX32(s->dsc_src.words[3], ZDMA_CH_SRC_DSCR_WORD3, INTR);
46022cd0945SFrancisco Iglesias
46122cd0945SFrancisco Iglesias /* FIXED burst types and non-rw modes are only supported in
46222cd0945SFrancisco Iglesias * simple dma mode.
46322cd0945SFrancisco Iglesias */
46422cd0945SFrancisco Iglesias if (ptype != PT_REG) {
46522cd0945SFrancisco Iglesias if (rw_mode != RW_MODE_RW) {
46622cd0945SFrancisco Iglesias qemu_log_mask(LOG_GUEST_ERROR,
46722cd0945SFrancisco Iglesias "zDMA: rw-mode=%d but not simple DMA mode.\n",
46822cd0945SFrancisco Iglesias rw_mode);
46922cd0945SFrancisco Iglesias }
47022cd0945SFrancisco Iglesias if (burst_type != AXI_BURST_INCR) {
47122cd0945SFrancisco Iglesias qemu_log_mask(LOG_GUEST_ERROR,
47222cd0945SFrancisco Iglesias "zDMA: burst_type=%d but not simple DMA mode.\n",
47322cd0945SFrancisco Iglesias burst_type);
47422cd0945SFrancisco Iglesias }
47522cd0945SFrancisco Iglesias burst_type = AXI_BURST_INCR;
47622cd0945SFrancisco Iglesias rw_mode = RW_MODE_RW;
47722cd0945SFrancisco Iglesias }
47822cd0945SFrancisco Iglesias
47922cd0945SFrancisco Iglesias if (rw_mode == RW_MODE_WO) {
48022cd0945SFrancisco Iglesias /* In Simple DMA Write-Only, we need to push DST size bytes
48122cd0945SFrancisco Iglesias * regardless of what SRC size is set to. */
48222cd0945SFrancisco Iglesias src_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2,
48322cd0945SFrancisco Iglesias SIZE);
48422cd0945SFrancisco Iglesias memcpy(s->buf, &s->regs[R_ZDMA_CH_WR_ONLY_WORD0], s->cfg.bus_width / 8);
48522cd0945SFrancisco Iglesias }
48622cd0945SFrancisco Iglesias
48722cd0945SFrancisco Iglesias while (src_size) {
48822cd0945SFrancisco Iglesias len = src_size > ARRAY_SIZE(s->buf) ? ARRAY_SIZE(s->buf) : src_size;
48922cd0945SFrancisco Iglesias if (burst_type == AXI_BURST_FIXED) {
49022cd0945SFrancisco Iglesias if (len > (s->cfg.bus_width / 8)) {
49122cd0945SFrancisco Iglesias len = s->cfg.bus_width / 8;
49222cd0945SFrancisco Iglesias }
49322cd0945SFrancisco Iglesias }
49422cd0945SFrancisco Iglesias
49522cd0945SFrancisco Iglesias if (rw_mode == RW_MODE_WO) {
49622cd0945SFrancisco Iglesias if (len > s->cfg.bus_width / 8) {
49722cd0945SFrancisco Iglesias len = s->cfg.bus_width / 8;
49822cd0945SFrancisco Iglesias }
49922cd0945SFrancisco Iglesias } else {
500783dbab1SPhilippe Mathieu-Daudé address_space_read(&s->dma_as, src_addr, s->attr, s->buf, len);
50122cd0945SFrancisco Iglesias if (burst_type == AXI_BURST_INCR) {
50222cd0945SFrancisco Iglesias src_addr += len;
50322cd0945SFrancisco Iglesias }
50422cd0945SFrancisco Iglesias }
50522cd0945SFrancisco Iglesias
50622cd0945SFrancisco Iglesias if (rw_mode != RW_MODE_RO) {
50722cd0945SFrancisco Iglesias zdma_write_dst(s, s->buf, len);
50822cd0945SFrancisco Iglesias }
50922cd0945SFrancisco Iglesias
51022cd0945SFrancisco Iglesias s->regs[R_ZDMA_CH_TOTAL_BYTE] += len;
51122cd0945SFrancisco Iglesias src_size -= len;
51222cd0945SFrancisco Iglesias }
51322cd0945SFrancisco Iglesias
51422cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, DMA_DONE, true);
51522cd0945SFrancisco Iglesias
51622cd0945SFrancisco Iglesias if (src_intr) {
51722cd0945SFrancisco Iglesias zdma_src_done(s);
51822cd0945SFrancisco Iglesias }
51922cd0945SFrancisco Iglesias
52022cd0945SFrancisco Iglesias if (ptype == PT_REG || src_cmd == CMD_STOP) {
52122cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_CTRL2, EN, 0);
52222cd0945SFrancisco Iglesias zdma_set_state(s, DISABLED);
52322cd0945SFrancisco Iglesias }
52422cd0945SFrancisco Iglesias
52522cd0945SFrancisco Iglesias if (src_cmd == CMD_HALT) {
52622cd0945SFrancisco Iglesias zdma_set_state(s, PAUSED);
52722cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, DMA_PAUSE, 1);
5284fc4678cSEdgar E. Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, DMA_DONE, false);
52922cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
53022cd0945SFrancisco Iglesias return;
53122cd0945SFrancisco Iglesias }
53222cd0945SFrancisco Iglesias
53322cd0945SFrancisco Iglesias zdma_update_descr_addr(s, src_type, R_ZDMA_CH_SRC_CUR_DSCR_LSB);
53422cd0945SFrancisco Iglesias }
53522cd0945SFrancisco Iglesias
zdma_run(XlnxZDMA * s)53622cd0945SFrancisco Iglesias static void zdma_run(XlnxZDMA *s)
53722cd0945SFrancisco Iglesias {
53822cd0945SFrancisco Iglesias while (s->state == ENABLED && !s->error) {
53922cd0945SFrancisco Iglesias zdma_load_src_descriptor(s);
54022cd0945SFrancisco Iglesias
54122cd0945SFrancisco Iglesias if (s->error) {
54222cd0945SFrancisco Iglesias zdma_set_state(s, DISABLED);
54322cd0945SFrancisco Iglesias } else {
54422cd0945SFrancisco Iglesias zdma_process_descr(s);
54522cd0945SFrancisco Iglesias }
54622cd0945SFrancisco Iglesias }
54722cd0945SFrancisco Iglesias
54822cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
54922cd0945SFrancisco Iglesias }
55022cd0945SFrancisco Iglesias
zdma_update_descr_addr_from_start(XlnxZDMA * s)55122cd0945SFrancisco Iglesias static void zdma_update_descr_addr_from_start(XlnxZDMA *s)
55222cd0945SFrancisco Iglesias {
55322cd0945SFrancisco Iglesias uint64_t src_addr, dst_addr;
55422cd0945SFrancisco Iglesias
55522cd0945SFrancisco Iglesias src_addr = zdma_get_regaddr64(s, R_ZDMA_CH_SRC_START_LSB);
55622cd0945SFrancisco Iglesias zdma_put_regaddr64(s, R_ZDMA_CH_SRC_CUR_DSCR_LSB, src_addr);
55722cd0945SFrancisco Iglesias dst_addr = zdma_get_regaddr64(s, R_ZDMA_CH_DST_START_LSB);
55822cd0945SFrancisco Iglesias zdma_put_regaddr64(s, R_ZDMA_CH_DST_CUR_DSCR_LSB, dst_addr);
55922cd0945SFrancisco Iglesias zdma_load_dst_descriptor(s);
56022cd0945SFrancisco Iglesias }
56122cd0945SFrancisco Iglesias
zdma_ch_ctrlx_postw(RegisterInfo * reg,uint64_t val64)56222cd0945SFrancisco Iglesias static void zdma_ch_ctrlx_postw(RegisterInfo *reg, uint64_t val64)
56322cd0945SFrancisco Iglesias {
56422cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(reg->opaque);
56522cd0945SFrancisco Iglesias
56622cd0945SFrancisco Iglesias if (ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL2, EN)) {
56722cd0945SFrancisco Iglesias s->error = false;
56822cd0945SFrancisco Iglesias
56922cd0945SFrancisco Iglesias if (s->state == PAUSED &&
57022cd0945SFrancisco Iglesias ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, CONT)) {
57122cd0945SFrancisco Iglesias if (ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, CONT_ADDR) == 1) {
57222cd0945SFrancisco Iglesias zdma_update_descr_addr_from_start(s);
57322cd0945SFrancisco Iglesias } else {
57422cd0945SFrancisco Iglesias bool src_type = FIELD_EX32(s->dsc_src.words[3],
57522cd0945SFrancisco Iglesias ZDMA_CH_SRC_DSCR_WORD3, TYPE);
57622cd0945SFrancisco Iglesias zdma_update_descr_addr(s, src_type,
57722cd0945SFrancisco Iglesias R_ZDMA_CH_SRC_CUR_DSCR_LSB);
57822cd0945SFrancisco Iglesias }
57922cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_CTRL0, CONT, false);
58022cd0945SFrancisco Iglesias zdma_set_state(s, ENABLED);
58122cd0945SFrancisco Iglesias } else if (s->state == DISABLED) {
58222cd0945SFrancisco Iglesias zdma_update_descr_addr_from_start(s);
58322cd0945SFrancisco Iglesias zdma_set_state(s, ENABLED);
58422cd0945SFrancisco Iglesias }
58522cd0945SFrancisco Iglesias } else {
58622cd0945SFrancisco Iglesias /* Leave Paused state? */
58722cd0945SFrancisco Iglesias if (s->state == PAUSED &&
58822cd0945SFrancisco Iglesias ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, CONT)) {
58922cd0945SFrancisco Iglesias zdma_set_state(s, DISABLED);
59022cd0945SFrancisco Iglesias }
59122cd0945SFrancisco Iglesias }
59222cd0945SFrancisco Iglesias
59322cd0945SFrancisco Iglesias zdma_run(s);
59422cd0945SFrancisco Iglesias }
59522cd0945SFrancisco Iglesias
59622cd0945SFrancisco Iglesias static RegisterAccessInfo zdma_regs_info[] = {
59722cd0945SFrancisco Iglesias { .name = "ZDMA_ERR_CTRL", .addr = A_ZDMA_ERR_CTRL,
59822cd0945SFrancisco Iglesias .rsvd = 0xfffffffe,
59922cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_ISR", .addr = A_ZDMA_CH_ISR,
60022cd0945SFrancisco Iglesias .rsvd = 0xfffff000,
60122cd0945SFrancisco Iglesias .w1c = 0xfff,
60222cd0945SFrancisco Iglesias .post_write = zdma_ch_isr_postw,
60322cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_IMR", .addr = A_ZDMA_CH_IMR,
60422cd0945SFrancisco Iglesias .reset = 0xfff,
60522cd0945SFrancisco Iglesias .rsvd = 0xfffff000,
60622cd0945SFrancisco Iglesias .ro = 0xfff,
60722cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_IEN", .addr = A_ZDMA_CH_IEN,
60822cd0945SFrancisco Iglesias .rsvd = 0xfffff000,
60922cd0945SFrancisco Iglesias .pre_write = zdma_ch_ien_prew,
61022cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_IDS", .addr = A_ZDMA_CH_IDS,
61122cd0945SFrancisco Iglesias .rsvd = 0xfffff000,
61222cd0945SFrancisco Iglesias .pre_write = zdma_ch_ids_prew,
61322cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_CTRL0", .addr = A_ZDMA_CH_CTRL0,
61422cd0945SFrancisco Iglesias .reset = 0x80,
61522cd0945SFrancisco Iglesias .rsvd = 0xffffff01,
61622cd0945SFrancisco Iglesias .post_write = zdma_ch_ctrlx_postw,
61722cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_CTRL1", .addr = A_ZDMA_CH_CTRL1,
61822cd0945SFrancisco Iglesias .reset = 0x3ff,
61922cd0945SFrancisco Iglesias .rsvd = 0xfffffc00,
62022cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_FCI", .addr = A_ZDMA_CH_FCI,
62122cd0945SFrancisco Iglesias .rsvd = 0xffffffc0,
62222cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_STATUS", .addr = A_ZDMA_CH_STATUS,
62322cd0945SFrancisco Iglesias .rsvd = 0xfffffffc,
62422cd0945SFrancisco Iglesias .ro = 0x3,
62522cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DATA_ATTR", .addr = A_ZDMA_CH_DATA_ATTR,
62622cd0945SFrancisco Iglesias .reset = 0x483d20f,
62722cd0945SFrancisco Iglesias .rsvd = 0xf0000000,
62822cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DSCR_ATTR", .addr = A_ZDMA_CH_DSCR_ATTR,
62922cd0945SFrancisco Iglesias .rsvd = 0xfffffe00,
63022cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_DSCR_WORD0", .addr = A_ZDMA_CH_SRC_DSCR_WORD0,
63122cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_DSCR_WORD1", .addr = A_ZDMA_CH_SRC_DSCR_WORD1,
63222cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
63322cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_DSCR_WORD2", .addr = A_ZDMA_CH_SRC_DSCR_WORD2,
63422cd0945SFrancisco Iglesias .rsvd = 0xc0000000,
63522cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_DSCR_WORD3", .addr = A_ZDMA_CH_SRC_DSCR_WORD3,
63622cd0945SFrancisco Iglesias .rsvd = 0xffffffe0,
63722cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_DSCR_WORD0", .addr = A_ZDMA_CH_DST_DSCR_WORD0,
63822cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_DSCR_WORD1", .addr = A_ZDMA_CH_DST_DSCR_WORD1,
63922cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
64022cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_DSCR_WORD2", .addr = A_ZDMA_CH_DST_DSCR_WORD2,
64122cd0945SFrancisco Iglesias .rsvd = 0xc0000000,
64222cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_DSCR_WORD3", .addr = A_ZDMA_CH_DST_DSCR_WORD3,
64322cd0945SFrancisco Iglesias .rsvd = 0xfffffffa,
64422cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_WR_ONLY_WORD0", .addr = A_ZDMA_CH_WR_ONLY_WORD0,
64522cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_WR_ONLY_WORD1", .addr = A_ZDMA_CH_WR_ONLY_WORD1,
64622cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_WR_ONLY_WORD2", .addr = A_ZDMA_CH_WR_ONLY_WORD2,
64722cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_WR_ONLY_WORD3", .addr = A_ZDMA_CH_WR_ONLY_WORD3,
64822cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_START_LSB", .addr = A_ZDMA_CH_SRC_START_LSB,
64922cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_START_MSB", .addr = A_ZDMA_CH_SRC_START_MSB,
65022cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
65122cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_START_LSB", .addr = A_ZDMA_CH_DST_START_LSB,
65222cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_START_MSB", .addr = A_ZDMA_CH_DST_START_MSB,
65322cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
65422cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_CUR_PYLD_LSB", .addr = A_ZDMA_CH_SRC_CUR_PYLD_LSB,
65522cd0945SFrancisco Iglesias .ro = 0xffffffff,
65622cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_CUR_PYLD_MSB", .addr = A_ZDMA_CH_SRC_CUR_PYLD_MSB,
65722cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
65822cd0945SFrancisco Iglesias .ro = 0x1ffff,
65922cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_CUR_PYLD_LSB", .addr = A_ZDMA_CH_DST_CUR_PYLD_LSB,
66022cd0945SFrancisco Iglesias .ro = 0xffffffff,
66122cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_CUR_PYLD_MSB", .addr = A_ZDMA_CH_DST_CUR_PYLD_MSB,
66222cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
66322cd0945SFrancisco Iglesias .ro = 0x1ffff,
66422cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_CUR_DSCR_LSB", .addr = A_ZDMA_CH_SRC_CUR_DSCR_LSB,
66522cd0945SFrancisco Iglesias .ro = 0xffffffff,
66622cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_SRC_CUR_DSCR_MSB", .addr = A_ZDMA_CH_SRC_CUR_DSCR_MSB,
66722cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
66822cd0945SFrancisco Iglesias .ro = 0x1ffff,
66922cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_CUR_DSCR_LSB", .addr = A_ZDMA_CH_DST_CUR_DSCR_LSB,
67022cd0945SFrancisco Iglesias .ro = 0xffffffff,
67122cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DST_CUR_DSCR_MSB", .addr = A_ZDMA_CH_DST_CUR_DSCR_MSB,
67222cd0945SFrancisco Iglesias .rsvd = 0xfffe0000,
67322cd0945SFrancisco Iglesias .ro = 0x1ffff,
67422cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_TOTAL_BYTE", .addr = A_ZDMA_CH_TOTAL_BYTE,
67522cd0945SFrancisco Iglesias .w1c = 0xffffffff,
67622cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_RATE_CNTL", .addr = A_ZDMA_CH_RATE_CNTL,
67722cd0945SFrancisco Iglesias .rsvd = 0xfffff000,
67822cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_IRQ_SRC_ACCT", .addr = A_ZDMA_CH_IRQ_SRC_ACCT,
67922cd0945SFrancisco Iglesias .rsvd = 0xffffff00,
68022cd0945SFrancisco Iglesias .ro = 0xff,
68122cd0945SFrancisco Iglesias .cor = 0xff,
68222cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_IRQ_DST_ACCT", .addr = A_ZDMA_CH_IRQ_DST_ACCT,
68322cd0945SFrancisco Iglesias .rsvd = 0xffffff00,
68422cd0945SFrancisco Iglesias .ro = 0xff,
68522cd0945SFrancisco Iglesias .cor = 0xff,
68622cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DBG0", .addr = A_ZDMA_CH_DBG0,
68722cd0945SFrancisco Iglesias .rsvd = 0xfffffe00,
68822cd0945SFrancisco Iglesias .ro = 0x1ff,
68928009852SEdgar E. Iglesias
69028009852SEdgar E. Iglesias /*
69128009852SEdgar E. Iglesias * There's SW out there that will check the debug regs for free space.
69228009852SEdgar E. Iglesias * Claim that we always have 0x100 free.
69328009852SEdgar E. Iglesias */
69428009852SEdgar E. Iglesias .reset = 0x100
69522cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_DBG1", .addr = A_ZDMA_CH_DBG1,
69622cd0945SFrancisco Iglesias .rsvd = 0xfffffe00,
69722cd0945SFrancisco Iglesias .ro = 0x1ff,
69822cd0945SFrancisco Iglesias },{ .name = "ZDMA_CH_CTRL2", .addr = A_ZDMA_CH_CTRL2,
69922cd0945SFrancisco Iglesias .rsvd = 0xfffffffe,
70022cd0945SFrancisco Iglesias .post_write = zdma_ch_ctrlx_postw,
70122cd0945SFrancisco Iglesias }
70222cd0945SFrancisco Iglesias };
70322cd0945SFrancisco Iglesias
zdma_reset(DeviceState * dev)70422cd0945SFrancisco Iglesias static void zdma_reset(DeviceState *dev)
70522cd0945SFrancisco Iglesias {
70622cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(dev);
70722cd0945SFrancisco Iglesias unsigned int i;
70822cd0945SFrancisco Iglesias
70922cd0945SFrancisco Iglesias for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
71022cd0945SFrancisco Iglesias register_reset(&s->regs_info[i]);
71122cd0945SFrancisco Iglesias }
71222cd0945SFrancisco Iglesias
71322cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
71422cd0945SFrancisco Iglesias }
71522cd0945SFrancisco Iglesias
zdma_read(void * opaque,hwaddr addr,unsigned size)71622cd0945SFrancisco Iglesias static uint64_t zdma_read(void *opaque, hwaddr addr, unsigned size)
71722cd0945SFrancisco Iglesias {
71822cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(opaque);
71922cd0945SFrancisco Iglesias RegisterInfo *r = &s->regs_info[addr / 4];
72022cd0945SFrancisco Iglesias
72122cd0945SFrancisco Iglesias if (!r->data) {
722ddfb0baaSMarkus Armbruster char *path = object_get_canonical_path(OBJECT(s));
72322cd0945SFrancisco Iglesias qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
724a13b6d8eSFrancisco Iglesias path,
72522cd0945SFrancisco Iglesias addr);
726a13b6d8eSFrancisco Iglesias g_free(path);
72722cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, INV_APB, true);
72822cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
72922cd0945SFrancisco Iglesias return 0;
73022cd0945SFrancisco Iglesias }
73122cd0945SFrancisco Iglesias return register_read(r, ~0, NULL, false);
73222cd0945SFrancisco Iglesias }
73322cd0945SFrancisco Iglesias
zdma_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)73422cd0945SFrancisco Iglesias static void zdma_write(void *opaque, hwaddr addr, uint64_t value,
73522cd0945SFrancisco Iglesias unsigned size)
73622cd0945SFrancisco Iglesias {
73722cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(opaque);
73822cd0945SFrancisco Iglesias RegisterInfo *r = &s->regs_info[addr / 4];
73922cd0945SFrancisco Iglesias
74022cd0945SFrancisco Iglesias if (!r->data) {
741ddfb0baaSMarkus Armbruster char *path = object_get_canonical_path(OBJECT(s));
74222cd0945SFrancisco Iglesias qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
743a13b6d8eSFrancisco Iglesias path,
74422cd0945SFrancisco Iglesias addr, value);
745a13b6d8eSFrancisco Iglesias g_free(path);
74622cd0945SFrancisco Iglesias ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, INV_APB, true);
74722cd0945SFrancisco Iglesias zdma_ch_imr_update_irq(s);
74822cd0945SFrancisco Iglesias return;
74922cd0945SFrancisco Iglesias }
75022cd0945SFrancisco Iglesias register_write(r, value, ~0, NULL, false);
75122cd0945SFrancisco Iglesias }
75222cd0945SFrancisco Iglesias
75322cd0945SFrancisco Iglesias static const MemoryRegionOps zdma_ops = {
75422cd0945SFrancisco Iglesias .read = zdma_read,
75522cd0945SFrancisco Iglesias .write = zdma_write,
75622cd0945SFrancisco Iglesias .endianness = DEVICE_LITTLE_ENDIAN,
75722cd0945SFrancisco Iglesias .valid = {
75822cd0945SFrancisco Iglesias .min_access_size = 4,
75922cd0945SFrancisco Iglesias .max_access_size = 4,
76022cd0945SFrancisco Iglesias },
76122cd0945SFrancisco Iglesias };
76222cd0945SFrancisco Iglesias
zdma_realize(DeviceState * dev,Error ** errp)76322cd0945SFrancisco Iglesias static void zdma_realize(DeviceState *dev, Error **errp)
76422cd0945SFrancisco Iglesias {
76522cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(dev);
76622cd0945SFrancisco Iglesias unsigned int i;
76722cd0945SFrancisco Iglesias
768783dbab1SPhilippe Mathieu-Daudé if (!s->dma_mr) {
769783dbab1SPhilippe Mathieu-Daudé error_setg(errp, TYPE_XLNX_ZDMA " 'dma' link not set");
770783dbab1SPhilippe Mathieu-Daudé return;
771783dbab1SPhilippe Mathieu-Daudé }
772783dbab1SPhilippe Mathieu-Daudé address_space_init(&s->dma_as, s->dma_mr, "zdma-dma");
773783dbab1SPhilippe Mathieu-Daudé
77422cd0945SFrancisco Iglesias for (i = 0; i < ARRAY_SIZE(zdma_regs_info); ++i) {
77522cd0945SFrancisco Iglesias RegisterInfo *r = &s->regs_info[zdma_regs_info[i].addr / 4];
77622cd0945SFrancisco Iglesias
77722cd0945SFrancisco Iglesias *r = (RegisterInfo) {
77822cd0945SFrancisco Iglesias .data = (uint8_t *)&s->regs[
77922cd0945SFrancisco Iglesias zdma_regs_info[i].addr / 4],
78022cd0945SFrancisco Iglesias .data_size = sizeof(uint32_t),
78122cd0945SFrancisco Iglesias .access = &zdma_regs_info[i],
78222cd0945SFrancisco Iglesias .opaque = s,
78322cd0945SFrancisco Iglesias };
78422cd0945SFrancisco Iglesias }
78522cd0945SFrancisco Iglesias
78622cd0945SFrancisco Iglesias s->attr = MEMTXATTRS_UNSPECIFIED;
78722cd0945SFrancisco Iglesias }
78822cd0945SFrancisco Iglesias
zdma_init(Object * obj)78922cd0945SFrancisco Iglesias static void zdma_init(Object *obj)
79022cd0945SFrancisco Iglesias {
79122cd0945SFrancisco Iglesias XlnxZDMA *s = XLNX_ZDMA(obj);
79222cd0945SFrancisco Iglesias SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
79322cd0945SFrancisco Iglesias
79422cd0945SFrancisco Iglesias memory_region_init_io(&s->iomem, obj, &zdma_ops, s,
79522cd0945SFrancisco Iglesias TYPE_XLNX_ZDMA, ZDMA_R_MAX * 4);
79622cd0945SFrancisco Iglesias sysbus_init_mmio(sbd, &s->iomem);
79722cd0945SFrancisco Iglesias sysbus_init_irq(sbd, &s->irq_zdma_ch_imr);
79822cd0945SFrancisco Iglesias }
79922cd0945SFrancisco Iglesias
80022cd0945SFrancisco Iglesias static const VMStateDescription vmstate_zdma = {
80122cd0945SFrancisco Iglesias .name = TYPE_XLNX_ZDMA,
80222cd0945SFrancisco Iglesias .version_id = 1,
80322cd0945SFrancisco Iglesias .minimum_version_id = 1,
80463e6b564SRichard Henderson .fields = (const VMStateField[]) {
80522cd0945SFrancisco Iglesias VMSTATE_UINT32_ARRAY(regs, XlnxZDMA, ZDMA_R_MAX),
80622cd0945SFrancisco Iglesias VMSTATE_UINT32(state, XlnxZDMA),
80722cd0945SFrancisco Iglesias VMSTATE_UINT32_ARRAY(dsc_src.words, XlnxZDMA, 4),
80822cd0945SFrancisco Iglesias VMSTATE_UINT32_ARRAY(dsc_dst.words, XlnxZDMA, 4),
80922cd0945SFrancisco Iglesias VMSTATE_END_OF_LIST(),
81022cd0945SFrancisco Iglesias }
81122cd0945SFrancisco Iglesias };
81222cd0945SFrancisco Iglesias
81322cd0945SFrancisco Iglesias static Property zdma_props[] = {
81422cd0945SFrancisco Iglesias DEFINE_PROP_UINT32("bus-width", XlnxZDMA, cfg.bus_width, 64),
8151f9d714eSPhilippe Mathieu-Daudé DEFINE_PROP_LINK("dma", XlnxZDMA, dma_mr,
8161f9d714eSPhilippe Mathieu-Daudé TYPE_MEMORY_REGION, MemoryRegion *),
81722cd0945SFrancisco Iglesias DEFINE_PROP_END_OF_LIST(),
81822cd0945SFrancisco Iglesias };
81922cd0945SFrancisco Iglesias
zdma_class_init(ObjectClass * klass,void * data)82022cd0945SFrancisco Iglesias static void zdma_class_init(ObjectClass *klass, void *data)
82122cd0945SFrancisco Iglesias {
82222cd0945SFrancisco Iglesias DeviceClass *dc = DEVICE_CLASS(klass);
82322cd0945SFrancisco Iglesias
824*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, zdma_reset);
82522cd0945SFrancisco Iglesias dc->realize = zdma_realize;
8264f67d30bSMarc-André Lureau device_class_set_props(dc, zdma_props);
82722cd0945SFrancisco Iglesias dc->vmsd = &vmstate_zdma;
82822cd0945SFrancisco Iglesias }
82922cd0945SFrancisco Iglesias
83022cd0945SFrancisco Iglesias static const TypeInfo zdma_info = {
83122cd0945SFrancisco Iglesias .name = TYPE_XLNX_ZDMA,
83222cd0945SFrancisco Iglesias .parent = TYPE_SYS_BUS_DEVICE,
83322cd0945SFrancisco Iglesias .instance_size = sizeof(XlnxZDMA),
83422cd0945SFrancisco Iglesias .class_init = zdma_class_init,
83522cd0945SFrancisco Iglesias .instance_init = zdma_init,
83622cd0945SFrancisco Iglesias };
83722cd0945SFrancisco Iglesias
zdma_register_types(void)83822cd0945SFrancisco Iglesias static void zdma_register_types(void)
83922cd0945SFrancisco Iglesias {
84022cd0945SFrancisco Iglesias type_register_static(&zdma_info);
84122cd0945SFrancisco Iglesias }
84222cd0945SFrancisco Iglesias
84322cd0945SFrancisco Iglesias type_init(zdma_register_types)
844