From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 63429C05027 for ; Mon, 6 Feb 2023 23:25:31 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pPAqt-0006Ub-08; Mon, 06 Feb 2023 18:24:47 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pPAqr-0006UE-Id for qemu-devel@nongnu.org; Mon, 06 Feb 2023 18:24:45 -0500 Received: from mail-wr1-x42c.google.com ([2a00:1450:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pPAqn-0004Uc-Oj for qemu-devel@nongnu.org; Mon, 06 Feb 2023 18:24:45 -0500 Received: by mail-wr1-x42c.google.com with SMTP id h16so11944646wrz.12 for ; Mon, 06 Feb 2023 15:24:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Jycar1ys7NFcIFL7RY55B5xsdWchgTljs+5CkvUwMkI=; b=NQgrjhWxy6Xu0jA/YoqoPNs3SHy3tbrM5PKfAI9t+t6KFD3ABsWyXzjbNfNeskMNVA frE7hFGFhrgJ4gMpBYPDlguSZzabsCRkBgP/xdMMOjpNTWmj5dAufWlCH2MRmGLCsUol MTcZcfSeGAoIKXVuaXASdYlzn0dvlSBlTDwUokxZGnuOLVX9n7p3t9vfoNB3ZQYoijvW nFdEP3BfRaNwtUVtjGDYdki7t3KR4y2prIc7GKplm0mSeJtXsz2DAI91A6SKXYVW3ooz AYGsmPKOwF04cwH1rCh1xOSqxNxEbpfR1KoX8lihZ2NjqsO/Pj0KR8faEnIf0ea48Jj3 Soqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Jycar1ys7NFcIFL7RY55B5xsdWchgTljs+5CkvUwMkI=; b=ZfeK0holLl8R/He28ShxmKlFGKrXfU4YTJOe61MaEKmgr7v511C2VPVvPuCRLA3SK+ JDBKQSVd9pig1P3UXE+9LwPZX6FKNDR9XqCWRu+YN0PR0ounOC/lhVGg8Ro8ioOyU/N0 WaLrdzBerh5lDIivEvW0GzdRiRVKH7P9miNs9kVg5L94xuRaIet0wkVYCEnH83M2dS6c dwlIEtV7BlT7NTbbRDalMGXDp8N1OPbJfnp+R1r2ehR/7lws8vQj7MDfFEwwR+kryEUa Oag3f3FC2iLLLV7W6sDVLeCg6TGb+vDgfIC5Zx/j63NhLbcr0GrDkXjQk31ospT5XaZJ Gwwg== X-Gm-Message-State: AO0yUKXDheQycHn1SOrXBYWuxhZ07OkemodjpQop4QsDyOL3zc5x0Ox1 pFalFhicKdrXPaZkrtEczYoUChtpAVDYKOaQ4YYFyg== X-Google-Smtp-Source: AK7set+9C8UWVt6cMQYJwIHwrVnZdxLpIiT/pjKiY1QusgoFaAABEyym7cU5dUVeUVPCQCcLu+O5bHUbgjj4T7K+vXE= X-Received: by 2002:a05:6000:50e:b0:2c3:e35a:19cd with SMTP id a14-20020a056000050e00b002c3e35a19cdmr13993wrf.364.1675725878153; Mon, 06 Feb 2023 15:24:38 -0800 (PST) MIME-Version: 1.0 References: <20220131222948.496588-1-venture@google.com> <20220131222948.496588-2-venture@google.com> In-Reply-To: <20220131222948.496588-2-venture@google.com> From: Hao Wu Date: Mon, 6 Feb 2023 15:24:26 -0800 Message-ID: Subject: Re: [PATCH v4 1/2] hw/sensor: Add SB-TSI Temperature Sensor Interface To: Patrick Venture Cc: cminyard@mvista.com, thuth@redhat.com, lvivier@redhat.com, pbonzini@redhat.com, f4bug@amsat.org, qemu-devel@nongnu.org, Doug Evans Content-Type: multipart/alternative; boundary="000000000000b616cb05f41055cc" Received-SPF: pass client-ip=2a00:1450:4864:20::42c; envelope-from=wuhaotsh@google.com; helo=mail-wr1-x42c.google.com X-Spam_score_int: -175 X-Spam_score: -17.6 X-Spam_bar: ----------------- X-Spam_report: (-17.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, ENV_AND_HDR_SPF_MATCH=-0.5, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5, USER_IN_DEF_SPF_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@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-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --000000000000b616cb05f41055cc Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, It seems like this patch set is reviewed but never merged. Who should take this patch set? What are our next steps for them? Thanks! On Mon, Jan 31, 2022 at 2:29 PM Patrick Venture wrote: > From: Hao Wu > > SB Temperature Sensor Interface (SB-TSI) is an SMBus compatible > interface that reports AMD SoC's Ttcl (normalized temperature), > and resembles a typical 8-pin remote temperature sensor's I2C interface > to BMC. > > This patch implements a basic AMD SB-TSI sensor that is > compatible with the open-source data sheet from AMD and Linux > kernel driver. > > Reference: > Linux kernel driver: > https://lkml.org/lkml/2020/12/11/968 > Register Map: > https://developer.amd.com/wp-content/resources/56255_3_03.PDF > (Chapter 6) > > Signed-off-by: Hao Wu > Signed-off-by: Patrick Venture > Reviewed-by: Doug Evans > Reviewed-by: Philippe Mathieu-Daud=C3=A9 > Acked-by: Corey Minyard > --- > meson.build | 1 + > hw/sensor/trace.h | 1 + > include/hw/sensor/sbtsi.h | 45 +++++ > hw/sensor/tmp_sbtsi.c | 369 ++++++++++++++++++++++++++++++++++++++ > hw/sensor/Kconfig | 4 + > hw/sensor/meson.build | 1 + > hw/sensor/trace-events | 5 + > 7 files changed, 426 insertions(+) > create mode 100644 hw/sensor/trace.h > create mode 100644 include/hw/sensor/sbtsi.h > create mode 100644 hw/sensor/tmp_sbtsi.c > create mode 100644 hw/sensor/trace-events > > diff --git a/meson.build b/meson.build > index c1b1db1e28..3634214546 100644 > --- a/meson.build > +++ b/meson.build > @@ -2494,6 +2494,7 @@ if have_system > 'hw/rtc', > 'hw/s390x', > 'hw/scsi', > + 'hw/sensor', > 'hw/sd', > 'hw/sh4', > 'hw/sparc', > diff --git a/hw/sensor/trace.h b/hw/sensor/trace.h > new file mode 100644 > index 0000000000..e4721560b0 > --- /dev/null > +++ b/hw/sensor/trace.h > @@ -0,0 +1 @@ > +#include "trace/trace-hw_sensor.h" > diff --git a/include/hw/sensor/sbtsi.h b/include/hw/sensor/sbtsi.h > new file mode 100644 > index 0000000000..9073f76ebb > --- /dev/null > +++ b/include/hw/sensor/sbtsi.h > @@ -0,0 +1,45 @@ > +/* > + * AMD SBI Temperature Sensor Interface (SB-TSI) > + * > + * Copyright 2021 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 > WITHOUT > + * 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 QEMU_TMP_SBTSI_H > +#define QEMU_TMP_SBTSI_H > + > +/* > + * SB-TSI registers only support SMBus byte data access. "_INT" register= s > are > + * the integer part of a temperature value or limit, and "_DEC" register= s > are > + * corresponding decimal parts. > + */ > +#define SBTSI_REG_TEMP_INT 0x01 /* RO */ > +#define SBTSI_REG_STATUS 0x02 /* RO */ > +#define SBTSI_REG_CONFIG 0x03 /* RO */ > +#define SBTSI_REG_TEMP_HIGH_INT 0x07 /* RW */ > +#define SBTSI_REG_TEMP_LOW_INT 0x08 /* RW */ > +#define SBTSI_REG_CONFIG_WR 0x09 /* RW */ > +#define SBTSI_REG_TEMP_DEC 0x10 /* RO */ > +#define SBTSI_REG_TEMP_HIGH_DEC 0x13 /* RW */ > +#define SBTSI_REG_TEMP_LOW_DEC 0x14 /* RW */ > +#define SBTSI_REG_ALERT_CONFIG 0xBF /* RW */ > +#define SBTSI_REG_MAN 0xFE /* RO */ > +#define SBTSI_REG_REV 0xFF /* RO */ > + > +#define SBTSI_STATUS_HIGH_ALERT BIT(4) > +#define SBTSI_STATUS_LOW_ALERT BIT(3) > +#define SBTSI_CONFIG_ALERT_MASK BIT(7) > +#define SBTSI_ALARM_EN BIT(0) > + > +/* The temperature we stored are in units of 0.125 degrees. */ > +#define SBTSI_TEMP_UNIT_IN_MILLIDEGREE 125 > + > +#endif > diff --git a/hw/sensor/tmp_sbtsi.c b/hw/sensor/tmp_sbtsi.c > new file mode 100644 > index 0000000000..d5406844ef > --- /dev/null > +++ b/hw/sensor/tmp_sbtsi.c > @@ -0,0 +1,369 @@ > +/* > + * AMD SBI Temperature Sensor Interface (SB-TSI) > + * > + * Copyright 2021 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 > WITHOUT > + * 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/smbus_slave.h" > +#include "hw/sensor/sbtsi.h" > +#include "hw/irq.h" > +#include "migration/vmstate.h" > +#include "qapi/error.h" > +#include "qapi/visitor.h" > +#include "qemu/log.h" > +#include "qemu/module.h" > +#include "qom/object.h" > +#include "trace.h" > + > +#define TYPE_SBTSI "sbtsi" > +#define SBTSI(obj) OBJECT_CHECK(SBTSIState, (obj), TYPE_SBTSI) > + > +/** > + * SBTSIState: > + * temperatures are in units of 0.125 degrees > + * @temperature: Temperature > + * @limit_low: Lowest temperature > + * @limit_high: Highest temperature > + * @status: The status register > + * @config: The config register > + * @alert_config: The config for alarm_l output. > + * @addr: The address to read/write for the next cmd. > + * @alarm: The alarm_l output pin (GPIO) > + */ > +typedef struct SBTSIState { > + SMBusDevice parent; > + > + uint32_t temperature; > + uint32_t limit_low; > + uint32_t limit_high; > + uint8_t status; > + uint8_t config; > + uint8_t alert_config; > + uint8_t addr; > + qemu_irq alarm; > +} SBTSIState; > + > +#define SBTSI_LIMIT_LOW_DEFAULT (0) > +#define SBTSI_LIMIT_HIGH_DEFAULT (560) > +#define SBTSI_MAN_DEFAULT (0) > +#define SBTSI_REV_DEFAULT (4) > +#define SBTSI_ALARM_L "alarm_l" > + > +/* > + * The integer part and decimal of the temperature both 8 bits. > + * Only the top 3 bits of the decimal parts are used. > + * So the max temperature is (2^8-1) + (2^3-1)/8 =3D 255.875 degrees. > + */ > +#define SBTSI_TEMP_MAX_IN_MILLIDEGREE 255875 > + > +/* The integer part of the temperature in terms of 0.125 degrees. */ > +static uint8_t get_temp_int(uint32_t temp) > +{ > + return temp >> 3; > +} > + > +/* > + * The decimal part of the temperature, in terms of 0.125 degrees. > + * H/W store it in the top 3 bits so we shift it by 5. > + */ > +static uint8_t get_temp_dec(uint32_t temp) > +{ > + return (temp & 0x7) << 5; > +} > + > +/* > + * Compute the temperature using the integer and decimal part, > + * in terms of 0.125 degrees. The decimal part are only the top 3 bits > + * so we shift it by 5 here. > + */ > +static uint32_t compute_temp(uint8_t integer, uint8_t decimal) > +{ > + return (integer << 3) + (decimal >> 5); > +} > + > +/* Compute new temp with new int part of the temperature. */ > +static uint32_t compute_temp_int(uint32_t temp, uint8_t integer) > +{ > + return compute_temp(integer, get_temp_dec(temp)); > +} > + > +/* Compute new temp with new dec part of the temperature. */ > +static uint32_t compute_temp_dec(uint32_t temp, uint8_t decimal) > +{ > + return compute_temp(get_temp_int(temp), decimal); > +} > + > +/* The integer part of the temperature. */ > +static void sbtsi_update_status(SBTSIState *s) > +{ > + s->status =3D 0; > + if (s->alert_config & SBTSI_ALARM_EN) { > + if (s->temperature >=3D s->limit_high) { > + s->status |=3D SBTSI_STATUS_HIGH_ALERT; > + } > + if (s->temperature <=3D s->limit_low) { > + s->status |=3D SBTSI_STATUS_LOW_ALERT; > + } > + } > +} > + > +static void sbtsi_update_alarm(SBTSIState *s) > +{ > + sbtsi_update_status(s); > + if (s->status !=3D 0 && !(s->config & SBTSI_CONFIG_ALERT_MASK)) { > + qemu_irq_raise(s->alarm); > + } else { > + qemu_irq_lower(s->alarm); > + } > +} > + > +static uint8_t sbtsi_read_byte(SMBusDevice *d) > +{ > + SBTSIState *s =3D SBTSI(d); > + uint8_t data =3D 0; > + > + switch (s->addr) { > + case SBTSI_REG_TEMP_INT: > + data =3D get_temp_int(s->temperature); > + break; > + > + case SBTSI_REG_TEMP_DEC: > + data =3D get_temp_dec(s->temperature); > + break; > + > + case SBTSI_REG_TEMP_HIGH_INT: > + data =3D get_temp_int(s->limit_high); > + break; > + > + case SBTSI_REG_TEMP_LOW_INT: > + data =3D get_temp_int(s->limit_low); > + break; > + > + case SBTSI_REG_TEMP_HIGH_DEC: > + data =3D get_temp_dec(s->limit_high); > + break; > + > + case SBTSI_REG_TEMP_LOW_DEC: > + data =3D get_temp_dec(s->limit_low); > + break; > + > + case SBTSI_REG_CONFIG: > + case SBTSI_REG_CONFIG_WR: > + data =3D s->config; > + break; > + > + case SBTSI_REG_STATUS: > + sbtsi_update_alarm(s); > + data =3D s->status; > + break; > + > + case SBTSI_REG_ALERT_CONFIG: > + data =3D s->alert_config; > + break; > + > + case SBTSI_REG_MAN: > + data =3D SBTSI_MAN_DEFAULT; > + break; > + > + case SBTSI_REG_REV: > + data =3D SBTSI_REV_DEFAULT; > + break; > + > + default: > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: reading from invalid reg: 0x%02x\n", > + __func__, s->addr); > + break; > + } > + > + trace_tmp_sbtsi_read_data(s->addr, data); > + return data; > +} > + > +static void sbtsi_write(SBTSIState *s, uint8_t data) > +{ > + trace_tmp_sbtsi_write_data(s->addr, data); > + switch (s->addr) { > + case SBTSI_REG_CONFIG_WR: > + s->config =3D data; > + break; > + > + case SBTSI_REG_TEMP_HIGH_INT: > + s->limit_high =3D compute_temp_int(s->limit_high, data); > + break; > + > + case SBTSI_REG_TEMP_LOW_INT: > + s->limit_low =3D compute_temp_int(s->limit_low, data); > + break; > + > + case SBTSI_REG_TEMP_HIGH_DEC: > + s->limit_high =3D compute_temp_dec(s->limit_high, data); > + break; > + > + case SBTSI_REG_TEMP_LOW_DEC: > + s->limit_low =3D compute_temp_dec(s->limit_low, data); > + break; > + > + case SBTSI_REG_ALERT_CONFIG: > + s->alert_config =3D data; > + break; > + > + case SBTSI_REG_TEMP_INT: > + case SBTSI_REG_TEMP_DEC: > + case SBTSI_REG_CONFIG: > + case SBTSI_REG_STATUS: > + case SBTSI_REG_MAN: > + case SBTSI_REG_REV: > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: writing to read only reg: 0x%02x data: 0x%02x\n", > + __func__, s->addr, data); > + break; > + > + default: > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: writing to invalid reg: 0x%02x data: 0x%02x\n", > + __func__, s->addr, data); > + break; > + } > + sbtsi_update_alarm(s); > +} > + > +static int sbtsi_write_data(SMBusDevice *d, uint8_t *buf, uint8_t len) > +{ > + SBTSIState *s =3D SBTSI(d); > + > + if (len =3D=3D 0) { > + qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", > __func__); > + return -1; > + } > + > + s->addr =3D buf[0]; > + if (len > 1) { > + sbtsi_write(s, buf[1]); > + if (len > 2) { > + qemu_log_mask(LOG_GUEST_ERROR, "%s: extra data at end\n", > __func__); > + } > + } > + return 0; > +} > + > +/* Units are millidegrees. */ > +static void sbtsi_get_temperature(Object *obj, Visitor *v, const char > *name, > + void *opaque, Error **errp) > +{ > + SBTSIState *s =3D SBTSI(obj); > + uint32_t temp =3D s->temperature * SBTSI_TEMP_UNIT_IN_MILLIDEGREE; > + > + visit_type_uint32(v, name, &temp, errp); > +} > + > +/* Units are millidegrees. */ > +static void sbtsi_set_temperature(Object *obj, Visitor *v, const char > *name, > + void *opaque, Error **errp) > +{ > + SBTSIState *s =3D SBTSI(obj); > + uint32_t temp; > + > + if (!visit_type_uint32(v, name, &temp, errp)) { > + return; > + } > + if (temp > SBTSI_TEMP_MAX_IN_MILLIDEGREE) { > + error_setg(errp, "value %" PRIu32 ".%03" PRIu32 " C is out of > range", > + temp / 1000, temp % 1000); > + return; > + } > + > + s->temperature =3D temp / SBTSI_TEMP_UNIT_IN_MILLIDEGREE; > + sbtsi_update_alarm(s); > +} > + > +static int sbtsi_post_load(void *opaque, int version_id) > +{ > + SBTSIState *s =3D opaque; > + > + sbtsi_update_alarm(s); > + return 0; > +} > + > +static const VMStateDescription vmstate_sbtsi =3D { > + .name =3D "SBTSI", > + .version_id =3D 0, > + .minimum_version_id =3D 0, > + .post_load =3D sbtsi_post_load, > + .fields =3D (VMStateField[]) { > + VMSTATE_UINT32(temperature, SBTSIState), > + VMSTATE_UINT32(limit_low, SBTSIState), > + VMSTATE_UINT32(limit_high, SBTSIState), > + VMSTATE_UINT8(config, SBTSIState), > + VMSTATE_UINT8(status, SBTSIState), > + VMSTATE_UINT8(addr, SBTSIState), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static void sbtsi_enter_reset(Object *obj, ResetType type) > +{ > + SBTSIState *s =3D SBTSI(obj); > + > + s->config =3D 0; > + s->limit_low =3D SBTSI_LIMIT_LOW_DEFAULT; > + s->limit_high =3D SBTSI_LIMIT_HIGH_DEFAULT; > +} > + > +static void sbtsi_hold_reset(Object *obj) > +{ > + SBTSIState *s =3D SBTSI(obj); > + > + qemu_irq_lower(s->alarm); > +} > + > +static void sbtsi_init(Object *obj) > +{ > + SBTSIState *s =3D SBTSI(obj); > + > + /* Current temperature in millidegrees. */ > + object_property_add(obj, "temperature", "uint32", > + sbtsi_get_temperature, sbtsi_set_temperature, > + NULL, NULL); > + qdev_init_gpio_out_named(DEVICE(obj), &s->alarm, SBTSI_ALARM_L, 0); > +} > + > +static void sbtsi_class_init(ObjectClass *klass, void *data) > +{ > + ResettableClass *rc =3D RESETTABLE_CLASS(klass); > + DeviceClass *dc =3D DEVICE_CLASS(klass); > + SMBusDeviceClass *k =3D SMBUS_DEVICE_CLASS(klass); > + > + dc->desc =3D "SB-TSI Temperature Sensor"; > + dc->vmsd =3D &vmstate_sbtsi; > + k->write_data =3D sbtsi_write_data; > + k->receive_byte =3D sbtsi_read_byte; > + rc->phases.enter =3D sbtsi_enter_reset; > + rc->phases.hold =3D sbtsi_hold_reset; > +} > + > +static const TypeInfo sbtsi_info =3D { > + .name =3D TYPE_SBTSI, > + .parent =3D TYPE_SMBUS_DEVICE, > + .instance_size =3D sizeof(SBTSIState), > + .instance_init =3D sbtsi_init, > + .class_init =3D sbtsi_class_init, > +}; > + > +static void sbtsi_register_types(void) > +{ > + type_register_static(&sbtsi_info); > +} > + > +type_init(sbtsi_register_types) > diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig > index 9c8a049b06..27f6f79c84 100644 > --- a/hw/sensor/Kconfig > +++ b/hw/sensor/Kconfig > @@ -21,3 +21,7 @@ config ADM1272 > config MAX34451 > bool > depends on I2C > + > +config AMDSBTSI > + bool > + depends on I2C > diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build > index 059c4ca935..f7b0e645eb 100644 > --- a/hw/sensor/meson.build > +++ b/hw/sensor/meson.build > @@ -4,3 +4,4 @@ softmmu_ss.add(when: 'CONFIG_DPS310', if_true: > files('dps310.c')) > softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c')) > softmmu_ss.add(when: 'CONFIG_ADM1272', if_true: files('adm1272.c')) > softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('max34451.c')) > +softmmu_ss.add(when: 'CONFIG_AMDSBTSI', if_true: files('tmp_sbtsi.c')) > diff --git a/hw/sensor/trace-events b/hw/sensor/trace-events > new file mode 100644 > index 0000000000..21ab3809e2 > --- /dev/null > +++ b/hw/sensor/trace-events > @@ -0,0 +1,5 @@ > +# See docs/devel/tracing.rst for syntax documentation. > + > +# tmp_sbtsi.c > +tmp_sbtsi_write_data(uint8_t addr, uint8_t value) "SBTSI write > addr:0x%02x data: 0x%02x" > +tmp_sbtsi_read_data(uint8_t addr, uint8_t value) "SBTSI read addr:0x%02x > data: 0x%02x" > -- > 2.34.1.575.g55b058a8bb-goog > > --000000000000b616cb05f41055cc Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

It seems like this patch set is rev= iewed but never merged. Who should take this patch set? What are our next s= teps for them?

Thanks!

On Mon, Jan 31, 20= 22 at 2:29 PM Patrick Venture <ven= ture@google.com> wrote:
From: Hao Wu <wuhaotsh@google.com>

SB Temperature Sensor Interface (SB-TSI) is an SMBus compatible
interface that reports AMD SoC's Ttcl (normalized temperature),
and resembles a typical 8-pin remote temperature sensor's I2C interface=
to BMC.

This patch implements a basic AMD SB-TSI sensor that is
compatible with the open-source data sheet from AMD and Linux
kernel driver.

Reference:
Linux kernel driver:
https://lkml.org/lkml/2020/12/11/968
Register Map:
https://developer.amd.com/wp-content/re= sources/56255_3_03.PDF
(Chapter 6)

Signed-off-by: Hao Wu <wuhaotsh@google.com>
Signed-off-by: Patrick Venture <venture@google.com>
Reviewed-by: Doug Evans <dje@google.com>
Reviewed-by: Philippe Mathieu-Daud=C3=A9 <f4bug@amsat.org>
Acked-by: Corey Minyard <cminyard@mvista.com>
---
=C2=A0meson.build=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|= =C2=A0 =C2=A01 +
=C2=A0hw/sensor/trace.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A01 +<= br> =C2=A0include/hw/sensor/sbtsi.h |=C2=A0 45 +++++
=C2=A0hw/sensor/tmp_sbtsi.c=C2=A0 =C2=A0 =C2=A0| 369 ++++++++++++++++++++++= ++++++++++++++++
=C2=A0hw/sensor/Kconfig=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A04 +<= br> =C2=A0hw/sensor/meson.build=C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A01 +
=C2=A0hw/sensor/trace-events=C2=A0 =C2=A0 |=C2=A0 =C2=A05 +
=C2=A07 files changed, 426 insertions(+)
=C2=A0create mode 100644 hw/sensor/trace.h
=C2=A0create mode 100644 include/hw/sensor/sbtsi.h
=C2=A0create mode 100644 hw/sensor/tmp_sbtsi.c
=C2=A0create mode 100644 hw/sensor/trace-events

diff --git a/meson.build b/meson.build
index c1b1db1e28..3634214546 100644
--- a/meson.build
+++ b/meson.build
@@ -2494,6 +2494,7 @@ if have_system
=C2=A0 =C2=A0 =C2=A0'hw/rtc',
=C2=A0 =C2=A0 =C2=A0'hw/s390x',
=C2=A0 =C2=A0 =C2=A0'hw/scsi',
+=C2=A0 =C2=A0 'hw/sensor',
=C2=A0 =C2=A0 =C2=A0'hw/sd',
=C2=A0 =C2=A0 =C2=A0'hw/sh4',
=C2=A0 =C2=A0 =C2=A0'hw/sparc',
diff --git a/hw/sensor/trace.h b/hw/sensor/trace.h
new file mode 100644
index 0000000000..e4721560b0
--- /dev/null
+++ b/hw/sensor/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-hw_sensor.h"
diff --git a/include/hw/sensor/sbtsi.h b/include/hw/sensor/sbtsi.h
new file mode 100644
index 0000000000..9073f76ebb
--- /dev/null
+++ b/include/hw/sensor/sbtsi.h
@@ -0,0 +1,45 @@
+/*
+ * AMD SBI Temperature Sensor Interface (SB-TSI)
+ *
+ * Copyright 2021 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 QEMU_TMP_SBTSI_H
+#define QEMU_TMP_SBTSI_H
+
+/*
+ * SB-TSI registers only support SMBus byte data access. "_INT" = registers are
+ * the integer part of a temperature value or limit, and "_DEC" = registers are
+ * corresponding decimal parts.
+ */
+#define SBTSI_REG_TEMP_INT=C2=A0 =C2=A0 =C2=A0 0x01 /* RO */
+#define SBTSI_REG_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x02 /* RO */
+#define SBTSI_REG_CONFIG=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x03 /* RO */
+#define SBTSI_REG_TEMP_HIGH_INT 0x07 /* RW */
+#define SBTSI_REG_TEMP_LOW_INT=C2=A0 0x08 /* RW */
+#define SBTSI_REG_CONFIG_WR=C2=A0 =C2=A0 =C2=A00x09 /* RW */
+#define SBTSI_REG_TEMP_DEC=C2=A0 =C2=A0 =C2=A0 0x10 /* RO */
+#define SBTSI_REG_TEMP_HIGH_DEC 0x13 /* RW */
+#define SBTSI_REG_TEMP_LOW_DEC=C2=A0 0x14 /* RW */
+#define SBTSI_REG_ALERT_CONFIG=C2=A0 0xBF /* RW */
+#define SBTSI_REG_MAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00xFE /* RO *= /
+#define SBTSI_REG_REV=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00xFF /* RO *= /
+
+#define SBTSI_STATUS_HIGH_ALERT BIT(4)
+#define SBTSI_STATUS_LOW_ALERT=C2=A0 BIT(3)
+#define SBTSI_CONFIG_ALERT_MASK BIT(7)
+#define SBTSI_ALARM_EN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 BIT(0)
+
+/* The temperature we stored are in units of 0.125 degrees. */
+#define SBTSI_TEMP_UNIT_IN_MILLIDEGREE 125
+
+#endif
diff --git a/hw/sensor/tmp_sbtsi.c b/hw/sensor/tmp_sbtsi.c
new file mode 100644
index 0000000000..d5406844ef
--- /dev/null
+++ b/hw/sensor/tmp_sbtsi.c
@@ -0,0 +1,369 @@
+/*
+ * AMD SBI Temperature Sensor Interface (SB-TSI)
+ *
+ * Copyright 2021 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/smbus_slave.h"
+#include "hw/sensor/sbtsi.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qom/object.h"
+#include "trace.h"
+
+#define TYPE_SBTSI "sbtsi"
+#define SBTSI(obj) OBJECT_CHECK(SBTSIState, (obj), TYPE_SBTSI)
+
+/**
+ * SBTSIState:
+ * temperatures are in units of 0.125 degrees
+ * @temperature: Temperature
+ * @limit_low: Lowest temperature
+ * @limit_high: Highest temperature
+ * @status: The status register
+ * @config: The config register
+ * @alert_config: The config for alarm_l output.
+ * @addr: The address to read/write for the next cmd.
+ * @alarm: The alarm_l output pin (GPIO)
+ */
+typedef struct SBTSIState {
+=C2=A0 =C2=A0 SMBusDevice parent;
+
+=C2=A0 =C2=A0 uint32_t temperature;
+=C2=A0 =C2=A0 uint32_t limit_low;
+=C2=A0 =C2=A0 uint32_t limit_high;
+=C2=A0 =C2=A0 uint8_t status;
+=C2=A0 =C2=A0 uint8_t config;
+=C2=A0 =C2=A0 uint8_t alert_config;
+=C2=A0 =C2=A0 uint8_t addr;
+=C2=A0 =C2=A0 qemu_irq alarm;
+} SBTSIState;
+
+#define SBTSI_LIMIT_LOW_DEFAULT (0)
+#define SBTSI_LIMIT_HIGH_DEFAULT (560)
+#define SBTSI_MAN_DEFAULT (0)
+#define SBTSI_REV_DEFAULT (4)
+#define SBTSI_ALARM_L "alarm_l"
+
+/*
+ * The integer part and decimal of the temperature both 8 bits.
+ * Only the top 3 bits of the decimal parts are used.
+ * So the max temperature is (2^8-1) + (2^3-1)/8 =3D 255.875 degrees.
+ */
+#define SBTSI_TEMP_MAX_IN_MILLIDEGREE 255875
+
+/* The integer part of the temperature in terms of 0.125 degrees. */
+static uint8_t get_temp_int(uint32_t temp)
+{
+=C2=A0 =C2=A0 return temp >> 3;
+}
+
+/*
+ * The decimal part of the temperature, in terms of 0.125 degrees.
+ * H/W store it in the top 3 bits so we shift it by 5.
+ */
+static uint8_t get_temp_dec(uint32_t temp)
+{
+=C2=A0 =C2=A0 return (temp & 0x7) << 5;
+}
+
+/*
+ * Compute the temperature using the integer and decimal part,
+ * in terms of 0.125 degrees. The decimal part are only the top 3 bits
+ * so we shift it by 5 here.
+ */
+static uint32_t compute_temp(uint8_t integer, uint8_t decimal)
+{
+=C2=A0 =C2=A0 return (integer << 3) + (decimal >> 5);
+}
+
+/* Compute new temp with new int part of the temperature. */
+static uint32_t compute_temp_int(uint32_t temp, uint8_t integer)
+{
+=C2=A0 =C2=A0 return compute_temp(integer, get_temp_dec(temp));
+}
+
+/* Compute new temp with new dec part of the temperature. */
+static uint32_t compute_temp_dec(uint32_t temp, uint8_t decimal)
+{
+=C2=A0 =C2=A0 return compute_temp(get_temp_int(temp), decimal);
+}
+
+/* The integer part of the temperature. */
+static void sbtsi_update_status(SBTSIState *s)
+{
+=C2=A0 =C2=A0 s->status =3D 0;
+=C2=A0 =C2=A0 if (s->alert_config & SBTSI_ALARM_EN) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (s->temperature >=3D s->limit_high= ) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 s->status |=3D SBTSI_STATUS_H= IGH_ALERT;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (s->temperature <=3D s->limit_low)= {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 s->status |=3D SBTSI_STATUS_L= OW_ALERT;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 }
+}
+
+static void sbtsi_update_alarm(SBTSIState *s)
+{
+=C2=A0 =C2=A0 sbtsi_update_status(s);
+=C2=A0 =C2=A0 if (s->status !=3D 0 && !(s->config & SBTS= I_CONFIG_ALERT_MASK)) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_irq_raise(s->alarm);
+=C2=A0 =C2=A0 } else {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_irq_lower(s->alarm);
+=C2=A0 =C2=A0 }
+}
+
+static uint8_t sbtsi_read_byte(SMBusDevice *d)
+{
+=C2=A0 =C2=A0 SBTSIState *s =3D SBTSI(d);
+=C2=A0 =C2=A0 uint8_t data =3D 0;
+
+=C2=A0 =C2=A0 switch (s->addr) {
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_INT:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D get_temp_int(s->temperature);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_DEC:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D get_temp_dec(s->temperature);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_HIGH_INT:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D get_temp_int(s->limit_high);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_LOW_INT:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D get_temp_int(s->limit_low);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_HIGH_DEC:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D get_temp_dec(s->limit_high);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_LOW_DEC:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D get_temp_dec(s->limit_low);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_CONFIG:
+=C2=A0 =C2=A0 case SBTSI_REG_CONFIG_WR:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D s->config;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_STATUS:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 sbtsi_update_alarm(s);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D s->status;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_ALERT_CONFIG:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D s->alert_config;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_MAN:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D SBTSI_MAN_DEFAULT;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_REV:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 data =3D SBTSI_REV_DEFAULT;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 default:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_GUEST_ERROR,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "%s: reading = from invalid reg: 0x%02x\n",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 __func__, s->ad= dr);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+=C2=A0 =C2=A0 }
+
+=C2=A0 =C2=A0 trace_tmp_sbtsi_read_data(s->addr, data);
+=C2=A0 =C2=A0 return data;
+}
+
+static void sbtsi_write(SBTSIState *s, uint8_t data)
+{
+=C2=A0 =C2=A0 trace_tmp_sbtsi_write_data(s->addr, data);
+=C2=A0 =C2=A0 switch (s->addr) {
+=C2=A0 =C2=A0 case SBTSI_REG_CONFIG_WR:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 s->config =3D data;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_HIGH_INT:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 s->limit_high =3D compute_temp_int(s->li= mit_high, data);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_LOW_INT:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 s->limit_low =3D compute_temp_int(s->lim= it_low, data);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_HIGH_DEC:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 s->limit_high =3D compute_temp_dec(s->li= mit_high, data);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_LOW_DEC:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 s->limit_low =3D compute_temp_dec(s->lim= it_low, data);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_ALERT_CONFIG:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 s->alert_config =3D data;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_INT:
+=C2=A0 =C2=A0 case SBTSI_REG_TEMP_DEC:
+=C2=A0 =C2=A0 case SBTSI_REG_CONFIG:
+=C2=A0 =C2=A0 case SBTSI_REG_STATUS:
+=C2=A0 =C2=A0 case SBTSI_REG_MAN:
+=C2=A0 =C2=A0 case SBTSI_REG_REV:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_GUEST_ERROR,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "%s: writing = to read only reg: 0x%02x data: 0x%02x\n",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 __func__, s->ad= dr, data);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+
+=C2=A0 =C2=A0 default:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_GUEST_ERROR,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "%s: writing = to invalid reg: 0x%02x data: 0x%02x\n",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 __func__, s->ad= dr, data);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 sbtsi_update_alarm(s);
+}
+
+static int sbtsi_write_data(SMBusDevice *d, uint8_t *buf, uint8_t len)
+{
+=C2=A0 =C2=A0 SBTSIState *s =3D SBTSI(d);
+
+=C2=A0 =C2=A0 if (len =3D=3D 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_GUEST_ERROR, "%s: writi= ng empty data\n", __func__);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return -1;
+=C2=A0 =C2=A0 }
+
+=C2=A0 =C2=A0 s->addr =3D buf[0];
+=C2=A0 =C2=A0 if (len > 1) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 sbtsi_write(s, buf[1]);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (len > 2) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_GUEST_ERROR, &= quot;%s: extra data at end\n", __func__);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 return 0;
+}
+
+/* Units are millidegrees. */
+static void sbtsi_get_temperature(Object *obj, Visitor *v, const char *nam= e,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void *opaque, Error **errp) +{
+=C2=A0 =C2=A0 SBTSIState *s =3D SBTSI(obj);
+=C2=A0 =C2=A0 uint32_t temp =3D s->temperature * SBTSI_TEMP_UNIT_IN_MIL= LIDEGREE;
+
+=C2=A0 =C2=A0 visit_type_uint32(v, name, &temp, errp);
+}
+
+/* Units are millidegrees. */
+static void sbtsi_set_temperature(Object *obj, Visitor *v, const char *nam= e,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void *opaque, Error **errp) +{
+=C2=A0 =C2=A0 SBTSIState *s =3D SBTSI(obj);
+=C2=A0 =C2=A0 uint32_t temp;
+
+=C2=A0 =C2=A0 if (!visit_type_uint32(v, name, &temp, errp)) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
+=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 if (temp > SBTSI_TEMP_MAX_IN_MILLIDEGREE) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 error_setg(errp, "value %" PRIu32 &q= uot;.%03" PRIu32 " C is out of range",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0temp = / 1000, temp % 1000);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
+=C2=A0 =C2=A0 }
+
+=C2=A0 =C2=A0 s->temperature =3D temp / SBTSI_TEMP_UNIT_IN_MILLIDEGREE;=
+=C2=A0 =C2=A0 sbtsi_update_alarm(s);
+}
+
+static int sbtsi_post_load(void *opaque, int version_id)
+{
+=C2=A0 =C2=A0 SBTSIState *s =3D opaque;
+
+=C2=A0 =C2=A0 sbtsi_update_alarm(s);
+=C2=A0 =C2=A0 return 0;
+}
+
+static const VMStateDescription vmstate_sbtsi =3D {
+=C2=A0 =C2=A0 .name =3D "SBTSI",
+=C2=A0 =C2=A0 .version_id =3D 0,
+=C2=A0 =C2=A0 .minimum_version_id =3D 0,
+=C2=A0 =C2=A0 .post_load =3D sbtsi_post_load,
+=C2=A0 =C2=A0 .fields =3D (VMStateField[]) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 VMSTATE_UINT32(temperature, SBTSIState),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 VMSTATE_UINT32(limit_low, SBTSIState),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 VMSTATE_UINT32(limit_high, SBTSIState),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 VMSTATE_UINT8(config, SBTSIState),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 VMSTATE_UINT8(status, SBTSIState),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 VMSTATE_UINT8(addr, SBTSIState),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 VMSTATE_END_OF_LIST()
+=C2=A0 =C2=A0 }
+};
+
+static void sbtsi_enter_reset(Object *obj, ResetType type)
+{
+=C2=A0 =C2=A0 SBTSIState *s =3D SBTSI(obj);
+
+=C2=A0 =C2=A0 s->config =3D 0;
+=C2=A0 =C2=A0 s->limit_low =3D SBTSI_LIMIT_LOW_DEFAULT;
+=C2=A0 =C2=A0 s->limit_high =3D SBTSI_LIMIT_HIGH_DEFAULT;
+}
+
+static void sbtsi_hold_reset(Object *obj)
+{
+=C2=A0 =C2=A0 SBTSIState *s =3D SBTSI(obj);
+
+=C2=A0 =C2=A0 qemu_irq_lower(s->alarm);
+}
+
+static void sbtsi_init(Object *obj)
+{
+=C2=A0 =C2=A0 SBTSIState *s =3D SBTSI(obj);
+
+=C2=A0 =C2=A0 /* Current temperature in millidegrees. */
+=C2=A0 =C2=A0 object_property_add(obj, "temperature", "uint= 32",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 sbtsi_get_temperature, sbtsi_set_temperature,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 NULL, NULL);
+=C2=A0 =C2=A0 qdev_init_gpio_out_named(DEVICE(obj), &s->alarm, SBTS= I_ALARM_L, 0);
+}
+
+static void sbtsi_class_init(ObjectClass *klass, void *data)
+{
+=C2=A0 =C2=A0 ResettableClass *rc =3D RESETTABLE_CLASS(klass);
+=C2=A0 =C2=A0 DeviceClass *dc =3D DEVICE_CLASS(klass);
+=C2=A0 =C2=A0 SMBusDeviceClass *k =3D SMBUS_DEVICE_CLASS(klass);
+
+=C2=A0 =C2=A0 dc->desc =3D "SB-TSI Temperature Sensor";
+=C2=A0 =C2=A0 dc->vmsd =3D &vmstate_sbtsi;
+=C2=A0 =C2=A0 k->write_data =3D sbtsi_write_data;
+=C2=A0 =C2=A0 k->receive_byte =3D sbtsi_read_byte;
+=C2=A0 =C2=A0 rc->phases.enter =3D sbtsi_enter_reset;
+=C2=A0 =C2=A0 rc->phases.hold =3D sbtsi_hold_reset;
+}
+
+static const TypeInfo sbtsi_info =3D {
+=C2=A0 =C2=A0 .name=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D TYPE_SBTSI,
+=C2=A0 =C2=A0 .parent=C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D TYPE_SMBUS_DEVICE, +=C2=A0 =C2=A0 .instance_size =3D sizeof(SBTSIState),
+=C2=A0 =C2=A0 .instance_init =3D sbtsi_init,
+=C2=A0 =C2=A0 .class_init=C2=A0 =C2=A0 =3D sbtsi_class_init,
+};
+
+static void sbtsi_register_types(void)
+{
+=C2=A0 =C2=A0 type_register_static(&sbtsi_info);
+}
+
+type_init(sbtsi_register_types)
diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig
index 9c8a049b06..27f6f79c84 100644
--- a/hw/sensor/Kconfig
+++ b/hw/sensor/Kconfig
@@ -21,3 +21,7 @@ config ADM1272
=C2=A0config MAX34451
=C2=A0 =C2=A0 =C2=A0bool
=C2=A0 =C2=A0 =C2=A0depends on I2C
+
+config AMDSBTSI
+=C2=A0 =C2=A0 bool
+=C2=A0 =C2=A0 depends on I2C
diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build
index 059c4ca935..f7b0e645eb 100644
--- a/hw/sensor/meson.build
+++ b/hw/sensor/meson.build
@@ -4,3 +4,4 @@ softmmu_ss.add(when: 'CONFIG_DPS310', if_true: file= s('dps310.c'))
=C2=A0softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('em= c141x.c'))
=C2=A0softmmu_ss.add(when: 'CONFIG_ADM1272', if_true: files('ad= m1272.c'))
=C2=A0softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('m= ax34451.c'))
+softmmu_ss.add(when: 'CONFIG_AMDSBTSI', if_true: files('tmp_sb= tsi.c'))
diff --git a/hw/sensor/trace-events b/hw/sensor/trace-events
new file mode 100644
index 0000000000..21ab3809e2
--- /dev/null
+++ b/hw/sensor/trace-events
@@ -0,0 +1,5 @@
+# See docs/devel/tracing.rst for syntax documentation.
+
+# tmp_sbtsi.c
+tmp_sbtsi_write_data(uint8_t addr, uint8_t value) "SBTSI write addr:0= x%02x data: 0x%02x"
+tmp_sbtsi_read_data(uint8_t addr, uint8_t value) "SBTSI read addr:0x%= 02x data: 0x%02x"
--
2.34.1.575.g55b058a8bb-goog

--000000000000b616cb05f41055cc--