All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Wang <wangzhiqiang.bj@bytedance.com>
To: "Cédric Le Goater" <clg@kaod.org>
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	郁雷 <yulei.sh@bytedance.com>,
	"open list:All patches CC here" <qemu-devel@nongnu.org>,
	"open list:ARM TCG CPUs" <qemu-arm@nongnu.org>,
	"Joel Stanley" <joel@jms.id.au>,
	"Lotus Xu" <xuxiaohan@bytedance.com>
Subject: Re: [External] Re: [PATCH 1/2] hw/misc: add an EMC141{3, 4} device model
Date: Thu, 8 Oct 2020 10:21:02 +0800	[thread overview]
Message-ID: <CAH0XSJtH_syj_9qyYFmiJhLRNhkDVgtpwRo0YrE-6CULsJ+cXg@mail.gmail.com> (raw)
In-Reply-To: <48d16207-7ffe-97cb-c248-dc1d3515de77@kaod.org>

On Thu, Oct 1, 2020 at 11:04 PM Cédric Le Goater <clg@kaod.org> wrote:
>
> Hello,
>
> On 9/29/20 7:53 AM, John Wang wrote:
> > Largely inspired by the TMP423 temperature sensor, here is a model for
>
> It's a TMP421 temperature sensor

Will fix

>
> > the EMC1413 temperature sensors.
> >
> > Specs can be found here :
> >   https://pdf1.alldatasheet.com/datasheet-pdf/view/533713/SMSC/EMC1413.html
>
>
> Have you tested it under a current Linux kernel ?

Yes, I tested it, it works well.
>
> > Signed-off-by: John Wang <wangzhiqiang.bj@bytedance.com>
> > ---
> >  hw/arm/Kconfig      |   1 +
> >  hw/misc/Kconfig     |   4 +
> >  hw/misc/emc1413.c   | 309 ++++++++++++++++++++++++++++++++++++++++++++
> >  hw/misc/meson.build |   1 +
> >  4 files changed, 315 insertions(+)
> >  create mode 100644 hw/misc/emc1413.c
> >
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index f303c6bead..8801ada145 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -402,6 +402,7 @@ config ASPEED_SOC
> >      select SSI_M25P80
> >      select TMP105
> >      select TMP421
> > +    select EMC1413
> >      select UNIMP
> >
> >  config MPS2
> > diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> > index 3185456110..91badf2d4d 100644
> > --- a/hw/misc/Kconfig
> > +++ b/hw/misc/Kconfig
> > @@ -13,6 +13,10 @@ config TMP421
> >      bool
> >      depends on I2C
> >
> > +config EMC1413
> > +    bool
> > +    depends on I2C
> > +
> >  config ISA_DEBUG
> >      bool
> >      depends on ISA_BUS
> > diff --git a/hw/misc/emc1413.c b/hw/misc/emc1413.c
> > new file mode 100644
> > index 0000000000..2430c3f074
> > --- /dev/null
> > +++ b/hw/misc/emc1413.c
> > @@ -0,0 +1,309 @@
> > +/*
> > + * SMSC EMC1413 temperature sensor.
> > + *
> > + * Copyright (c) 2020 Bytedance Corporation
> > + * Written by John Wang <wangzhiqiang.bj@bytedance.com>
> > + *
> > + * 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 or
> > + * (at your option) version 3 of the License.
> > + *
> > + * 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.
> > + *
> > + * You should have received a copy of the GNU General Public License along
> > + * with this program; if not, see <http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "hw/i2c/i2c.h"
> > +#include "migration/vmstate.h"
> > +#include "qapi/error.h"
> > +#include "qapi/visitor.h"
> > +#include "qemu/module.h"
> > +#include "qom/object.h"
> > +
> > +#define DEVICE_ID_REG                    0xfd
> > +#define MANUFACTURER_ID_REG              0xfe
> > +#define REVISION_REG                     0xff
> > +#define EMC1413_DEVICE_ID                0x21
> > +#define EMC1414_DEVICE_ID                0x25
> > +
> > +typedef struct DeviceInfo {
> > +    uint8_t model;
> > +    const char *name;
> > +} DeviceInfo;
> > +
> > +static const DeviceInfo devices[] = {
> > +    { EMC1413_DEVICE_ID, "emc1413" },
> > +    { EMC1414_DEVICE_ID, "emc1414" },
> > +};
> >
>
> DeviceInfo is a bit redundant with EMC1413Class. We could define all
> the attributes under the class.

yes, will remove this

>
> > +struct EMC1413State {
> > +    I2CSlave i2c;
> > +    uint8_t temperature[4];
> > +    uint8_t min[4];
> > +    uint8_t max[4];
> > +    uint8_t len;
> > +    uint8_t data;
> > +    uint8_t pointer;
> > +
> > +};
> > +
> > +struct EMC1413Class {
> > +    I2CSlaveClass parent_class;
> > +    DeviceInfo *dev;
> > +};
> > +
> > +#define TYPE_EMC1413 "emc1413-generic"
> > +OBJECT_DECLARE_TYPE(EMC1413State, EMC1413Class, EMC1413)
> > +
> > +
> > +/* the EMC1413 registers */
> > +#define EMC1413_TEMP_HIGH0               0x00
> > +#define EMC1413_TEMP_HIGH1               0x01
> > +#define EMC1413_TEMP_HIGH2               0x23
> > +#define EMC1413_TEMP_HIGH3               0x2a
> > +#define EMC1413_TEMP_MAX_HIGH0           0x05
> > +#define EMC1413_TEMP_MIN_HIGH0           0x06
> > +#define EMC1413_TEMP_MAX_HIGH1           0x07
> > +#define EMC1413_TEMP_MIN_HIGH1           0x08
> > +#define EMC1413_TEMP_MAX_HIGH2           0x15
> > +#define EMC1413_TEMP_MIN_HIGH2           0x16
> > +#define EMC1413_TEMP_MAX_HIGH3           0x2c
> > +#define EMC1413_TEMP_MIN_HIGH3           0x2d
>
> There are much more and it might not be necessary to model
> them all. Do we care about the status or config reg ?

I think we don't care about them. The linux driver doesn't care about
`config reg`,
as for `status reg`, in our project (openbmc) we don't care about it.

>
> > +static void emc1413_get_temperature(Object *obj, Visitor *v, const char *name,
> > +                                   void *opaque, Error **errp)
> > +{
> > +    EMC1413State *s = EMC1413(obj);
> > +    int64_t value;
> > +    int tempid;
> > +
> > +    if (sscanf(name, "temperature%d", &tempid) != 1) {
> > +        error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
> > +        return;
> > +    }
> > +
> > +    if (tempid >= 4 || tempid < 0) {
> > +        error_setg(errp, "error reading %s", name);
> > +        return;
> > +    }
> > +
> > +    value = s->temperature[tempid] * 1000;
> > +
> > +    visit_type_int(v, name, &value, errp);
> > +}
> > +
> > +static void emc1413_set_temperature(Object *obj, Visitor *v, const char *name,
> > +                                   void *opaque, Error **errp)
> > +{
> > +    EMC1413State *s = EMC1413(obj);
> > +    int64_t temp;
> > +    int tempid;
> > +
> > +    if (!visit_type_int(v, name, &temp, errp)) {
> > +        return;
> > +    }
> > +
> > +    if (sscanf(name, "temperature%d", &tempid) != 1) {
> > +        error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
> > +        return;
> > +    }
> > +
> > +    if (tempid >= 4 || tempid < 0) {
> > +        error_setg(errp, "error reading %s", name);
> > +        return;
> > +    }
> > +
> > +    s->temperature[tempid] = temp / 1000;
> > +}
> > +
> > +struct emc1413_reg {
> > +    uint8_t addr;
> > +    uint8_t *data;
> > +};
> > +
> > +static void emc1413_read(EMC1413State *s)
> > +{
> > +    EMC1413Class *sc = EMC1413_GET_CLASS(s);
> > +    uint8_t smsc_manufacturer_id = 0x5d;
> > +    uint8_t revision = 0x04;
> > +    struct emc1413_reg emc1413_regs[] = {
> > +        {DEVICE_ID_REG, &sc->dev->model},
> > +        {MANUFACTURER_ID_REG, &smsc_manufacturer_id},
> > +        {REVISION_REG, &revision},
>
> These attributes belong to the DeviceInfo structure or EMC1413Class if you
> decide to remove DeviceInfo.

yes

>
> > +        {EMC1413_TEMP_HIGH0, &s->temperature[0]},
> > +        {EMC1413_TEMP_HIGH1, &s->temperature[1]},
> > +        {EMC1413_TEMP_HIGH2, &s->temperature[2]},
> > +        {EMC1413_TEMP_HIGH3, &s->temperature[3]},
> > +        {EMC1413_TEMP_MAX_HIGH0, &s->max[0]},
> > +        {EMC1413_TEMP_MAX_HIGH1, &s->max[1]},
> > +        {EMC1413_TEMP_MAX_HIGH2, &s->max[2]},
> > +        {EMC1413_TEMP_MAX_HIGH3, &s->max[3]},
> > +        {EMC1413_TEMP_MIN_HIGH0, &s->min[0]},
> > +        {EMC1413_TEMP_MIN_HIGH1, &s->min[1]},
> > +        {EMC1413_TEMP_MIN_HIGH2, &s->min[2]},
> > +        {EMC1413_TEMP_MIN_HIGH3, &s->min[3]},
> > +    };
> > +    size_t i;
> > +    for (i = 0; i < ARRAY_SIZE(emc1413_regs); i++) {
> > +        if (emc1413_regs[i].addr == s->pointer) {
> > +            s->data = *(emc1413_regs[i].data);
> > +            return;
> > +        }
> > +    }
> > +}
> > +
> > +static void emc1413_write(EMC1413State *s)
> > +{
> > +    struct emc1413_reg emc1413_regs[] = {
> > +        {EMC1413_TEMP_MAX_HIGH0, &s->max[0]},
> > +        {EMC1413_TEMP_MAX_HIGH1, &s->max[1]},
> > +        {EMC1413_TEMP_MAX_HIGH2, &s->max[2]},
> > +        {EMC1413_TEMP_MAX_HIGH3, &s->max[3]},
> > +        {EMC1413_TEMP_MIN_HIGH0, &s->min[0]},
> > +        {EMC1413_TEMP_MIN_HIGH1, &s->min[1]},
> > +        {EMC1413_TEMP_MIN_HIGH2, &s->min[2]},
> > +        {EMC1413_TEMP_MIN_HIGH3, &s->min[3]},
> > +    };
> > +    size_t i;
> > +    for (i = 0; i < ARRAY_SIZE(emc1413_regs); i++) {
> > +        if (emc1413_regs[i].addr == s->pointer) {
> > +            *(emc1413_regs[i].data) = s->data;
> > +            return;
> > +        }
> > +    }
> > +}
> > +
> > +static uint8_t emc1413_rx(I2CSlave *i2c)
> > +{
> > +    EMC1413State *s = EMC1413(i2c);
> > +
> > +    if (s->len == 0) {
> > +        s->len++;
> > +        return s->data;
> > +    } else {
> > +        return 0xff;
> > +    }
> > +}
> > +
> > +static int emc1413_tx(I2CSlave *i2c, uint8_t data)
> > +{
> > +    EMC1413State *s = EMC1413(i2c);
> > +
> > +    if (s->len == 0) {
> > +        /* first byte is the reg pointer */
> > +        s->pointer = data;
> > +        s->len++;
> > +    } else if (s->len == 1) {
> > +        s->data = data;
> > +        emc1413_write(s);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int emc1413_event(I2CSlave *i2c, enum i2c_event event)
> > +{
> > +    EMC1413State *s = EMC1413(i2c);
> > +
> > +    if (event == I2C_START_RECV) {
> > +        emc1413_read(s);
> > +    }
> > +
> > +    s->len = 0;
> > +    return 0;
> > +}
> > +
> > +static const VMStateDescription vmstate_emc1413 = {
> > +    .name = "EMC1413",
> > +    .version_id = 0,
> > +    .minimum_version_id = 0,
> > +    .fields = (VMStateField[]) {
> > +        VMSTATE_UINT8(len, EMC1413State),
> > +        VMSTATE_UINT8(data, EMC1413State),
> > +        VMSTATE_UINT8(pointer, EMC1413State),
> > +        VMSTATE_UINT8_ARRAY(temperature, EMC1413State, 4),
> > +        VMSTATE_I2C_SLAVE(i2c, EMC1413State),
> > +        VMSTATE_END_OF_LIST()
> > +    }
> > +};
> > +
> > +static void emc1413_reset(I2CSlave *i2c)
> > +{
> > +    EMC1413State *s = EMC1413(i2c);
> > +
> > +    memset(s->temperature, 0, sizeof(s->temperature));
> > +    memset(s->min, 0, sizeof(s->min));
> > +    memset(s->max, 0x55, sizeof(s->max));
> > +    s->pointer = 0;
> > +    s->len = 0;
> > +}
> > +
> > +static void emc1413_realize(DeviceState *dev, Error **errp)
> > +{
> > +    EMC1413State *s = EMC1413(dev);
> > +
> > +    emc1413_reset(&s->i2c);
> > +}
> > +
> > +static void emc1413_initfn(Object *obj)
> > +{
> > +    object_property_add(obj, "temperature0", "int",
> > +                        emc1413_get_temperature,
> > +                        emc1413_set_temperature, NULL, NULL);
> > +    object_property_add(obj, "temperature1", "int",
> > +                        emc1413_get_temperature,
> > +                        emc1413_set_temperature, NULL, NULL);
> > +    object_property_add(obj, "temperature2", "int",
> > +                        emc1413_get_temperature,
> > +                        emc1413_set_temperature, NULL, NULL);
> > +    object_property_add(obj, "temperature3", "int",
> > +                        emc1413_get_temperature,
> > +                        emc1413_set_temperature, NULL, NULL);
> > +}
> > +
> > +static void emc1413_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
> > +    EMC1413Class *sc = EMC1413_CLASS(klass);
> > +
> > +    dc->realize = emc1413_realize;
> > +    k->event = emc1413_event;
> > +    k->recv = emc1413_rx;
> > +    k->send = emc1413_tx;
> > +    dc->vmsd = &vmstate_emc1413;
> > +    sc->dev = (DeviceInfo *) data;
> > +}
> > +
> > +static const TypeInfo emc1413_info = {
> > +    .name          = TYPE_EMC1413,
> > +    .parent        = TYPE_I2C_SLAVE,
> > +    .instance_size = sizeof(EMC1413State),
> > +    .class_size    = sizeof(EMC1413Class),
> > +    .instance_init = emc1413_initfn,
> > +    .abstract      = true,
> > +};
> > +
> > +static void emc1413_register_types(void)
> > +{
> > +    int i;
> > +
> > +    type_register_static(&emc1413_info);
> > +    for (i = 0; i < ARRAY_SIZE(devices); ++i) {
> > +        TypeInfo ti = {
> > +            .name       = devices[i].name,
> > +            .parent     = TYPE_EMC1413,
> > +            .class_init = emc1413_class_init,
> > +            .class_data = (void *) &devices[i],
> > +        };
> > +        type_register(&ti);
> > +    }
> > +}
> > +
> > +type_init(emc1413_register_types)
> > diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> > index 793d45b1dc..08821c72ba 100644
> > --- a/hw/misc/meson.build
> > +++ b/hw/misc/meson.build
> > @@ -9,6 +9,7 @@ softmmu_ss.add(when: 'CONFIG_PCI_TESTDEV', if_true: files('pci-testdev.c'))
> >  softmmu_ss.add(when: 'CONFIG_SGA', if_true: files('sga.c'))
> >  softmmu_ss.add(when: 'CONFIG_TMP105', if_true: files('tmp105.c'))
> >  softmmu_ss.add(when: 'CONFIG_TMP421', if_true: files('tmp421.c'))
> > +softmmu_ss.add(when: 'CONFIG_EMC1413', if_true: files('emc1413.c'))
> >  softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
> >  softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
> >
> >
>


      reply	other threads:[~2020-10-08  2:22 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-29  5:53 [PATCH 1/2] hw/misc: add an EMC141{3,4} device model John Wang
2020-09-29  5:53 ` [PATCH 2/2] aspeed: Add support for the g220a-bmc board John Wang
2020-10-01 14:56   ` Cédric Le Goater
2020-10-08  1:56     ` [External] " John Wang
2020-10-05 22:55   ` Joel Stanley
2020-10-01 15:04 ` [PATCH 1/2] hw/misc: add an EMC141{3,4} device model Cédric Le Goater
2020-10-08  2:21   ` John Wang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAH0XSJtH_syj_9qyYFmiJhLRNhkDVgtpwRo0YrE-6CULsJ+cXg@mail.gmail.com \
    --to=wangzhiqiang.bj@bytedance.com \
    --cc=clg@kaod.org \
    --cc=joel@jms.id.au \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=xuxiaohan@bytedance.com \
    --cc=yulei.sh@bytedance.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.