From nobody Fri May 17 01:12:43 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1611882484; cv=none; d=zohomail.com; s=zohoarc; b=NQksXEtY1yi6h+Xhkv28saFz0tyMpPsIx+npWU7ZV4oHszT5JkI14C00VzstJ1VCJzLzh0nNzL76EUOyqFy9UR3CIqE8u4ToJ4w3AqBS0scoZjaUzJk2ZHWbKEVHO2c0WUl2FkFjn8lciuOUmYZmDaBoV9ZmPcgFdIXXkxyrThw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1611882484; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=MXpYq4rGrYnKEV9MTkJ+FJRm52fVhSZVjQB4Boy0H48=; b=cqol6v7KZ4aSDDkLcBTGSpFpGqIZUNTNUgCAxyNSZGdskJR/oORJRDXeHe3VHiXR4eT/TlZLbCO9r0KCkFbb97bkrUuqKwIHnz6o+vEifWwZPw9E+linAgmR7rGP+x1frwBBjnYXt8XXgXzqF0WCtzq1jb8fOGV8MAHAK9XiARI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1611882484773548.2158797250789; Thu, 28 Jan 2021 17:08:04 -0800 (PST) Received: from localhost ([::1]:56090 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l5IGZ-0007Bx-NO for importer@patchew.org; Thu, 28 Jan 2021 20:08:03 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:55572) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3CF8TYAgKChsNL81FKJ87FF7C5.3FDH5DL-45M5CEFE7EL.FI7@flex--wuhaotsh.bounces.google.com>) id 1l5ICs-00031A-Cs for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:14 -0500 Received: from mail-pg1-x549.google.com ([2607:f8b0:4864:20::549]:40245) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3CF8TYAgKChsNL81FKJ87FF7C5.3FDH5DL-45M5CEFE7EL.FI7@flex--wuhaotsh.bounces.google.com>) id 1l5ICo-0004Uo-NW for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:14 -0500 Received: by mail-pg1-x549.google.com with SMTP id w4so5136182pgc.7 for ; Thu, 28 Jan 2021 17:04:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=MXpYq4rGrYnKEV9MTkJ+FJRm52fVhSZVjQB4Boy0H48=; b=CcaFOYbh8D6CEG6AS96j0pzXFdNjXI4VrwnGuCmYzu90YDYxKvjs+F/eSLcv3kaGBK 9jLViZefuaHKqrtrYsvN7hvHCSeR/F8efy2G5dWHYKcLPFvHlTevRkO3RR/R6G4F1pj2 4ZM6GLHtnyeolUM3cOyP74SL68gPK16hc9Wt/0p7FcfeocbZzO3eqd/ETCO/fq462idI r29xZx2t7TBibdZFA3XeKNMIzxoDpuk6vNLdWEjm7sbOZId5W/sCGM5d75LewpaZVDBk e3qg5FDcalO3JrNWOnUHUfoeeRP27U8hJQT1CdbodfOLV/sLWYuhxvcVxDDKFdtuglgf ArFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=MXpYq4rGrYnKEV9MTkJ+FJRm52fVhSZVjQB4Boy0H48=; b=L/S8gEQtx6hm+EJsfMIFtt9mr/Qbh9+eccIV8mdJNA1EChYLF8K4QhOaEV72Q9eKIi YvsNtsodBi12AsWbJrtWZhsikXaa3GW2Bg0tNMqQh+iCURO8tRIH4hvQxB4DuBTHanM0 VcgPBzV1JeB1h1SHREWnuUMj2rb6G1fHZe56I6vt3ixK3Sgde2y955CWGJpA+WDXdYQm qq+HL447F9o3GpNxvQNp2SZ+x0hmD1s3kCMqj0qgcpArBhbuEtheWob0ASBGo3Fe4PFF u4WMrJxCqo0zoIib+sNo7SdClHP+UuyfcZ0QQkcvD5gTRcSqznHVDYeULN4vngDTiIsw fIZA== X-Gm-Message-State: AOAM531vTeE/lO6RuVTuqOHS/CrWRVK5/zIqgvN2rYi897fdjfXgRCfM fIOwen8QqF+Vxg5AC2WmbJVxfRC6XUF94Q== X-Google-Smtp-Source: ABdhPJz6WuPtLKuXCJIebecu3Wp0YgBSKUro3B1QrY6RC590e/BvsiQ8KWRmr8bvk9OpNqpoWi5s/OcdfvNujg== X-Received: from mimik.c.googlers.com ([fda3:e722:ac3:10:7f:e700:c0a8:4e]) (user=wuhaotsh job=sendgmr) by 2002:a17:90a:4088:: with SMTP id l8mr2019690pjg.106.1611882248047; Thu, 28 Jan 2021 17:04:08 -0800 (PST) Date: Thu, 28 Jan 2021 16:58:40 -0800 In-Reply-To: <20210129005845.416272-1-wuhaotsh@google.com> Message-Id: <20210129005845.416272-2-wuhaotsh@google.com> Mime-Version: 1.0 References: <20210129005845.416272-1-wuhaotsh@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH v2 1/6] hw/arm: Remove GPIO from unimplemented NPCM7XX To: peter.maydell@linaro.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::549; envelope-from=3CF8TYAgKChsNL81FKJ87FF7C5.3FDH5DL-45M5CEFE7EL.FI7@flex--wuhaotsh.bounces.google.com; helo=mail-pg1-x549.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: cminyard@mvista.com, venture@google.com, hskinnemoen@google.com, qemu-devel@nongnu.org, wuhaotsh@google.com, kfting@nuvoton.com, qemu-arm@nongnu.org, Avi.Fishman@nuvoton.com, dje@google.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Hao Wu From: wuhaotsh--- via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" NPCM7XX GPIO devices have been implemented in hw/gpio/npcm7xx-gpio.c. So we removed them from the unimplemented devices list. Reviewed-by: Doug Evans Reviewed-by: Tyrong Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- hw/arm/npcm7xx.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 72040d4079..d1fe9bd1df 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -576,14 +576,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **= errp) create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * = KiB); create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * = KiB); create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * = KiB); - create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * = KiB); create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * = KiB); create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * = KiB); create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * = KiB); --=20 2.30.0.365.g02bc693789-goog From nobody Fri May 17 01:12:43 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1611882388; cv=none; d=zohomail.com; s=zohoarc; b=MVpHkVp6CPg6gkc2zMOxXS1KQtpO5nLRxH6G5o2zuPQFWKiZm7hZh4t5X+sXjR0gCCPdOS2T/zt/qxF+/Hvxq/X3jA0wUrVTIdjrWeR+roJZ32CQI8w5p6sT3tbbY3+7UyRdsIPm6ilgdgnM2qbvNVHF7TL54XgYpsGB8uDuFfg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1611882388; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=y8MKzimp70vELove8IbdVmHzk7jaNVB3xQIiOR8YBwo=; b=mbifY5MLnZQj00uWoBuTdQyFjD0VcT43eWOtYtpP5ZCHerd9Y1OzhTwnKr8b/slWD6syAqtJVzPP1E5ALHqdtpDVD/Yx3tnpDRIRIwiqM5ScHHdMAxvP0s2hdDBuil+wsqPb/J02ro0It0QU7or3jXUw2+eS1HzXq9T0JokK7/c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1611882388768805.5115426458417; Thu, 28 Jan 2021 17:06:28 -0800 (PST) Received: from localhost ([::1]:51024 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l5IF1-00057t-Jb for importer@patchew.org; Thu, 28 Jan 2021 20:06:27 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:55628) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3CV8TYAgKChwOM92GLK98GG8D6.4GEI6EM-56N6DFGF8FM.GJ8@flex--wuhaotsh.bounces.google.com>) id 1l5ICu-00034P-2z for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:16 -0500 Received: from mail-pf1-x449.google.com ([2607:f8b0:4864:20::449]:36839) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3CV8TYAgKChwOM92GLK98GG8D6.4GEI6EM-56N6DFGF8FM.GJ8@flex--wuhaotsh.bounces.google.com>) id 1l5ICp-0004Vr-Rd for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:15 -0500 Received: by mail-pf1-x449.google.com with SMTP id z3so4727212pfj.3 for ; Thu, 28 Jan 2021 17:04:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=y8MKzimp70vELove8IbdVmHzk7jaNVB3xQIiOR8YBwo=; b=Vi4sB6JsHdFKw89c4AoSzsaEFILG0dCrzF9xsu/izgrSOBdRlGnEPDvAcZSMUyOlbO W2mvjWo81hmuyU4v1/7ompsUNRerKALgOdy3WDQp3rwDeZg63aQDkpRp9wUC7eeadu7+ WWtnV41BsU2PnkWcKiFNhEob9AkJxhv8gZKu8s8+e9YfWXRC/Io+JQ8B1zacO1bO7tb0 Ky/xlIxzfCHzTdd+lC2M1Bb2PxRCACBf3un94yN9DqWHHaQdvuoTUDpJJurDBIs9akQj 2LZ43g3R/ThxwdBnHhQ5nttyEXw0dPOyCpvOfZg4zunTx65SiCfqOO4K3btjygMtMPuH BYUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=y8MKzimp70vELove8IbdVmHzk7jaNVB3xQIiOR8YBwo=; b=aDozpuT8vhs8KqBDGu0ZbhMtMxANXp6smYHSHZW2c9kWgbIeR9IaeiVcimv6B9rPOm 9W16iee3urO4tgGzfoJUVz9Vop2lzl/2x0EpbUgkwh75DJMJslk4YyRiXWTAZ6puXGB3 2Pd/4gbLIR9B8R8Tgz34L38lXPCWpYT4mncjIGFEii0HMJu68vlDWHDc9Bkck8tKfRp3 hy566IhYYD48COBGFEcMDv+lH/QeTKj2c5HN+zCtc6SSYdxqCsmpIvcvzLcVmxPR/E06 CSLwtVMyLt/QlX+X+obE6prTIrQK9/kvWoELRYohdrKqIiOdO0vP9U/TQ4QlwRSDblRn MpOQ== X-Gm-Message-State: AOAM530h/NCfwtJPi/U/k3xgMvBs8Ex5kj9URf/LWn+VeFY85MiSDK5l KUemiaJrQgncgyqlQFmlVBDy4ueNHDaYhA== X-Google-Smtp-Source: ABdhPJwJ4A7VZCLJ4Z9seLJyysU3TnMUerUvKVUrJ8SQG59SqkRoW/nS2IWWm99uaGB8hxoFaFlpSHVP5UFrKQ== X-Received: from mimik.c.googlers.com ([fda3:e722:ac3:10:7f:e700:c0a8:4e]) (user=wuhaotsh job=sendgmr) by 2002:a17:90a:8d83:: with SMTP id d3mr70688pjo.0.1611882249714; Thu, 28 Jan 2021 17:04:09 -0800 (PST) Date: Thu, 28 Jan 2021 16:58:41 -0800 In-Reply-To: <20210129005845.416272-1-wuhaotsh@google.com> Message-Id: <20210129005845.416272-3-wuhaotsh@google.com> Mime-Version: 1.0 References: <20210129005845.416272-1-wuhaotsh@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH v2 2/6] hw/i2c: Implement NPCM7XX SMBus Module Single Mode To: peter.maydell@linaro.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::449; envelope-from=3CV8TYAgKChwOM92GLK98GG8D6.4GEI6EM-56N6DFGF8FM.GJ8@flex--wuhaotsh.bounces.google.com; helo=mail-pf1-x449.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: cminyard@mvista.com, venture@google.com, hskinnemoen@google.com, qemu-devel@nongnu.org, wuhaotsh@google.com, kfting@nuvoton.com, qemu-arm@nongnu.org, Avi.Fishman@nuvoton.com, dje@google.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Hao Wu From: wuhaotsh--- via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This commit implements the single-byte mode of the SMBus. Each Nuvoton SoC has 16 System Management Bus (SMBus). These buses compliant with SMBus and I2C protocol. This patch implements the single-byte mode of the SMBus. In this mode, the user sends or receives a byte each time. The SMBus device transmits it to the underlying i2c device and sends an interrupt back to the QEMU guest. Reviewed-by: Doug Evans Reviewed-by: Tyrong Ting Signed-off-by: Hao Wu Reviewed-by: Corey Minyard Ack-by: Corey Minyard --- docs/system/arm/nuvoton.rst | 2 +- hw/arm/npcm7xx.c | 68 ++- hw/i2c/meson.build | 1 + hw/i2c/npcm7xx_smbus.c | 781 +++++++++++++++++++++++++++++++++ hw/i2c/trace-events | 11 + include/hw/arm/npcm7xx.h | 2 + include/hw/i2c/npcm7xx_smbus.h | 88 ++++ 7 files changed, 936 insertions(+), 17 deletions(-) create mode 100644 hw/i2c/npcm7xx_smbus.c create mode 100644 include/hw/i2c/npcm7xx_smbus.h diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst index a1786342e2..34fc799b2d 100644 --- a/docs/system/arm/nuvoton.rst +++ b/docs/system/arm/nuvoton.rst @@ -43,6 +43,7 @@ Supported devices * GPIO controller * Analog to Digital Converter (ADC) * Pulse Width Modulation (PWM) + * SMBus controller (SMBF) =20 Missing devices --------------- @@ -58,7 +59,6 @@ Missing devices =20 * Ethernet controllers (GMAC and EMC) * USB device (USBD) - * SMBus controller (SMBF) * Peripheral SPI controller (PSPI) * SD/MMC host * PECI interface diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index d1fe9bd1df..f8950f9470 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -102,6 +102,22 @@ enum NPCM7xxInterrupt { NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */ NPCM7XX_EHCI_IRQ =3D 61, NPCM7XX_OHCI_IRQ =3D 62, + NPCM7XX_SMBUS0_IRQ =3D 64, + NPCM7XX_SMBUS1_IRQ, + NPCM7XX_SMBUS2_IRQ, + NPCM7XX_SMBUS3_IRQ, + NPCM7XX_SMBUS4_IRQ, + NPCM7XX_SMBUS5_IRQ, + NPCM7XX_SMBUS6_IRQ, + NPCM7XX_SMBUS7_IRQ, + NPCM7XX_SMBUS8_IRQ, + NPCM7XX_SMBUS9_IRQ, + NPCM7XX_SMBUS10_IRQ, + NPCM7XX_SMBUS11_IRQ, + NPCM7XX_SMBUS12_IRQ, + NPCM7XX_SMBUS13_IRQ, + NPCM7XX_SMBUS14_IRQ, + NPCM7XX_SMBUS15_IRQ, NPCM7XX_PWM0_IRQ =3D 93, /* PWM module 0 */ NPCM7XX_PWM1_IRQ, /* PWM module 1 */ NPCM7XX_GPIO0_IRQ =3D 116, @@ -152,6 +168,26 @@ static const hwaddr npcm7xx_pwm_addr[] =3D { 0xf0104000, }; =20 +/* Direct memory-mapped access to each SMBus Module. */ +static const hwaddr npcm7xx_smbus_addr[] =3D { + 0xf0080000, + 0xf0081000, + 0xf0082000, + 0xf0083000, + 0xf0084000, + 0xf0085000, + 0xf0086000, + 0xf0087000, + 0xf0088000, + 0xf0089000, + 0xf008a000, + 0xf008b000, + 0xf008c000, + 0xf008d000, + 0xf008e000, + 0xf008f000, +}; + static const struct { hwaddr regs_addr; uint32_t unconnected_pins; @@ -353,6 +389,11 @@ static void npcm7xx_init(Object *obj) object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_= GPIO); } =20 + for (i =3D 0; i < ARRAY_SIZE(s->smbus); i++) { + object_initialize_child(obj, "smbus[*]", &s->smbus[i], + TYPE_NPCM7XX_SMBUS); + } + object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI); object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI); =20 @@ -509,6 +550,17 @@ static void npcm7xx_realize(DeviceState *dev, Error **= errp) npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i)); } =20 + /* SMBus modules. Cannot fail. */ + QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_smbus_addr) !=3D ARRAY_SIZE(s->sm= bus)); + for (i =3D 0; i < ARRAY_SIZE(s->smbus); i++) { + Object *obj =3D OBJECT(&s->smbus[i]); + + sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_smbus_addr[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0, + npcm7xx_irq(s, NPCM7XX_SMBUS0_IRQ + i)); + } + /* USB Host */ object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true, &error_abort); @@ -576,22 +628,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **= errp) create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * = KiB); create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * = KiB); create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * = KiB); - create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * = KiB); create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * = KiB); create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * = KiB); create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * = KiB); diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build index 3a511539ad..cdcd694a7f 100644 --- a/hw/i2c/meson.build +++ b/hw/i2c/meson.build @@ -9,6 +9,7 @@ i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos42= 10_i2c.c')) i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c')) i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c')) i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c')) +i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c')) i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c')) i2c_ss.add(when: 'CONFIG_VERSATILE_I2C', if_true: files('versatile_i2c.c')) i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c')) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c new file mode 100644 index 0000000000..c72b6e446f --- /dev/null +++ b/hw/i2c/npcm7xx_smbus.c @@ -0,0 +1,781 @@ +/* + * Nuvoton NPCM7xx SMBus Module. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WIT= HOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/i2c/npcm7xx_smbus.h" +#include "migration/vmstate.h" +#include "qemu/bitops.h" +#include "qemu/guest-random.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#include "trace.h" + +#define NPCM7XX_SMBUS_VERSION 1 +#define NPCM7XX_SMBUS_FIFO_EN 0 + +enum NPCM7xxSMBusCommonRegister { + NPCM7XX_SMB_SDA =3D 0x0, + NPCM7XX_SMB_ST =3D 0x2, + NPCM7XX_SMB_CST =3D 0x4, + NPCM7XX_SMB_CTL1 =3D 0x6, + NPCM7XX_SMB_ADDR1 =3D 0x8, + NPCM7XX_SMB_CTL2 =3D 0xa, + NPCM7XX_SMB_ADDR2 =3D 0xc, + NPCM7XX_SMB_CTL3 =3D 0xe, + NPCM7XX_SMB_CST2 =3D 0x18, + NPCM7XX_SMB_CST3 =3D 0x19, + NPCM7XX_SMB_VER =3D 0x1f, +}; + +enum NPCM7xxSMBusBank0Register { + NPCM7XX_SMB_ADDR3 =3D 0x10, + NPCM7XX_SMB_ADDR7 =3D 0x11, + NPCM7XX_SMB_ADDR4 =3D 0x12, + NPCM7XX_SMB_ADDR8 =3D 0x13, + NPCM7XX_SMB_ADDR5 =3D 0x14, + NPCM7XX_SMB_ADDR9 =3D 0x15, + NPCM7XX_SMB_ADDR6 =3D 0x16, + NPCM7XX_SMB_ADDR10 =3D 0x17, + NPCM7XX_SMB_CTL4 =3D 0x1a, + NPCM7XX_SMB_CTL5 =3D 0x1b, + NPCM7XX_SMB_SCLLT =3D 0x1c, + NPCM7XX_SMB_FIF_CTL =3D 0x1d, + NPCM7XX_SMB_SCLHT =3D 0x1e, +}; + +enum NPCM7xxSMBusBank1Register { + NPCM7XX_SMB_FIF_CTS =3D 0x10, + NPCM7XX_SMB_FAIR_PER =3D 0x11, + NPCM7XX_SMB_TXF_CTL =3D 0x12, + NPCM7XX_SMB_T_OUT =3D 0x14, + NPCM7XX_SMB_TXF_STS =3D 0x1a, + NPCM7XX_SMB_RXF_STS =3D 0x1c, + NPCM7XX_SMB_RXF_CTL =3D 0x1e, +}; + +/* ST fields */ +#define NPCM7XX_SMBST_STP BIT(7) +#define NPCM7XX_SMBST_SDAST BIT(6) +#define NPCM7XX_SMBST_BER BIT(5) +#define NPCM7XX_SMBST_NEGACK BIT(4) +#define NPCM7XX_SMBST_STASTR BIT(3) +#define NPCM7XX_SMBST_NMATCH BIT(2) +#define NPCM7XX_SMBST_MODE BIT(1) +#define NPCM7XX_SMBST_XMIT BIT(0) + +/* CST fields */ +#define NPCM7XX_SMBCST_ARPMATCH BIT(7) +#define NPCM7XX_SMBCST_MATCHAF BIT(6) +#define NPCM7XX_SMBCST_TGSCL BIT(5) +#define NPCM7XX_SMBCST_TSDA BIT(4) +#define NPCM7XX_SMBCST_GCMATCH BIT(3) +#define NPCM7XX_SMBCST_MATCH BIT(2) +#define NPCM7XX_SMBCST_BB BIT(1) +#define NPCM7XX_SMBCST_BUSY BIT(0) + +/* CST2 fields */ +#define NPCM7XX_SMBCST2_INTSTS BIT(7) +#define NPCM7XX_SMBCST2_MATCH7F BIT(6) +#define NPCM7XX_SMBCST2_MATCH6F BIT(5) +#define NPCM7XX_SMBCST2_MATCH5F BIT(4) +#define NPCM7XX_SMBCST2_MATCH4F BIT(3) +#define NPCM7XX_SMBCST2_MATCH3F BIT(2) +#define NPCM7XX_SMBCST2_MATCH2F BIT(1) +#define NPCM7XX_SMBCST2_MATCH1F BIT(0) + +/* CST3 fields */ +#define NPCM7XX_SMBCST3_EO_BUSY BIT(7) +#define NPCM7XX_SMBCST3_MATCH10F BIT(2) +#define NPCM7XX_SMBCST3_MATCH9F BIT(1) +#define NPCM7XX_SMBCST3_MATCH8F BIT(0) + +/* CTL1 fields */ +#define NPCM7XX_SMBCTL1_STASTRE BIT(7) +#define NPCM7XX_SMBCTL1_NMINTE BIT(6) +#define NPCM7XX_SMBCTL1_GCMEN BIT(5) +#define NPCM7XX_SMBCTL1_ACK BIT(4) +#define NPCM7XX_SMBCTL1_EOBINTE BIT(3) +#define NPCM7XX_SMBCTL1_INTEN BIT(2) +#define NPCM7XX_SMBCTL1_STOP BIT(1) +#define NPCM7XX_SMBCTL1_START BIT(0) + +/* CTL2 fields */ +#define NPCM7XX_SMBCTL2_SCLFRQ(rv) extract8((rv), 1, 6) +#define NPCM7XX_SMBCTL2_ENABLE BIT(0) + +/* CTL3 fields */ +#define NPCM7XX_SMBCTL3_SCL_LVL BIT(7) +#define NPCM7XX_SMBCTL3_SDA_LVL BIT(6) +#define NPCM7XX_SMBCTL3_BNK_SEL BIT(5) +#define NPCM7XX_SMBCTL3_400K_MODE BIT(4) +#define NPCM7XX_SMBCTL3_IDL_START BIT(3) +#define NPCM7XX_SMBCTL3_ARPMEN BIT(2) +#define NPCM7XX_SMBCTL3_SCLFRQ(rv) extract8((rv), 0, 2) + +/* ADDR fields */ +#define NPCM7XX_ADDR_EN BIT(7) +#define NPCM7XX_ADDR_A(rv) extract8((rv), 0, 6) + +#define KEEP_OLD_BIT(o, n, b) (((n) & (~(b))) | ((o) & (b))) +#define WRITE_ONE_CLEAR(o, n, b) ((n) & (b) ? (o) & (~(b)) : (o)) + +#define NPCM7XX_SMBUS_ENABLED(s) ((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE) + +/* Reset values */ +#define NPCM7XX_SMB_ST_INIT_VAL 0x00 +#define NPCM7XX_SMB_CST_INIT_VAL 0x10 +#define NPCM7XX_SMB_CST2_INIT_VAL 0x00 +#define NPCM7XX_SMB_CST3_INIT_VAL 0x00 +#define NPCM7XX_SMB_CTL1_INIT_VAL 0x00 +#define NPCM7XX_SMB_CTL2_INIT_VAL 0x00 +#define NPCM7XX_SMB_CTL3_INIT_VAL 0xc0 +#define NPCM7XX_SMB_CTL4_INIT_VAL 0x07 +#define NPCM7XX_SMB_CTL5_INIT_VAL 0x00 +#define NPCM7XX_SMB_ADDR_INIT_VAL 0x00 +#define NPCM7XX_SMB_SCLLT_INIT_VAL 0x00 +#define NPCM7XX_SMB_SCLHT_INIT_VAL 0x00 + +static uint8_t npcm7xx_smbus_get_version(void) +{ + return NPCM7XX_SMBUS_FIFO_EN << 7 | NPCM7XX_SMBUS_VERSION; +} + +static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s) +{ + int level; + + if (s->ctl1 & NPCM7XX_SMBCTL1_INTEN) { + level =3D !!((s->ctl1 & NPCM7XX_SMBCTL1_NMINTE && + s->st & NPCM7XX_SMBST_NMATCH) || + (s->st & NPCM7XX_SMBST_BER) || + (s->st & NPCM7XX_SMBST_NEGACK) || + (s->st & NPCM7XX_SMBST_SDAST) || + (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE && + s->st & NPCM7XX_SMBST_SDAST) || + (s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE && + s->cst3 & NPCM7XX_SMBCST3_EO_BUSY)); + + if (level) { + s->cst2 |=3D NPCM7XX_SMBCST2_INTSTS; + } else { + s->cst2 &=3D ~NPCM7XX_SMBCST2_INTSTS; + } + qemu_set_irq(s->irq, level); + } +} + +static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s) +{ + s->st &=3D ~NPCM7XX_SMBST_SDAST; + s->st |=3D NPCM7XX_SMBST_NEGACK; + s->status =3D NPCM7XX_SMBUS_STATUS_NEGACK; +} + +static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value) +{ + int rv =3D i2c_send(s->bus, value); + + if (rv) { + npcm7xx_smbus_nack(s); + } else { + s->st |=3D NPCM7XX_SMBST_SDAST; + } + trace_npcm7xx_smbus_send_byte((DEVICE(s)->canonical_path), value, !rv); + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s) +{ + s->sda =3D i2c_recv(s->bus); + s->st |=3D NPCM7XX_SMBST_SDAST; + if (s->st & NPCM7XX_SMBCTL1_ACK) { + trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); + i2c_nack(s->bus); + s->st &=3D NPCM7XX_SMBCTL1_ACK; + } + trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda); + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_start(NPCM7xxSMBusState *s) +{ + /* + * We can start the bus if one of these is true: + * 1. The bus is idle (so we can request it) + * 2. We are the occupier (it's a repeated start condition.) + */ + int available =3D !i2c_bus_busy(s->bus) || + s->status !=3D NPCM7XX_SMBUS_STATUS_IDLE; + + if (available) { + s->st |=3D NPCM7XX_SMBST_MODE | NPCM7XX_SMBST_XMIT | NPCM7XX_SMBST= _SDAST; + s->cst |=3D NPCM7XX_SMBCST_BUSY; + } else { + s->st &=3D ~NPCM7XX_SMBST_MODE; + s->cst &=3D ~NPCM7XX_SMBCST_BUSY; + s->st |=3D NPCM7XX_SMBST_BER; + } + + trace_npcm7xx_smbus_start(DEVICE(s)->canonical_path, available); + s->cst |=3D NPCM7XX_SMBCST_BB; + s->status =3D NPCM7XX_SMBUS_STATUS_IDLE; + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_send_address(NPCM7xxSMBusState *s, uint8_t value) +{ + int recv; + int rv; + + recv =3D value & BIT(0); + rv =3D i2c_start_transfer(s->bus, value >> 1, recv); + trace_npcm7xx_smbus_send_address(DEVICE(s)->canonical_path, + value >> 1, recv, !rv); + if (rv) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: requesting i2c bus for 0x%02x failed: %d\n", + DEVICE(s)->canonical_path, value, rv); + /* Failed to start transfer. NACK to reject.*/ + if (recv) { + s->st &=3D ~NPCM7XX_SMBST_XMIT; + } else { + s->st |=3D NPCM7XX_SMBST_XMIT; + } + npcm7xx_smbus_nack(s); + npcm7xx_smbus_update_irq(s); + return; + } + + s->st &=3D ~NPCM7XX_SMBST_NEGACK; + if (recv) { + s->status =3D NPCM7XX_SMBUS_STATUS_RECEIVING; + s->st &=3D ~NPCM7XX_SMBST_XMIT; + } else { + s->status =3D NPCM7XX_SMBUS_STATUS_SENDING; + s->st |=3D NPCM7XX_SMBST_XMIT; + } + + if (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE) { + s->st |=3D NPCM7XX_SMBST_STASTR; + if (!recv) { + s->st |=3D NPCM7XX_SMBST_SDAST; + } + } else if (recv) { + npcm7xx_smbus_recv_byte(s); + } + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_execute_stop(NPCM7xxSMBusState *s) +{ + i2c_end_transfer(s->bus); + s->st =3D 0; + s->cst =3D 0; + s->status =3D NPCM7XX_SMBUS_STATUS_IDLE; + s->cst3 |=3D NPCM7XX_SMBCST3_EO_BUSY; + trace_npcm7xx_smbus_stop(DEVICE(s)->canonical_path); + npcm7xx_smbus_update_irq(s); +} + + +static void npcm7xx_smbus_stop(NPCM7xxSMBusState *s) +{ + if (s->st & NPCM7XX_SMBST_MODE) { + switch (s->status) { + case NPCM7XX_SMBUS_STATUS_RECEIVING: + case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE: + s->status =3D NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE; + break; + + case NPCM7XX_SMBUS_STATUS_NEGACK: + s->status =3D NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK; + break; + + default: + npcm7xx_smbus_execute_stop(s); + break; + } + } +} + +static uint8_t npcm7xx_smbus_read_sda(NPCM7xxSMBusState *s) +{ + uint8_t value =3D s->sda; + + switch (s->status) { + case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE: + npcm7xx_smbus_execute_stop(s); + break; + + case NPCM7XX_SMBUS_STATUS_RECEIVING: + npcm7xx_smbus_recv_byte(s); + break; + + default: + /* Do nothing */ + break; + } + + return value; +} + +static void npcm7xx_smbus_write_sda(NPCM7xxSMBusState *s, uint8_t value) +{ + s->sda =3D value; + if (s->st & NPCM7XX_SMBST_MODE) { + switch (s->status) { + case NPCM7XX_SMBUS_STATUS_IDLE: + npcm7xx_smbus_send_address(s, value); + break; + case NPCM7XX_SMBUS_STATUS_SENDING: + npcm7xx_smbus_send_byte(s, value); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to SDA in invalid status %d: %u\n", + DEVICE(s)->canonical_path, s->status, value); + break; + } + } +} + +static void npcm7xx_smbus_write_st(NPCM7xxSMBusState *s, uint8_t value) +{ + s->st =3D WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STP); + s->st =3D WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_BER); + s->st =3D WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STASTR); + s->st =3D WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_NMATCH); + + if (value & NPCM7XX_SMBST_NEGACK) { + s->st &=3D ~NPCM7XX_SMBST_NEGACK; + if (s->status =3D=3D NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK) { + npcm7xx_smbus_execute_stop(s); + } + } + + if (value & NPCM7XX_SMBST_STASTR && + s->status =3D=3D NPCM7XX_SMBUS_STATUS_RECEIVING) { + npcm7xx_smbus_recv_byte(s); + } + + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_write_cst(NPCM7xxSMBusState *s, uint8_t value) +{ + uint8_t new_value =3D s->cst; + + s->cst =3D WRITE_ONE_CLEAR(new_value, value, NPCM7XX_SMBCST_BB); + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_write_cst3(NPCM7xxSMBusState *s, uint8_t value) +{ + s->cst3 =3D WRITE_ONE_CLEAR(s->cst3, value, NPCM7XX_SMBCST3_EO_BUSY); + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_write_ctl1(NPCM7xxSMBusState *s, uint8_t value) +{ + s->ctl1 =3D KEEP_OLD_BIT(s->ctl1, value, + NPCM7XX_SMBCTL1_START | NPCM7XX_SMBCTL1_STOP | NPCM7XX_SMBCTL1= _ACK); + + if (value & NPCM7XX_SMBCTL1_START) { + npcm7xx_smbus_start(s); + } + + if (value & NPCM7XX_SMBCTL1_STOP) { + npcm7xx_smbus_stop(s); + } + + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_write_ctl2(NPCM7xxSMBusState *s, uint8_t value) +{ + s->ctl2 =3D value; + + if (!NPCM7XX_SMBUS_ENABLED(s)) { + /* Disable this SMBus module. */ + s->ctl1 =3D 0; + s->st =3D 0; + s->cst3 =3D s->cst3 & (~NPCM7XX_SMBCST3_EO_BUSY); + s->cst =3D 0; + } +} + +static void npcm7xx_smbus_write_ctl3(NPCM7xxSMBusState *s, uint8_t value) +{ + uint8_t old_ctl3 =3D s->ctl3; + + /* Write to SDA and SCL bits are ignored. */ + s->ctl3 =3D KEEP_OLD_BIT(old_ctl3, value, + NPCM7XX_SMBCTL3_SCL_LVL | NPCM7XX_SMBCTL3_SDA_= LVL); +} + +static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned s= ize) +{ + NPCM7xxSMBusState *s =3D opaque; + uint64_t value =3D 0; + uint8_t bank =3D s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL; + + /* The order of the registers are their order in memory. */ + switch (offset) { + case NPCM7XX_SMB_SDA: + value =3D npcm7xx_smbus_read_sda(s); + break; + + case NPCM7XX_SMB_ST: + value =3D s->st; + break; + + case NPCM7XX_SMB_CST: + value =3D s->cst; + break; + + case NPCM7XX_SMB_CTL1: + value =3D s->ctl1; + break; + + case NPCM7XX_SMB_ADDR1: + value =3D s->addr[0]; + break; + + case NPCM7XX_SMB_CTL2: + value =3D s->ctl2; + break; + + case NPCM7XX_SMB_ADDR2: + value =3D s->addr[1]; + break; + + case NPCM7XX_SMB_CTL3: + value =3D s->ctl3; + break; + + case NPCM7XX_SMB_CST2: + value =3D s->cst2; + break; + + case NPCM7XX_SMB_CST3: + value =3D s->cst3; + break; + + case NPCM7XX_SMB_VER: + value =3D npcm7xx_smbus_get_version(); + break; + + /* This register is either invalid or banked at this point. */ + default: + if (bank) { + /* Bank 1 */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + } else { + /* Bank 0 */ + switch (offset) { + case NPCM7XX_SMB_ADDR3: + value =3D s->addr[2]; + break; + + case NPCM7XX_SMB_ADDR7: + value =3D s->addr[6]; + break; + + case NPCM7XX_SMB_ADDR4: + value =3D s->addr[3]; + break; + + case NPCM7XX_SMB_ADDR8: + value =3D s->addr[7]; + break; + + case NPCM7XX_SMB_ADDR5: + value =3D s->addr[4]; + break; + + case NPCM7XX_SMB_ADDR9: + value =3D s->addr[8]; + break; + + case NPCM7XX_SMB_ADDR6: + value =3D s->addr[5]; + break; + + case NPCM7XX_SMB_ADDR10: + value =3D s->addr[9]; + break; + + case NPCM7XX_SMB_CTL4: + value =3D s->ctl4; + break; + + case NPCM7XX_SMB_CTL5: + value =3D s->ctl5; + break; + + case NPCM7XX_SMB_SCLLT: + value =3D s->scllt; + break; + + case NPCM7XX_SMB_SCLHT: + value =3D s->sclht; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from invalid offset 0x%" HWADDR_PRIx "\n= ", + DEVICE(s)->canonical_path, offset); + break; + } + } + break; + } + + trace_npcm7xx_smbus_read(DEVICE(s)->canonical_path, offset, value, siz= e); + + return value; +} + +static void npcm7xx_smbus_write(void *opaque, hwaddr offset, uint64_t valu= e, + unsigned size) +{ + NPCM7xxSMBusState *s =3D opaque; + uint8_t bank =3D s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL; + + trace_npcm7xx_smbus_write(DEVICE(s)->canonical_path, offset, value, si= ze); + + /* The order of the registers are their order in memory. */ + switch (offset) { + case NPCM7XX_SMB_SDA: + npcm7xx_smbus_write_sda(s, value); + break; + + case NPCM7XX_SMB_ST: + npcm7xx_smbus_write_st(s, value); + break; + + case NPCM7XX_SMB_CST: + npcm7xx_smbus_write_cst(s, value); + break; + + case NPCM7XX_SMB_CTL1: + npcm7xx_smbus_write_ctl1(s, value); + break; + + case NPCM7XX_SMB_ADDR1: + s->addr[0] =3D value; + break; + + case NPCM7XX_SMB_CTL2: + npcm7xx_smbus_write_ctl2(s, value); + break; + + case NPCM7XX_SMB_ADDR2: + s->addr[1] =3D value; + break; + + case NPCM7XX_SMB_CTL3: + npcm7xx_smbus_write_ctl3(s, value); + break; + + case NPCM7XX_SMB_CST2: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + + case NPCM7XX_SMB_CST3: + npcm7xx_smbus_write_cst3(s, value); + break; + + case NPCM7XX_SMB_VER: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + + /* This register is either invalid or banked at this point. */ + default: + if (bank) { + /* Bank 1 */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + } else { + /* Bank 0 */ + switch (offset) { + case NPCM7XX_SMB_ADDR3: + s->addr[2] =3D value; + break; + + case NPCM7XX_SMB_ADDR7: + s->addr[6] =3D value; + break; + + case NPCM7XX_SMB_ADDR4: + s->addr[3] =3D value; + break; + + case NPCM7XX_SMB_ADDR8: + s->addr[7] =3D value; + break; + + case NPCM7XX_SMB_ADDR5: + s->addr[4] =3D value; + break; + + case NPCM7XX_SMB_ADDR9: + s->addr[8] =3D value; + break; + + case NPCM7XX_SMB_ADDR6: + s->addr[5] =3D value; + break; + + case NPCM7XX_SMB_ADDR10: + s->addr[9] =3D value; + break; + + case NPCM7XX_SMB_CTL4: + s->ctl4 =3D value; + break; + + case NPCM7XX_SMB_CTL5: + s->ctl5 =3D value; + break; + + case NPCM7XX_SMB_SCLLT: + s->scllt =3D value; + break; + + case NPCM7XX_SMB_SCLHT: + s->sclht =3D value; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + } + } + break; + } +} + +static const MemoryRegionOps npcm7xx_smbus_ops =3D { + .read =3D npcm7xx_smbus_read, + .write =3D npcm7xx_smbus_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + .unaligned =3D false, + }, +}; + +static void npcm7xx_smbus_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxSMBusState *s =3D NPCM7XX_SMBUS(obj); + + s->st =3D NPCM7XX_SMB_ST_INIT_VAL; + s->cst =3D NPCM7XX_SMB_CST_INIT_VAL; + s->cst2 =3D NPCM7XX_SMB_CST2_INIT_VAL; + s->cst3 =3D NPCM7XX_SMB_CST3_INIT_VAL; + s->ctl1 =3D NPCM7XX_SMB_CTL1_INIT_VAL; + s->ctl2 =3D NPCM7XX_SMB_CTL2_INIT_VAL; + s->ctl3 =3D NPCM7XX_SMB_CTL3_INIT_VAL; + s->ctl4 =3D NPCM7XX_SMB_CTL4_INIT_VAL; + s->ctl5 =3D NPCM7XX_SMB_CTL5_INIT_VAL; + + for (int i =3D 0; i < NPCM7XX_SMBUS_NR_ADDRS; ++i) { + s->addr[i] =3D NPCM7XX_SMB_ADDR_INIT_VAL; + } + s->scllt =3D NPCM7XX_SMB_SCLLT_INIT_VAL; + s->sclht =3D NPCM7XX_SMB_SCLHT_INIT_VAL; + + s->status =3D NPCM7XX_SMBUS_STATUS_IDLE; +} + +static void npcm7xx_smbus_hold_reset(Object *obj) +{ + NPCM7xxSMBusState *s =3D NPCM7XX_SMBUS(obj); + + qemu_irq_lower(s->irq); +} + +static void npcm7xx_smbus_init(Object *obj) +{ + NPCM7xxSMBusState *s =3D NPCM7XX_SMBUS(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + sysbus_init_irq(sbd, &s->irq); + memory_region_init_io(&s->iomem, obj, &npcm7xx_smbus_ops, s, + "regs", 4 * KiB); + sysbus_init_mmio(sbd, &s->iomem); + + s->bus =3D i2c_init_bus(DEVICE(s), "i2c-bus"); + s->status =3D NPCM7XX_SMBUS_STATUS_IDLE; +} + +static const VMStateDescription vmstate_npcm7xx_smbus =3D { + .name =3D "npcm7xx-smbus", + .version_id =3D 0, + .minimum_version_id =3D 0, + .fields =3D (VMStateField[]) { + VMSTATE_UINT8(sda, NPCM7xxSMBusState), + VMSTATE_UINT8(st, NPCM7xxSMBusState), + VMSTATE_UINT8(cst, NPCM7xxSMBusState), + VMSTATE_UINT8(cst2, NPCM7xxSMBusState), + VMSTATE_UINT8(cst3, NPCM7xxSMBusState), + VMSTATE_UINT8(ctl1, NPCM7xxSMBusState), + VMSTATE_UINT8(ctl2, NPCM7xxSMBusState), + VMSTATE_UINT8(ctl3, NPCM7xxSMBusState), + VMSTATE_UINT8(ctl4, NPCM7xxSMBusState), + VMSTATE_UINT8(ctl5, NPCM7xxSMBusState), + VMSTATE_UINT8_ARRAY(addr, NPCM7xxSMBusState, NPCM7XX_SMBUS_NR_ADDR= S), + VMSTATE_UINT8(scllt, NPCM7xxSMBusState), + VMSTATE_UINT8(sclht, NPCM7xxSMBusState), + VMSTATE_END_OF_LIST(), + }, +}; + +static void npcm7xx_smbus_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->desc =3D "NPCM7xx System Management Bus"; + dc->vmsd =3D &vmstate_npcm7xx_smbus; + rc->phases.enter =3D npcm7xx_smbus_enter_reset; + rc->phases.hold =3D npcm7xx_smbus_hold_reset; +} + +static const TypeInfo npcm7xx_smbus_types[] =3D { + { + .name =3D TYPE_NPCM7XX_SMBUS, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(NPCM7xxSMBusState), + .class_init =3D npcm7xx_smbus_class_init, + .instance_init =3D npcm7xx_smbus_init, + }, +}; +DEFINE_TYPES(npcm7xx_smbus_types); diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events index 08db8fa689..c3bb70ad04 100644 --- a/hw/i2c/trace-events +++ b/hw/i2c/trace-events @@ -14,3 +14,14 @@ aspeed_i2c_bus_read(uint32_t busid, uint64_t offset, uns= igned size, uint64_t val aspeed_i2c_bus_write(uint32_t busid, uint64_t offset, unsigned size, uint6= 4_t value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64 aspeed_i2c_bus_send(const char *mode, int i, int count, uint8_t byte) "%s = send %d/%d 0x%02x" aspeed_i2c_bus_recv(const char *mode, int i, int count, uint8_t byte) "%s = recv %d/%d 0x%02x" + +# npcm7xx_smbus.c + +npcm7xx_smbus_read(const char *id, uint64_t offset, uint64_t value, unsign= ed size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u" +npcm7xx_smbus_write(const char *id, uint64_t offset, uint64_t value, unsig= ned size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u" +npcm7xx_smbus_start(const char *id, int success) "%s starting, success: %d" +npcm7xx_smbus_send_address(const char *id, uint8_t addr, int recv, int suc= cess) "%s sending address: 0x%02x, recv: %d, success: %d" +npcm7xx_smbus_send_byte(const char *id, uint8_t value, int success) "%s se= nd byte: 0x%02x, success: %d" +npcm7xx_smbus_recv_byte(const char *id, uint8_t value) "%s recv byte: 0x%0= 2x" +npcm7xx_smbus_stop(const char *id) "%s stopping" +npcm7xx_smbus_nack(const char *id) "%s nacking" diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h index f6227aa8aa..cea1bd1f62 100644 --- a/include/hw/arm/npcm7xx.h +++ b/include/hw/arm/npcm7xx.h @@ -20,6 +20,7 @@ #include "hw/adc/npcm7xx_adc.h" #include "hw/cpu/a9mpcore.h" #include "hw/gpio/npcm7xx_gpio.h" +#include "hw/i2c/npcm7xx_smbus.h" #include "hw/mem/npcm7xx_mc.h" #include "hw/misc/npcm7xx_clk.h" #include "hw/misc/npcm7xx_gcr.h" @@ -85,6 +86,7 @@ typedef struct NPCM7xxState { NPCM7xxMCState mc; NPCM7xxRNGState rng; NPCM7xxGPIOState gpio[8]; + NPCM7xxSMBusState smbus[16]; EHCISysBusState ehci; OHCISysBusState ohci; NPCM7xxFIUState fiu[2]; diff --git a/include/hw/i2c/npcm7xx_smbus.h b/include/hw/i2c/npcm7xx_smbus.h new file mode 100644 index 0000000000..b9761a6993 --- /dev/null +++ b/include/hw/i2c/npcm7xx_smbus.h @@ -0,0 +1,88 @@ +/* + * Nuvoton NPCM7xx SMBus Module. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WIT= HOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#ifndef NPCM7XX_SMBUS_H +#define NPCM7XX_SMBUS_H + +#include "exec/memory.h" +#include "hw/i2c/i2c.h" +#include "hw/irq.h" +#include "hw/sysbus.h" + +/* + * Number of addresses this module contains. Do not change this without + * incrementing the version_id in the vmstate. + */ +#define NPCM7XX_SMBUS_NR_ADDRS 10 + +typedef enum NPCM7xxSMBusStatus { + NPCM7XX_SMBUS_STATUS_IDLE, + NPCM7XX_SMBUS_STATUS_SENDING, + NPCM7XX_SMBUS_STATUS_RECEIVING, + NPCM7XX_SMBUS_STATUS_NEGACK, + NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE, + NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK, +} NPCM7xxSMBusStatus; + +/* + * struct NPCM7xxSMBusState - System Management Bus device state. + * @bus: The underlying I2C Bus. + * @irq: GIC interrupt line to fire on events (if enabled). + * @sda: The serial data register. + * @st: The status register. + * @cst: The control status register. + * @cst2: The control status register 2. + * @cst3: The control status register 3. + * @ctl1: The control register 1. + * @ctl2: The control register 2. + * @ctl3: The control register 3. + * @ctl4: The control register 4. + * @ctl5: The control register 5. + * @addr: The SMBus module's own addresses on the I2C bus. + * @scllt: The SCL low time register. + * @sclht: The SCL high time register. + * @status: The current status of the SMBus. + */ +typedef struct NPCM7xxSMBusState { + SysBusDevice parent; + + MemoryRegion iomem; + + I2CBus *bus; + qemu_irq irq; + + uint8_t sda; + uint8_t st; + uint8_t cst; + uint8_t cst2; + uint8_t cst3; + uint8_t ctl1; + uint8_t ctl2; + uint8_t ctl3; + uint8_t ctl4; + uint8_t ctl5; + uint8_t addr[NPCM7XX_SMBUS_NR_ADDRS]; + + uint8_t scllt; + uint8_t sclht; + + NPCM7xxSMBusStatus status; +} NPCM7xxSMBusState; + +#define TYPE_NPCM7XX_SMBUS "npcm7xx-smbus" +#define NPCM7XX_SMBUS(obj) OBJECT_CHECK(NPCM7xxSMBusState, (obj), \ + TYPE_NPCM7XX_SMBUS) + +#endif /* NPCM7XX_SMBUS_H */ --=20 2.30.0.365.g02bc693789-goog From nobody Fri May 17 01:12:43 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1611882358; cv=none; d=zohomail.com; s=zohoarc; b=UC8BJQfQIKnZMiSizHMv+6AEphvrGK9fcoRrlWQLSGDBXfwhZEsYuvYMxkfQ8wZFk/MuSr0EBqW0zXEKP6W8oczw+aOvX105/fI9wUuvO+1SKgUV+dQ4oa1uEVITHJ8echqz7F4eVbflCdALGQpBdWXnk8C79gSrHmS1EB4Cta4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1611882358; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=ELaBYRMM2IbotDCIKyZuXyvpnGXxuQRotS+jnVcGgmk=; b=VfGYAyzyl4luKkWtHvkZZ1h4AmEWn0hpF1ax77UKy1hV+RAj+9SMO38f8ubDShp/5dCIkXzCSgBq8P/+EFKQF2WhWFYSk4UCkwjqnLe+PBdPDnTaUpm8O2oqLus25yEnrsy9E/Exk6Dy6qHIlvM7/cZNWE2L7Q3Nnb4MUYZ/t64= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1611882357986447.16639219050546; Thu, 28 Jan 2021 17:05:57 -0800 (PST) Received: from localhost ([::1]:49326 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l5IEW-0004Q9-OQ for importer@patchew.org; Thu, 28 Jan 2021 20:05:56 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:55596) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3C18TYAgKCh4QOB4INMBAIIAF8.6IGK8GO-78P8FHIHAHO.ILA@flex--wuhaotsh.bounces.google.com>) id 1l5ICs-00032K-V7 for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:14 -0500 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]:41933) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3C18TYAgKCh4QOB4INMBAIIAF8.6IGK8GO-78P8FHIHAHO.ILA@flex--wuhaotsh.bounces.google.com>) id 1l5ICr-0004W9-Ek for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:14 -0500 Received: by mail-pj1-x104a.google.com with SMTP id o3so4621082pju.6 for ; Thu, 28 Jan 2021 17:04:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=ELaBYRMM2IbotDCIKyZuXyvpnGXxuQRotS+jnVcGgmk=; b=HRCvWaTXgEvzg559vIeY9WNgVG9kk+zzl5IXFom0uQQwXHbONTVsqbRRLGCVHBTGhU CUL3H/Buhk0LRyckH/GKyIJCoAVLA63/YBKw3G+prWDJxsaK3fywZkqRM3gMipTd1UyU HmCj3yDxTM9ETyXarFXLevgY3H0tgTkCltYOb4kR2vWswE05aK+VKfxQQSSKfauD8kgS Khn/6aqXDtgJWKhRB+oDOlOja8jzuwWznDpX8zWAECoRyB/F0Ed4bbMCCjM5FFksGX9/ /+wvRJpWYSkwW4WDU41h4T/QOaa516riIjjgTb/xCp73k2LNTODdJ03Fd778aYReZP4o Ar8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ELaBYRMM2IbotDCIKyZuXyvpnGXxuQRotS+jnVcGgmk=; b=opckq6X+6IBQZwo7nY0Ke5EimLjxTam4Snz1pxzr11U9X2nOI+KhjkO/XYBb7CtL3l RP7mDmtTx+B6DzPe7uJiCX8janhLoLyyyN1H+9eK/ND6mH/YSdaeaE7lVxaheFJ+ysoz bQYr15K9CTKQfu8lKM2pGGlw0nsx6p6E9Mz7K7C1JDAM7IIoRNJwXx1TZChpf+zJB4LQ uTgU97PWDh07T3gtDqGTFVDTwpsbMvU2fZSRrznNcYyh2Rqy+VTrW5kCy8oRTeT97M+a stUcMxzLuNDZNaJhTgzXyDKIoy4hV0qF8p+UTcxOgmMPIpRWnqGuxB3MpphGL/cP+Thu Yq6Q== X-Gm-Message-State: AOAM53210F98IEaO+UhED8NqnQWNuaUxRWTGgQ+v9uVos1P5XfMJEyan k7/KorydoJ8vlaOjA16YZ3nMh/9+THKenA== X-Google-Smtp-Source: ABdhPJwFkNUN7HOClSDQdQ2F4yv8IdEinemvAlG/iu7lciK4ZW9rxJw6d4c4792ccwYmFgz4jErteU4BTfHIVQ== X-Received: from mimik.c.googlers.com ([fda3:e722:ac3:10:7f:e700:c0a8:4e]) (user=wuhaotsh job=sendgmr) by 2002:a17:90a:4209:: with SMTP id o9mr2049452pjg.75.1611882251532; Thu, 28 Jan 2021 17:04:11 -0800 (PST) Date: Thu, 28 Jan 2021 16:58:42 -0800 In-Reply-To: <20210129005845.416272-1-wuhaotsh@google.com> Message-Id: <20210129005845.416272-4-wuhaotsh@google.com> Mime-Version: 1.0 References: <20210129005845.416272-1-wuhaotsh@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH v2 3/6] hw/arm: Add I2C sensors for NPCM750 eval board To: peter.maydell@linaro.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::104a; envelope-from=3C18TYAgKCh4QOB4INMBAIIAF8.6IGK8GO-78P8FHIHAHO.ILA@flex--wuhaotsh.bounces.google.com; helo=mail-pj1-x104a.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: cminyard@mvista.com, venture@google.com, hskinnemoen@google.com, qemu-devel@nongnu.org, wuhaotsh@google.com, kfting@nuvoton.com, qemu-arm@nongnu.org, Avi.Fishman@nuvoton.com, dje@google.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Hao Wu From: wuhaotsh--- via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add I2C temperature sensors for NPCM750 eval board. Reviewed-by: Doug Evans Reviewed-by: Tyrong Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 3fdd5cab01..47a215bd01 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -98,6 +98,24 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *ma= chine, return NPCM7XX(obj); } =20 +static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, uint32_t num) +{ + g_assert(num < ARRAY_SIZE(soc->smbus)); + return I2C_BUS(qdev_get_child_bus(DEVICE(&soc->smbus[num]), "i2c-bus")= ); +} + +static void npcm750_evb_i2c_init(NPCM7xxState *soc) +{ + /* lm75 temperature sensor on SVB, tmp105 is compatible */ + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), "tmp105", 0x48); + /* lm75 temperature sensor on EB, tmp105 is compatible */ + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x48); + /* tmp100 temperature sensor on EB, tmp105 is compatible */ + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x48); + /* tmp100 temperature sensor on SVB, tmp105 is compatible */ + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48); +} + static void npcm750_evb_init(MachineState *machine) { NPCM7xxState *soc; @@ -108,6 +126,7 @@ static void npcm750_evb_init(MachineState *machine) =20 npcm7xx_load_bootrom(machine, soc); npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0,= 0)); + npcm750_evb_i2c_init(soc); npcm7xx_load_kernel(machine, soc); } =20 --=20 2.30.0.365.g02bc693789-goog From nobody Fri May 17 01:12:43 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1611882497; cv=none; d=zohomail.com; s=zohoarc; b=Lk3d0Ex64S2utXqFYjCGD6PmnT9VH/IdtgoQ6bvkMA3iV2cO86l4m6pY5mBlI+hw46EvMeDBCQ92EbrlLmkJ6mAL/WbOWegubtI+Ctn6Xbld1o8BPrS7DwQSw+uF2CbLuVyb9UcBmg4/PDPubMZgtf5fOjC1UTdiX97yjZK9vac= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1611882497; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=5L59xU9wVj0tK8cnn1xfmiztIbM883HqzN6NgU/DUus=; b=IUnDJKfThf2EpJBMAAwZPus0FT2ZGd7/mwM3DOTgn7LxkNzX94KAKJHA+6/vO0tk+9EtIC1INe32mnwM6dd77NUAur/2q9bdSiSH9kHKy0eslTnKmLuP7beO+l4K/k8ozM7zQFxOCspIBB2ftSri6YDEnsJ1Yro06mYrVwFJ+W8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 161188249725294.64460651548461; Thu, 28 Jan 2021 17:08:17 -0800 (PST) Received: from localhost ([::1]:56682 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l5IGl-0007Qc-Rp for importer@patchew.org; Thu, 28 Jan 2021 20:08:16 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:55640) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3DV8TYAgKCiASQD6KPODCKKCHA.8KIMAIQ-9ARAHJKJCJQ.KNC@flex--wuhaotsh.bounces.google.com>) id 1l5ICu-00035y-Ma for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:16 -0500 Received: from mail-pg1-x54a.google.com ([2607:f8b0:4864:20::54a]:52862) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3DV8TYAgKCiASQD6KPODCKKCHA.8KIMAIQ-9ARAHJKJCJQ.KNC@flex--wuhaotsh.bounces.google.com>) id 1l5ICs-0004WW-Vp for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:16 -0500 Received: by mail-pg1-x54a.google.com with SMTP id 18so5106150pgf.19 for ; Thu, 28 Jan 2021 17:04:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=5L59xU9wVj0tK8cnn1xfmiztIbM883HqzN6NgU/DUus=; b=TDvJ+JOvg5KNVqJep2Rs2uPZInicmC0tZ+wrLDjT5u3s3JVeRj9qORVWfV79nxtb19 QLr7PuNw0QZEsNZkrs+fezPgIXmMzuSlP6FASzYZKRQfwSMw/hNeBsBCd1+v+cX0dlFT HKCdyb3k1klUffiGk7cGqD8MsihinrMBqmTROUyg1yZsW5uwZHoqEVtoBPnOWWsiHpVU YQiED6l9omBtXrPgonHWpGr9s2hg2mRIw1XHyjbKFms20Ntyamr6iKnQr+pAEPJdD+0w 3jfRWv+fq0b1j48an9FBk3tyrlZ4AdoAoZqpNOGvbS9eUDvZmYUfPFKRP0dPQFpVn2Qf QDpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=5L59xU9wVj0tK8cnn1xfmiztIbM883HqzN6NgU/DUus=; b=lBn2YpZuN87EMw0WdGyEv1MQPJ0bqAL10YDUTsTXyPcg4Jun0XqdFBBgfbkncsPGpg WFXUPztDS68wrk4+18n05LvT2q3Xnpn5UUEUTrrRJsJxYsU4uWhqMj5oJTyqyFYmZ6nE /5rjjVyujH+eCSmdo0qW9SnXzcdeUo/RZrxj0sWTYER0+sS05PPCgXSlOxSVhWlqqtD3 fL2Yklx0gQ1AaL8qGm8iKEcFaHeMX4i+DfB6pIWnRz/JYvHqbeU/2tbcwAT8ZheaTHF0 FkaAY0EGBCUUkDLyXjtyUzSSQW6GCRUwAtkfLvbLEgmRbU5YQHQmrEvTeLP+g+YAGyqH 7U3g== X-Gm-Message-State: AOAM530i5654e8f2bOrjqedb79r5oFdivsF12Lvs3cGyGZyuzC76qY9d aUwmRNts5LkCRx9w8i+CbeDMywMs/MEQag== X-Google-Smtp-Source: ABdhPJytIpPOhP87UEj3VVVqGvq8I7+WpjLx+tb+JAbe9FR6fyoaQuESaUBcLzOu1DB8autMLHqdNcJMvz0t8g== X-Received: from mimik.c.googlers.com ([fda3:e722:ac3:10:7f:e700:c0a8:4e]) (user=wuhaotsh job=sendgmr) by 2002:a17:90a:d305:: with SMTP id p5mr2059893pju.33.1611882253387; Thu, 28 Jan 2021 17:04:13 -0800 (PST) Date: Thu, 28 Jan 2021 16:58:43 -0800 In-Reply-To: <20210129005845.416272-1-wuhaotsh@google.com> Message-Id: <20210129005845.416272-5-wuhaotsh@google.com> Mime-Version: 1.0 References: <20210129005845.416272-1-wuhaotsh@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH v2 4/6] hw/arm: Add I2C sensors and EEPROM for GSJ machine To: peter.maydell@linaro.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::54a; envelope-from=3DV8TYAgKCiASQD6KPODCKKCHA.8KIMAIQ-9ARAHJKJCJQ.KNC@flex--wuhaotsh.bounces.google.com; helo=mail-pg1-x54a.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: cminyard@mvista.com, venture@google.com, hskinnemoen@google.com, qemu-devel@nongnu.org, wuhaotsh@google.com, kfting@nuvoton.com, qemu-arm@nongnu.org, Avi.Fishman@nuvoton.com, dje@google.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Hao Wu From: wuhaotsh--- via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add AT24 EEPROM and temperature sensors for GSJ machine. Reviewed-by: Doug Evans Reviewed-by: Tyrong Ting Signed-off-by: Hao Wu --- default-configs/devices/arm-softmmu.mak | 1 + hw/arm/npcm7xx_boards.c | 27 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devi= ces/arm-softmmu.mak index 0500156a0c..d9805dd539 100644 --- a/default-configs/devices/arm-softmmu.mak +++ b/default-configs/devices/arm-softmmu.mak @@ -7,6 +7,7 @@ CONFIG_ARM_V7M=3Dy # CONFIG_TEST_DEVICES=3Dn =20 CONFIG_ARM_VIRT=3Dy +CONFIG_AT24C=3Dy CONFIG_CUBIEBOARD=3Dy CONFIG_EXYNOS4=3Dy CONFIG_HIGHBANK=3Dy diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 47a215bd01..2d757b4013 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -19,6 +19,7 @@ #include "exec/address-spaces.h" #include "hw/arm/npcm7xx.h" #include "hw/core/cpu.h" +#include "hw/i2c/smbus_eeprom.h" #include "hw/loader.h" #include "hw/qdev-properties.h" #include "qapi/error.h" @@ -104,6 +105,17 @@ static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, = uint32_t num) return I2C_BUS(qdev_get_child_bus(DEVICE(&soc->smbus[num]), "i2c-bus")= ); } =20 +static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr, + uint32_t rsize) +{ + I2CBus *i2c_bus =3D npcm7xx_i2c_get_bus(soc, bus); + I2CSlave *i2c_dev =3D i2c_slave_new("at24c-eeprom", addr); + DeviceState *dev =3D DEVICE(i2c_dev); + + qdev_prop_set_uint32(dev, "rom-size", rsize); + i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort); +} + static void npcm750_evb_i2c_init(NPCM7xxState *soc) { /* lm75 temperature sensor on SVB, tmp105 is compatible */ @@ -116,6 +128,20 @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48); } =20 +static void quanta_gsj_i2c_init(NPCM7xxState *soc) +{ + /* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatib= le. */ + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x5c); + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x5c); + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 3), "tmp105", 0x5c); + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), "tmp105", 0x5c); + + at24c_eeprom_init(soc, 9, 0x55, 8192); + at24c_eeprom_init(soc, 10, 0x55, 8192); + + /* TODO: Add addtional i2c devices. */ +} + static void npcm750_evb_init(MachineState *machine) { NPCM7xxState *soc; @@ -141,6 +167,7 @@ static void quanta_gsj_init(MachineState *machine) npcm7xx_load_bootrom(machine, soc); npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e", drive_get(IF_MTD, 0, 0)); + quanta_gsj_i2c_init(soc); npcm7xx_load_kernel(machine, soc); } =20 --=20 2.30.0.365.g02bc693789-goog From nobody Fri May 17 01:12:43 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1611882739; cv=none; d=zohomail.com; s=zohoarc; b=YQbq8NJpPevlzCxm/rtKw/0hEXQO6rNjSwM/oEAG+fBz/A9KRZOQEmTTHok1UffUjgguxER9aP7XadSQNZyojtqrohK8p8PY9R4NnH6v5A/PB8nRiyRRUcZYFdSlVNHYLZ6WfrglvaOBmqWj2mLRSevff8XKVZaXZpGu4XrecJI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1611882739; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=PDVjhBTkNEN6+4rAJ7Cd8nEPSfTjViQIWXCbv9mKhXE=; b=IOyTgVzXwxMVaCJI475pGQcFO0MDJIrulgzzSq6njFKeaGJNCcqlAhnqTJVtOfUpMuSIhaoXgp1nYrM0fMbVBIFPqSGPWFSXPI7MxXbo4RHU2rkNe9DekO7TbRkol3s+CKVYdCcvudiCaKmLBXyojJRo4/oXjpHzY+lgxKMi6Xc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1611882739516364.31399241089946; Thu, 28 Jan 2021 17:12:19 -0800 (PST) Received: from localhost ([::1]:34138 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l5IKg-0001S9-4f for importer@patchew.org; Thu, 28 Jan 2021 20:12:18 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:55676) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3D18TYAgKCiIUSF8MRQFEMMEJC.AMKOCKS-BCTCJLMLELS.MPE@flex--wuhaotsh.bounces.google.com>) id 1l5ICy-0003Fu-Fz for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:20 -0500 Received: from mail-pg1-x54a.google.com ([2607:f8b0:4864:20::54a]:38557) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3D18TYAgKCiIUSF8MRQFEMMEJC.AMKOCKS-BCTCJLMLELS.MPE@flex--wuhaotsh.bounces.google.com>) id 1l5ICv-0004Xl-2k for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:20 -0500 Received: by mail-pg1-x54a.google.com with SMTP id l2so5112760pgi.5 for ; Thu, 28 Jan 2021 17:04:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=PDVjhBTkNEN6+4rAJ7Cd8nEPSfTjViQIWXCbv9mKhXE=; b=gRHgTttRQIbxp+u8aFItfneBzkAV+Ugco5J8BZwtZ8jpIyid+qx1MUhc9T1Jgl2hcu kVgTRHbcz4tXHAeQDx3dI619pgtgCALy2Ys3UilQ79kmUX+fW11CyQZlb4UldL3KB8t7 xNBXU+V8lv0RDSM0KMBwWt+sYZE4NltZxTWbaUIsvVl107neUMMNBgLcNKOC+0cwY3Ih ymcnPjrgf9vkHks0Vkl7ZOGlekS4KNBCBrohmHlisgCI7UZOdVyWk0NeIfhDbGJGHhEM CvqWsO0JcVgVGFyL//AcBQmm1Pu6/IHozapM1yVNZ6RfS+sWRk1lbSEymZByVrG7XXQ9 5bdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=PDVjhBTkNEN6+4rAJ7Cd8nEPSfTjViQIWXCbv9mKhXE=; b=rNvmmZirYx00HsB+fSNYJAUdQKNrBv+w2kCOltBWWGWSeNrTCUK60oqkB8w2UOcCMh a6Q4AR5fidzAF17jZ8S5MSHQhLfGU5cZ+POnuio9U7c8C3PZtRCyTo1g/EP+Jy5jipY9 SzXkKIqecP2l6wn7R1LcUx8aQUUkmw3MHYs7KNn1i3g003ytHFCARTvDDhCJzUtxfLFu oIhRg8K1ChR7KoUwhdner0NHjHKfMJCSY7ogTw6oFXhHM+Tu1gss/w1XsBBYulF4a9om 4yzyoLqtYSgn8NKfaUWvHWYilwnI60G6nIdwsE26AQhCLHQ7DM9+NDlPRtzel2Q0tjtI tiAw== X-Gm-Message-State: AOAM532nUKUZZMQsR29tGai7XwdpMemdBKMNOfTsPbZg3RSZvrlUh3wh Qr867HJkh/LuV23VcSvY1f52vb7HirIuqQ== X-Google-Smtp-Source: ABdhPJwc9b/BFTTlqeZOl6PadJNaBV80fsIbbvQ4oJvy1zN9ErPIVQDfshJMgZRoWYvNbE/g7YWITdoIkWBg5Q== X-Received: from mimik.c.googlers.com ([fda3:e722:ac3:10:7f:e700:c0a8:4e]) (user=wuhaotsh job=sendgmr) by 2002:a17:902:be0d:b029:e1:4ab:8fd2 with SMTP id r13-20020a170902be0db02900e104ab8fd2mr1837219pls.6.1611882255089; Thu, 28 Jan 2021 17:04:15 -0800 (PST) Date: Thu, 28 Jan 2021 16:58:44 -0800 In-Reply-To: <20210129005845.416272-1-wuhaotsh@google.com> Message-Id: <20210129005845.416272-6-wuhaotsh@google.com> Mime-Version: 1.0 References: <20210129005845.416272-1-wuhaotsh@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH v2 5/6] hw/i2c: Add a QTest for NPCM7XX SMBus Device To: peter.maydell@linaro.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::54a; envelope-from=3D18TYAgKCiIUSF8MRQFEMMEJC.AMKOCKS-BCTCJLMLELS.MPE@flex--wuhaotsh.bounces.google.com; helo=mail-pg1-x54a.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: cminyard@mvista.com, venture@google.com, hskinnemoen@google.com, qemu-devel@nongnu.org, wuhaotsh@google.com, kfting@nuvoton.com, qemu-arm@nongnu.org, Avi.Fishman@nuvoton.com, dje@google.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Hao Wu From: wuhaotsh--- via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch adds a QTest for NPCM7XX SMBus's single byte mode. It sends a byte to a device in the evaluation board, and verify the retrieved value is equivalent to the sent value. Reviewed-by: Doug Evans Reviewed-by: Tyrong Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_smbus-test.c | 352 +++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+) create mode 100644 tests/qtest/npcm7xx_smbus-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 16d04625b8..aa62d59817 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -138,6 +138,7 @@ qtests_npcm7xx =3D \ 'npcm7xx_gpio-test', 'npcm7xx_pwm-test', 'npcm7xx_rng-test', + 'npcm7xx_smbus-test', 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] qtests_arm =3D \ diff --git a/tests/qtest/npcm7xx_smbus-test.c b/tests/qtest/npcm7xx_smbus-t= est.c new file mode 100644 index 0000000000..4594b107df --- /dev/null +++ b/tests/qtest/npcm7xx_smbus-test.c @@ -0,0 +1,352 @@ +/* + * QTests for Nuvoton NPCM7xx SMBus Modules. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WIT= HOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "libqos/i2c.h" +#include "libqos/libqtest.h" +#include "hw/misc/tmp105_regs.h" + +#define NR_SMBUS_DEVICES 16 +#define SMBUS_ADDR(x) (0xf0080000 + 0x1000 * (x)) +#define SMBUS_IRQ(x) (64 + (x)) + +#define EVB_DEVICE_ADDR 0x48 +#define INVALID_DEVICE_ADDR 0x01 + +const int evb_bus_list[] =3D {0, 1, 2, 6}; + +/* Offsets */ +enum CommonRegister { + OFFSET_SDA =3D 0x0, + OFFSET_ST =3D 0x2, + OFFSET_CST =3D 0x4, + OFFSET_CTL1 =3D 0x6, + OFFSET_ADDR1 =3D 0x8, + OFFSET_CTL2 =3D 0xa, + OFFSET_ADDR2 =3D 0xc, + OFFSET_CTL3 =3D 0xe, + OFFSET_CST2 =3D 0x18, + OFFSET_CST3 =3D 0x19, +}; + +enum NPCM7xxSMBusBank0Register { + OFFSET_ADDR3 =3D 0x10, + OFFSET_ADDR7 =3D 0x11, + OFFSET_ADDR4 =3D 0x12, + OFFSET_ADDR8 =3D 0x13, + OFFSET_ADDR5 =3D 0x14, + OFFSET_ADDR9 =3D 0x15, + OFFSET_ADDR6 =3D 0x16, + OFFSET_ADDR10 =3D 0x17, + OFFSET_CTL4 =3D 0x1a, + OFFSET_CTL5 =3D 0x1b, + OFFSET_SCLLT =3D 0x1c, + OFFSET_FIF_CTL =3D 0x1d, + OFFSET_SCLHT =3D 0x1e, +}; + +enum NPCM7xxSMBusBank1Register { + OFFSET_FIF_CTS =3D 0x10, + OFFSET_FAIR_PER =3D 0x11, + OFFSET_TXF_CTL =3D 0x12, + OFFSET_T_OUT =3D 0x14, + OFFSET_TXF_STS =3D 0x1a, + OFFSET_RXF_STS =3D 0x1c, + OFFSET_RXF_CTL =3D 0x1e, +}; + +/* ST fields */ +#define ST_STP BIT(7) +#define ST_SDAST BIT(6) +#define ST_BER BIT(5) +#define ST_NEGACK BIT(4) +#define ST_STASTR BIT(3) +#define ST_NMATCH BIT(2) +#define ST_MODE BIT(1) +#define ST_XMIT BIT(0) + +/* CST fields */ +#define CST_ARPMATCH BIT(7) +#define CST_MATCHAF BIT(6) +#define CST_TGSCL BIT(5) +#define CST_TSDA BIT(4) +#define CST_GCMATCH BIT(3) +#define CST_MATCH BIT(2) +#define CST_BB BIT(1) +#define CST_BUSY BIT(0) + +/* CST2 fields */ +#define CST2_INSTTS BIT(7) +#define CST2_MATCH7F BIT(6) +#define CST2_MATCH6F BIT(5) +#define CST2_MATCH5F BIT(4) +#define CST2_MATCH4F BIT(3) +#define CST2_MATCH3F BIT(2) +#define CST2_MATCH2F BIT(1) +#define CST2_MATCH1F BIT(0) + +/* CST3 fields */ +#define CST3_EO_BUSY BIT(7) +#define CST3_MATCH10F BIT(2) +#define CST3_MATCH9F BIT(1) +#define CST3_MATCH8F BIT(0) + +/* CTL1 fields */ +#define CTL1_STASTRE BIT(7) +#define CTL1_NMINTE BIT(6) +#define CTL1_GCMEN BIT(5) +#define CTL1_ACK BIT(4) +#define CTL1_EOBINTE BIT(3) +#define CTL1_INTEN BIT(2) +#define CTL1_STOP BIT(1) +#define CTL1_START BIT(0) + +/* CTL2 fields */ +#define CTL2_SCLFRQ(rv) extract8((rv), 1, 6) +#define CTL2_ENABLE BIT(0) + +/* CTL3 fields */ +#define CTL3_SCL_LVL BIT(7) +#define CTL3_SDA_LVL BIT(6) +#define CTL3_BNK_SEL BIT(5) +#define CTL3_400K_MODE BIT(4) +#define CTL3_IDL_START BIT(3) +#define CTL3_ARPMEN BIT(2) +#define CTL3_SCLFRQ(rv) extract8((rv), 0, 2) + +/* ADDR fields */ +#define ADDR_EN BIT(7) +#define ADDR_A(rv) extract8((rv), 0, 6) + + +static void check_running(QTestState *qts, uint64_t base_addr) +{ + g_assert_true(qtest_readb(qts, base_addr + OFFSET_CST) & CST_BUSY); + g_assert_true(qtest_readb(qts, base_addr + OFFSET_CST) & CST_BB); +} + +static void check_stopped(QTestState *qts, uint64_t base_addr) +{ + uint8_t cst3; + + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_ST), =3D=3D, 0); + g_assert_false(qtest_readb(qts, base_addr + OFFSET_CST) & CST_BUSY); + g_assert_false(qtest_readb(qts, base_addr + OFFSET_CST) & CST_BB); + + cst3 =3D qtest_readb(qts, base_addr + OFFSET_CST3); + g_assert_true(cst3 & CST3_EO_BUSY); + qtest_writeb(qts, base_addr + OFFSET_CST3, cst3); + cst3 =3D qtest_readb(qts, base_addr + OFFSET_CST3); + g_assert_false(cst3 & CST3_EO_BUSY); +} + +static void enable_bus(QTestState *qts, uint64_t base_addr) +{ + uint8_t ctl2 =3D qtest_readb(qts, base_addr + OFFSET_CTL2); + + ctl2 |=3D CTL2_ENABLE; + qtest_writeb(qts, base_addr + OFFSET_CTL2, ctl2); + g_assert_true(qtest_readb(qts, base_addr + OFFSET_CTL2) & CTL2_ENABLE); +} + +static void disable_bus(QTestState *qts, uint64_t base_addr) +{ + uint8_t ctl2 =3D qtest_readb(qts, base_addr + OFFSET_CTL2); + + ctl2 &=3D ~CTL2_ENABLE; + qtest_writeb(qts, base_addr + OFFSET_CTL2, ctl2); + g_assert_false(qtest_readb(qts, base_addr + OFFSET_CTL2) & CTL2_ENABLE= ); +} + +static void start_transfer(QTestState *qts, uint64_t base_addr) +{ + uint8_t ctl1; + + ctl1 =3D CTL1_START | CTL1_INTEN | CTL1_STASTRE; + qtest_writeb(qts, base_addr + OFFSET_CTL1, ctl1); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_CTL1), =3D=3D, + CTL1_INTEN | CTL1_STASTRE | CTL1_INTEN); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_ST), =3D=3D, + ST_MODE | ST_XMIT | ST_SDAST); + check_running(qts, base_addr); +} + +static void stop_transfer(QTestState *qts, uint64_t base_addr) +{ + uint8_t ctl1 =3D qtest_readb(qts, base_addr + OFFSET_CTL1); + + ctl1 &=3D ~(CTL1_START | CTL1_ACK); + ctl1 |=3D CTL1_STOP | CTL1_INTEN | CTL1_EOBINTE; + qtest_writeb(qts, base_addr + OFFSET_CTL1, ctl1); + ctl1 =3D qtest_readb(qts, base_addr + OFFSET_CTL1); + g_assert_false(ctl1 & CTL1_STOP); +} + +static void send_byte(QTestState *qts, uint64_t base_addr, uint8_t byte) +{ + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_ST), =3D=3D, + ST_MODE | ST_XMIT | ST_SDAST); + qtest_writeb(qts, base_addr + OFFSET_SDA, byte); +} + +static uint8_t recv_byte(QTestState *qts, uint64_t base_addr) +{ + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_ST), =3D=3D, + ST_MODE | ST_SDAST); + return qtest_readb(qts, base_addr + OFFSET_SDA); +} + +static void send_address(QTestState *qts, uint64_t base_addr, uint8_t addr, + bool recv, bool valid) +{ + uint8_t encoded_addr =3D (addr << 1) | (recv ? 1 : 0); + uint8_t st; + + qtest_writeb(qts, base_addr + OFFSET_SDA, encoded_addr); + st =3D qtest_readb(qts, base_addr + OFFSET_ST); + + if (valid) { + if (recv) { + g_assert_cmphex(st, =3D=3D, ST_MODE | ST_SDAST | ST_STASTR); + } else { + g_assert_cmphex(st, =3D=3D, ST_MODE | ST_XMIT | ST_SDAST | ST_= STASTR); + } + + qtest_writeb(qts, base_addr + OFFSET_ST, ST_STASTR); + st =3D qtest_readb(qts, base_addr + OFFSET_ST); + if (recv) { + g_assert_cmphex(st, =3D=3D, ST_MODE | ST_SDAST); + } else { + g_assert_cmphex(st, =3D=3D, ST_MODE | ST_XMIT | ST_SDAST); + } + } else { + if (recv) { + g_assert_cmphex(st, =3D=3D, ST_MODE | ST_NEGACK); + } else { + g_assert_cmphex(st, =3D=3D, ST_MODE | ST_XMIT | ST_NEGACK); + } + } +} + +static void send_nack(QTestState *qts, uint64_t base_addr) +{ + uint8_t ctl1 =3D qtest_readb(qts, base_addr + OFFSET_CTL1); + + ctl1 &=3D ~(CTL1_START | CTL1_STOP); + ctl1 |=3D CTL1_ACK | CTL1_INTEN; + qtest_writeb(qts, base_addr + OFFSET_CTL1, ctl1); +} + +/* Check the SMBus's status is set correctly when disabled. */ +static void test_disable_bus(gconstpointer data) +{ + intptr_t index =3D (intptr_t)data; + uint64_t base_addr =3D SMBUS_ADDR(index); + QTestState *qts =3D qtest_init("-machine npcm750-evb"); + + disable_bus(qts, base_addr); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_CTL1), =3D=3D, 0); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_ST), =3D=3D, 0); + g_assert_false(qtest_readb(qts, base_addr + OFFSET_CST3) & CST3_EO_BUS= Y); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_CST), =3D=3D, 0); + qtest_quit(qts); +} + +/* Check the SMBus returns a NACK for an invalid address. */ +static void test_invalid_addr(gconstpointer data) +{ + intptr_t index =3D (intptr_t)data; + uint64_t base_addr =3D SMBUS_ADDR(index); + int irq =3D SMBUS_IRQ(index); + QTestState *qts =3D qtest_init("-machine npcm750-evb"); + + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + enable_bus(qts, base_addr); + g_assert_false(qtest_get_irq(qts, irq)); + start_transfer(qts, base_addr); + send_address(qts, base_addr, INVALID_DEVICE_ADDR, false, false); + g_assert_true(qtest_get_irq(qts, irq)); + stop_transfer(qts, base_addr); + check_running(qts, base_addr); + qtest_writeb(qts, base_addr + OFFSET_ST, ST_NEGACK); + g_assert_false(qtest_readb(qts, base_addr + OFFSET_ST) & ST_NEGACK); + check_stopped(qts, base_addr); + qtest_quit(qts); +} + +/* Check the SMBus can send and receive bytes to a device in single mode. = */ +static void test_single_mode(gconstpointer data) +{ + intptr_t index =3D (intptr_t)data; + uint64_t base_addr =3D SMBUS_ADDR(index); + int irq =3D SMBUS_IRQ(index); + uint8_t value =3D 0x60; + QTestState *qts =3D qtest_init("-machine npcm750-evb"); + + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + enable_bus(qts, base_addr); + + /* Sending */ + g_assert_false(qtest_get_irq(qts, irq)); + start_transfer(qts, base_addr); + g_assert_true(qtest_get_irq(qts, irq)); + send_address(qts, base_addr, EVB_DEVICE_ADDR, false, true); + send_byte(qts, base_addr, TMP105_REG_CONFIG); + send_byte(qts, base_addr, value); + stop_transfer(qts, base_addr); + check_stopped(qts, base_addr); + + /* Receiving */ + start_transfer(qts, base_addr); + send_address(qts, base_addr, EVB_DEVICE_ADDR, false, true); + send_byte(qts, base_addr, TMP105_REG_CONFIG); + start_transfer(qts, base_addr); + send_address(qts, base_addr, EVB_DEVICE_ADDR, true, true); + send_nack(qts, base_addr); + stop_transfer(qts, base_addr); + check_running(qts, base_addr); + g_assert_cmphex(recv_byte(qts, base_addr), =3D=3D, value); + check_stopped(qts, base_addr); + qtest_quit(qts); +} + +static void smbus_add_test(const char *name, int index, GTestDataFunc fn) +{ + g_autofree char *full_name =3D g_strdup_printf( + "npcm7xx_smbus[%d]/%s", index, name); + qtest_add_data_func(full_name, (void *)(intptr_t)index, fn); +} +#define add_test(name, td) smbus_add_test(#name, td, test_##name) + +int main(int argc, char **argv) +{ + int i; + + g_test_init(&argc, &argv, NULL); + g_test_set_nonfatal_assertions(); + + for (i =3D 0; i < NR_SMBUS_DEVICES; ++i) { + add_test(disable_bus, i); + add_test(invalid_addr, i); + } + + for (i =3D 0; i < ARRAY_SIZE(evb_bus_list); ++i) { + add_test(single_mode, evb_bus_list[i]); + } + + return g_test_run(); +} --=20 2.30.0.365.g02bc693789-goog From nobody Fri May 17 01:12:43 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1611882602; cv=none; d=zohomail.com; s=zohoarc; b=R4/gOpOv63/x/5Rd378R1UGPXwosAHn22XiUzHe5QAROhEXXGdzOGOdcmIWXhGS+O74A2aMDz0QzFn6+5audySIy/JY+FCAXzGsDGnwqs/EVdHLBIwhHbvSuazB/F2c7YjFxcwXul7QLtAzeicWqSzrj5Oe0//Uf//WTcO9fvpM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1611882602; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=670NcSEVXiQ/MdDkXJ2LgL1hRHqoDibS53P7IaEqbDs=; b=QMZjeqagMJHpZbtArNDABZlT+Fc4k2TQK9zEkCnIub0iXBhWryv+oI0/0i6FFM9GZ8qRrW8GAZ0oTFPd9e5cLw4sEnKPaPQSi7P6b/MrKEtdo9AlvjLNZorzTsiFJZRSn236sugH+eS8jKK6XtLWMm/ic/uws0TPOML9uBPOj1Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1611882602384363.6368389246652; Thu, 28 Jan 2021 17:10:02 -0800 (PST) Received: from localhost ([::1]:60826 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l5IIT-0000gc-7v for importer@patchew.org; Thu, 28 Jan 2021 20:10:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:55694) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3EV8TYAgKCiQWUHAOTSHGOOGLE.COMQEMU-DEVELNONGNU.ORG@flex--wuhaotsh.bounces.google.com>) id 1l5ID0-0003JZ-9O for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:22 -0500 Received: from mail-pg1-x54a.google.com ([2607:f8b0:4864:20::54a]:44430) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3EV8TYAgKCiQWUHAOTSHGOOGLE.COMQEMU-DEVELNONGNU.ORG@flex--wuhaotsh.bounces.google.com>) id 1l5ICx-0004Z1-8v for qemu-devel@nongnu.org; Thu, 28 Jan 2021 20:04:22 -0500 Received: by mail-pg1-x54a.google.com with SMTP id 139so5126700pgd.11 for ; Thu, 28 Jan 2021 17:04:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=670NcSEVXiQ/MdDkXJ2LgL1hRHqoDibS53P7IaEqbDs=; b=qeo9XUmkv9NnOUln2994KOYb5K1wymY4BzEFTPyfbsPndtlkbDNWT3bThtNDPnoO4x 6l3BeJDP/nc86ffvMhS7+3pbQw48eepZEvpaTb9cRydmKNPE+21YmQrhJNzCBV8mxQB7 jeb6emTF+epieZGGucdxFXKthgQge33Wh8UU+hMfdxzuS6IMbm24Bp221rQ2pRtc5JNo gFXBvMTrAa7l3lrahLjRTQ7klvtpRz3q/f8Wf53H0Hv8NxvcemXjuyyf5XgLnLZ5Lje0 XqOZmR8tTh9jb4vnVOCiBay59AcR81JVnX1SdTImhT+J+00/g0aMc/OoHQVHj76p0FyU 3/eQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=670NcSEVXiQ/MdDkXJ2LgL1hRHqoDibS53P7IaEqbDs=; b=kpZaC/t2DP+y8wnZVanpxBT+w87Ta2UNH8SAssch9SS9Hu3aR+Cp2Iufywy/3/0UJR b/U2dMxqlLTZbLgZsYVNxvA9d/FC/1MUt/fFhnNlLs96YPvmjI+ddpLUqbKvmyjyagvy Aju7Dou588RDLf8ryw6TIoxtMMtK18WW3PYugSOQN+idbNZoebwKV3Ma4D6aVxG9nNhs Fs03Vhg6mGnycZaVJEnKjIH6mdYBopTme2hhm0IxoG6+KxpiNn9Rpv7+zmgm2gHINWnR 3KnNhc1x9pDsJDuMYAMH9OW0wlV8vKJ4I4J+5h3LUrKVFKpb6eeZIYOTCIgAc8p828nO fhSw== X-Gm-Message-State: AOAM5313Bh3uuGyD+lpXyc+6xwl1+ohTR/Btb12v3JRKkTHxXJ/9d0zT FSIOGcNk05/+C0ZD+1LgU+xD9/L7mBYtag== X-Google-Smtp-Source: ABdhPJwEkWK7zahm9tlRFXU+wq3XyrD0B1S7uhQTnpMpHHojlU291NKldeQmQniedBkTS+ZTUXCXTEaC9bayFA== X-Received: from mimik.c.googlers.com ([fda3:e722:ac3:10:7f:e700:c0a8:4e]) (user=wuhaotsh job=sendgmr) by 2002:a63:50a:: with SMTP id 10mr2008781pgf.273.1611882257700; Thu, 28 Jan 2021 17:04:17 -0800 (PST) Date: Thu, 28 Jan 2021 16:58:45 -0800 In-Reply-To: <20210129005845.416272-1-wuhaotsh@google.com> Message-Id: <20210129005845.416272-7-wuhaotsh@google.com> Mime-Version: 1.0 References: <20210129005845.416272-1-wuhaotsh@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH v2 6/6] hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode To: peter.maydell@linaro.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::54a; envelope-from=3EV8TYAgKCiQWUHAOTSHGOOGLE.COMQEMU-DEVELNONGNU.ORG@flex--wuhaotsh.bounces.google.com; helo=mail-pg1-x54a.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: cminyard@mvista.com, venture@google.com, hskinnemoen@google.com, qemu-devel@nongnu.org, wuhaotsh@google.com, kfting@nuvoton.com, qemu-arm@nongnu.org, Avi.Fishman@nuvoton.com, dje@google.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Hao Wu From: wuhaotsh--- via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch implements the FIFO mode of the SMBus module. In FIFO, the user transmits or receives at most 16 bytes at a time. The FIFO mode allows the module to transmit large amount of data faster than single byte mode. Reviewed-by: Doug Evans Reviewed-by: Tyrong Ting Signed-off-by: Hao Wu Reviewed-by: Corey Minyard Ack-by: Corey Minyard --- hw/i2c/npcm7xx_smbus.c | 342 +++++++++++++++++++++++++++++-- hw/i2c/trace-events | 1 + include/hw/i2c/npcm7xx_smbus.h | 25 +++ tests/qtest/npcm7xx_smbus-test.c | 149 +++++++++++++- 4 files changed, 501 insertions(+), 16 deletions(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index c72b6e446f..be3253d251 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -27,7 +27,7 @@ #include "trace.h" =20 #define NPCM7XX_SMBUS_VERSION 1 -#define NPCM7XX_SMBUS_FIFO_EN 0 +#define NPCM7XX_SMBUS_FIFO_EN 1 =20 enum NPCM7xxSMBusCommonRegister { NPCM7XX_SMB_SDA =3D 0x0, @@ -132,10 +132,41 @@ enum NPCM7xxSMBusBank1Register { #define NPCM7XX_ADDR_EN BIT(7) #define NPCM7XX_ADDR_A(rv) extract8((rv), 0, 6) =20 +/* FIFO Mode Register Fields */ +/* FIF_CTL fields */ +#define NPCM7XX_SMBFIF_CTL_FIFO_EN BIT(4) +#define NPCM7XX_SMBFIF_CTL_FAIR_RDY_IE BIT(2) +#define NPCM7XX_SMBFIF_CTL_FAIR_RDY BIT(1) +#define NPCM7XX_SMBFIF_CTL_FAIR_BUSY BIT(0) +/* FIF_CTS fields */ +#define NPCM7XX_SMBFIF_CTS_STR BIT(7) +#define NPCM7XX_SMBFIF_CTS_CLR_FIFO BIT(6) +#define NPCM7XX_SMBFIF_CTS_RFTE_IE BIT(3) +#define NPCM7XX_SMBFIF_CTS_RXF_TXE BIT(1) +/* TXF_CTL fields */ +#define NPCM7XX_SMBTXF_CTL_THR_TXIE BIT(6) +#define NPCM7XX_SMBTXF_CTL_TX_THR(rv) extract8((rv), 0, 5) +/* T_OUT fields */ +#define NPCM7XX_SMBT_OUT_ST BIT(7) +#define NPCM7XX_SMBT_OUT_IE BIT(6) +#define NPCM7XX_SMBT_OUT_CLKDIV(rv) extract8((rv), 0, 6) +/* TXF_STS fields */ +#define NPCM7XX_SMBTXF_STS_TX_THST BIT(6) +#define NPCM7XX_SMBTXF_STS_TX_BYTES(rv) extract8((rv), 0, 5) +/* RXF_STS fields */ +#define NPCM7XX_SMBRXF_STS_RX_THST BIT(6) +#define NPCM7XX_SMBRXF_STS_RX_BYTES(rv) extract8((rv), 0, 5) +/* RXF_CTL fields */ +#define NPCM7XX_SMBRXF_CTL_THR_RXIE BIT(6) +#define NPCM7XX_SMBRXF_CTL_LAST BIT(5) +#define NPCM7XX_SMBRXF_CTL_RX_THR(rv) extract8((rv), 0, 5) + #define KEEP_OLD_BIT(o, n, b) (((n) & (~(b))) | ((o) & (b))) #define WRITE_ONE_CLEAR(o, n, b) ((n) & (b) ? (o) & (~(b)) : (o)) =20 #define NPCM7XX_SMBUS_ENABLED(s) ((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE) +#define NPCM7XX_SMBUS_FIFO_ENABLED(s) (NPCM7XX_SMBUS_FIFO_EN && \ + (s)->fif_ctl & NPCM7XX_SMBFIF_CTL_FIFO_EN) =20 /* Reset values */ #define NPCM7XX_SMB_ST_INIT_VAL 0x00 @@ -150,6 +181,14 @@ enum NPCM7xxSMBusBank1Register { #define NPCM7XX_SMB_ADDR_INIT_VAL 0x00 #define NPCM7XX_SMB_SCLLT_INIT_VAL 0x00 #define NPCM7XX_SMB_SCLHT_INIT_VAL 0x00 +#define NPCM7XX_SMB_FIF_CTL_INIT_VAL 0x00 +#define NPCM7XX_SMB_FIF_CTS_INIT_VAL 0x00 +#define NPCM7XX_SMB_FAIR_PER_INIT_VAL 0x00 +#define NPCM7XX_SMB_TXF_CTL_INIT_VAL 0x00 +#define NPCM7XX_SMB_T_OUT_INIT_VAL 0x3f +#define NPCM7XX_SMB_TXF_STS_INIT_VAL 0x00 +#define NPCM7XX_SMB_RXF_STS_INIT_VAL 0x00 +#define NPCM7XX_SMB_RXF_CTL_INIT_VAL 0x01 =20 static uint8_t npcm7xx_smbus_get_version(void) { @@ -169,7 +208,13 @@ static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState= *s) (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE && s->st & NPCM7XX_SMBST_SDAST) || (s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE && - s->cst3 & NPCM7XX_SMBCST3_EO_BUSY)); + s->cst3 & NPCM7XX_SMBCST3_EO_BUSY) || + (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE && + s->rxf_sts & NPCM7XX_SMBRXF_STS_RX_THST) || + (s->txf_ctl & NPCM7XX_SMBTXF_CTL_THR_TXIE && + s->txf_sts & NPCM7XX_SMBTXF_STS_TX_THST) || + (s->fif_cts & NPCM7XX_SMBFIF_CTS_RFTE_IE && + s->fif_cts & NPCM7XX_SMBFIF_CTS_RXF_TXE)); =20 if (level) { s->cst2 |=3D NPCM7XX_SMBCST2_INTSTS; @@ -187,6 +232,13 @@ static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s) s->status =3D NPCM7XX_SMBUS_STATUS_NEGACK; } =20 +static void npcm7xx_smbus_clear_buffer(NPCM7xxSMBusState *s) +{ + s->fif_cts &=3D ~NPCM7XX_SMBFIF_CTS_RXF_TXE; + s->txf_sts =3D 0; + s->rxf_sts =3D 0; +} + static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value) { int rv =3D i2c_send(s->bus, value); @@ -195,6 +247,15 @@ static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState = *s, uint8_t value) npcm7xx_smbus_nack(s); } else { s->st |=3D NPCM7XX_SMBST_SDAST; + if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { + s->fif_cts |=3D NPCM7XX_SMBFIF_CTS_RXF_TXE; + if (NPCM7XX_SMBTXF_STS_TX_BYTES(s->txf_sts) =3D=3D + NPCM7XX_SMBTXF_CTL_TX_THR(s->txf_ctl)) { + s->txf_sts =3D NPCM7XX_SMBTXF_STS_TX_THST; + } else { + s->txf_sts =3D 0; + } + } } trace_npcm7xx_smbus_send_byte((DEVICE(s)->canonical_path), value, !rv); npcm7xx_smbus_update_irq(s); @@ -213,6 +274,67 @@ static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState = *s) npcm7xx_smbus_update_irq(s); } =20 +static void npcm7xx_smbus_recv_fifo(NPCM7xxSMBusState *s) +{ + uint8_t expected_bytes =3D NPCM7XX_SMBRXF_CTL_RX_THR(s->rxf_ctl); + uint8_t received_bytes =3D NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts); + uint8_t pos; + + if (received_bytes =3D=3D expected_bytes) { + return; + } + + while (received_bytes < expected_bytes && + received_bytes < NPCM7XX_SMBUS_FIFO_SIZE) { + pos =3D (s->rx_cur + received_bytes) % NPCM7XX_SMBUS_FIFO_SIZE; + s->rx_fifo[pos] =3D i2c_recv(s->bus); + trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), + s->rx_fifo[pos]); + ++received_bytes; + } + + trace_npcm7xx_smbus_recv_fifo((DEVICE(s)->canonical_path), + received_bytes, expected_bytes); + s->rxf_sts =3D received_bytes; + if (unlikely(received_bytes < expected_bytes)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid rx_thr value: 0x%02x\n", + DEVICE(s)->canonical_path, expected_bytes); + return; + } + + s->rxf_sts |=3D NPCM7XX_SMBRXF_STS_RX_THST; + if (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_LAST) { + trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); + i2c_nack(s->bus); + s->rxf_ctl &=3D ~NPCM7XX_SMBRXF_CTL_LAST; + } + if (received_bytes =3D=3D NPCM7XX_SMBUS_FIFO_SIZE) { + s->st |=3D NPCM7XX_SMBST_SDAST; + s->fif_cts |=3D NPCM7XX_SMBFIF_CTS_RXF_TXE; + } else if (!(s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE)) { + s->st |=3D NPCM7XX_SMBST_SDAST; + } else { + s->st &=3D ~NPCM7XX_SMBST_SDAST; + } + npcm7xx_smbus_update_irq(s); +} + +static void npcm7xx_smbus_read_byte_fifo(NPCM7xxSMBusState *s) +{ + uint8_t received_bytes =3D NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts); + + if (received_bytes =3D=3D 0) { + npcm7xx_smbus_recv_fifo(s); + return; + } + + s->sda =3D s->rx_fifo[s->rx_cur]; + s->rx_cur =3D (s->rx_cur + 1u) % NPCM7XX_SMBUS_FIFO_SIZE; + --s->rxf_sts; + npcm7xx_smbus_update_irq(s); +} + static void npcm7xx_smbus_start(NPCM7xxSMBusState *s) { /* @@ -226,6 +348,9 @@ static void npcm7xx_smbus_start(NPCM7xxSMBusState *s) if (available) { s->st |=3D NPCM7XX_SMBST_MODE | NPCM7XX_SMBST_XMIT | NPCM7XX_SMBST= _SDAST; s->cst |=3D NPCM7XX_SMBCST_BUSY; + if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { + s->fif_cts |=3D NPCM7XX_SMBFIF_CTS_RXF_TXE; + } } else { s->st &=3D ~NPCM7XX_SMBST_MODE; s->cst &=3D ~NPCM7XX_SMBCST_BUSY; @@ -277,7 +402,15 @@ static void npcm7xx_smbus_send_address(NPCM7xxSMBusSta= te *s, uint8_t value) s->st |=3D NPCM7XX_SMBST_SDAST; } } else if (recv) { - npcm7xx_smbus_recv_byte(s); + s->st |=3D NPCM7XX_SMBST_SDAST; + if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { + npcm7xx_smbus_recv_fifo(s); + } else { + npcm7xx_smbus_recv_byte(s); + } + } else if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { + s->st |=3D NPCM7XX_SMBST_SDAST; + s->fif_cts |=3D NPCM7XX_SMBFIF_CTS_RXF_TXE; } npcm7xx_smbus_update_irq(s); } @@ -320,11 +453,31 @@ static uint8_t npcm7xx_smbus_read_sda(NPCM7xxSMBusSta= te *s) =20 switch (s->status) { case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE: - npcm7xx_smbus_execute_stop(s); + if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { + if (NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) <=3D 1) { + npcm7xx_smbus_execute_stop(s); + } + if (NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) =3D=3D 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read to SDA with an empty rx-fifo buffe= r, " + "result undefined: %u\n", + DEVICE(s)->canonical_path, s->sda); + break; + } + npcm7xx_smbus_read_byte_fifo(s); + value =3D s->sda; + } else { + npcm7xx_smbus_execute_stop(s); + } break; =20 case NPCM7XX_SMBUS_STATUS_RECEIVING: - npcm7xx_smbus_recv_byte(s); + if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { + npcm7xx_smbus_read_byte_fifo(s); + value =3D s->sda; + } else { + npcm7xx_smbus_recv_byte(s); + } break; =20 default: @@ -370,8 +523,12 @@ static void npcm7xx_smbus_write_st(NPCM7xxSMBusState *= s, uint8_t value) } =20 if (value & NPCM7XX_SMBST_STASTR && - s->status =3D=3D NPCM7XX_SMBUS_STATUS_RECEIVING) { - npcm7xx_smbus_recv_byte(s); + s->status =3D=3D NPCM7XX_SMBUS_STATUS_RECEIVING) { + if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { + npcm7xx_smbus_recv_fifo(s); + } else { + npcm7xx_smbus_recv_byte(s); + } } =20 npcm7xx_smbus_update_irq(s); @@ -417,6 +574,7 @@ static void npcm7xx_smbus_write_ctl2(NPCM7xxSMBusState = *s, uint8_t value) s->st =3D 0; s->cst3 =3D s->cst3 & (~NPCM7XX_SMBCST3_EO_BUSY); s->cst =3D 0; + npcm7xx_smbus_clear_buffer(s); } } =20 @@ -429,6 +587,70 @@ static void npcm7xx_smbus_write_ctl3(NPCM7xxSMBusState= *s, uint8_t value) NPCM7XX_SMBCTL3_SCL_LVL | NPCM7XX_SMBCTL3_SDA_= LVL); } =20 +static void npcm7xx_smbus_write_fif_ctl(NPCM7xxSMBusState *s, uint8_t valu= e) +{ + uint8_t new_ctl =3D value; + + new_ctl =3D KEEP_OLD_BIT(s->fif_ctl, new_ctl, NPCM7XX_SMBFIF_CTL_FAIR_= RDY); + new_ctl =3D WRITE_ONE_CLEAR(new_ctl, value, NPCM7XX_SMBFIF_CTL_FAIR_RD= Y); + new_ctl =3D KEEP_OLD_BIT(s->fif_ctl, new_ctl, NPCM7XX_SMBFIF_CTL_FAIR_= BUSY); + s->fif_ctl =3D new_ctl; +} + +static void npcm7xx_smbus_write_fif_cts(NPCM7xxSMBusState *s, uint8_t valu= e) +{ + s->fif_cts =3D WRITE_ONE_CLEAR(s->fif_cts, value, NPCM7XX_SMBFIF_CTS_S= TR); + s->fif_cts =3D WRITE_ONE_CLEAR(s->fif_cts, value, NPCM7XX_SMBFIF_CTS_R= XF_TXE); + s->fif_cts =3D KEEP_OLD_BIT(value, s->fif_cts, NPCM7XX_SMBFIF_CTS_RFTE= _IE); + + if (value & NPCM7XX_SMBFIF_CTS_CLR_FIFO) { + npcm7xx_smbus_clear_buffer(s); + } +} + +static void npcm7xx_smbus_write_txf_ctl(NPCM7xxSMBusState *s, uint8_t valu= e) +{ + s->txf_ctl =3D value; +} + +static void npcm7xx_smbus_write_t_out(NPCM7xxSMBusState *s, uint8_t value) +{ + uint8_t new_t_out =3D value; + + if ((value & NPCM7XX_SMBT_OUT_ST) || (!(s->t_out & NPCM7XX_SMBT_OUT_ST= ))) { + new_t_out &=3D ~NPCM7XX_SMBT_OUT_ST; + } else { + new_t_out |=3D NPCM7XX_SMBT_OUT_ST; + } + + s->t_out =3D new_t_out; +} + +static void npcm7xx_smbus_write_txf_sts(NPCM7xxSMBusState *s, uint8_t valu= e) +{ + s->txf_sts =3D WRITE_ONE_CLEAR(s->txf_sts, value, NPCM7XX_SMBTXF_STS_T= X_THST); +} + +static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t valu= e) +{ + if (value & NPCM7XX_SMBRXF_STS_RX_THST) { + s->rxf_sts &=3D ~NPCM7XX_SMBRXF_STS_RX_THST; + if (s->status =3D=3D NPCM7XX_SMBUS_STATUS_RECEIVING) { + npcm7xx_smbus_recv_fifo(s); + } + } +} + +static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t valu= e) +{ + uint8_t new_ctl =3D value; + + if (!(value & NPCM7XX_SMBRXF_CTL_LAST)) { + new_ctl =3D KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_L= AST); + } + s->rxf_ctl =3D new_ctl; +} + static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned s= ize) { NPCM7xxSMBusState *s =3D opaque; @@ -485,9 +707,41 @@ static uint64_t npcm7xx_smbus_read(void *opaque, hwadd= r offset, unsigned size) default: if (bank) { /* Bank 1 */ - qemu_log_mask(LOG_GUEST_ERROR, - "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", - DEVICE(s)->canonical_path, offset); + switch (offset) { + case NPCM7XX_SMB_FIF_CTS: + value =3D s->fif_cts; + break; + + case NPCM7XX_SMB_FAIR_PER: + value =3D s->fair_per; + break; + + case NPCM7XX_SMB_TXF_CTL: + value =3D s->txf_ctl; + break; + + case NPCM7XX_SMB_T_OUT: + value =3D s->t_out; + break; + + case NPCM7XX_SMB_TXF_STS: + value =3D s->txf_sts; + break; + + case NPCM7XX_SMB_RXF_STS: + value =3D s->rxf_sts; + break; + + case NPCM7XX_SMB_RXF_CTL: + value =3D s->rxf_ctl; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from invalid offset 0x%" HWADDR_PRIx "\n= ", + DEVICE(s)->canonical_path, offset); + break; + } } else { /* Bank 0 */ switch (offset) { @@ -535,6 +789,10 @@ static uint64_t npcm7xx_smbus_read(void *opaque, hwadd= r offset, unsigned size) value =3D s->scllt; break; =20 + case NPCM7XX_SMB_FIF_CTL: + value =3D s->fif_ctl; + break; + case NPCM7XX_SMB_SCLHT: value =3D s->sclht; break; @@ -616,9 +874,41 @@ static void npcm7xx_smbus_write(void *opaque, hwaddr o= ffset, uint64_t value, default: if (bank) { /* Bank 1 */ - qemu_log_mask(LOG_GUEST_ERROR, - "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", - DEVICE(s)->canonical_path, offset); + switch (offset) { + case NPCM7XX_SMB_FIF_CTS: + npcm7xx_smbus_write_fif_cts(s, value); + break; + + case NPCM7XX_SMB_FAIR_PER: + s->fair_per =3D value; + break; + + case NPCM7XX_SMB_TXF_CTL: + npcm7xx_smbus_write_txf_ctl(s, value); + break; + + case NPCM7XX_SMB_T_OUT: + npcm7xx_smbus_write_t_out(s, value); + break; + + case NPCM7XX_SMB_TXF_STS: + npcm7xx_smbus_write_txf_sts(s, value); + break; + + case NPCM7XX_SMB_RXF_STS: + npcm7xx_smbus_write_rxf_sts(s, value); + break; + + case NPCM7XX_SMB_RXF_CTL: + npcm7xx_smbus_write_rxf_ctl(s, value); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + } } else { /* Bank 0 */ switch (offset) { @@ -666,6 +956,10 @@ static void npcm7xx_smbus_write(void *opaque, hwaddr o= ffset, uint64_t value, s->scllt =3D value; break; =20 + case NPCM7XX_SMB_FIF_CTL: + npcm7xx_smbus_write_fif_ctl(s, value); + break; + case NPCM7XX_SMB_SCLHT: s->sclht =3D value; break; @@ -712,7 +1006,18 @@ static void npcm7xx_smbus_enter_reset(Object *obj, Re= setType type) s->scllt =3D NPCM7XX_SMB_SCLLT_INIT_VAL; s->sclht =3D NPCM7XX_SMB_SCLHT_INIT_VAL; =20 + s->fif_ctl =3D NPCM7XX_SMB_FIF_CTL_INIT_VAL; + s->fif_cts =3D NPCM7XX_SMB_FIF_CTS_INIT_VAL; + s->fair_per =3D NPCM7XX_SMB_FAIR_PER_INIT_VAL; + s->txf_ctl =3D NPCM7XX_SMB_TXF_CTL_INIT_VAL; + s->t_out =3D NPCM7XX_SMB_T_OUT_INIT_VAL; + s->txf_sts =3D NPCM7XX_SMB_TXF_STS_INIT_VAL; + s->rxf_sts =3D NPCM7XX_SMB_RXF_STS_INIT_VAL; + s->rxf_ctl =3D NPCM7XX_SMB_RXF_CTL_INIT_VAL; + + npcm7xx_smbus_clear_buffer(s); s->status =3D NPCM7XX_SMBUS_STATUS_IDLE; + s->rx_cur =3D 0; } =20 static void npcm7xx_smbus_hold_reset(Object *obj) @@ -754,6 +1059,17 @@ static const VMStateDescription vmstate_npcm7xx_smbus= =3D { VMSTATE_UINT8_ARRAY(addr, NPCM7xxSMBusState, NPCM7XX_SMBUS_NR_ADDR= S), VMSTATE_UINT8(scllt, NPCM7xxSMBusState), VMSTATE_UINT8(sclht, NPCM7xxSMBusState), + VMSTATE_UINT8(fif_ctl, NPCM7xxSMBusState), + VMSTATE_UINT8(fif_cts, NPCM7xxSMBusState), + VMSTATE_UINT8(fair_per, NPCM7xxSMBusState), + VMSTATE_UINT8(txf_ctl, NPCM7xxSMBusState), + VMSTATE_UINT8(t_out, NPCM7xxSMBusState), + VMSTATE_UINT8(txf_sts, NPCM7xxSMBusState), + VMSTATE_UINT8(rxf_sts, NPCM7xxSMBusState), + VMSTATE_UINT8(rxf_ctl, NPCM7xxSMBusState), + VMSTATE_UINT8_ARRAY(rx_fifo, NPCM7xxSMBusState, + NPCM7XX_SMBUS_FIFO_SIZE), + VMSTATE_UINT8(rx_cur, NPCM7xxSMBusState), VMSTATE_END_OF_LIST(), }, }; diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events index c3bb70ad04..82fe6f965f 100644 --- a/hw/i2c/trace-events +++ b/hw/i2c/trace-events @@ -25,3 +25,4 @@ npcm7xx_smbus_send_byte(const char *id, uint8_t value, in= t success) "%s send byt npcm7xx_smbus_recv_byte(const char *id, uint8_t value) "%s recv byte: 0x%0= 2x" npcm7xx_smbus_stop(const char *id) "%s stopping" npcm7xx_smbus_nack(const char *id) "%s nacking" +npcm7xx_smbus_recv_fifo(const char *id, uint8_t received, uint8_t expected= ) "%s recv fifo: received %u, expected %u" diff --git a/include/hw/i2c/npcm7xx_smbus.h b/include/hw/i2c/npcm7xx_smbus.h index b9761a6993..7d59ee917e 100644 --- a/include/hw/i2c/npcm7xx_smbus.h +++ b/include/hw/i2c/npcm7xx_smbus.h @@ -27,6 +27,9 @@ */ #define NPCM7XX_SMBUS_NR_ADDRS 10 =20 +/* Size of the FIFO buffer. */ +#define NPCM7XX_SMBUS_FIFO_SIZE 16 + typedef enum NPCM7xxSMBusStatus { NPCM7XX_SMBUS_STATUS_IDLE, NPCM7XX_SMBUS_STATUS_SENDING, @@ -53,6 +56,16 @@ typedef enum NPCM7xxSMBusStatus { * @addr: The SMBus module's own addresses on the I2C bus. * @scllt: The SCL low time register. * @sclht: The SCL high time register. + * @fif_ctl: The FIFO control register. + * @fif_cts: The FIFO control status register. + * @fair_per: The fair preriod register. + * @txf_ctl: The transmit FIFO control register. + * @t_out: The SMBus timeout register. + * @txf_sts: The transmit FIFO status register. + * @rxf_sts: The receive FIFO status register. + * @rxf_ctl: The receive FIFO control register. + * @rx_fifo: The FIFO buffer for receiving in FIFO mode. + * @rx_cur: The current position of rx_fifo. * @status: The current status of the SMBus. */ typedef struct NPCM7xxSMBusState { @@ -78,6 +91,18 @@ typedef struct NPCM7xxSMBusState { uint8_t scllt; uint8_t sclht; =20 + uint8_t fif_ctl; + uint8_t fif_cts; + uint8_t fair_per; + uint8_t txf_ctl; + uint8_t t_out; + uint8_t txf_sts; + uint8_t rxf_sts; + uint8_t rxf_ctl; + + uint8_t rx_fifo[NPCM7XX_SMBUS_FIFO_SIZE]; + uint8_t rx_cur; + NPCM7xxSMBusStatus status; } NPCM7xxSMBusState; =20 diff --git a/tests/qtest/npcm7xx_smbus-test.c b/tests/qtest/npcm7xx_smbus-t= est.c index 4594b107df..4f9f493872 100644 --- a/tests/qtest/npcm7xx_smbus-test.c +++ b/tests/qtest/npcm7xx_smbus-test.c @@ -132,6 +132,44 @@ enum NPCM7xxSMBusBank1Register { #define ADDR_EN BIT(7) #define ADDR_A(rv) extract8((rv), 0, 6) =20 +/* FIF_CTL fields */ +#define FIF_CTL_FIFO_EN BIT(4) + +/* FIF_CTS fields */ +#define FIF_CTS_CLR_FIFO BIT(6) +#define FIF_CTS_RFTE_IE BIT(3) +#define FIF_CTS_RXF_TXE BIT(1) + +/* TXF_CTL fields */ +#define TXF_CTL_THR_TXIE BIT(6) +#define TXF_CTL_TX_THR(rv) extract8((rv), 0, 5) + +/* TXF_STS fields */ +#define TXF_STS_TX_THST BIT(6) +#define TXF_STS_TX_BYTES(rv) extract8((rv), 0, 5) + +/* RXF_CTL fields */ +#define RXF_CTL_THR_RXIE BIT(6) +#define RXF_CTL_LAST BIT(5) +#define RXF_CTL_RX_THR(rv) extract8((rv), 0, 5) + +/* RXF_STS fields */ +#define RXF_STS_RX_THST BIT(6) +#define RXF_STS_RX_BYTES(rv) extract8((rv), 0, 5) + + +static void choose_bank(QTestState *qts, uint64_t base_addr, uint8_t bank) +{ + uint8_t ctl3 =3D qtest_readb(qts, base_addr + OFFSET_CTL3); + + if (bank) { + ctl3 |=3D CTL3_BNK_SEL; + } else { + ctl3 &=3D ~CTL3_BNK_SEL; + } + + qtest_writeb(qts, base_addr + OFFSET_CTL3, ctl3); +} =20 static void check_running(QTestState *qts, uint64_t base_addr) { @@ -203,10 +241,33 @@ static void send_byte(QTestState *qts, uint64_t base_= addr, uint8_t byte) qtest_writeb(qts, base_addr + OFFSET_SDA, byte); } =20 +static bool check_recv(QTestState *qts, uint64_t base_addr) +{ + uint8_t st, fif_ctl, rxf_ctl, rxf_sts; + bool fifo; + + st =3D qtest_readb(qts, base_addr + OFFSET_ST); + choose_bank(qts, base_addr, 0); + fif_ctl =3D qtest_readb(qts, base_addr + OFFSET_FIF_CTL); + fifo =3D fif_ctl & FIF_CTL_FIFO_EN; + if (!fifo) { + return st =3D=3D (ST_MODE | ST_SDAST); + } + + choose_bank(qts, base_addr, 1); + rxf_ctl =3D qtest_readb(qts, base_addr + OFFSET_RXF_CTL); + rxf_sts =3D qtest_readb(qts, base_addr + OFFSET_RXF_STS); + + if ((rxf_ctl & RXF_CTL_THR_RXIE) && RXF_STS_RX_BYTES(rxf_sts) < 16) { + return st =3D=3D ST_MODE; + } else { + return st =3D=3D (ST_MODE | ST_SDAST); + } +} + static uint8_t recv_byte(QTestState *qts, uint64_t base_addr) { - g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_ST), =3D=3D, - ST_MODE | ST_SDAST); + g_assert_true(check_recv(qts, base_addr)); return qtest_readb(qts, base_addr + OFFSET_SDA); } =20 @@ -229,7 +290,7 @@ static void send_address(QTestState *qts, uint64_t base= _addr, uint8_t addr, qtest_writeb(qts, base_addr + OFFSET_ST, ST_STASTR); st =3D qtest_readb(qts, base_addr + OFFSET_ST); if (recv) { - g_assert_cmphex(st, =3D=3D, ST_MODE | ST_SDAST); + g_assert_true(check_recv(qts, base_addr)); } else { g_assert_cmphex(st, =3D=3D, ST_MODE | ST_XMIT | ST_SDAST); } @@ -251,6 +312,29 @@ static void send_nack(QTestState *qts, uint64_t base_a= ddr) qtest_writeb(qts, base_addr + OFFSET_CTL1, ctl1); } =20 +static void start_fifo_mode(QTestState *qts, uint64_t base_addr) +{ + choose_bank(qts, base_addr, 0); + qtest_writeb(qts, base_addr + OFFSET_FIF_CTL, FIF_CTL_FIFO_EN); + g_assert_true(qtest_readb(qts, base_addr + OFFSET_FIF_CTL) & + FIF_CTL_FIFO_EN); + choose_bank(qts, base_addr, 1); + qtest_writeb(qts, base_addr + OFFSET_FIF_CTS, + FIF_CTS_CLR_FIFO | FIF_CTS_RFTE_IE); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_FIF_CTS), =3D=3D, + FIF_CTS_RFTE_IE); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_TXF_STS), =3D=3D, = 0); + g_assert_cmphex(qtest_readb(qts, base_addr + OFFSET_RXF_STS), =3D=3D, = 0); +} + +static void start_recv_fifo(QTestState *qts, uint64_t base_addr, uint8_t b= ytes) +{ + choose_bank(qts, base_addr, 1); + qtest_writeb(qts, base_addr + OFFSET_TXF_CTL, 0); + qtest_writeb(qts, base_addr + OFFSET_RXF_CTL, + RXF_CTL_THR_RXIE | RXF_CTL_LAST | bytes); +} + /* Check the SMBus's status is set correctly when disabled. */ static void test_disable_bus(gconstpointer data) { @@ -324,6 +408,64 @@ static void test_single_mode(gconstpointer data) qtest_quit(qts); } =20 +/* Check the SMBus can send and receive bytes in FIFO mode. */ +static void test_fifo_mode(gconstpointer data) +{ + intptr_t index =3D (intptr_t)data; + uint64_t base_addr =3D SMBUS_ADDR(index); + int irq =3D SMBUS_IRQ(index); + uint8_t value =3D 0x60; + QTestState *qts =3D qtest_init("-machine npcm750-evb"); + + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + enable_bus(qts, base_addr); + start_fifo_mode(qts, base_addr); + g_assert_false(qtest_get_irq(qts, irq)); + + /* Sending */ + start_transfer(qts, base_addr); + send_address(qts, base_addr, EVB_DEVICE_ADDR, false, true); + choose_bank(qts, base_addr, 1); + g_assert_true(qtest_readb(qts, base_addr + OFFSET_FIF_CTS) & + FIF_CTS_RXF_TXE); + qtest_writeb(qts, base_addr + OFFSET_TXF_CTL, TXF_CTL_THR_TXIE); + send_byte(qts, base_addr, TMP105_REG_CONFIG); + send_byte(qts, base_addr, value); + g_assert_true(qtest_readb(qts, base_addr + OFFSET_FIF_CTS) & + FIF_CTS_RXF_TXE); + g_assert_true(qtest_readb(qts, base_addr + OFFSET_TXF_STS) & + TXF_STS_TX_THST); + g_assert_cmpuint(TXF_STS_TX_BYTES( + qtest_readb(qts, base_addr + OFFSET_TXF_STS)), =3D= =3D, 0); + g_assert_true(qtest_get_irq(qts, irq)); + stop_transfer(qts, base_addr); + check_stopped(qts, base_addr); + + /* Receiving */ + start_fifo_mode(qts, base_addr); + start_transfer(qts, base_addr); + send_address(qts, base_addr, EVB_DEVICE_ADDR, false, true); + send_byte(qts, base_addr, TMP105_REG_CONFIG); + start_transfer(qts, base_addr); + qtest_writeb(qts, base_addr + OFFSET_FIF_CTS, FIF_CTS_RXF_TXE); + start_recv_fifo(qts, base_addr, 1); + send_address(qts, base_addr, EVB_DEVICE_ADDR, true, true); + g_assert_false(qtest_readb(qts, base_addr + OFFSET_FIF_CTS) & + FIF_CTS_RXF_TXE); + g_assert_true(qtest_readb(qts, base_addr + OFFSET_RXF_STS) & + RXF_STS_RX_THST); + g_assert_cmpuint(RXF_STS_RX_BYTES( + qtest_readb(qts, base_addr + OFFSET_RXF_STS)), =3D= =3D, 1); + send_nack(qts, base_addr); + stop_transfer(qts, base_addr); + check_running(qts, base_addr); + g_assert_cmphex(recv_byte(qts, base_addr), =3D=3D, value); + g_assert_cmpuint(RXF_STS_RX_BYTES( + qtest_readb(qts, base_addr + OFFSET_RXF_STS)), =3D= =3D, 0); + check_stopped(qts, base_addr); + qtest_quit(qts); +} + static void smbus_add_test(const char *name, int index, GTestDataFunc fn) { g_autofree char *full_name =3D g_strdup_printf( @@ -346,6 +488,7 @@ int main(int argc, char **argv) =20 for (i =3D 0; i < ARRAY_SIZE(evb_bus_list); ++i) { add_test(single_mode, evb_bus_list[i]); + add_test(fifo_mode, evb_bus_list[i]); } =20 return g_test_run(); --=20 2.30.0.365.g02bc693789-goog