From nobody Sun Feb 8 21:28:44 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1680221388; cv=none; d=zohomail.com; s=zohoarc; b=RUuQQSMbdZFmQyKkzA47zEtBuR6LOg8ge0h30OOqSoIaP+Sm7p1Jk13HcKKfHfHojB0aTORcmit4oXCEX89Z5Rlu1OES8HpLPFIZTheOb15bOIQvREDEGxTZHYnpQvQZ3OMBHPm0KBs7lxG7gdiKZFofFaNqEV3dK0tbmr3aE/I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1680221388; 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:References:Sender:Subject:To; bh=8gvomdt3DUwUN4FoSBnJV4Ctxju8JwPTYOQalHBdVD4=; b=DLQOFomwDxiDXwl6x2WUKp0CBNDf5mmtMQP1fGfiTvxHxShFlv+8XgdzVqsEwqenE3WGDvo2IALML3eoQA/51PCtIy8/FmKVCN8KP8ikqRi8ckwtQBtZNYjQ1TnO32z67PcClCrNKTYKJ2Wxet80ijIZsPyYWH75pc5KTOJLxJY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1680221388970186.51000828557665; Thu, 30 Mar 2023 17:09:48 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pi2KS-0007SM-2k; Thu, 30 Mar 2023 20:09:16 -0400 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 <3hyQmZAYKCpAD2DECB08805y.w86Ay6E-xyFy578707E.8B0@flex--titusr.bounces.google.com>) id 1pi2K9-0007Cb-DE for qemu-devel@nongnu.org; Thu, 30 Mar 2023 20:08:57 -0400 Received: from mail-yw1-x114a.google.com ([2607:f8b0:4864:20::114a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3hyQmZAYKCpAD2DECB08805y.w86Ay6E-xyFy578707E.8B0@flex--titusr.bounces.google.com>) id 1pi2K6-0005qQ-6P for qemu-devel@nongnu.org; Thu, 30 Mar 2023 20:08:57 -0400 Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-5458201ab8cso207036377b3.23 for ; Thu, 30 Mar 2023 17:08:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1680221319; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=8gvomdt3DUwUN4FoSBnJV4Ctxju8JwPTYOQalHBdVD4=; b=UEfgoMO4eZQeg9kuztrUq2cXxkWJmLL3WxzcUu/vTNNLbE7hASopSjKN9Lc5UAkL0e fhzkZPiq92TAWvBKIVZtmDOG+2CF+RjCWAhlDa1p/gaBLQzf9TvyMbuXfYtPvYs5DXJ6 O2/S0gUXr6GAwLOjq8C3X/DJ+asKLUBeI6qQ9+KLMotSimFJOpWSkO9JDsqz57Oqk04C GlCByLNnK0sDDrj3+Sjy/ObynhFcYXnHIMZkTppUlX3pGU+95vPZwhSStRkxbH+QXmSK T+xSsh7O5Yg+AnBfF9jha6pPPEEOjU4ea7raDB4q+aGrCVh3ckrmdjR0D1qfHBxQnEjs EjZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680221319; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=8gvomdt3DUwUN4FoSBnJV4Ctxju8JwPTYOQalHBdVD4=; b=0iJ6t/rlFfJhyqybZewwUt15uyw2HgERuh5jd3cI549VNX0FwLtlEviTPmW0LPjxRd BfXO3Q0La+jTmu40uv+xwgh4qFLf3s7NmIbWXiNHFNd1GrgYqe5REfXDwdWwzPCz42Jh ApaF1Nltqu6XiNX1At7zM+Scxz1y/zD+KGyEfdbfYQ0+6Fq/plAWy25Qd0qSQoLkKSgw kibzHGahRJR96WdxBYZmWxBQrt6Drk7LrPPtx71JDnTiCvtHLF0Gl3lC/RgeukalaPp/ S6KBIdZBe5sd7ekfKA53tDW/GsDGRNWVfmNvQzEABJ2kLlUca8o1eEztZClDADs+50qS DSKA== X-Gm-Message-State: AAQBX9fXyGlb4No0a9Ol6OwIkP8D56pscFW7mIebGtIkCt88XImthYoZ P5HdoOw2q5Eb2IN7LgRgARZTFKzQ2E8= X-Google-Smtp-Source: AKy350bMKwN4e9D5fZq0GnlqP+dMuSeSVPl5UJpB9T0Zsu7bFb1uBlAWqN5xEc5SLF1FP5lwTuEo4bXHCCg= X-Received: from titusr.c.googlers.com ([fda3:e722:ac3:cc00:14:4d90:c0a8:22b8]) (user=titusr job=sendgmr) by 2002:a05:6902:18d5:b0:b75:3fd4:1b31 with SMTP id ck21-20020a05690218d500b00b753fd41b31mr17197516ybb.1.1680221319710; Thu, 30 Mar 2023 17:08:39 -0700 (PDT) Date: Fri, 31 Mar 2023 00:07:55 +0000 In-Reply-To: <20230331000756.1712787-1-titusr@google.com> Mime-Version: 1.0 References: <20230331000756.1712787-1-titusr@google.com> X-Mailer: git-send-email 2.40.0.423.gd6c402a77b-goog Message-ID: <20230331000756.1712787-7-titusr@google.com> Subject: [PATCH 6/7] hw/sensor: add ADM1266 device model From: Titus Rwantare To: philmd@linaro.org, minyard@acm.org Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Titus Rwantare , Hao Wu 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::114a; envelope-from=3hyQmZAYKCpAD2DECB08805y.w86Ay6E-xyFy578707E.8B0@flex--titusr.bounces.google.com; helo=mail-yw1-x114a.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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1680221389978100003 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The ADM1266 is a cascadable super sequencer with margin control and fault recording. This commit adds basic support for its PMBus commands and models the identification registers that can be modified in a firmware update. Reviewed-by: Hao Wu Signed-off-by: Titus Rwantare Acked-by: Corey Minyard --- hw/arm/Kconfig | 1 + hw/sensor/Kconfig | 5 + hw/sensor/adm1266.c | 255 ++++++++++++++++++++++++++++++++++++++++++ hw/sensor/meson.build | 1 + 4 files changed, 262 insertions(+) create mode 100644 hw/sensor/adm1266.c diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index b5aed4aff5..4e44a7451d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -407,6 +407,7 @@ config XLNX_VERSAL config NPCM7XX bool select A9MPCORE + select ADM1266 select ADM1272 select ARM_GIC select SMBUS diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig index e03bd09b50..bc6331b4ab 100644 --- a/hw/sensor/Kconfig +++ b/hw/sensor/Kconfig @@ -22,6 +22,11 @@ config ADM1272 bool depends on I2C =20 +config ADM1266 + bool + depends on PMBUS + default y if PMBUS + config MAX34451 bool depends on I2C diff --git a/hw/sensor/adm1266.c b/hw/sensor/adm1266.c new file mode 100644 index 0000000000..0745b12b1d --- /dev/null +++ b/hw/sensor/adm1266.c @@ -0,0 +1,255 @@ +/* + * Analog Devices ADM1266 Cascadable Super Sequencer with Margin Control a= nd + * Fault Recording with PMBus + * + * https://www.analog.com/media/en/technical-documentation/data-sheets/adm= 1266.pdf + * + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include +#include "hw/i2c/pmbus_device.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" + +#define TYPE_ADM1266 "adm1266" +OBJECT_DECLARE_SIMPLE_TYPE(ADM1266State, ADM1266) + +#define ADM1266_BLACKBOX_CONFIG 0xD3 +#define ADM1266_PDIO_CONFIG 0xD4 +#define ADM1266_READ_STATE 0xD9 +#define ADM1266_READ_BLACKBOX 0xDE +#define ADM1266_SET_RTC 0xDF +#define ADM1266_GPIO_SYNC_CONFIGURATION 0xE1 +#define ADM1266_BLACKBOX_INFORMATION 0xE6 +#define ADM1266_PDIO_STATUS 0xE9 +#define ADM1266_GPIO_STATUS 0xEA + +/* Defaults */ +#define ADM1266_OPERATION_DEFAULT 0x80 +#define ADM1266_CAPABILITY_DEFAULT 0xA0 +#define ADM1266_CAPABILITY_NO_PEC 0x20 +#define ADM1266_PMBUS_REVISION_DEFAULT 0x22 +#define ADM1266_MFR_ID_DEFAULT "ADI" +#define ADM1266_MFR_ID_DEFAULT_LEN 32 +#define ADM1266_MFR_MODEL_DEFAULT "ADM1266-A1" +#define ADM1266_MFR_MODEL_DEFAULT_LEN 32 +#define ADM1266_MFR_REVISION_DEFAULT "25" +#define ADM1266_MFR_REVISION_DEFAULT_LEN 8 + +#define ADM1266_NUM_PAGES 17 +/** + * PAGE Index + * Page 0 VH1. + * Page 1 VH2. + * Page 2 VH3. + * Page 3 VH4. + * Page 4 VP1. + * Page 5 VP2. + * Page 6 VP3. + * Page 7 VP4. + * Page 8 VP5. + * Page 9 VP6. + * Page 10 VP7. + * Page 11 VP8. + * Page 12 VP9. + * Page 13 VP10. + * Page 14 VP11. + * Page 15 VP12. + * Page 16 VP13. + */ +typedef struct ADM1266State { + PMBusDevice parent; + + char mfr_id[32]; + char mfr_model[32]; + char mfr_rev[8]; +} ADM1266State; + +static const uint8_t adm1266_ic_device_id[] =3D {0x03, 0x41, 0x12, 0x66}; +static const uint8_t adm1266_ic_device_rev[] =3D {0x08, 0x01, 0x08, 0x07, = 0x0, + 0x0, 0x07, 0x41, 0x30}; + +static void adm1266_exit_reset(Object *obj) +{ + ADM1266State *s =3D ADM1266(obj); + PMBusDevice *pmdev =3D PMBUS_DEVICE(obj); + + pmdev->page =3D 0; + pmdev->capability =3D ADM1266_CAPABILITY_NO_PEC; + + for (int i =3D 0; i < ADM1266_NUM_PAGES; i++) { + pmdev->pages[i].operation =3D ADM1266_OPERATION_DEFAULT; + pmdev->pages[i].revision =3D ADM1266_PMBUS_REVISION_DEFAULT; + pmdev->pages[i].vout_mode =3D 0; + pmdev->pages[i].read_vout =3D pmbus_data2linear_mode(12, 0); + pmdev->pages[i].vout_margin_high =3D pmbus_data2linear_mode(15, 0); + pmdev->pages[i].vout_margin_low =3D pmbus_data2linear_mode(3, 0); + pmdev->pages[i].vout_ov_fault_limit =3D pmbus_data2linear_mode(16,= 0); + pmdev->pages[i].revision =3D ADM1266_PMBUS_REVISION_DEFAULT; + } + + strncpy(s->mfr_id, ADM1266_MFR_ID_DEFAULT, 4); + strncpy(s->mfr_model, ADM1266_MFR_MODEL_DEFAULT, 11); + strncpy(s->mfr_rev, ADM1266_MFR_REVISION_DEFAULT, 3); +} + +static uint8_t adm1266_read_byte(PMBusDevice *pmdev) +{ + ADM1266State *s =3D ADM1266(pmdev); + + switch (pmdev->code) { + case PMBUS_MFR_ID: /* R/W block */ + pmbus_send_string(pmdev, s->mfr_id); + break; + + case PMBUS_MFR_MODEL: /* R/W block */ + pmbus_send_string(pmdev, s->mfr_model); + break; + + case PMBUS_MFR_REVISION: /* R/W block */ + pmbus_send_string(pmdev, s->mfr_rev); + break; + + case PMBUS_IC_DEVICE_ID: + pmbus_send(pmdev, adm1266_ic_device_id, sizeof(adm1266_ic_device_i= d)); + break; + + case PMBUS_IC_DEVICE_REV: + pmbus_send(pmdev, adm1266_ic_device_rev, sizeof(adm1266_ic_device_= rev)); + break; + + default: + qemu_log_mask(LOG_UNIMP, + "%s: reading from unimplemented register: 0x%02x\n", + __func__, pmdev->code); + return 0xFF; + } + + return 0; +} + +static int adm1266_write_data(PMBusDevice *pmdev, const uint8_t *buf, + uint8_t len) +{ + ADM1266State *s =3D ADM1266(pmdev); + + switch (pmdev->code) { + case PMBUS_MFR_ID: /* R/W block */ + pmbus_receive_block(pmdev, (uint8_t *)s->mfr_id, sizeof(s->mfr_id)= ); + break; + + case PMBUS_MFR_MODEL: /* R/W block */ + pmbus_receive_block(pmdev, (uint8_t *)s->mfr_model, + sizeof(s->mfr_model)); + break; + + case PMBUS_MFR_REVISION: /* R/W block*/ + pmbus_receive_block(pmdev, (uint8_t *)s->mfr_rev, sizeof(s->mfr_re= v)); + break; + + case ADM1266_SET_RTC: /* do nothing */ + break; + + default: + qemu_log_mask(LOG_UNIMP, + "%s: writing to unimplemented register: 0x%02x\n", + __func__, pmdev->code); + break; + } + return 0; +} + +static void adm1266_get(Object *obj, Visitor *v, const char *name, void *o= paque, + Error **errp) +{ + uint16_t value; + PMBusDevice *pmdev =3D PMBUS_DEVICE(obj); + PMBusVoutMode *mode =3D (PMBusVoutMode *)&pmdev->pages[0].vout_mode; + + if (strcmp(name, "vout") =3D=3D 0) { + value =3D pmbus_linear_mode2data(*(uint16_t *)opaque, mode->exp); + } else { + value =3D *(uint16_t *)opaque; + } + + visit_type_uint16(v, name, &value, errp); +} + +static void adm1266_set(Object *obj, Visitor *v, const char *name, void *o= paque, + Error **errp) +{ + uint16_t *internal =3D opaque; + uint16_t value; + PMBusDevice *pmdev =3D PMBUS_DEVICE(obj); + PMBusVoutMode *mode =3D (PMBusVoutMode *)&pmdev->pages[0].vout_mode; + + if (!visit_type_uint16(v, name, &value, errp)) { + return; + } + + *internal =3D pmbus_data2linear_mode(value, mode->exp); + pmbus_check_limits(pmdev); +} + +static const VMStateDescription vmstate_adm1266 =3D { + .name =3D "ADM1266", + .version_id =3D 0, + .minimum_version_id =3D 0, + .fields =3D (VMStateField[]){ + VMSTATE_PMBUS_DEVICE(parent, ADM1266State), + VMSTATE_END_OF_LIST() + } +}; + +static void adm1266_init(Object *obj) +{ + PMBusDevice *pmdev =3D PMBUS_DEVICE(obj); + uint64_t flags =3D PB_HAS_VOUT_MODE | PB_HAS_VOUT | PB_HAS_VOUT_MARGIN= | + PB_HAS_VOUT_RATING | PB_HAS_STATUS_MFR_SPECIFIC; + + for (int i =3D 0; i < ADM1266_NUM_PAGES; i++) { + pmbus_page_config(pmdev, i, flags); + + object_property_add(obj, "vout[*]", "uint16", + adm1266_get, + adm1266_set, NULL, &pmdev->pages[i].read_vout); + } +} + +static void adm1266_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + DeviceClass *dc =3D DEVICE_CLASS(klass); + PMBusDeviceClass *k =3D PMBUS_DEVICE_CLASS(klass); + + dc->desc =3D "Analog Devices ADM1266 Hot Swap controller"; + dc->vmsd =3D &vmstate_adm1266; + k->write_data =3D adm1266_write_data; + k->receive_byte =3D adm1266_read_byte; + k->device_num_pages =3D 17; + + rc->phases.exit =3D adm1266_exit_reset; +} + +static const TypeInfo adm1266_info =3D { + .name =3D TYPE_ADM1266, + .parent =3D TYPE_PMBUS_DEVICE, + .instance_size =3D sizeof(ADM1266State), + .instance_init =3D adm1266_init, + .class_init =3D adm1266_class_init, +}; + +static void adm1266_register_types(void) +{ + type_register_static(&adm1266_info); +} + +type_init(adm1266_register_types) diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build index 9e9be602c3..4528ee6215 100644 --- a/hw/sensor/meson.build +++ b/hw/sensor/meson.build @@ -3,6 +3,7 @@ softmmu_ss.add(when: 'CONFIG_TMP421', if_true: files('tmp42= 1.c')) 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_ADM1266', if_true: files('adm1266.c')) softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('max34451.c')) softmmu_ss.add(when: 'CONFIG_LSM303DLHC_MAG', if_true: files('lsm303dlhc_m= ag.c')) softmmu_ss.add(when: 'CONFIG_ISL_PMBUS_VR', if_true: files('isl_pmbus_vr.c= ')) --=20 2.40.0.423.gd6c402a77b-goog