aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTitus Rwantare <titusr@google.com>2023-10-23 23:46:40 +0000
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2023-11-07 13:08:48 +0100
commitcfb0884c6f941977db1e0ce53ac659a8428e4e48 (patch)
tree53e15756068a300146595076aed41c37c7d5cd1c
parentcc610857bbd3551f4b86ae2299336b5d9aa0db2b (diff)
downloadqemu-cfb0884c6f941977db1e0ce53ac659a8428e4e48.zip
qemu-cfb0884c6f941977db1e0ce53ac659a8428e4e48.tar.gz
qemu-cfb0884c6f941977db1e0ce53ac659a8428e4e48.tar.bz2
hw/i2c: pmbus add support for block receive
PMBus devices can send and receive variable length data using the block read and write format, with the first byte in the payload denoting the length. This is mostly used for strings and on-device logs. Devices can respond to a block read with an empty string. Reviewed-by: Hao Wu <wuhaotsh@google.com> Acked-by: Corey Minyard <cminyard@mvista.com> Signed-off-by: Titus Rwantare <titusr@google.com> Message-ID: <20231023-staging-pmbus-v3-v4-1-07a8cb7cd20a@google.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
-rw-r--r--hw/i2c/pmbus_device.c30
-rw-r--r--include/hw/i2c/pmbus_device.h7
2 files changed, 36 insertions, 1 deletions
diff --git a/hw/i2c/pmbus_device.c b/hw/i2c/pmbus_device.c
index cef5166..ea15490 100644
--- a/hw/i2c/pmbus_device.c
+++ b/hw/i2c/pmbus_device.c
@@ -102,7 +102,6 @@ void pmbus_send_string(PMBusDevice *pmdev, const char *data)
}
size_t len = strlen(data);
- g_assert(len > 0);
g_assert(len + pmdev->out_buf_len < SMBUS_DATA_MAX_LEN);
pmdev->out_buf[len + pmdev->out_buf_len] = len;
@@ -112,6 +111,35 @@ void pmbus_send_string(PMBusDevice *pmdev, const char *data)
pmdev->out_buf_len += len + 1;
}
+uint8_t pmbus_receive_block(PMBusDevice *pmdev, uint8_t *dest, size_t len)
+{
+ /* dest may contain data from previous writes */
+ memset(dest, 0, len);
+
+ /* Exclude command code from return value */
+ pmdev->in_buf++;
+ pmdev->in_buf_len--;
+
+ /* The byte after the command code denotes the length */
+ uint8_t sent_len = pmdev->in_buf[0];
+
+ if (sent_len != pmdev->in_buf_len - 1) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: length mismatch. Expected %d bytes, got %d bytes\n",
+ __func__, sent_len, pmdev->in_buf_len - 1);
+ }
+
+ /* exclude length byte */
+ pmdev->in_buf++;
+ pmdev->in_buf_len--;
+
+ if (pmdev->in_buf_len < len) {
+ len = pmdev->in_buf_len;
+ }
+ memcpy(dest, pmdev->in_buf, len);
+ return len;
+}
+
static uint64_t pmbus_receive_uint(PMBusDevice *pmdev)
{
diff --git a/include/hw/i2c/pmbus_device.h b/include/hw/i2c/pmbus_device.h
index 93f5d57..7dc00cc 100644
--- a/include/hw/i2c/pmbus_device.h
+++ b/include/hw/i2c/pmbus_device.h
@@ -502,6 +502,13 @@ void pmbus_send64(PMBusDevice *state, uint64_t data);
void pmbus_send_string(PMBusDevice *state, const char *data);
/**
+ * @brief Receive data sent with Block Write.
+ * @param dest - memory with enough capacity to receive the write
+ * @param len - the capacity of dest
+ */
+uint8_t pmbus_receive_block(PMBusDevice *pmdev, uint8_t *dest, size_t len);
+
+/**
* @brief Receive data over PMBus
* These methods help track how much data is being received over PMBus
* Log to GUEST_ERROR if too much or too little is sent.