From patchwork Tue Jan 19 22:35:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 8065551 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 36DDCBEEE5 for ; Tue, 19 Jan 2016 22:43:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C6A0D2054C for ; Tue, 19 Jan 2016 22:43:09 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 15D702052A for ; Tue, 19 Jan 2016 22:43:08 +0000 (UTC) Received: from localhost ([::1]:39516 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aLezT-0001s8-Fk for patchwork-qemu-devel@patchwork.kernel.org; Tue, 19 Jan 2016 17:43:07 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49752) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aLeuN-0000f5-AV for qemu-devel@nongnu.org; Tue, 19 Jan 2016 17:37:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aLeuJ-0003rc-Uh for qemu-devel@nongnu.org; Tue, 19 Jan 2016 17:37:51 -0500 Received: from mail-cys01nam02on0041.outbound.protection.outlook.com ([104.47.37.41]:64320 helo=NAM02-CY1-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aLeuJ-0003rO-HY for qemu-devel@nongnu.org; Tue, 19 Jan 2016 17:37:47 -0500 Received: from BL2NAM02FT005.eop-nam02.prod.protection.outlook.com (10.152.76.56) by BL2NAM02HT197.eop-nam02.prod.protection.outlook.com (10.152.77.12) with Microsoft SMTP Server (TLS) id 15.1.355.15; Tue, 19 Jan 2016 22:37:44 +0000 Authentication-Results: spf=fail (sender IP is 149.199.60.96) smtp.mailfrom=xilinx.com; suse.de; dkim=none (message not signed) header.d=none; suse.de; dmarc=none action=none header.from=xilinx.com; Received-SPF: Fail (protection.outlook.com: domain of xilinx.com does not designate 149.199.60.96 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.60.96; helo=xsj-tvapsmtpgw01; Received: from xsj-tvapsmtpgw01 (149.199.60.96) by BL2NAM02FT005.mail.protection.outlook.com (10.152.76.252) with Microsoft SMTP Server (TLS) id 15.1.355.15 via Frontend Transport; Tue, 19 Jan 2016 22:37:44 +0000 Received: from 172-16-1-203.xilinx.com ([172.16.1.203]:34447 helo=xsj-tvapsmtp02.xilinx.com) by xsj-tvapsmtpgw01 with esmtp (Exim 4.63) (envelope-from ) id 1aLeuF-0008Qx-A4; Tue, 19 Jan 2016 14:37:43 -0800 Received: from [127.0.0.1] (port=41666 helo=tsj-smtp-dlp1.xlnx.xilinx.com) by xsj-tvapsmtp02.xilinx.com with esmtp (Exim 4.63) (envelope-from ) id 1aLeuF-0007gr-6N; Tue, 19 Jan 2016 14:37:43 -0800 Received: from xsj-tvapsmtp02 (smtptest.xilinx.com [172.16.1.203]) by tsj-smtp-dlp1.xlnx.xilinx.com (8.13.8/8.13.1) with ESMTP id u0JMW9hb015252; Tue, 19 Jan 2016 14:32:10 -0800 Received: from [172.19.74.182] (port=39722 helo=xsjalistai50.xlnx.xilinx.com) by xsj-tvapsmtp02 with esmtp (Exim 4.63) (envelope-from ) id 1aLeuE-0007gn-EM; Tue, 19 Jan 2016 14:37:42 -0800 From: Alistair Francis To: Date: Tue, 19 Jan 2016 14:35:16 -0800 Message-ID: X-Mailer: git-send-email 2.5.0 In-Reply-To: References: X-RCIS-Action: ALLOW X-TM-AS-MML: disable X-TM-AS-Product-Ver: IMSS-7.1.0.1679-8.0.0.1202-22054.006 X-TM-AS-Result: No--16.296-7.0-31-10 X-imss-scan-details: No--16.296-7.0-31-10 X-TMASE-MatchedRID: iWSYTvjq7DmBmL85GH6eoKDH6drx3JPVOpsJsMfjjbOdYFRaUAqcE2Qc KyBERs/hvWHPishKM7Pb1xHZ2IjXh4aw96TXEsdWiUPZPmKZOQlzd7C7BtJobn3gfGZAU8fLvWi 5ex0jCdLTt2aq5KlFB0J0IOaBXZ9CArNSS+s3I8XYxkZC4pzxSPpV/0XEKBthf4jbu8jm0oWnci ta11QPxXwJAEPNLre5FOr8dnoaghRF/TNFimjSuAPZZctd3P4B5Y0kb0hqatxTfBIiyrchxjK2i eu8M5yxf227lWDvLKvFLqTgoGRsKzBTj9KDVuZ7S8S2F9lkvO+E6lq+K7jthyF4YnLQT6Kr0n11 w4V7l9UMe9sx52OpkKdU6xPWHi+4DNPgNrpPUB0SuhBXNJb1dF5ALR9IgmTsP2Mbe05f8LY6NtR r0yUR75py3AeEwMcLFLK3mUfqfM8GlwKxlQJO5qwxbZnudyr79mnDjfUPq54g/IN5/tyAcQHRYZ wdOCUnYCR1tL+r3kf5cIJUSfdkyJAkbmNSA7MD8ijD3r9lLsLt/okBLaEo+IeUNQK7Qj5c1dhPM QOQ0Io8wUilj93Ec4oEnR1uYBPSK0GqbXFQeoXhuXUWQoMQt1g3VqSTJ7So82HMiBe0UlWzGYEK /2YaaN3o2BF2dhTP5RmSVfgTNGBDahFICcsPXMg6fo0rxLVrB3WB/vm5tBi/wPtA9baOj8yP62b okeB3+vy126mU+WqpuV/S1LzluSoLG8HLfjNfXhKwXj03jsC8k98SikuQ7HAWrboZbYdvLJbswL UY6eGgPPok7JOqQIAy6p60ZV62fJ5/bZ6npdiQZS2ujCtcuA== X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:149.199.60.96; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(1109001)(1110001)(339900001)(189002)(199003)(4326007)(76176999)(229853001)(5001960100002)(1220700001)(189998001)(19580395003)(36756003)(50226001)(19580405001)(50466002)(33646002)(106466001)(81156007)(5003940100001)(71366001)(5003600100002)(2906002)(1096002)(48376002)(110136002)(64026002)(118296001)(2351001)(6806005)(50986999)(5008740100001)(2950100001)(86362001)(586003)(47776003)(105606002)(85426001)(11100500001)(87936001)(575784001)(77096005)(92566002)(107986001); DIR:OUT; SFP:1101; SCL:1; SRVR:BL2NAM02HT197; H:xsj-tvapsmtpgw01; FPR:; SPF:Fail; PTR:unknown-60-96.xilinx.com; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: 4ae877bc-ff5d-41d6-e0a9-08d321212604 X-Exchange-Antispam-Report-Test: UriScan:; BCL:0; PCL:0; RULEID:; SRVR:BL2NAM02HT197; UriScan:(192813158149592); X-Microsoft-Antispam-PRVS: <16812d046f5a4ec08aca9127ece358ab@BL2NAM02HT197.eop-nam02.prod.protection.outlook.com> X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(520078)(13018025)(13017025)(8121501046)(13023025)(13015025)(5005006)(13024025)(3002001)(10201501046); SRVR:BL2NAM02HT197; BCL:0; PCL:0; RULEID:; SRVR:BL2NAM02HT197; X-Forefront-PRVS: 0826B2F01B X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jan 2016 22:37:44.0782 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.60.96]; Helo=[xsj-tvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL2NAM02HT197 X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 104.47.37.41 Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair.francis@xilinx.com, crosthwaitepeter@gmail.com, edgar.iglesias@gmail.com, afaerber@suse.de Subject: [Qemu-devel] [PATCH v2 09/16] dma: Add Xilinx Zynq devcfg device model X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Peter Crosthwaite Minimal device model for devcfg module of Zynq. DMA capabilities and interrupt generation supported. Signed-off-by: Peter Crosthwaite Signed-off-by: Alistair Francis --- Changed since v4: Create device state header. Use REG/FIELD/EX macros Use register init_block32 Remove un-needed timer code Changed since v3: Stylistic updates. Changed over to new decoding scheme. Use .rsvd in definitions as appropriate. Author reset (s/petalogix/xilinx). Changed since v2: Some QOM styling updates. Re-implemented nw0 for lock register as pre_write Changed since v1: Rebased against new version of Register API. Use action callbacks for side effects rather than switch. Documented reasons for ge0, ge1 (Verbatim from TRM) Added ui1 definitions for unimplemented major features Removed dead lock code default-configs/arm-softmmu.mak | 1 + hw/dma/Makefile.objs | 1 + hw/dma/xlnx-zynq-devcfg.c | 406 ++++++++++++++++++++++++++++++++++++++ include/hw/dma/xlnx-zynq-devcfg.h | 62 ++++++ 4 files changed, 470 insertions(+) create mode 100644 hw/dma/xlnx-zynq-devcfg.c create mode 100644 include/hw/dma/xlnx-zynq-devcfg.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index d9b90a5..bc3914d 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -66,6 +66,7 @@ CONFIG_PXA2XX=y CONFIG_BITBANG_I2C=y CONFIG_FRAMEBUFFER=y CONFIG_XILINX_SPIPS=y +CONFIG_ZYNQ_DEVCFG=y CONFIG_ARM11SCU=y CONFIG_A9SCU=y diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs index 0e65ed0..eaf0a81 100644 --- a/hw/dma/Makefile.objs +++ b/hw/dma/Makefile.objs @@ -5,6 +5,7 @@ common-obj-$(CONFIG_PL330) += pl330.o common-obj-$(CONFIG_I82374) += i82374.o common-obj-$(CONFIG_I8257) += i8257.o common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o +common-obj-$(CONFIG_ZYNQ_DEVCFG) += xlnx-zynq-devcfg.o common-obj-$(CONFIG_ETRAXFS) += etraxfs_dma.o common-obj-$(CONFIG_STP2000) += sparc32_dma.o common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o diff --git a/hw/dma/xlnx-zynq-devcfg.c b/hw/dma/xlnx-zynq-devcfg.c new file mode 100644 index 0000000..747d830 --- /dev/null +++ b/hw/dma/xlnx-zynq-devcfg.c @@ -0,0 +1,406 @@ +/* + * QEMU model of the Xilinx Zynq Devcfg Interface + * + * (C) 2011 PetaLogix Pty Ltd + * (C) 2014 Xilinx Inc. + * Written by Peter Crosthwaite + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/dma/xlnx-zynq-devcfg.h" +#include "qemu/bitops.h" +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" + +#define FREQ_HZ 900000000 + +#define BTT_MAX 0x400 + +#ifndef XLNX_ZYNQ_DEVCFG_ERR_DEBUG +#define XLNX_ZYNQ_DEVCFG_ERR_DEBUG 0 +#endif + +#define DB_PRINT(...) do { \ + if (XLNX_ZYNQ_DEVCFG_ERR_DEBUG) { \ + qemu_log("%s: ", __func__); \ + qemu_log(__VA_ARGS__); \ + } \ +} while (0); + +REG32(CTRL, 0x00) + FIELD(CTRL, FORCE_RST, 31, 1) /* Not supported, wr ignored */ + FIELD(CTRL, PCAP_PR, 27, 1) /* Forced to 0 on bad unlock */ + FIELD(CTRL, PCAP_MODE, 26, 1) + FIELD(CTRL, MULTIBOOT_EN, 24, 1) + FIELD(CTRL, USER_MODE, 15, 1) + FIELD(CTRL, PCFG_AES_FUSE, 12, 1) + FIELD(CTRL, PCFG_AES_EN, 9, 3) + FIELD(CTRL, SEU_EN, 8, 1) + FIELD(CTRL, SEC_EN, 7, 1) + FIELD(CTRL, SPNIDEN, 6, 1) + FIELD(CTRL, SPIDEN, 5, 1) + FIELD(CTRL, NIDEN, 4, 1) + FIELD(CTRL, DBGEN, 3, 1) + FIELD(CTRL, DAP_EN, 0, 3) + +REG32(LOCK, 0x04) + #define AES_FUSE_LOCK 4 + #define AES_EN_LOCK 3 + #define SEU_LOCK 2 + #define SEC_LOCK 1 + #define DBG_LOCK 0 + +/* mapping bits in R_LOCK to what they lock in R_CTRL */ +static const uint32_t lock_ctrl_map[] = { + [AES_FUSE_LOCK] = R_CTRL_PCFG_AES_FUSE_MASK, + [AES_EN_LOCK] = R_CTRL_PCFG_AES_EN_MASK, + [SEU_LOCK] = R_CTRL_SEU_EN_MASK, + [SEC_LOCK] = R_CTRL_SEC_EN_MASK, + [DBG_LOCK] = R_CTRL_SPNIDEN_MASK | R_CTRL_SPIDEN_MASK | + R_CTRL_NIDEN_MASK | R_CTRL_DBGEN_MASK | + R_CTRL_DAP_EN_MASK, +}; + +REG32(CFG, 0x08) + FIELD(CFG, RFIFO_TH, 10, 2) + FIELD(CFG, WFIFO_TH, 8, 2) + FIELD(CFG, RCLK_EDGE, 7, 1) + FIELD(CFG, WCLK_EDGE, 6, 1) + FIELD(CFG, DISABLE_SRC_INC, 5, 1) + FIELD(CFG, DISABLE_DST_INC, 4, 1) +#define R_CFG_RO 0xFFFFF000 +#define R_CFG_RESET 0x50B + +REG32(INT_STS, 0x0C) + FIELD(INT_STS, PSS_GTS_USR_B, 31, 1) + FIELD(INT_STS, PSS_FST_CFG_B, 30, 1) + FIELD(INT_STS, PSS_CFG_RESET_B, 27, 1) + FIELD(INT_STS, RX_FIFO_OV, 18, 1) + FIELD(INT_STS, WR_FIFO_LVL, 17, 1) + FIELD(INT_STS, RD_FIFO_LVL, 16, 1) + FIELD(INT_STS, DMA_CMD_ERR, 15, 1) + FIELD(INT_STS, DMA_Q_OV, 14, 1) + FIELD(INT_STS, DMA_DONE, 13, 1) + FIELD(INT_STS, DMA_P_DONE, 12, 1) + FIELD(INT_STS, P2D_LEN_ERR, 11, 1) + FIELD(INT_STS, PCFG_DONE, 2, 1) + #define R_INT_STS_RSVD ((0x7 << 24) | (0x1 << 19) | (0xF < 7)) + +REG32(INT_MASK, 0x10) + +REG32(STATUS, 0x14) + FIELD(STATUS, DMA_CMD_Q_F, 31, 1) + FIELD(STATUS, DMA_CMD_Q_E, 30, 1) + FIELD(STATUS, DMA_DONE_CNT, 28, 2) + FIELD(STATUS, RX_FIFO_LVL, 20, 5) + FIELD(STATUS, TX_FIFO_LVL, 12, 7) + FIELD(STATUS, PSS_GTS_USR_B, 11, 1) + FIELD(STATUS, PSS_FST_CFG_B, 10, 1) + FIELD(STATUS, PSS_CFG_RESET_B, 5, 1) + +REG32(DMA_SRC_ADDR, 0x18) +REG32(DMA_DST_ADDR, 0x1C) +REG32(DMA_SRC_LEN, 0x20) +REG32(DMA_DST_LEN, 0x24) +REG32(ROM_SHADOW, 0x28) +REG32(SW_ID, 0x30) +REG32(UNLOCK, 0x34) + +#define R_UNLOCK_MAGIC 0x757BDF0D + +REG32(MCTRL, 0x80) + FIELD(MCTRL, PS_VERSION, 28, 4) + FIELD(MCTRL, PCFG_POR_B, 8, 1) + FIELD(MCTRL, INT_PCAP_LPBK, 4, 1) + FIELD(MCTRL, QEMU, 3, 1) + +static void xlnx_zynq_devcfg_update_ixr(XlnxZynqDevcfg *s) +{ + qemu_set_irq(s->irq, ~s->regs[R_INT_MASK] & s->regs[R_INT_STS]); +} + +static void xlnx_zynq_devcfg_reset(DeviceState *dev) +{ + XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(dev); + int i; + + for (i = 0; i < XLNX_ZYNQ_DEVCFG_R_MAX; ++i) { + register_reset(&s->regs_info[i]); + } +} + +static void xlnx_zynq_devcfg_dma_go(XlnxZynqDevcfg *s) +{ + for (;;) { + uint8_t buf[BTT_MAX]; + XlnxZynqDevcfgDMACmd *dmah = s->dma_cmd_fifo; + uint32_t btt = BTT_MAX; + bool loopback = s->regs[R_MCTRL] & R_MCTRL_INT_PCAP_LPBK_MASK; + + btt = MIN(btt, dmah->src_len); + if (loopback) { + btt = MIN(btt, dmah->dest_len); + } + DB_PRINT("reading %x bytes from %x\n", btt, dmah->src_addr); + dma_memory_read(&address_space_memory, dmah->src_addr, buf, btt); + dmah->src_len -= btt; + dmah->src_addr += btt; + if (loopback) { + DB_PRINT("writing %x bytes from %x\n", btt, dmah->dest_addr); + dma_memory_write(&address_space_memory, dmah->dest_addr, buf, btt); + dmah->dest_len -= btt; + dmah->dest_addr += btt; + } + if (!dmah->src_len && !dmah->dest_len) { + DB_PRINT("dma operation finished\n"); + s->regs[R_INT_STS] |= R_INT_STS_DMA_DONE_MASK | + R_INT_STS_DMA_P_DONE_MASK; + s->dma_cmd_fifo_num--; + memmove(s->dma_cmd_fifo, &s->dma_cmd_fifo[1], + sizeof(*s->dma_cmd_fifo) * XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN + - 1); + } + xlnx_zynq_devcfg_update_ixr(s); + if (!s->dma_cmd_fifo_num) { /* All done */ + return; + } + } +} + +static void r_ixr_post_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque); + + xlnx_zynq_devcfg_update_ixr(s); +} + +static uint64_t r_ctrl_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque); + int i; + + for (i = 0; i < ARRAY_SIZE(lock_ctrl_map); ++i) { + if (s->regs[R_LOCK] & 1 << i) { + val &= ~lock_ctrl_map[i]; + val |= lock_ctrl_map[i] & s->regs[R_CTRL]; + } + } + return val; +} + +static void r_ctrl_post_write(RegisterInfo *reg, uint64_t val) +{ + uint32_t aes_en = F_EX32(val, CTRL, PCFG_AES_EN); + + if (aes_en != 0 && aes_en != 7) { + qemu_log_mask(LOG_UNIMP, "%s: warning, aes-en bits inconsistent," + "unimplemented security reset should happen!\n", + reg->prefix); + } +} + +static void r_unlock_post_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque); + + if (val == R_UNLOCK_MAGIC) { + DB_PRINT("successful unlock\n"); + /* BootROM will have already done the actual unlock so no need to do + * anything in successful subsequent unlock + */ + } else { /* bad unlock attempt */ + qemu_log_mask(LOG_GUEST_ERROR, "%s: failed unlock\n", reg->prefix); + s->regs[R_CTRL] &= ~R_CTRL_PCAP_PR_MASK; + s->regs[R_CTRL] &= ~R_CTRL_PCFG_AES_EN_MASK; + /* core becomes inaccessible */ + memory_region_set_enabled(&s->iomem, false); + } +} + +static uint64_t r_lock_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque); + + /* once bits are locked they stay locked */ + return s->regs[R_LOCK] | val; +} + +static void r_dma_dst_len_post_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque); + + s->dma_cmd_fifo[s->dma_cmd_fifo_num] = (XlnxZynqDevcfgDMACmd) { + .src_addr = s->regs[R_DMA_SRC_ADDR] & ~0x3UL, + .dest_addr = s->regs[R_DMA_DST_ADDR] & ~0x3UL, + .src_len = s->regs[R_DMA_SRC_LEN] << 2, + .dest_len = s->regs[R_DMA_DST_LEN] << 2, + }; + s->dma_cmd_fifo_num++; + DB_PRINT("dma transfer started; %d total transfers pending\n", + s->dma_cmd_fifo_num); + xlnx_zynq_devcfg_dma_go(s); +} + +static const RegisterAccessInfo xlnx_zynq_devcfg_regs_info[] = { + { .name = "CTRL", .decode.addr = A_CTRL, + .reset = R_CTRL_PCAP_PR_MASK | R_CTRL_PCAP_MODE_MASK | 0x3 << 13, + .rsvd = 0x1 << 28 | 0x3ff << 13 | 0x3 << 13, + .ui1 = (RegisterAccessError[]) { + { .mask = R_CTRL_FORCE_RST_MASK, + .reason = "PS reset not implemented" }, + { .mask = R_CTRL_PCAP_MODE_MASK, + .reason = "FPGA Fabric doesn't exist" }, + { .mask = R_CTRL_PCFG_AES_EN_MASK, + .reason = "AES not implemented" }, + {}, + }, + .pre_write = r_ctrl_pre_write, + .post_write = r_ctrl_post_write, + }, + { .name = "LOCK", .decode.addr = A_LOCK, + .rsvd = ~ONES(5), + .pre_write = r_lock_pre_write, + }, + { .name = "CFG", .decode.addr = A_CFG, + .reset = 1 << R_CFG_RFIFO_TH_SHIFT | 1 << R_CFG_WFIFO_TH_SHIFT | 0x8, + .rsvd = 0xfffff00f, + }, + { .name = "INT_STS", .decode.addr = A_INT_STS, + .w1c = ~R_INT_STS_RSVD, + .reset = R_INT_STS_PSS_GTS_USR_B_MASK | + R_INT_STS_PSS_CFG_RESET_B_MASK | + R_INT_STS_WR_FIFO_LVL_MASK, + .rsvd = R_INT_STS_RSVD, + .post_write = r_ixr_post_write, + }, + { .name = "INT_MASK", .decode.addr = A_INT_MASK, + .reset = ~0, + .rsvd = R_INT_STS_RSVD, + .post_write = r_ixr_post_write, + }, + { .name = "STATUS", .decode.addr = A_STATUS, + .reset = R_STATUS_DMA_CMD_Q_E_MASK | + R_STATUS_PSS_GTS_USR_B_MASK | + R_STATUS_PSS_CFG_RESET_B_MASK, + .ro = ~0, + }, + { .name = "DMA_SRC_ADDR", .decode.addr = A_DMA_SRC_ADDR, }, + { .name = "DMA_DST_ADDR", .decode.addr = A_DMA_DST_ADDR, }, + { .name = "DMA_SRC_LEN", .decode.addr = A_DMA_SRC_LEN, + .ro = ~ONES(27) }, + { .name = "DMA_DST_LEN", .decode.addr = A_DMA_DST_LEN, + .ro = ~ONES(27), + .post_write = r_dma_dst_len_post_write, + }, + { .name = "ROM_SHADOW", .decode.addr = A_ROM_SHADOW, + .rsvd = ~0ull, + }, + { .name = "SW_ID", .decode.addr = A_SW_ID, }, + { .name = "UNLOCK", .decode.addr = A_UNLOCK, + .post_write = r_unlock_post_write, + }, + { .name = "MCTRL", .decode.addr = R_MCTRL * 4, + /* Silicon 3.0 for version field, the mysterious reserved bit 23 + * and QEMU platform identifier. + */ + .reset = 0x2 << R_MCTRL_PS_VERSION_SHIFT | 1 << 23 | R_MCTRL_QEMU_MASK, + .ro = ~R_MCTRL_INT_PCAP_LPBK_MASK, + .rsvd = 0x00f00303, + }, +}; + +static const MemoryRegionOps xlnx_zynq_devcfg_reg_ops = { + .read = register_read_memory_le, + .write = register_write_memory_le, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + +static const VMStateDescription vmstate_xlnx_zynq_devcfg_dma_cmd = { + .name = "xlnx_zynq_devcfg_dma_cmd", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(src_addr, XlnxZynqDevcfgDMACmd), + VMSTATE_UINT32(dest_addr, XlnxZynqDevcfgDMACmd), + VMSTATE_UINT32(src_len, XlnxZynqDevcfgDMACmd), + VMSTATE_UINT32(dest_len, XlnxZynqDevcfgDMACmd), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_xlnx_zynq_devcfg = { + .name = "xlnx_zynq_devcfg", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(dma_cmd_fifo, XlnxZynqDevcfg, + XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN, 0, + vmstate_xlnx_zynq_devcfg_dma_cmd, + XlnxZynqDevcfgDMACmd), + VMSTATE_UINT8(dma_cmd_fifo_num, XlnxZynqDevcfg), + VMSTATE_UINT32_ARRAY(regs, XlnxZynqDevcfg, XLNX_ZYNQ_DEVCFG_R_MAX), + VMSTATE_END_OF_LIST() + } +}; + +static void xlnx_zynq_devcfg_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(obj); + + sysbus_init_irq(sbd, &s->irq); + + memory_region_init(&s->iomem, obj, "devcfg", XLNX_ZYNQ_DEVCFG_R_MAX * 4); + register_init_block32(DEVICE(obj), xlnx_zynq_devcfg_regs_info, + ARRAY_SIZE(xlnx_zynq_devcfg_regs_info), + s->regs_info, s->regs, &s->iomem, + &xlnx_zynq_devcfg_reg_ops, + XLNX_ZYNQ_DEVCFG_ERR_DEBUG); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void xlnx_zynq_devcfg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = xlnx_zynq_devcfg_reset; + dc->vmsd = &vmstate_xlnx_zynq_devcfg; +} + +static const TypeInfo xlnx_zynq_devcfg_info = { + .name = TYPE_XLNX_ZYNQ_DEVCFG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(XlnxZynqDevcfg), + .instance_init = xlnx_zynq_devcfg_init, + .class_init = xlnx_zynq_devcfg_class_init, +}; + +static void xlnx_zynq_devcfg_register_types(void) +{ + type_register_static(&xlnx_zynq_devcfg_info); +} + +type_init(xlnx_zynq_devcfg_register_types) diff --git a/include/hw/dma/xlnx-zynq-devcfg.h b/include/hw/dma/xlnx-zynq-devcfg.h new file mode 100644 index 0000000..d40e5c8 --- /dev/null +++ b/include/hw/dma/xlnx-zynq-devcfg.h @@ -0,0 +1,62 @@ +/* + * QEMU model of the Xilinx Devcfg Interface + * + * (C) 2011 PetaLogix Pty Ltd + * (C) 2014 Xilinx Inc. + * Written by Peter Crosthwaite + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef XLNX_ZYNQ_DEVCFG_H + +#include "hw/register.h" +#include "hw/sysbus.h" + +#define TYPE_XLNX_ZYNQ_DEVCFG "xlnx.ps7-dev-cfg" + +#define XLNX_ZYNQ_DEVCFG(obj) \ + OBJECT_CHECK(XlnxZynqDevcfg, (obj), TYPE_XLNX_ZYNQ_DEVCFG) + +#define XLNX_ZYNQ_DEVCFG_R_MAX 0x118 + +#define XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN 10 + +typedef struct XlnxZynqDevcfgDMACmd { + uint32_t src_addr; + uint32_t dest_addr; + uint32_t src_len; + uint32_t dest_len; +} XlnxZynqDevcfgDMACmd; + +typedef struct XlnxZynqDevcfg { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + + XlnxZynqDevcfgDMACmd dma_cmd_fifo[XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN]; + uint8_t dma_cmd_fifo_num; + + uint32_t regs[XLNX_ZYNQ_DEVCFG_R_MAX]; + RegisterInfo regs_info[XLNX_ZYNQ_DEVCFG_R_MAX]; +} XlnxZynqDevcfg; + +#define XLNX_ZYNQ_DEVCFG_H +#endif