get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2223378,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2223378/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260415073341.690754-1-joel@jms.id.au/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/1.2/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": "<20260415073341.690754-1-joel@jms.id.au>",
    "list_archive_url": null,
    "date": "2026-04-15T07:33:31",
    "name": "[v2] 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/1.2/people/48628/?format=api",
        "name": "Joel Stanley",
        "email": "joel@jms.id.au"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260415073341.690754-1-joel@jms.id.au/mbox/",
    "series": [
        {
            "id": 499937,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/499937/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=499937",
            "date": "2026-04-15T07:33:31",
            "name": "[v2] hw/i2c: Add designware i2c controller",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/499937/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2223378/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2223378/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=SsIWmQXf;\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 4fwXxB5QqGz1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 15 Apr 2026 17:35:25 +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 1wCulN-0008A0-OG; Wed, 15 Apr 2026 03:34:18 -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 1wCulL-00089C-K6\n for qemu-devel@nongnu.org; Wed, 15 Apr 2026 03:34:15 -0400",
            "from mail-pj1-x1030.google.com ([2607:f8b0:4864:20::1030])\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 1wCulH-0003vM-GB\n for qemu-devel@nongnu.org; Wed, 15 Apr 2026 03:34:15 -0400",
            "by mail-pj1-x1030.google.com with SMTP id\n 98e67ed59e1d1-35d99bae2ebso5502099a91.3\n for <qemu-devel@nongnu.org>; Wed, 15 Apr 2026 00:34:11 -0700 (PDT)",
            "from donnager-debian.. ([45.124.203.19])\n by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-35fd308cf98sm1072994a91.7.2026.04.15.00.34.04\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 15 Apr 2026 00:34:09 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1776238450; x=1776843250; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:sender:from:to:cc:subject:date:message-id:reply-to;\n bh=4DmJnDS2TtvtZ5B5Vy2jF/Xa5Ct3BX4VbnR5p9AoeB4=;\n b=SsIWmQXf1ufcgPzU10d85Vh1MEBoO0G4Lr1vjvuS33t6Q01Y7/FjU3JFzY4ei4QOqC\n YF/hLI0lBR3UbGV0Sky+mPdTpr5TAmW7epqMgbfBFcILB1Y20fvZfKZONR1DSP/3iKPL\n Ob+BjjCN8warSqKPd7FAbtfeLIxPbZmPjPpF3GWcixLsluVP8tG91LWukrEJdRHouWon\n zKHvBRtZVr9b7uHHS+TqjdszzWWK4a69at/smweYXqsCruNqV/6vU++sWTsIzBAuX6Q3\n qSlw3/CaUwCKc23uhIJABc0b1dh/RIAzpK1Z2K+DGG2/174LTirGCVgYK9z8zNaGfeTc\n XmGw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776238450; x=1776843250;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:sender:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=4DmJnDS2TtvtZ5B5Vy2jF/Xa5Ct3BX4VbnR5p9AoeB4=;\n b=Aj/4SauqK9EW8oFAEwygjxas4sXAzU5O/Vion7YUnr3xyYpxUm18lLdNu7LyC5n8TO\n fNU6Ns2H4TLY6oGqo1wbzWOLlpi4jc3Bd60+N2RtsNoGJB0qT81hhKvKk8lPnj3eIzD7\n gCFrU3cY6w3Frc4RfLZ6+QFxUDvVQFeup7sqAtwfmmpUaxqsouQrORzc/d2Nb/RdzVpP\n 13rJhqYR8k0jsv6MuH5jjihZZMaN4aq0anMG1xsuqDiokmk+pfXSV2lV5GjU/e/5e5rU\n Z2KZDwr3hhfycL5vHzrlCotOwIZyaYvErYpSJ4T6dh9PDveE1XwMdcUzOwJIrB+1CO1C\n qw3A==",
        "X-Gm-Message-State": "AOJu0YyzjKK3Ro4u2vCAvyv4mE/Q7iXRuxykjFnNvgIYP0pxxFXNpa4F\n K8dDv+G3nq5i3C16soW0bFMlmie/utqUP9WWCSCoFo1L3lwPWqgVBOCOKoekCRKW",
        "X-Gm-Gg": "AeBDieuDCqS6AWXqT+5CSrokbFnXXtbI+TAbwgMDyXIvIb3J2aDSWqGqFvAeVVDVYcg\n JYO3Htjt2Wi3LGYziaSN6stOaxMIUYU7jLo4uMJS0cTfKEgC6AuH/xZ4uGqKa9Ur3uBdJXpDdaw\n Vty++w27o18rCiDZvz8MOK33kMmjJBf36dkCjQrHoRq0qTrAGABA56q292JQHcnDGeolQRCD0ln\n 7HfMIYe+QF+uT4XIHwjVBffsXJYoADcnamKpcHUSRs+f61sB3mPMK6lrsUKOt6UK2s077Nwj3VE\n Ws7ujXBG9gYQ7I6YusaiUo0o1NecSFeFIYgo4uIePFv9XiKBJvHPJH9zc7+oUyTOmxI6ax/4KCr\n LSCLFtxO7FaNzy0zC3qfGFjYmT4mg2wbfFXdprbft5ArNZzS9HSvh+YrcWqfsVj4jjYGUfElW6O\n yHlR2ppM/HgoFlVcbbLAezlLWhvRM1AWcKeeZKiJ1njGphjVwjGvJY20UnDuQ+5vozOAblDF4Qs\n pA2Z8hqmhLLn//iPUiDKw==",
        "X-Received": "by 2002:a17:90b:4c0c:b0:35f:b306:5d47 with SMTP id\n 98e67ed59e1d1-35fb306602emr12292873a91.1.1776238449667;\n Wed, 15 Apr 2026 00:34:09 -0700 (PDT)",
        "From": "Joel Stanley <joel@jms.id.au>",
        "To": "qemu-devel@nongnu.org, Alistair Francis <alistair.francis@wdc.com>,\n Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>",
        "Cc": "Chris Rauer <crauer@google.com>, Paolo Bonzini <pbonzini@redhat.com>,\n Alano Song <alanosong@163.com>, qemu-riscv@nongnu.org,\n Hao Wu <wuhaotsh@google.com>",
        "Subject": "[PATCH v2] hw/i2c: Add designware i2c controller",
        "Date": "Wed, 15 Apr 2026 17:33:31 +1000",
        "Message-ID": "<20260415073341.690754-1-joel@jms.id.au>",
        "X-Mailer": "git-send-email 2.47.3",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Received-SPF": "pass client-ip=2607:f8b0:4864:20::1030;\n envelope-from=joel.stan@gmail.com; helo=mail-pj1-x1030.google.com",
        "X-Spam_score_int": "-17",
        "X-Spam_score": "-1.8",
        "X-Spam_bar": "-",
        "X-Spam_report": "(-1.8 / 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.248,\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\nThis supersedes my v1 submission as well as Alano's similar submission\nfrom January:\n\n https://lore.kernel.org/qemu-devel/20260106131253.16192-1-AlanoSong@163.com/\n\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": [
        "v2"
    ]
}