From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by 2002:a05:6512:15a3:0:0:0:0 with SMTP id bp35csp1350302lfb; Thu, 6 Jan 2022 15:16:44 -0800 (PST) X-Google-Smtp-Source: ABdhPJyY2ii+l3usg//o7IvxRZtzOWEC92GHjtBvhbQXIKDmfX95q+tJa8DJv728ymcp8Javoxgy X-Received: by 2002:a25:e7d6:: with SMTP id e205mr59821308ybh.596.1641511004043; Thu, 06 Jan 2022 15:16:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1641511004; cv=none; d=google.com; s=arc-20160816; b=l8RVFOYPx9vtUcQsA0gLirMZavI5NbAZTLT2cLBWnGX9h3KLsEd4rm0JR5JJlhs7xn sfbH7nqlOgcSMSELSS9DOkw+yuerxymD4f60l6eFzaOpI5yD+8zTQDfusS+CNeJPDNgH uC09jPfPX7Bm9RbZHA2svjLx412II1nQDeO8Dpd7t3O507N/o2swRSYpfIIOKg+cBn1d w9yRBtCEu67P2701Uzyj8op5Gn3nyKeReI7x35oTLcfMYbvbePcJxyGiIQGHlmvBKClo vswhguF3CH8EDaWLHOBYtIs+4GbP3Oplj5FJbF77HsJHvzCfqbeb8tcirJCAw9VgCmfn +kBA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding:cc:to :from:subject:references:mime-version:message-id:in-reply-to:date :dkim-signature; bh=vW4Xo7g4Y3w1c48JyjTkubYnaRSDR0XM7VsJM/RJjGE=; b=Q7IZY1JiR/CQtuAnCf2/9ObneNXNDKyR//xnfDnTYfmJFJvgUdcA95NgkJusCz/EvH aj0Se835VmGBj7kUnLOXb8pgQbaHyYOdp1eklO59hong/zdtHb9E7iTlZNtmht5vG8oY p4WfVeMqkVar7zYOxFvROd1TDU3NQynyPLK72zTBKTmRSqxTV5E2Eu9LNBph5w80W0qq 9foYzJ1aDE/nU3zh4KQ3qUttCq3ZJdduncWSiYgWOT4/13R7kGXb9WmEQ+5wKss0PrZo NsZb7t+kd1/miLT6E6MG/lu6g9vYsxwtSRhOaHoZr1tYzTey/tYUGeRq/TWMxs+TZRmh CDyg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=pKKXdDQJ; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id e132si2404106yba.320.2022.01.06.15.16.43 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Thu, 06 Jan 2022 15:16:44 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=pKKXdDQJ; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from localhost ([::1]:41040 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1n5bzv-0002ge-46 for alex.bennee@linaro.org; Thu, 06 Jan 2022 18:16:43 -0500 Received: from eggs.gnu.org ([209.51.188.92]:34662) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3wHbXYQYKCCEQFQRPODLLDIB.9LJNBJR-7OJKLKDKR.LOD@flex--titusr.bounces.google.com>) id 1n5bzc-0002fJ-I8 for qemu-arm@nongnu.org; Thu, 06 Jan 2022 18:16:24 -0500 Received: from [2607:f8b0:4864:20::749] (port=37722 helo=mail-qk1-x749.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3wHbXYQYKCCEQFQRPODLLDIB.9LJNBJR-7OJKLKDKR.LOD@flex--titusr.bounces.google.com>) id 1n5bza-00067a-L9 for qemu-arm@nongnu.org; Thu, 06 Jan 2022 18:16:24 -0500 Received: by mail-qk1-x749.google.com with SMTP id br9-20020a05620a460900b0046ad784c791so2996790qkb.4 for ; Thu, 06 Jan 2022 15:16:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=vW4Xo7g4Y3w1c48JyjTkubYnaRSDR0XM7VsJM/RJjGE=; b=pKKXdDQJb544tOHDI8mINAGzVuxbozTjstb7q2gUfk8Ul9HUP98vBG8yz6xTeldAs+ l7IhnNTeNZRqV9XGczB+Kcsa9qIGmQ13c4S49Kq6qFia5V9xywTsiTr5Dklx/eO5amXQ xGsq1ZHMOzQCH6cieqmzrMaEOcqLXd3O/NT1q1kyhYoA45jlUaivUC5TqgrvHd/UVDzV 344XjjIxtzgydNx30n18lfREOIfXK24p98hzALkN32msPpttehVdyYyy3DuVzogTG8Xu xtwzvuSvVI8ul+ZILWqxutg7qNKV0t3WsiLna7EtRma7RbPbt0Rt4f7FJ5C+kZOA3QsV UhTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=vW4Xo7g4Y3w1c48JyjTkubYnaRSDR0XM7VsJM/RJjGE=; b=zyIJ8J3CJT1NlPbpc/j5z6UDI6vJJjBwbWDnjhz81qTNaHeCTSb9mHc7PDDLUJokXe gSjBtRaLO9Vj8vLPZE9UCY9BEeQx2sqc+DYJlh0vba5wXXQS6AfyqhRuMS32XKbyLRl1 i+s5cg83PVUOniQppNDk0r7Gr+4DzpdJq8Aj7FCkI6tapAMUvhh+2vZRnHfi1gvIgFY8 U1hlUO9wNZItnpyZwCR7CsnhINWuGFeB08dAgBFCyxzNuxN5pYQ87RauMgg/i+mUuYRS QfjiKj0RAh5n9viLRaDWOl+W2krBMo5ISO9cHy/o1t5msPWblBtl8AFef87cPTlAOSkW F/EQ== X-Gm-Message-State: AOAM532AyDzXz58n1Ix1XQKSvSyH/ZP5arg9Ps8XwyPH17dERQT5VrsF IoJ/iqwcDcMvBhr9Wg1ZzWDWl0N1G8Y= X-Received: from titusr.c.googlers.com ([fda3:e722:ac3:cc00:14:4d90:c0a8:22b8]) (user=titusr job=sendgmr) by 2002:a05:6102:3f55:: with SMTP id l21mr4209104vsv.67.1641510592976; Thu, 06 Jan 2022 15:09:52 -0800 (PST) Date: Thu, 6 Jan 2022 23:09:32 +0000 In-Reply-To: <20220106230936.417020-1-titusr@google.com> Message-Id: <20220106230936.417020-2-titusr@google.com> Mime-Version: 1.0 References: <20220106230936.417020-1-titusr@google.com> X-Mailer: git-send-email 2.34.1.448.ga2b2bfdf31-goog Subject: [PATCH 1/5] hw/i2c: pmbus updates From: Titus Rwantare To: f4bug@amsat.org, minyard@acm.org Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, venture@google.com, Titus Rwantare , Hao Wu Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::749 (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::749; envelope-from=3wHbXYQYKCCEQFQRPODLLDIB.9LJNBJR-7OJKLKDKR.LOD@flex--titusr.bounces.google.com; helo=mail-qk1-x749.google.com X-Spam_score_int: -87 X-Spam_score: -8.8 X-Spam_bar: -------- X-Spam_report: (-8.8 / 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, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-arm@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org Sender: "Qemu-arm" X-TUID: kCw1xYnbcYDK - add vout min register - add PEC unsupported warning to pmbus_device class - guard against out of range pmbus page accesses Signed-off-by: Titus Rwantare Reviewed-by: Hao Wu --- MAINTAINERS | 12 ++++- hw/i2c/pmbus_device.c | 88 +++++++++++++++++++++++++++++++---- include/hw/i2c/pmbus_device.h | 3 ++ 3 files changed, 92 insertions(+), 11 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f871d759fd..6349e3da1f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2790,7 +2790,7 @@ R: Paolo Bonzini R: Bandan Das R: Stefan Hajnoczi R: Thomas Huth -R: Darren Kenny =20 +R: Darren Kenny R: Qiuhao Li S: Maintained F: tests/qtest/fuzz/ @@ -3029,6 +3029,16 @@ F: include/hw/i2c/smbus_master.h F: include/hw/i2c/smbus_slave.h F: include/hw/i2c/smbus_eeprom.h =20 +PMBus +M: Titus Rwantare +S: Maintained +F: hw/i2c/pmbus_device.c +F: hw/sensor/adm1272.c +F: hw/sensor/max34451.c +F: include/hw/i2c/pmbus_device.h +F: tests/qtest/adm1272-test.c +F: tests/qtest/max34451-test.c + Firmware schema specifications M: Philippe Mathieu-Daud=C3=A9 R: Daniel P. Berrange diff --git a/hw/i2c/pmbus_device.c b/hw/i2c/pmbus_device.c index 24f8f522d9..3beb02afad 100644 --- a/hw/i2c/pmbus_device.c +++ b/hw/i2c/pmbus_device.c @@ -89,16 +89,16 @@ void pmbus_send_string(PMBusDevice *pmdev, const char *= data) } =20 =20 -static uint64_t pmbus_receive_uint(const uint8_t *buf, uint8_t len) +static uint64_t pmbus_receive_uint(PMBusDevice *pmdev) { uint64_t ret =3D 0; =20 /* Exclude command code from return value */ - buf++; - len--; + pmdev->in_buf++; + pmdev->in_buf_len--; =20 - for (int i =3D len - 1; i >=3D 0; i--) { - ret =3D ret << 8 | buf[i]; + for (int i =3D pmdev->in_buf_len - 1; i >=3D 0; i--) { + ret =3D ret << 8 | pmdev->in_buf[i]; } return ret; } @@ -110,7 +110,7 @@ uint8_t pmbus_receive8(PMBusDevice *pmdev) "%s: length mismatch. Expected 1 byte, got %d bytes\= n", __func__, pmdev->in_buf_len - 1); } - return pmbus_receive_uint(pmdev->in_buf, pmdev->in_buf_len); + return pmbus_receive_uint(pmdev); } =20 uint16_t pmbus_receive16(PMBusDevice *pmdev) @@ -120,7 +120,7 @@ uint16_t pmbus_receive16(PMBusDevice *pmdev) "%s: length mismatch. Expected 2 bytes, got %d bytes= \n", __func__, pmdev->in_buf_len - 1); } - return pmbus_receive_uint(pmdev->in_buf, pmdev->in_buf_len); + return pmbus_receive_uint(pmdev); } =20 uint32_t pmbus_receive32(PMBusDevice *pmdev) @@ -130,7 +130,7 @@ uint32_t pmbus_receive32(PMBusDevice *pmdev) "%s: length mismatch. Expected 4 bytes, got %d bytes= \n", __func__, pmdev->in_buf_len - 1); } - return pmbus_receive_uint(pmdev->in_buf, pmdev->in_buf_len); + return pmbus_receive_uint(pmdev); } =20 uint64_t pmbus_receive64(PMBusDevice *pmdev) @@ -140,7 +140,7 @@ uint64_t pmbus_receive64(PMBusDevice *pmdev) "%s: length mismatch. Expected 8 bytes, got %d bytes= \n", __func__, pmdev->in_buf_len - 1); } - return pmbus_receive_uint(pmdev->in_buf, pmdev->in_buf_len); + return pmbus_receive_uint(pmdev); } =20 static uint8_t pmbus_out_buf_pop(PMBusDevice *pmdev) @@ -243,18 +243,47 @@ void pmbus_check_limits(PMBusDevice *pmdev) } } =20 +/* assert the status_cml error upon receipt of malformed command */ +static void pmbus_cml_error(PMBusDevice *pmdev) +{ + for (int i =3D 0; i < pmdev->num_pages; i++) { + pmdev->pages[i].status_word |=3D PMBUS_STATUS_CML; + pmdev->pages[i].status_cml |=3D PB_CML_FAULT_INVALID_CMD; + } +} + static uint8_t pmbus_receive_byte(SMBusDevice *smd) { PMBusDevice *pmdev =3D PMBUS_DEVICE(smd); PMBusDeviceClass *pmdc =3D PMBUS_DEVICE_GET_CLASS(pmdev); uint8_t ret =3D 0xFF; - uint8_t index =3D pmdev->page; + uint8_t index; =20 if (pmdev->out_buf_len !=3D 0) { ret =3D pmbus_out_buf_pop(pmdev); return ret; } =20 + /* + * Reading from all pages will return the value from page 0, + * this is unspecified behaviour in general. + */ + if (pmdev->page =3D=3D PB_ALL_PAGES) { + index =3D 0; + qemu_log_mask(LOG_GUEST_ERROR, + "%s: tried to read from all pages\n", + __func__); + pmbus_cml_error(pmdev); + } else if (pmdev->page > pmdev->num_pages - 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: page %d is out of range\n", + __func__, pmdev->page); + pmbus_cml_error(pmdev); + return -1; + } else { + index =3D pmdev->page; + } + switch (pmdev->code) { case PMBUS_PAGE: pmbus_send8(pmdev, pmdev->page); @@ -278,6 +307,11 @@ static uint8_t pmbus_receive_byte(SMBusDevice *smd) =20 case PMBUS_CAPABILITY: pmbus_send8(pmdev, pmdev->capability); + if (pmdev->capability & BIT(7)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: PEC is enabled but not yet supported.\n", + __func__); + } break; =20 case PMBUS_VOUT_MODE: /* R/W byte */ @@ -368,6 +402,14 @@ static uint8_t pmbus_receive_byte(SMBusDevice *smd) } break; =20 + case PMBUS_VOUT_MIN: /* R/W word */ + if (pmdev->pages[index].page_flags & PB_HAS_VOUT_RATING) { + pmbus_send16(pmdev, pmdev->pages[index].vout_min); + } else { + goto passthough; + } + break; + /* TODO: implement coefficients support */ =20 case PMBUS_POUT_MAX: /* R/W word */ @@ -708,6 +750,10 @@ static uint8_t pmbus_receive_byte(SMBusDevice *smd) pmbus_send8(pmdev, pmdev->pages[index].status_other); break; =20 + case PMBUS_STATUS_MFR_SPECIFIC: /* R/W byte */ + pmbus_send8(pmdev, pmdev->pages[index].status_mfr_specific); + break; + case PMBUS_READ_EIN: /* Read-Only block 5 bytes */ if (pmdev->pages[index].page_flags & PB_HAS_EIN) { pmbus_send(pmdev, pmdev->pages[index].read_ein, 5); @@ -1026,6 +1072,7 @@ static int pmbus_write_data(SMBusDevice *smd, uint8_t= *buf, uint8_t len) pmdev->page =3D pmbus_receive8(pmdev); return 0; } + /* loop through all the pages when 0xFF is received */ if (pmdev->page =3D=3D PB_ALL_PAGES) { for (int i =3D 0; i < pmdev->num_pages; i++) { @@ -1036,6 +1083,15 @@ static int pmbus_write_data(SMBusDevice *smd, uint8_= t *buf, uint8_t len) return 0; } =20 + if (pmdev->page > pmdev->num_pages - 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: page %u is out of range\n", + __func__, pmdev->page); + pmdev->page =3D 0; /* undefined behaviour - reset to page 0 */ + pmbus_cml_error(pmdev); + return -1; + } + index =3D pmdev->page; =20 switch (pmdev->code) { @@ -1149,6 +1205,14 @@ static int pmbus_write_data(SMBusDevice *smd, uint8_= t *buf, uint8_t len) } break; =20 + case PMBUS_VOUT_MIN: /* R/W word */ + if (pmdev->pages[index].page_flags & PB_HAS_VOUT_RATING) { + pmdev->pages[index].vout_min =3D pmbus_receive16(pmdev); + } else { + goto passthrough; + } + break; + case PMBUS_POUT_MAX: /* R/W word */ if (pmdev->pages[index].page_flags & PB_HAS_VOUT) { pmdev->pages[index].pout_max =3D pmbus_receive16(pmdev); @@ -1482,6 +1546,10 @@ static int pmbus_write_data(SMBusDevice *smd, uint8_= t *buf, uint8_t len) pmdev->pages[index].status_other =3D pmbus_receive8(pmdev); break; =20 + case PMBUS_STATUS_MFR_SPECIFIC: /* R/W byte */ + pmdev->pages[index].status_mfr_specific =3D pmbus_receive8(pmdev); + break; + case PMBUS_PAGE_PLUS_READ: /* Block Read-only */ case PMBUS_CAPABILITY: /* Read-Only byte */ case PMBUS_COEFFICIENTS: /* Read-only block 5 bytes */ diff --git a/include/hw/i2c/pmbus_device.h b/include/hw/i2c/pmbus_device.h index 62bd38c83f..72c0483149 100644 --- a/include/hw/i2c/pmbus_device.h +++ b/include/hw/i2c/pmbus_device.h @@ -43,6 +43,7 @@ enum pmbus_registers { PMBUS_VOUT_DROOP =3D 0x28, /* R/W word */ PMBUS_VOUT_SCALE_LOOP =3D 0x29, /* R/W word */ PMBUS_VOUT_SCALE_MONITOR =3D 0x2A, /* R/W word */ + PMBUS_VOUT_MIN =3D 0x2B, /* R/W word */ PMBUS_COEFFICIENTS =3D 0x30, /* Read-only block 5 bytes *= / PMBUS_POUT_MAX =3D 0x31, /* R/W word */ PMBUS_MAX_DUTY =3D 0x32, /* R/W word */ @@ -255,6 +256,7 @@ OBJECT_DECLARE_TYPE(PMBusDevice, PMBusDeviceClass, #define PB_HAS_TEMP3 BIT_ULL(42) #define PB_HAS_TEMP_RATING BIT_ULL(43) #define PB_HAS_MFR_INFO BIT_ULL(50) +#define PB_HAS_STATUS_MFR_SPECIFIC BIT_ULL(51) =20 struct PMBusDeviceClass { SMBusDeviceClass parent_class; @@ -295,6 +297,7 @@ typedef struct PMBusPage { uint16_t vout_droop; /* R/W word */ uint16_t vout_scale_loop; /* R/W word */ uint16_t vout_scale_monitor; /* R/W word */ + uint16_t vout_min; /* R/W word */ uint8_t coefficients[5]; /* Read-only block 5 bytes */ uint16_t pout_max; /* R/W word */ uint16_t max_duty; /* R/W word */ --=20 2.34.1.448.ga2b2bfdf31-goog