[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] watchdog: add support to emulate winbond w83627
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCH] watchdog: add support to emulate winbond w83627thf |
Date: |
Wed, 7 Oct 2015 11:09:29 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 |
On 07/10/2015 10:49, Daniel Fahlgren wrote:
> Hi,
>
> On Mon, 2015-09-14 at 22:07 +0200, Daniel Fahlgren wrote:
>> This patch adds support to emulate the watchdog functionality on the
>> Winbond w83627thf chip. The other features of the chip are not emulated.
>> It has been tested with Ubuntu 6.06, 14.04 and 15.04 as guests using the
>> w83627hf_wdt module.
>
> Ping, who should I poke about this? The maintainers file does not
> mention the watchdog system.
Hi,
sorry for missing this patch.
I have a couple of questions. First, where can I find a spec for this
chip in order to review the code, and what are the other features?
Second, what are the advantages over the existing watchdog devices?
Paolo
>> Signed-off-by: Daniel Fahlgren <address@hidden>
>> ---
>> default-configs/i386-softmmu.mak | 1 +
>> default-configs/x86_64-softmmu.mak | 1 +
>> hw/watchdog/Makefile.objs | 1 +
>> hw/watchdog/wdt_w83627thf.c | 255
>> +++++++++++++++++++++++++++++++++++++
>> 4 files changed, 258 insertions(+)
>> create mode 100644 hw/watchdog/wdt_w83627thf.c
>>
>> diff --git a/default-configs/i386-softmmu.mak
>> b/default-configs/i386-softmmu.mak
>> index 9393cf0..30abc6f 100644
>> --- a/default-configs/i386-softmmu.mak
>> +++ b/default-configs/i386-softmmu.mak
>> @@ -35,6 +35,7 @@ CONFIG_MC146818RTC=y
>> CONFIG_PAM=y
>> CONFIG_PCI_PIIX=y
>> CONFIG_WDT_IB700=y
>> +CONFIG_WDT_W83627THF=y
>> CONFIG_XEN_I386=$(CONFIG_XEN)
>> CONFIG_ISA_DEBUG=y
>> CONFIG_ISA_TESTDEV=y
>> diff --git a/default-configs/x86_64-softmmu.mak
>> b/default-configs/x86_64-softmmu.mak
>> index 28e2099..906d14b 100644
>> --- a/default-configs/x86_64-softmmu.mak
>> +++ b/default-configs/x86_64-softmmu.mak
>> @@ -35,6 +35,7 @@ CONFIG_MC146818RTC=y
>> CONFIG_PAM=y
>> CONFIG_PCI_PIIX=y
>> CONFIG_WDT_IB700=y
>> +CONFIG_WDT_W83627THF=y
>> CONFIG_XEN_I386=$(CONFIG_XEN)
>> CONFIG_ISA_DEBUG=y
>> CONFIG_ISA_TESTDEV=y
>> diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
>> index 72e3ffd..e021b24 100644
>> --- a/hw/watchdog/Makefile.objs
>> +++ b/hw/watchdog/Makefile.objs
>> @@ -2,3 +2,4 @@ common-obj-y += watchdog.o
>> common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
>> common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
>> common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
>> +common-obj-$(CONFIG_WDT_W83627THF) += wdt_w83627thf.o
>> diff --git a/hw/watchdog/wdt_w83627thf.c b/hw/watchdog/wdt_w83627thf.c
>> new file mode 100644
>> index 0000000..143bb8f
>> --- /dev/null
>> +++ b/hw/watchdog/wdt_w83627thf.c
>> @@ -0,0 +1,255 @@
>> +/*
>> + * Virtual hardware watchdog.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * By Daniel Fahlgren (address@hidden)
>> + */
>> +
>> +#include <inttypes.h>
>> +
>> +#include "qemu-common.h"
>> +#include "qemu/timer.h"
>> +#include "sysemu/watchdog.h"
>> +#include "hw/isa/isa.h"
>> +
>> +/* #define W83627THF_DEBUG 1 */
>> +
>> +#ifdef W83627THF_DEBUG
>> +#define w83627thf_debug(fs, ...) \
>> + fprintf(stderr, "w83627thf: %s: "fs, __func__, ##__VA_ARGS__)
>> +#else
>> +#define w83627thf_debug(fs, ...)
>> +#endif
>> +
>> +#define WATCHDOG_W83627THF_DEVICE(obj) \
>> + OBJECT_CHECK(W83627THFState, (obj), "w83627thf")
>> +
>> +#define CHIP_VERSION 0x82
>> +
>> +#define CHIP_VERSION_REGISTER 0x20
>> +#define PLED_MODE_REGISTER 0xF5
>> +#define TIMEOUT_REGISTER 0xF6
>> +#define TIMER_REGISTER 0xF7
>> +
>> +#define PLED_MINUTE_MODE 0x08
>> +
>> +#define WDT_W83627THF_EFER 0x2E
>> +#define WDT_W83627THF_EFDR 0x2F
>> +
>> +enum {
>> + normal_mode = 0,
>> + extended_mode1 = 1,
>> + extended_mode2 = 2
>> +};
>> +
>> +/* Device state. */
>> +typedef struct W83627THFState {
>> + ISADevice parent_obj;
>> +
>> + QEMUTimer *timer;
>> +
>> + PortioList port_list;
>> +
>> + uint8_t running_mode;
>> +
>> + uint8_t selected_register;
>> +
>> + uint8_t pled_mode_register;
>> + uint8_t timeout_register;
>> + uint8_t timer_register;
>> +
>> +} W83627THFState;
>> +
>> +static WatchdogTimerModel model = {
>> + .wdt_name = "w83627thf",
>> + .wdt_description = "Winbond w83627thf",
>> +};
>> +
>> +static const VMStateDescription vmstate_w83627thf = {
>> + .name = "vmstate_w83627thf",
>> + .version_id = 0,
>> + .minimum_version_id = 0,
>> + .fields = (VMStateField[]) {
>> + VMSTATE_TIMER_PTR(timer, W83627THFState),
>> + VMSTATE_UINT8(running_mode, W83627THFState),
>> + VMSTATE_UINT8(selected_register, W83627THFState),
>> + VMSTATE_UINT8(pled_mode_register, W83627THFState),
>> + VMSTATE_UINT8(timeout_register, W83627THFState),
>> + VMSTATE_UINT8(timer_register, W83627THFState),
>> + VMSTATE_END_OF_LIST()
>> + }
>> +};
>> +
>> +/* This function is called when the watchdog has been changed, either when
>> the
>> + * timer has expired or has been keep-alived.
>> + */
>> +static void wdt_w83627thf_restart_timer(W83627THFState *state)
>> +{
>> + uint64_t timeout = 1000;
>> +
>> + if (state->timeout_register == 0) {
>> + timer_del(state->timer);
>> + return;
>> + }
>> +
>> + if (state->pled_mode_register & PLED_MINUTE_MODE) {
>> + timeout = 60000;
>> + }
>> +
>> + timer_mod(state->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
>> timeout);
>> +}
>> +
>> +/* This function is called when the timer has expired. Will count down the
>> + * counter and possibly fire the watchdog.
>> + */
>> +static void wdt_w83627thf_timer_tick(void *vp)
>> +{
>> + W83627THFState *state = vp;
>> +
>> + state->timeout_register--;
>> + if (state->timeout_register == 0) {
>> + state->timer_register |= 0x10;
>> + timer_del(state->timer);
>> + watchdog_perform_action();
>> + return;
>> + }
>> +
>> + wdt_w83627thf_restart_timer(state);
>> +}
>> +
>> +/* This function is called when writing to the Extended Function Enable
>> + * Registers.
>> + */
>> +static void wdt_w83627thf_write_efer(void *vp, uint32_t addr, uint32_t data)
>> +{
>> + W83627THFState *state = vp;
>> +
>> + w83627thf_debug("data = %x\n", data);
>> +
>> + if (data == 0x87) {
>> + if (state->running_mode == normal_mode) {
>> + state->running_mode = extended_mode1;
>> + } else {
>> + state->running_mode = extended_mode2;
>> + }
>> + } else if (data == 0xAA) {
>> + state->running_mode = normal_mode;
>> + } else if (state->running_mode == extended_mode2) {
>> + state->selected_register = data;
>> + }
>> +}
>> +
>> +/* This function is called when reading from the Extended Function Data
>> + * Register.
>> + */
>> +static uint32_t wdt_w83627thf_read_efdr(void *vp, uint32_t addr)
>> +{
>> + uint8_t data = 0;
>> + const W83627THFState *state = vp;
>> +
>> + switch (state->selected_register) {
>> + case CHIP_VERSION_REGISTER:
>> + data = CHIP_VERSION;
>> + break;
>> + case PLED_MODE_REGISTER:
>> + data = state->pled_mode_register;
>> + break;
>> + case TIMEOUT_REGISTER:
>> + data = state->timeout_register;
>> + break;
>> + case TIMER_REGISTER:
>> + data = state->timer_register;
>> + break;
>> + }
>> +
>> + w83627thf_debug("reg = %x, data = %x\n", state->selected_register,
>> data);
>> +
>> + return data;
>> +}
>> +
>> +/* This function is called when writing to the Extended Function Data
>> Register.
>> + */
>> +static void wdt_w83627thf_write_efdr(void *vp, uint32_t addr, uint32_t data)
>> +{
>> + W83627THFState *state = vp;
>> +
>> + w83627thf_debug("reg = %x, data = %x\n", state->selected_register,
>> data);
>> +
>> + switch (state->selected_register) {
>> + case PLED_MODE_REGISTER:
>> + state->pled_mode_register = data;
>> + break;
>> + case TIMEOUT_REGISTER:
>> + state->timeout_register = data;
>> + wdt_w83627thf_restart_timer(state);
>> + break;
>> + case TIMER_REGISTER:
>> + if (data & 0x20) {
>> + timer_del(state->timer);
>> + watchdog_perform_action();
>> + }
>> + state->timer_register = (data & ~0x20);
>> + break;
>> + }
>> +}
>> +
>> +static const MemoryRegionPortio wdt_portio_list[] = {
>> + { WDT_W83627THF_EFER, 1, 1, .write = wdt_w83627thf_write_efer, },
>> + { WDT_W83627THF_EFDR, 1, 1, .read = wdt_w83627thf_read_efdr,
>> + .write = wdt_w83627thf_write_efdr },
>> + PORTIO_END_OF_LIST(),
>> +};
>> +
>> +static void wdt_w83627thf_realize(DeviceState *dev, Error **errp)
>> +{
>> + W83627THFState *d = WATCHDOG_W83627THF_DEVICE(dev);
>> +
>> + d->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, wdt_w83627thf_timer_tick,
>> d);
>> +
>> + portio_list_init(&d->port_list, OBJECT(d), wdt_portio_list, d,
>> "w83627thf");
>> + portio_list_add(&d->port_list, isa_address_space_io(&d->parent_obj), 0);
>> +}
>> +
>> +static void wdt_w83627thf_reset(DeviceState *dev)
>> +{
>> + W83627THFState *d = WATCHDOG_W83627THF_DEVICE(dev);
>> +
>> + timer_del(d->timer);
>> +}
>> +
>> +static void wdt_w83627thf_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> + dc->realize = wdt_w83627thf_realize;
>> + dc->reset = wdt_w83627thf_reset;
>> + dc->vmsd = &vmstate_w83627thf;
>> + set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>> +}
>> +
>> +static const TypeInfo w83627thf_info = {
>> + .name = "w83627thf",
>> + .parent = TYPE_ISA_DEVICE,
>> + .instance_size = sizeof(W83627THFState),
>> + .class_init = wdt_w83627thf_class_init,
>> +};
>> +
>> +static void w83627thf_register_types(void)
>> +{
>> + watchdog_add_model(&model);
>> + type_register_static(&w83627thf_info);
>> +}
>> +
>> +type_init(w83627thf_register_types)
>
> Best regards,
> Daniel Fahlgren
>
>
>