get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2225496/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2225496,
    "url": "http://patchwork.ozlabs.org/api/patches/2225496/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260421053140.752059-2-joel@jms.id.au/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260421053140.752059-2-joel@jms.id.au>",
    "list_archive_url": null,
    "date": "2026-04-21T05:31:26",
    "name": "[v3,01/13] hw/i2c: Add designware i2c controller",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "e844902a50cd58a87fea2dcb7384acdaa1677031",
    "submitter": {
        "id": 48628,
        "url": "http://patchwork.ozlabs.org/api/people/48628/?format=api",
        "name": "Joel Stanley",
        "email": "joel@jms.id.au"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260421053140.752059-2-joel@jms.id.au/mbox/",
    "series": [
        {
            "id": 500733,
            "url": "http://patchwork.ozlabs.org/api/series/500733/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=500733",
            "date": "2026-04-21T05:31:26",
            "name": "hw/riscv: Add the Tenstorrent Atlantis machine",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/500733/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2225496/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2225496/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=UOz6AhKX;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g09yF4KJMz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 21 Apr 2026 15:33:57 +1000 (AEST)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wF3jd-0000RE-S1; Tue, 21 Apr 2026 01:33:21 -0400",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <joel.stan@gmail.com>)\n id 1wF3jW-0000PF-1N\n for qemu-devel@nongnu.org; Tue, 21 Apr 2026 01:33:15 -0400",
            "from mail-pj1-x1032.google.com ([2607:f8b0:4864:20::1032])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <joel.stan@gmail.com>)\n id 1wF3jS-0004OO-1z\n for qemu-devel@nongnu.org; Tue, 21 Apr 2026 01:33:13 -0400",
            "by mail-pj1-x1032.google.com with SMTP id\n 98e67ed59e1d1-36146ae9dd4so2853127a91.3\n for <qemu-devel@nongnu.org>; Mon, 20 Apr 2026 22:33:09 -0700 (PDT)",
            "from donnager-debian.. ([203.221.103.1])\n by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-36141898ebasm12472308a91.7.2026.04.20.22.33.03\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 20 Apr 2026 22:33:07 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1776749588; x=1777354388; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date\n :message-id:reply-to;\n bh=3ppIvCHSoxfKxKlEXcLNRGER0aNeuOrWaORT80Wayz0=;\n b=UOz6AhKXoigxVy5sBlBhhX4Jwzlh42hxOk+8Z3Ntc+aj7eMogxFgILbjbeyV3DJR1x\n WEpByapvfrno1mW+u3regaFwBGgwF9qrlaRUF19QhSVtNzMXE/uXfs2lxTDXBlcksHD4\n TBFWXEPGCcWXZHz43FizDXLV14QOVhNAvu2VaH8BDvyK1puova4YHBJYy7GoXSLf2K2u\n zuMKVxllZjD8g2bw7IN8648FVmjy0Ze6Znv6GZ3K7q51BDI+t5RM3VrD6NwZbCyJ4Gn/\n TDAf7WRp+6CdrOhXzG52T8IjeuLxcwqNg+MtFii48NeecmZx8vygL0nr2FVkllCObwaZ\n 50xQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776749588; x=1777354388;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:sender:x-gm-gg\n :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n bh=3ppIvCHSoxfKxKlEXcLNRGER0aNeuOrWaORT80Wayz0=;\n b=m6MvFsdjj0XNxsITGoMNqIDkfH+laceoUOOTjL3JM0M+W0oLHD2BmcuRztztf/5eYw\n wYq5G5rDPgA3leHcNFT+E0i2B0jfHfaAfY9wrevSdeIUyM9heVm8LfhmFlHmPIPvvKON\n j/xnCmtsh9geEgNvh137nWOnuIhb9CglLKi1uiXkNJ4ys7NxXozV6UFYTF1Wif6vAWX1\n tqnPShEzSUR98ZAQFUcutFUjC9iuWJQfcnB5qyERHb8hSivSgjhI1btHGAFx3tzKq/eq\n l7YXC4eQI3Jyzajoo+YrSP492H61zIiYE81soJMyAP+o82FAd5TG2KrCT2ZAh1RtF6ry\n 7ZnA==",
        "X-Forwarded-Encrypted": "i=1;\n AFNElJ+ZH+wgJkdiorssPo6pUy+R9Fp3M+P7Eso025xJS21Sv+utu1VUXgFyUfFKG8iSc5Nx5pMi4D6sre8f@nongnu.org",
        "X-Gm-Message-State": "AOJu0YzBnJYZn4eM77OHP/zrGol3T/UOTTvqcwrIdIs1wepYyYAleznE\n ZzGXkWsS7ndfqCVCPFGKDFPugoS3dafWmXz7PV43Xou/TJZxp85lhe7U",
        "X-Gm-Gg": "AeBDievQApzAsoJg9oVer2e9E+d82F/u8QW/JWnwlFlDQXWV/S7DEcQ4ADDBh0jfajr\n TYR9g7EmfTf/0qzhmpo+q0ciTokXsJgo4ktjfs2NXAlN0qXFu/9CdF6IjzOxjzR7CinX+1s7a8t\n g/BNE/aPEze95VBGy0lC3ADmC+NXCJzIJDM4wLOQ6BpMxovEANhieNSDC4m3fVDsITWMlZw+gFY\n iIEyUPmVyQJewhwCH9WxJfUbSZfc7VfdkHUi8jH20Ky112bxcdy9fWzdMCHvXKbmjo0pfRzEt5H\n azu/Yc2rwv+CVdRFBebqlNst+al3UbXEJgFaDsRPjHYLUrc+ecfh6/UhuqsjwhF32+X8vkwF/vz\n LT0yDLdmJ8z6Y1zhWz/CAzZqPLrlPjLDSDIbIjY9DBZ8AEnokEeP6g7OHue8WnkzoIlcWkFnQW+\n IInxBccHb5Kks4aVXTKpkZgj0+IUfgnIl8KHsCzN1Y0my66EXc4vqKO4XnyAKN61pAyPCcI6bRL\n FEIBclAh605htwVSECIpYpY9blVBGL786DE1w==",
        "X-Received": "by 2002:a17:90b:3f84:b0:359:1130:1047 with SMTP id\n 98e67ed59e1d1-36140468c28mr16076858a91.17.1776749588157;\n Mon, 20 Apr 2026 22:33:08 -0700 (PDT)",
        "From": "Joel Stanley <joel@jms.id.au>",
        "To": "Alistair Francis <alistair.francis@wdc.com>,\n Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>",
        "Cc": "Chris Rauer <crauer@google.com>, Michael Ellerman <mpe@kernel.org>,\n Nicholas Piggin <npiggin@gmail.com>,\n Joel Stanley <jms@oss.tenstorrent.com>,\n Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>,\n qemu-riscv@nongnu.org, qemu-devel@nongnu.org, Hao Wu <wuhaotsh@google.com>",
        "Subject": "[PATCH v3 01/13] hw/i2c: Add designware i2c controller",
        "Date": "Tue, 21 Apr 2026 15:31:26 +1000",
        "Message-ID": "<20260421053140.752059-2-joel@jms.id.au>",
        "X-Mailer": "git-send-email 2.47.3",
        "In-Reply-To": "<20260421053140.752059-1-joel@jms.id.au>",
        "References": "<20260421053140.752059-1-joel@jms.id.au>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Received-SPF": "pass client-ip=2607:f8b0:4864:20::1032;\n envelope-from=joel.stan@gmail.com; helo=mail-pj1-x1032.google.com",
        "X-Spam_score_int": "-16",
        "X-Spam_score": "-1.7",
        "X-Spam_bar": "-",
        "X-Spam_report": "(-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001,\n FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=no autolearn_force=no",
        "X-Spam_action": "no action",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "qemu development <qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"
    },
    "content": "From: Chris Rauer <crauer@google.com>\n\nIn the past this model has been submitted for use with the arm virt\nmachine, however in this case it will be used by the upcoming\nTenstorrent Atlantis RISC-V machine.\n\nThis is a re-submission of the model with Chris' permission, with a\nlight touch of updates to make it build with qemu master.\n\nReviewed-by: Hao Wu <wuhaotsh@google.com>\nSigned-off-by: Chris Rauer <crauer@google.com>\nLink: https://lore.kernel.org/qemu-devel/20220110214755.810343-2-venture@google.com\n[jms: rebase and minor build fixes for class_init and reset callback]\nSigned-off-by: Joel Stanley <joel@jms.id.au>\n---\nv2: Add trace event for read and write, document Alano and myself as\nreviewers.\n---\n MAINTAINERS                     |   8 +\n include/hw/i2c/designware_i2c.h | 101 ++++\n hw/i2c/designware_i2c.c         | 818 ++++++++++++++++++++++++++++++++\n hw/i2c/Kconfig                  |   4 +\n hw/i2c/meson.build              |   1 +\n hw/i2c/trace-events             |   4 +\n 6 files changed, 936 insertions(+)\n create mode 100644 include/hw/i2c/designware_i2c.h\n create mode 100644 hw/i2c/designware_i2c.c",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex aa4267b15806..e1942a86eba5 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -2716,6 +2716,14 @@ S: Orphan\n F: hw/gpio/pcf8574.c\n F: include/gpio/pcf8574.h\n \n+DesignWare I2C\n+M: Chris Rauer <crauer@google.com>\n+R: Alano Song <alanosong@163.com>\n+R: Joel Stanley <joel@jms.id.au>\n+S: Maintained\n+F: hw/i2c/designware_i2c.c\n+F: include/hw/i2c/designware_i2c.h\n+\n Generic Loader\n M: Alistair Francis <alistair@alistair23.me>\n S: Maintained\ndiff --git a/include/hw/i2c/designware_i2c.h b/include/hw/i2c/designware_i2c.h\nnew file mode 100644\nindex 000000000000..0d8f904f51b7\n--- /dev/null\n+++ b/include/hw/i2c/designware_i2c.h\n@@ -0,0 +1,101 @@\n+/*\n+ * DesignWare I2C Module.\n+ *\n+ * Copyright 2021 Google LLC\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+#ifndef DESIGNWARE_I2C_H\n+#define DESIGNWARE_I2C_H\n+\n+#include \"hw/i2c/i2c.h\"\n+#include \"hw/core/irq.h\"\n+#include \"hw/core/sysbus.h\"\n+\n+/* Size of the FIFO buffers. */\n+#define DESIGNWARE_I2C_RX_FIFO_SIZE 16\n+#define DESIGNWARE_I2C_TX_FIFO_SIZE 16\n+\n+typedef enum DesignWareI2CStatus {\n+    DW_I2C_STATUS_IDLE,\n+    DW_I2C_STATUS_SENDING_ADDRESS,\n+    DW_I2C_STATUS_SENDING,\n+    DW_I2C_STATUS_RECEIVING,\n+} DesignWareI2CStatus;\n+\n+/*\n+ * struct DesignWareI2CState - DesignWare I2C device state.\n+ * @bus: The underlying I2C Bus\n+ * @irq: GIC interrupt line to fire on events\n+ * @ic_con: : I2C control register\n+ * @ic_tar: I2C target address register\n+ * @ic_sar: I2C slave address register\n+ * @ic_ss_scl_hcnt: Standard speed i2c clock scl high count register\n+ * @ic_ss_scl_lcnt: Standard speed i2c clock scl low count register\n+ * @ic_fs_scl_hcnt: Fast mode or fast mode plus i2c clock scl high count\n+ *                  register\n+ * @ic_fs_scl_lcnt:Fast mode or fast mode plus i2c clock scl low count\n+ *                  register\n+ * @ic_intr_mask: I2C Interrupt Mask Register\n+ * @ic_raw_intr_stat: I2C raw interrupt status register\n+ * @ic_rx_tl: I2C receive FIFO threshold register\n+ * @ic_tx_tl: I2C transmit FIFO threshold register\n+ * @ic_enable: I2C enable register\n+ * @ic_status: I2C status register\n+ * @ic_txflr: I2C transmit fifo level register\n+ * @ic_rxflr: I2C receive fifo level register\n+ * @ic_sda_hold: I2C SDA hold time length register\n+ * @ic_tx_abrt_source: The I2C transmit abort source register\n+ * @ic_sda_setup: I2C SDA setup register\n+ * @ic_enable_status: I2C enable status register\n+ * @ic_fs_spklen: I2C SS, FS or FM+ spike suppression limit\n+ * @ic_comp_param_1: Component parameter register\n+ * @ic_comp_version: I2C component version register\n+ * @ic_comp_type: I2C component type register\n+ * @rx_fifo: The FIFO buffer for receiving in FIFO mode.\n+ * @rx_cur: The current position of rx_fifo.\n+ * @status: The current status of the SMBus.\n+ */\n+typedef struct DesignWareI2CState {\n+    SysBusDevice parent;\n+\n+    MemoryRegion iomem;\n+\n+    I2CBus      *bus;\n+    qemu_irq     irq;\n+\n+    uint32_t ic_con;\n+    uint32_t ic_tar;\n+    uint32_t ic_sar;\n+    uint32_t ic_ss_scl_hcnt;\n+    uint32_t ic_ss_scl_lcnt;\n+    uint32_t ic_fs_scl_hcnt;\n+    uint32_t ic_fs_scl_lcnt;\n+    uint32_t ic_intr_mask;\n+    uint32_t ic_raw_intr_stat;\n+    uint32_t ic_rx_tl;\n+    uint32_t ic_tx_tl;\n+    uint32_t ic_enable;\n+    uint32_t ic_status;\n+    uint32_t ic_txflr;\n+    uint32_t ic_rxflr;\n+    uint32_t ic_sda_hold;\n+    uint32_t ic_tx_abrt_source;\n+    uint32_t ic_sda_setup;\n+    uint32_t ic_enable_status;\n+    uint32_t ic_fs_spklen;\n+    uint32_t ic_comp_param_1;\n+    uint32_t ic_comp_version;\n+    uint32_t ic_comp_type;\n+\n+    uint8_t      rx_fifo[DESIGNWARE_I2C_RX_FIFO_SIZE];\n+    uint8_t      rx_cur;\n+\n+    DesignWareI2CStatus status;\n+} DesignWareI2CState;\n+\n+#define TYPE_DESIGNWARE_I2C \"designware-i2c\"\n+#define DESIGNWARE_I2C(obj) OBJECT_CHECK(DesignWareI2CState, (obj), \\\n+                                        TYPE_DESIGNWARE_I2C)\n+\n+#endif /* DESIGNWARE_I2C_H */\ndiff --git a/hw/i2c/designware_i2c.c b/hw/i2c/designware_i2c.c\nnew file mode 100644\nindex 000000000000..3e0e7dab2333\n--- /dev/null\n+++ b/hw/i2c/designware_i2c.c\n@@ -0,0 +1,818 @@\n+/*\n+ * DesignWare I2C Module.\n+ *\n+ * Copyright 2021 Google LLC\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#include \"qemu/osdep.h\"\n+\n+#include \"hw/i2c/designware_i2c.h\"\n+#include \"migration/vmstate.h\"\n+#include \"qemu/bitops.h\"\n+#include \"qemu/guest-random.h\"\n+#include \"qemu/log.h\"\n+#include \"qemu/module.h\"\n+#include \"qemu/units.h\"\n+#include \"trace.h\"\n+\n+enum DesignWareI2CRegister {\n+    DW_IC_CON                   = 0x00,\n+    DW_IC_TAR                   = 0x04,\n+    DW_IC_SAR                   = 0x08,\n+    DW_IC_DATA_CMD              = 0x10,\n+    DW_IC_SS_SCL_HCNT           = 0x14,\n+    DW_IC_SS_SCL_LCNT           = 0x18,\n+    DW_IC_FS_SCL_HCNT           = 0x1c,\n+    DW_IC_FS_SCL_LCNT           = 0x20,\n+    DW_IC_INTR_STAT             = 0x2c,\n+    DW_IC_INTR_MASK             = 0x30,\n+    DW_IC_RAW_INTR_STAT         = 0x34,\n+    DW_IC_RX_TL                 = 0x38,\n+    DW_IC_TX_TL                 = 0x3c,\n+    DW_IC_CLR_INTR              = 0x40,\n+    DW_IC_CLR_RX_UNDER          = 0x44,\n+    DW_IC_CLR_RX_OVER           = 0x48,\n+    DW_IC_CLR_TX_OVER           = 0x4c,\n+    DW_IC_CLR_RD_REQ            = 0x50,\n+    DW_IC_CLR_TX_ABRT           = 0x54,\n+    DW_IC_CLR_RX_DONE           = 0x58,\n+    DW_IC_CLR_ACTIVITY          = 0x5c,\n+    DW_IC_CLR_STOP_DET          = 0x60,\n+    DW_IC_CLR_START_DET         = 0x64,\n+    DW_IC_CLR_GEN_CALL          = 0x68,\n+    DW_IC_ENABLE                = 0x6c,\n+    DW_IC_STATUS                = 0x70,\n+    DW_IC_TXFLR                 = 0x74,\n+    DW_IC_RXFLR                 = 0x78,\n+    DW_IC_SDA_HOLD              = 0x7c,\n+    DW_IC_TX_ABRT_SOURCE        = 0x80,\n+    DW_IC_SLV_DATA_NACK_ONLY    = 0x84,\n+    DW_IC_DMA_CR                = 0x88,\n+    DW_IC_DMA_TDLR              = 0x8c,\n+    DW_IC_DMA_RDLR              = 0x90,\n+    DW_IC_SDA_SETUP             = 0x94,\n+    DW_IC_ACK_GENERAL_CALL      = 0x98,\n+    DW_IC_ENABLE_STATUS         = 0x9c,\n+    DW_IC_FS_SPKLEN             = 0xa0,\n+    DW_IC_CLR_RESTART_DET       = 0xa8,\n+    DW_IC_COMP_PARAM_1          = 0xf4,\n+    DW_IC_COMP_VERSION          = 0xf8,\n+    DW_IC_COMP_TYPE             = 0xfc,\n+};\n+\n+/* DW_IC_CON fields */\n+#define DW_IC_CON_STOP_DET_IF_MASTER_ACTIV  BIT(10)\n+#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL     BIT(9)\n+#define DW_IC_CON_TX_EMPTY_CTRL             BIT(8)\n+#define DW_IC_CON_STOP_IF_ADDRESSED         BIT(7)\n+#define DW_IC_CON_SLAVE_DISABLE             BIT(6)\n+#define DW_IC_CON_IC_RESTART_EN             BIT(5)\n+#define DW_IC_CON_10BITADDR_MASTER          BIT(4)\n+#define DW_IC_CON_10BITADDR_SLAVE           BIT(3)\n+#define DW_IC_CON_SPEED(rv)                 extract32((rv), 1, 2)\n+#define DW_IC_CON_MASTER_MODE               BIT(0)\n+\n+/* DW_IC_TAR fields */\n+#define DW_IC_TAR_IC_10BITADDR_MASTER  BIT(12)\n+#define DW_IC_TAR_SPECIAL              BIT(11)\n+#define DW_IC_TAR_GC_OR_START          BIT(10)\n+#define DW_IC_TAR_ADDRESS(rv)          extract32((rv), 0, 10)\n+\n+/* DW_IC_DATA_CMD fields */\n+#define DW_IC_DATA_CMD_RESTART  BIT(10)\n+#define DW_IC_DATA_CMD_STOP     BIT(9)\n+#define DW_IC_DATA_CMD_CMD      BIT(8)\n+#define DW_IC_DATA_CMD_DAT(rv)  extract32((rv), 0, 8)\n+\n+/* DW_IC_INTR_STAT/INTR_MASK/RAW_INTR_STAT fields */\n+#define DW_IC_INTR_RESTART_DET  BIT(12)\n+#define DW_IC_INTR_GEN_CALL     BIT(11)\n+#define DW_IC_INTR_START_DET    BIT(10)\n+#define DW_IC_INTR_STOP_DET     BIT(9)\n+#define DW_IC_INTR_ACTIVITY     BIT(8)\n+#define DW_IC_INTR_RX_DONE      BIT(7)\n+#define DW_IC_INTR_TX_ABRT      BIT(6)\n+#define DW_IC_INTR_RD_REQ       BIT(5)\n+#define DW_IC_INTR_TX_EMPTY     BIT(4) /* Hardware clear only. */\n+#define DW_IC_INTR_TX_OVER      BIT(3)\n+#define DW_IC_INTR_RX_FULL      BIT(2) /* Hardware clear only. */\n+#define DW_IC_INTR_RX_OVER      BIT(1)\n+#define DW_IC_INTR_RX_UNDER     BIT(0)\n+\n+/* DW_IC_ENABLE fields */\n+#define DW_IC_ENABLE_TX_CMD_BLOCK  BIT(2)\n+#define DW_IC_ENABLE_ABORT         BIT(1)\n+#define DW_IC_ENABLE_ENABLE        BIT(0)\n+\n+/* DW_IC_STATUS fields */\n+#define DW_IC_STATUS_SLV_ACTIVITY  BIT(6)\n+#define DW_IC_STATUS_MST_ACTIVITY  BIT(5)\n+#define DW_IC_STATUS_RFF           BIT(4)\n+#define DW_IC_STATUS_RFNE          BIT(3)\n+#define DW_IC_STATUS_TFE           BIT(2)\n+#define DW_IC_STATUS_TFNF          BIT(1)\n+#define DW_IC_STATUS_ACTIVITY      BIT(0)\n+\n+/* DW_IC_TX_ABRT_SOURCE fields */\n+#define DW_IC_TX_TX_FLUSH_CNT          extract32((rv), 23, 9)\n+#define DW_IC_TX_ABRT_USER_ABRT        BIT(16)\n+#define DW_IC_TX_ABRT_SLVRD_INTX       BIT(15)\n+#define DW_IC_TX_ABRT_SLV_ARBLOST      BIT(14)\n+#define DW_IC_TX_ABRT_SLVFLUSH_TXFIFO  BIT(13)\n+#define DW_IC_TX_ARB_LOST              BIT(12)\n+#define DW_IC_TX_ABRT_MASTER_DIS       BIT(11)\n+#define DW_IC_TX_ABRT_10B_RD_NORSTRT   BIT(10)\n+#define DW_IC_TX_ABRT_SBYTE_NORSTRT    BIT(9)\n+#define DW_IC_TX_ABRT_HS_NORSTRT       BIT(8)\n+#define DW_IC_TX_ABRT_SBYTE_ACKDET     BIT(7)\n+#define DW_IC_TX_ABRT_HS_ACKDET        BIT(6)\n+#define DW_IC_TX_ABRT_GCALL_READ       BIT(5)\n+#define DW_IC_TX_ABRT_GCALL_NOACK      BIT(4)\n+#define DW_IC_TX_ABRT_TXDATA_NOACK     BIT(3)\n+#define DW_IC_TX_ABRT_10ADDR2_NOACK    BIT(2)\n+#define DW_IC_TX_ABRT_10ADDR1_NOACK    BIT(1)\n+#define DW_IC_TX_ABRT_7B_ADDR_NOACK    BIT(0)\n+\n+\n+/* IC_ENABLE_STATUS fields */\n+#define DW_IC_ENABLE_STATUS_SLV_RX_DATA_LOST         BIT(2)\n+#define DW_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY  BIT(1)\n+#define DW_IC_ENABLE_STATUS_IC_EN                    BIT(0)\n+\n+/* Masks for writable registers. */\n+#define DW_IC_CON_MASK          0x000003ff\n+#define DW_IC_TAR_MASK          0x00000fff\n+#define DW_IC_SAR_MASK          0x000003ff\n+#define DW_IC_SS_SCL_HCNT_MASK  0x0000ffff\n+#define DW_IC_SS_SCL_LCNT_MASK  0x0000ffff\n+#define DW_IC_FS_SCL_HCNT_MASK  0x0000ffff\n+#define DW_IC_FS_SCL_LCNT_MASK  0x0000ffff\n+#define DW_IC_INTR_MASK_MASK    0x00001fff\n+#define DW_IC_ENABLE_MASK       0x00000007\n+#define DW_IC_SDA_HOLD_MASK     0x00ffffff\n+#define DW_IC_SDA_SETUP_MASK    0x000000ff\n+#define DW_IC_FS_SPKLEN_MASK    0x000000ff\n+\n+/* Reset values */\n+#define DW_IC_CON_INIT_VAL          0x7d\n+#define DW_IC_TAR_INIT_VAL          0x1055\n+#define DW_IC_SAR_INIT_VAL          0x55\n+#define DW_IC_SS_SCL_HCNT_INIT_VAL  0x190\n+#define DW_IC_SS_SCL_LCNT_INIT_VAL  0x1d6\n+#define DW_IC_FS_SCL_HCNT_INIT_VAL  0x3c\n+#define DW_IC_FS_SCL_LCNT_INIT_VAL  0x82\n+#define DW_IC_INTR_MASK_INIT_VAL    0x8ff\n+#define DW_IC_STATUS_INIT_VAL       0x6\n+#define DW_IC_SDA_HOLD_INIT_VAL     0x1\n+#define DW_IC_SDA_SETUP_INIT_VAL    0x64\n+#define DW_IC_FS_SPKLEN_INIT_VAL    0x2\n+\n+#define DW_IC_COMP_PARAM_1_HAS_ENCODED_PARAMS   BIT(7)\n+#define DW_IC_COMP_PARAM_1_HAS_DMA              0 /* bit 6 - DMA disabled. */\n+#define DW_IC_COMP_PARAM_1_INTR_IO              BIT(5)\n+#define DW_IC_COMP_PARAM_1_HC_COUNT_VAL         0 /* bit 4 - disabled */\n+#define DW_IC_COMP_PARAM_1_HIGH_SPEED_MODE      (BIT(2) | BIT(3))\n+#define DW_IC_COMP_PARAM_1_APB_DATA_WIDTH_32    BIT(1) /* bits 0, 1 */\n+#define DW_IC_COMP_PARAM_1_INIT_VAL             \\\n+    (DW_IC_COMP_PARAM_1_APB_DATA_WIDTH_32 | \\\n+    DW_IC_COMP_PARAM_1_HIGH_SPEED_MODE | \\\n+    DW_IC_COMP_PARAM_1_HC_COUNT_VAL | \\\n+    DW_IC_COMP_PARAM_1_INTR_IO | \\\n+    DW_IC_COMP_PARAM_1_HAS_DMA | \\\n+    DW_IC_COMP_PARAM_1_HAS_ENCODED_PARAMS | \\\n+    ((DESIGNWARE_I2C_RX_FIFO_SIZE - 1) << 8) | \\\n+    ((DESIGNWARE_I2C_TX_FIFO_SIZE - 1) << 16))\n+#define DW_IC_COMP_VERSION_INIT_VAL             0x3132302a\n+#define DW_IC_COMP_TYPE_INIT_VAL                0x44570140\n+\n+static void dw_i2c_update_irq(DesignWareI2CState *s)\n+{\n+    int level;\n+    uint32_t intr = s->ic_raw_intr_stat & s->ic_intr_mask;\n+\n+    level = !!((intr & DW_IC_INTR_RX_UNDER) |\n+        (intr & DW_IC_INTR_RX_OVER) |\n+        (intr & DW_IC_INTR_RX_FULL) |\n+        (intr & DW_IC_INTR_TX_OVER) |\n+        (intr & DW_IC_INTR_TX_EMPTY) |\n+        (intr & DW_IC_INTR_RD_REQ) |\n+        (intr & DW_IC_INTR_TX_ABRT) |\n+        (intr & DW_IC_INTR_RX_DONE) |\n+        (intr & DW_IC_INTR_ACTIVITY) |\n+        (intr & DW_IC_INTR_STOP_DET) |\n+        (intr & DW_IC_INTR_START_DET) |\n+        (intr & DW_IC_INTR_GEN_CALL) |\n+        (intr & DW_IC_INTR_RESTART_DET)\n+        );\n+    qemu_set_irq(s->irq, level);\n+}\n+\n+static uint32_t dw_i2c_read_ic_data_cmd(DesignWareI2CState *s)\n+{\n+    uint32_t value = s->rx_fifo[s->rx_cur];\n+\n+    if (s->status != DW_I2C_STATUS_RECEIVING) {\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: Attempted to read from RX fifo when not in receive \"\n+                      \"state.\\n\", DEVICE(s)->canonical_path);\n+        if (s->status != DW_I2C_STATUS_IDLE) {\n+            s->ic_raw_intr_stat &= ~DW_IC_INTR_RX_UNDER;\n+            dw_i2c_update_irq(s);\n+        }\n+        return 0;\n+    }\n+\n+    s->rx_cur = (s->rx_cur + 1) % DESIGNWARE_I2C_RX_FIFO_SIZE;\n+\n+    if (s->ic_rxflr > 0) {\n+        s->ic_rxflr--;\n+    } else {\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_RX_UNDER;\n+        dw_i2c_update_irq(s);\n+        return 0;\n+    }\n+\n+    if (s->ic_rxflr <= s->ic_rx_tl) {\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_RX_FULL;\n+        dw_i2c_update_irq(s);\n+    }\n+\n+    return value;\n+}\n+\n+static uint64_t dw_i2c_read(void *opaque, hwaddr offset, unsigned size)\n+{\n+    uint64_t value = 0;\n+\n+    DesignWareI2CState *s = opaque;\n+\n+    switch (offset) {\n+    case DW_IC_CON:\n+        value = s->ic_con;\n+        break;\n+    case DW_IC_TAR:\n+        value = s->ic_tar;\n+        break;\n+    case DW_IC_SAR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported read - ic_sar\\n\",\n+                      DEVICE(s)->canonical_path);\n+        value = s->ic_sar;\n+        break;\n+    case DW_IC_DATA_CMD:\n+        value = dw_i2c_read_ic_data_cmd(s);\n+        break;\n+    case DW_IC_SS_SCL_HCNT:\n+        value = s->ic_ss_scl_hcnt;\n+        break;\n+    case DW_IC_SS_SCL_LCNT:\n+        value = s->ic_ss_scl_lcnt;\n+        break;\n+    case DW_IC_FS_SCL_HCNT:\n+        value = s->ic_fs_scl_hcnt;\n+        break;\n+    case DW_IC_FS_SCL_LCNT:\n+        value = s->ic_fs_scl_lcnt;\n+        break;\n+    case DW_IC_INTR_STAT:\n+        value = s->ic_raw_intr_stat & s->ic_intr_mask;\n+        break;\n+    case DW_IC_INTR_MASK:\n+        value = s->ic_intr_mask;\n+        break;\n+    case DW_IC_RAW_INTR_STAT:\n+        value = s->ic_raw_intr_stat;\n+        break;\n+    case DW_IC_RX_TL:\n+        value = s->ic_rx_tl;\n+        break;\n+    case DW_IC_TX_TL:\n+        value = s->ic_tx_tl;\n+        break;\n+    case DW_IC_CLR_INTR:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_GEN_CALL |\n+            DW_IC_INTR_RESTART_DET |\n+            DW_IC_INTR_START_DET |\n+            DW_IC_INTR_STOP_DET |\n+            DW_IC_INTR_ACTIVITY |\n+            DW_IC_INTR_RX_DONE |\n+            DW_IC_INTR_TX_ABRT |\n+            DW_IC_INTR_RD_REQ |\n+            DW_IC_INTR_TX_OVER |\n+            DW_IC_INTR_RX_OVER |\n+            DW_IC_INTR_RX_UNDER);\n+        s->ic_tx_abrt_source = 0;\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_RX_UNDER:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_RX_UNDER);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_RX_OVER:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_RX_OVER);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_TX_OVER:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_TX_OVER);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_RD_REQ:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_RD_REQ);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_TX_ABRT:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_TX_ABRT);\n+        s->ic_tx_abrt_source = 0;\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_RX_DONE:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_RX_DONE);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_ACTIVITY:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_ACTIVITY);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_STOP_DET:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_STOP_DET);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_START_DET:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_START_DET);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_CLR_GEN_CALL:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_GEN_CALL);\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_ENABLE:\n+        value = s->ic_enable;\n+        break;\n+    case DW_IC_STATUS:\n+        value = s->ic_status;\n+        break;\n+    case DW_IC_TXFLR:\n+        value = s->ic_txflr;\n+        break;\n+    case DW_IC_RXFLR:\n+        value = s->ic_rxflr;\n+        break;\n+    case DW_IC_SDA_HOLD:\n+        value = s->ic_sda_hold;\n+        break;\n+    case DW_IC_TX_ABRT_SOURCE:\n+        value = s->ic_tx_abrt_source;\n+        break;\n+    case DW_IC_SLV_DATA_NACK_ONLY:\n+        qemu_log_mask(LOG_UNIMP,\n+                      \"%s: unsupported read - ic_slv_data_nack_only\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_DMA_CR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported read - ic_dma_cr\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_DMA_TDLR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported read - ic_dma_tdlr\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_DMA_RDLR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported read - ic_dma_rdlr\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_SDA_SETUP:\n+        value = s->ic_sda_setup;\n+        break;\n+    case DW_IC_ACK_GENERAL_CALL:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported read - ic_ack_general_call\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_ENABLE_STATUS:\n+        value = s->ic_enable_status;\n+        break;\n+    case DW_IC_FS_SPKLEN:\n+        value = s->ic_fs_spklen;\n+        break;\n+    case DW_IC_CLR_RESTART_DET:\n+        s->ic_raw_intr_stat &= ~(DW_IC_INTR_RESTART_DET);\n+        break;\n+    case DW_IC_COMP_PARAM_1:\n+        value = s->ic_comp_param_1;\n+        break;\n+    case DW_IC_COMP_VERSION:\n+        value = s->ic_comp_version;\n+        break;\n+    case DW_IC_COMP_TYPE:\n+        value = s->ic_comp_type;\n+        break;\n+\n+    /* This register is invalid at this point. */\n+    default:\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: read from invalid offset 0x%\" HWADDR_PRIx \"\\n\",\n+                      DEVICE(s)->canonical_path, offset);\n+        break;\n+    }\n+\n+    trace_dw_i2c_read(DEVICE(s)->canonical_path, offset, value);\n+\n+    return value;\n+}\n+\n+static void dw_i2c_write_ic_con(DesignWareI2CState *s, uint32_t value)\n+{\n+    if (value & DW_IC_CON_RX_FIFO_FULL_HLD_CTRL) {\n+        qemu_log_mask(LOG_UNIMP,\n+                      \"%s: unsupported ic_con flag - RX_FIFO_FULL_HLD_CTRL\\n\",\n+                      DEVICE(s)->canonical_path);\n+    }\n+\n+    if (!(s->ic_enable & DW_IC_ENABLE_ENABLE)) {\n+        s->ic_con = value & DW_IC_CON_MASK;\n+    } else {\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: invalid setting to ic_con %d when ic_enable[0]==1\\n\",\n+                      DEVICE(s)->canonical_path, value);\n+    }\n+}\n+\n+static void dw_i2c_reset_to_idle(DesignWareI2CState *s)\n+{\n+        s->ic_enable_status &= ~DW_IC_ENABLE_STATUS_IC_EN;\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_TX_EMPTY;\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_RX_FULL;\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_RX_UNDER;\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_RX_OVER;\n+        s->ic_rxflr = 0;\n+        s->ic_status &= ~DW_IC_STATUS_ACTIVITY;\n+        s->status = DW_I2C_STATUS_IDLE;\n+        dw_i2c_update_irq(s);\n+}\n+\n+static void dw_ic_tx_abort(DesignWareI2CState *s, uint32_t src)\n+{\n+    s->ic_tx_abrt_source |= src;\n+    s->ic_raw_intr_stat |= DW_IC_INTR_TX_ABRT;\n+    dw_i2c_reset_to_idle(s);\n+    dw_i2c_update_irq(s);\n+}\n+\n+static void dw_i2c_write_ic_data_cmd(DesignWareI2CState *s, uint32_t value)\n+{\n+    int recv = !!(value & DW_IC_DATA_CMD_CMD);\n+\n+    if (s->status == DW_I2C_STATUS_IDLE ||\n+        s->ic_raw_intr_stat & DW_IC_INTR_TX_ABRT) {\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: Attempted to write to TX fifo when it is held in \"\n+                      \"reset.\\n\", DEVICE(s)->canonical_path);\n+        return;\n+    }\n+\n+    /* Send the address if it hasn't been sent yet. */\n+    if (s->status == DW_I2C_STATUS_SENDING_ADDRESS) {\n+        int rv = i2c_start_transfer(s->bus, DW_IC_TAR_ADDRESS(s->ic_tar), recv);\n+        if (rv) {\n+            dw_ic_tx_abort(s, DW_IC_TX_ABRT_7B_ADDR_NOACK);\n+            return;\n+        }\n+        s->status = recv ? DW_I2C_STATUS_RECEIVING : DW_I2C_STATUS_SENDING;\n+    }\n+\n+    /* Send data */\n+    if (!recv) {\n+        int rv = i2c_send(s->bus, DW_IC_DATA_CMD_DAT(value));\n+        if (rv) {\n+            i2c_end_transfer(s->bus);\n+            dw_ic_tx_abort(s, DW_IC_TX_ABRT_TXDATA_NOACK);\n+            return;\n+        }\n+        dw_i2c_update_irq(s);\n+    }\n+\n+    /* Restart command */\n+    if (value & DW_IC_DATA_CMD_RESTART && s->ic_con & DW_IC_CON_IC_RESTART_EN) {\n+        s->ic_raw_intr_stat |= DW_IC_INTR_RESTART_DET |\n+                               DW_IC_INTR_START_DET |\n+                               DW_IC_INTR_ACTIVITY;\n+        s->ic_status |= DW_IC_STATUS_ACTIVITY;\n+        dw_i2c_update_irq(s);\n+\n+        if (i2c_start_transfer(s->bus, DW_IC_TAR_ADDRESS(s->ic_tar), recv)) {\n+            dw_ic_tx_abort(s, DW_IC_TX_ABRT_7B_ADDR_NOACK);\n+            return;\n+        }\n+\n+        s->status = recv ? DW_I2C_STATUS_RECEIVING : DW_I2C_STATUS_SENDING;\n+    }\n+\n+    /* Receive data */\n+    if (recv) {\n+        uint8_t pos = (s->rx_cur + s->ic_rxflr) % DESIGNWARE_I2C_RX_FIFO_SIZE;\n+\n+        if (s->ic_rxflr < DESIGNWARE_I2C_RX_FIFO_SIZE) {\n+            s->rx_fifo[pos] = i2c_recv(s->bus);\n+            s->ic_rxflr++;\n+        } else {\n+            s->ic_raw_intr_stat |= DW_IC_INTR_RX_OVER;\n+            dw_i2c_update_irq(s);\n+        }\n+\n+        if (s->ic_rxflr > s->ic_rx_tl) {\n+            s->ic_raw_intr_stat |= DW_IC_INTR_RX_FULL;\n+            dw_i2c_update_irq(s);\n+        }\n+        if (value & DW_IC_DATA_CMD_STOP) {\n+            i2c_nack(s->bus);\n+        }\n+    }\n+\n+    /* Stop command */\n+    if (value & DW_IC_DATA_CMD_STOP) {\n+        s->ic_raw_intr_stat |= DW_IC_INTR_STOP_DET;\n+        s->ic_status &= ~DW_IC_STATUS_ACTIVITY;\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_TX_EMPTY;\n+        i2c_end_transfer(s->bus);\n+        dw_i2c_update_irq(s);\n+    }\n+}\n+\n+static void dw_i2c_write_ic_enable(DesignWareI2CState *s, uint32_t value)\n+{\n+    if (value & DW_IC_ENABLE_ENABLE && !(s->ic_con & DW_IC_CON_SLAVE_DISABLE)) {\n+        qemu_log_mask(LOG_UNIMP,\n+                      \"%s: Designware I2C slave mode is not supported.\\n\",\n+                      DEVICE(s)->canonical_path);\n+        return;\n+    }\n+\n+    s->ic_enable = value & DW_IC_ENABLE_MASK;\n+\n+    if (value & DW_IC_ENABLE_ABORT || value & DW_IC_ENABLE_TX_CMD_BLOCK) {\n+        dw_ic_tx_abort(s, DW_IC_TX_ABRT_USER_ABRT);\n+        return;\n+    }\n+\n+    if (value & DW_IC_ENABLE_ENABLE) {\n+        s->ic_enable_status |= DW_IC_ENABLE_STATUS_IC_EN;\n+        s->ic_status |= DW_IC_STATUS_ACTIVITY;\n+        s->ic_raw_intr_stat |= DW_IC_INTR_ACTIVITY |\n+                               DW_IC_INTR_START_DET |\n+                               DW_IC_INTR_TX_EMPTY;\n+        s->status = DW_I2C_STATUS_SENDING_ADDRESS;\n+        dw_i2c_update_irq(s);\n+    } else if ((value & DW_IC_ENABLE_ENABLE) == 0) {\n+        dw_i2c_reset_to_idle(s);\n+    }\n+\n+}\n+\n+static void dw_i2c_write_ic_rx_tl(DesignWareI2CState *s, uint32_t value)\n+{\n+    /* Note that a value of 0 for ic_rx_tl indicates a threashold of 1. */\n+    if (value > DESIGNWARE_I2C_RX_FIFO_SIZE - 1) {\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: invalid setting to ic_rx_tl %d\\n\",\n+                      DEVICE(s)->canonical_path, value);\n+        s->ic_rx_tl = DESIGNWARE_I2C_RX_FIFO_SIZE - 1;\n+    } else {\n+        s->ic_rx_tl = value;\n+    }\n+\n+    if (s->ic_rxflr > s->ic_rx_tl && s->ic_enable & DW_IC_ENABLE_ENABLE) {\n+        s->ic_raw_intr_stat |= DW_IC_INTR_RX_FULL;\n+    } else {\n+        s->ic_raw_intr_stat &= ~DW_IC_INTR_RX_FULL;\n+    }\n+    dw_i2c_update_irq(s);\n+}\n+\n+static void dw_i2c_write_ic_tx_tl(DesignWareI2CState *s, uint32_t value)\n+{\n+    /*\n+     * Note that a value of 0 for ic_tx_tl indicates a threashold of 1.\n+     * However, the tx threshold is not used in the model because commands are\n+     * always sent out as soon as they are written.\n+     */\n+    if (value > DESIGNWARE_I2C_TX_FIFO_SIZE - 1) {\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: invalid setting to ic_tx_tl %d\\n\",\n+                      DEVICE(s)->canonical_path, value);\n+        s->ic_tx_tl = DESIGNWARE_I2C_TX_FIFO_SIZE - 1;\n+    } else {\n+        s->ic_tx_tl = value;\n+    }\n+}\n+\n+static void dw_i2c_write(void *opaque, hwaddr offset, uint64_t value,\n+                              unsigned size)\n+{\n+    DesignWareI2CState *s = opaque;\n+\n+    trace_dw_i2c_write(DEVICE(s)->canonical_path, offset, value);\n+\n+    /* The order of the registers are their order in memory. */\n+    switch (offset) {\n+    case DW_IC_CON:\n+        dw_i2c_write_ic_con(s, value);\n+        break;\n+    case DW_IC_TAR:\n+        s->ic_tar = value & DW_IC_TAR_MASK;\n+        break;\n+    case DW_IC_SAR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported write - ic_sar\\n\",\n+                      DEVICE(s)->canonical_path);\n+        s->ic_sar = value & DW_IC_SAR_MASK;\n+        break;\n+    case DW_IC_DATA_CMD:\n+        dw_i2c_write_ic_data_cmd(s, value);\n+        break;\n+    case DW_IC_SS_SCL_HCNT:\n+        s->ic_ss_scl_hcnt = value & DW_IC_SS_SCL_HCNT_MASK;\n+        break;\n+    case DW_IC_SS_SCL_LCNT:\n+        s->ic_ss_scl_lcnt = value & DW_IC_SS_SCL_LCNT_MASK;\n+        break;\n+    case DW_IC_FS_SCL_HCNT:\n+        s->ic_fs_scl_hcnt = value & DW_IC_FS_SCL_HCNT_MASK;\n+        break;\n+    case DW_IC_FS_SCL_LCNT:\n+        s->ic_fs_scl_lcnt = value & DW_IC_FS_SCL_LCNT_MASK;\n+        break;\n+    case DW_IC_INTR_MASK:\n+        s->ic_intr_mask = value & DW_IC_INTR_MASK_MASK;\n+        dw_i2c_update_irq(s);\n+        break;\n+    case DW_IC_RX_TL:\n+        dw_i2c_write_ic_rx_tl(s, value);\n+        break;\n+    case DW_IC_TX_TL:\n+        dw_i2c_write_ic_tx_tl(s, value);\n+        break;\n+    case DW_IC_ENABLE:\n+        dw_i2c_write_ic_enable(s, value);\n+        break;\n+    case DW_IC_SDA_HOLD:\n+        s->ic_sda_hold = value & DW_IC_SDA_HOLD_MASK;\n+        break;\n+    case DW_IC_SLV_DATA_NACK_ONLY:\n+        qemu_log_mask(LOG_UNIMP,\n+                      \"%s: unsupported write - ic_slv_data_nack_only\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_DMA_CR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported write - ic_dma_cr\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_DMA_TDLR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported write - ic_dma_tdlr\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_DMA_RDLR:\n+        qemu_log_mask(LOG_UNIMP, \"%s: unsupported write - ic_dma_rdlr\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_SDA_SETUP:\n+        s->ic_sda_setup = value & DW_IC_SDA_SETUP_MASK;\n+        break;\n+    case DW_IC_ACK_GENERAL_CALL:\n+        qemu_log_mask(LOG_UNIMP,\n+                      \"%s: unsupported write - ic_ack_general_call\\n\",\n+                      DEVICE(s)->canonical_path);\n+        break;\n+    case DW_IC_FS_SPKLEN:\n+        s->ic_fs_spklen = value & DW_IC_FS_SPKLEN_MASK;\n+        break;\n+\n+    /* This register is invalid at this point. */\n+    default:\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: write to invalid offset or readonly register 0x%\"\n+                      HWADDR_PRIx \"\\n\",\n+                      DEVICE(s)->canonical_path, offset);\n+        break;\n+    }\n+}\n+\n+static const MemoryRegionOps designware_i2c_ops = {\n+    .read = dw_i2c_read,\n+    .write = dw_i2c_write,\n+    .endianness = DEVICE_LITTLE_ENDIAN,\n+    .valid = {\n+        .min_access_size = 4,\n+        .max_access_size = 4,\n+        .unaligned = false,\n+    },\n+};\n+\n+static void designware_i2c_enter_reset(Object *obj, ResetType type)\n+{\n+    DesignWareI2CState *s = DESIGNWARE_I2C(obj);\n+\n+    s->ic_con = DW_IC_CON_INIT_VAL;\n+    s->ic_tar = DW_IC_TAR_INIT_VAL;\n+    s->ic_sar = DW_IC_SAR_INIT_VAL;\n+    s->ic_ss_scl_hcnt = DW_IC_SS_SCL_HCNT_INIT_VAL;\n+    s->ic_ss_scl_lcnt = DW_IC_SS_SCL_LCNT_INIT_VAL;\n+    s->ic_fs_scl_hcnt = DW_IC_FS_SCL_HCNT_INIT_VAL;\n+    s->ic_fs_scl_lcnt = DW_IC_FS_SCL_LCNT_INIT_VAL;\n+    s->ic_intr_mask = DW_IC_INTR_MASK_INIT_VAL;\n+    s->ic_raw_intr_stat = 0;\n+    s->ic_rx_tl = 0;\n+    s->ic_tx_tl = 0;\n+    s->ic_enable = 0;\n+    s->ic_status = DW_IC_STATUS_INIT_VAL;\n+    s->ic_txflr = 0;\n+    s->ic_rxflr = 0;\n+    s->ic_sda_hold = DW_IC_SDA_HOLD_INIT_VAL;\n+    s->ic_tx_abrt_source = 0;\n+    s->ic_sda_setup = DW_IC_SDA_SETUP_INIT_VAL;\n+    s->ic_enable_status = 0;\n+    s->ic_fs_spklen = DW_IC_FS_SPKLEN_INIT_VAL;\n+    s->ic_comp_param_1 = DW_IC_COMP_PARAM_1_INIT_VAL;\n+    s->ic_comp_version = DW_IC_COMP_VERSION_INIT_VAL;\n+    s->ic_comp_type = DW_IC_COMP_TYPE_INIT_VAL;\n+\n+    s->rx_cur = 0;\n+    s->status = DW_I2C_STATUS_IDLE;\n+}\n+\n+static void designware_i2c_hold_reset(Object *obj, ResetType type)\n+{\n+    DesignWareI2CState *s = DESIGNWARE_I2C(obj);\n+\n+    qemu_irq_lower(s->irq);\n+}\n+\n+static const VMStateDescription vmstate_designware_i2c = {\n+    .name = TYPE_DESIGNWARE_I2C,\n+    .version_id = 0,\n+    .minimum_version_id = 0,\n+    .fields = (VMStateField[]) {\n+        VMSTATE_UINT32(ic_con, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_tar, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_sar, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_ss_scl_hcnt, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_ss_scl_lcnt, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_fs_scl_hcnt, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_fs_scl_lcnt, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_intr_mask, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_raw_intr_stat, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_rx_tl, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_tx_tl, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_enable, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_status, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_txflr, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_rxflr, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_sda_hold, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_tx_abrt_source, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_sda_setup, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_enable_status, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_fs_spklen, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_comp_param_1, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_comp_version, DesignWareI2CState),\n+        VMSTATE_UINT32(ic_comp_type, DesignWareI2CState),\n+        VMSTATE_UINT32(status, DesignWareI2CState),\n+        VMSTATE_UINT8_ARRAY(rx_fifo, DesignWareI2CState,\n+                        DESIGNWARE_I2C_RX_FIFO_SIZE),\n+        VMSTATE_UINT8(rx_cur, DesignWareI2CState),\n+        VMSTATE_END_OF_LIST(),\n+    },\n+};\n+\n+static void designware_i2c_smbus_init(Object *obj)\n+{\n+    DesignWareI2CState *s = DESIGNWARE_I2C(obj);\n+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);\n+\n+    sysbus_init_irq(sbd, &s->irq);\n+\n+    memory_region_init_io(&s->iomem, obj, &designware_i2c_ops, s,\n+                          \"regs\", 4 * KiB);\n+    sysbus_init_mmio(sbd, &s->iomem);\n+\n+    s->bus = i2c_init_bus(DEVICE(s), \"i2c-bus\");\n+}\n+\n+static void designware_i2c_class_init(ObjectClass *klass, const void *data)\n+{\n+    ResettableClass *rc = RESETTABLE_CLASS(klass);\n+    DeviceClass *dc = DEVICE_CLASS(klass);\n+\n+    dc->desc = \"Designware I2C\";\n+    dc->vmsd = &vmstate_designware_i2c;\n+    rc->phases.enter = designware_i2c_enter_reset;\n+    rc->phases.hold = designware_i2c_hold_reset;\n+}\n+\n+static const TypeInfo designware_i2c_types[] = {\n+    {\n+        .name = TYPE_DESIGNWARE_I2C,\n+        .parent = TYPE_SYS_BUS_DEVICE,\n+        .instance_size = sizeof(DesignWareI2CState),\n+        .class_init = designware_i2c_class_init,\n+        .instance_init = designware_i2c_smbus_init,\n+    },\n+};\n+DEFINE_TYPES(designware_i2c_types);\ndiff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig\nindex 596a7a3165ad..d3f394edeb9c 100644\n--- a/hw/i2c/Kconfig\n+++ b/hw/i2c/Kconfig\n@@ -18,6 +18,10 @@ config ARM_SBCON_I2C\n     bool\n     select BITBANG_I2C\n \n+config DESIGNWARE_I2C\n+    bool\n+    select I2C\n+\n config ACPI_SMBUS\n     bool\n     select SMBUS\ndiff --git a/hw/i2c/meson.build b/hw/i2c/meson.build\nindex c459adcb596c..88aea35662dd 100644\n--- a/hw/i2c/meson.build\n+++ b/hw/i2c/meson.build\n@@ -11,6 +11,7 @@ i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))\n i2c_ss.add(when: 'CONFIG_ALLWINNER_I2C', if_true: files('allwinner-i2c.c'))\n i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))\n i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c'))\n+i2c_ss.add(when: 'CONFIG_DESIGNWARE_I2C', if_true: files('designware_i2c.c'))\n i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c'))\n i2c_ss.add(when: 'CONFIG_ARM_SBCON_I2C', if_true: files('arm_sbcon_i2c.c'))\n i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c'))\ndiff --git a/hw/i2c/trace-events b/hw/i2c/trace-events\nindex 1ad0e95c0e60..8a78d2d3c8de 100644\n--- a/hw/i2c/trace-events\n+++ b/hw/i2c/trace-events\n@@ -61,3 +61,7 @@ pca954x_read_data(uint8_t value) \"PCA954X read data: 0x%02x\"\n \n imx_i2c_read(const char *id, const char *reg, uint64_t ofs, uint64_t value) \"%s:[%s (0x%\" PRIx64 \")] -> 0x%02\" PRIx64\n imx_i2c_write(const char *id, const char *reg, uint64_t ofs, uint64_t value) \"%s:[%s (0x%\" PRIx64 \")] <- 0x%02\" PRIx64\n+\n+# designware_i2c.c\n+dw_i2c_read(const char *id, uint64_t ofs, uint64_t value) \"%s: offset 0x%02\" PRIx64 \" -> value: 0x%02\" PRIx64\n+dw_i2c_write(const char *id, uint64_t ofs, uint64_t value) \"%s: offset: 0x%02\" PRIx64 \" <- value: 0x%02\" PRIx64\n",
    "prefixes": [
        "v3",
        "01/13"
    ]
}