All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <f4bug@amsat.org>
To: Alistair Francis <alistair.francis@xilinx.com>,
	qemu-devel@nongnu.org, edgar.iglesias@xilinx.com,
	edgar.iglesias@gmail.com
Cc: alistair23@gmail.com
Subject: Re: [Qemu-devel] [PATCH v2 1/5] timer: Initial commit of xlnx-pmu-iomod-pit device
Date: Thu, 1 Mar 2018 15:21:46 -0300	[thread overview]
Message-ID: <a7c53011-5689-3cbf-09e1-ee466511467d@amsat.org> (raw)
In-Reply-To: <000b7176df121bd34c3329c45b93dc79d5f4f3ff.1519856998.git.alistair.francis@xilinx.com>

On 02/28/2018 07:31 PM, Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
> ---
> V2:
>  - Use UINT32_MAX and uint64_t in xlnx_iomod_pit_ctr_pr()
>  - Name frequency varaible frequency_hz
>  - Shorten R_MAX #define
> 
>  include/hw/timer/xlnx-pmu-iomod-pit.h |  58 ++++++++
>  hw/timer/xlnx-pmu-iomod-pit.c         | 241 ++++++++++++++++++++++++++++++++++
>  hw/timer/Makefile.objs                |   2 +
>  3 files changed, 301 insertions(+)
>  create mode 100644 include/hw/timer/xlnx-pmu-iomod-pit.h
>  create mode 100644 hw/timer/xlnx-pmu-iomod-pit.c
> 
> diff --git a/include/hw/timer/xlnx-pmu-iomod-pit.h b/include/hw/timer/xlnx-pmu-iomod-pit.h
> new file mode 100644
> index 0000000000..75cac6bedd
> --- /dev/null
> +++ b/include/hw/timer/xlnx-pmu-iomod-pit.h
> @@ -0,0 +1,58 @@
> +/*
> + * QEMU model of Xilinx I/O Module PIT
> + *
> + * Copyright (c) 2013 Xilinx Inc
> + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/ptimer.h"
> +
> +#define TYPE_XLNX_ZYNQMP_IOMODULE_PIT "xlnx.pmu_iomodule_pit"
> +
> +#define XLNX_ZYNQMP_IOMODULE_PIT(obj) \
> +     OBJECT_CHECK(XlnxPMUPIT, (obj), TYPE_XLNX_ZYNQMP_IOMODULE_PIT)
> +
> +#define XLNX_ZYNQMP_IOMOD_PIT_R_MAX (0x08 + 1)

0x04?

> +
> +typedef struct XlnxPMUPIT {
> +    SysBusDevice parent_obj;
> +    MemoryRegion iomem;
> +
> +    QEMUBH *bh;
> +    ptimer_state *ptimer;
> +
> +    qemu_irq irq;
> +    /* IRQ to pulse out when present timer hits zero */
> +    qemu_irq hit_out;
> +
> +    /* Counter in Pre-Scalar(ps) Mode */
> +    uint32_t ps_counter;
> +    /* ps_mode irq-in to enable/disable pre-scalar */
> +    bool ps_enable;
> +    /* State var to remember hit_in level */
> +    bool ps_level;
> +
> +    uint32_t frequency_hz;
> +
> +    uint32_t regs[XLNX_ZYNQMP_IOMOD_PIT_R_MAX];
> +    RegisterInfo regs_info[XLNX_ZYNQMP_IOMOD_PIT_R_MAX];
> +} XlnxPMUPIT;
> diff --git a/hw/timer/xlnx-pmu-iomod-pit.c b/hw/timer/xlnx-pmu-iomod-pit.c
> new file mode 100644
> index 0000000000..a6bdc5211d
> --- /dev/null
> +++ b/hw/timer/xlnx-pmu-iomod-pit.c
> @@ -0,0 +1,241 @@
> +/*
> + * QEMU model of Xilinx I/O Module PIT
> + *
> + * Copyright (c) 2013 Xilinx Inc
> + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "hw/ptimer.h"
> +#include "hw/register.h"
> +#include "qemu/main-loop.h"
> +#include "qemu/log.h"
> +#include "qapi/error.h"
> +#include "hw/timer/xlnx-pmu-iomod-pit.h"
> +
> +#ifndef XLNX_ZYNQMP_IOMODULE_PIT_ERR_DEBUG
> +#define XLNX_ZYNQMP_IOMODULE_PIT_ERR_DEBUG 0
> +#endif
> +
> +REG32(PIT_PRELOAD, 0x00)
> +REG32(PIT_COUNTER, 0x04)
> +REG32(PIT_CONTROL, 0x08)
> +    FIELD(PIT_CONTROL, PRELOAD, 1, 1)
> +    FIELD(PIT_CONTROL, EN, 0, 1)
> +
> +static uint64_t xlnx_iomod_pit_ctr_pr(RegisterInfo *reg, uint64_t val)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(reg->opaque);
> +    uint64_t ret;
> +
> +    if (s->ps_enable) {
> +        ret = s->ps_counter;
> +    } else {
> +        ret = ptimer_get_count(s->ptimer);
> +    }
> +
> +    return ret & UINT32_MAX;
> +}
> +
> +static void xlnx_iomod_pit_control_pw(RegisterInfo *reg, uint64_t val)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(reg->opaque);
> +
> +    ptimer_stop(s->ptimer);
> +
> +    if (val & R_PIT_CONTROL_EN_MASK) {
> +        if (s->ps_enable) {
> +            /* pre-scalar mode do-Nothing here */
> +            s->ps_counter = s->regs[R_PIT_PRELOAD];
> +        } else {
> +            ptimer_set_limit(s->ptimer, s->regs[R_PIT_PRELOAD], 1);
> +            ptimer_run(s->ptimer, !(val & R_PIT_CONTROL_PRELOAD_MASK));
> +

blank line

> +        }
> +    }
> +}
> +
> +static const RegisterAccessInfo xlnx_iomod_pit_regs_info[] = {
> +    { .name = "PIT_PRELOAD",  .addr = A_PIT_PRELOAD,
> +        .ro = 0xffffffff,

Or UINT32_MAX

> +    },{ .name = "PIT_COUNTER",  .addr = A_PIT_COUNTER,
> +        .ro = 0xffffffff,
> +        .post_read = xlnx_iomod_pit_ctr_pr,
> +    },{ .name = "PIT_CONTROL",  .addr = A_PIT_CONTROL,
> +        .rsvd = 0xfffffffc,

Or        = ~(R_PIT_CONTROL_PRELOAD_MASK | R_PIT_CONTROL_EN_MASK),

and I always forgot this is mostly generated.

> +        .post_write = xlnx_iomod_pit_control_pw,
> +    }
> +};
> +
> +static void xlnx_iomod_pit_timer_hit(void *opaque)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(opaque);
> +
> +    qemu_irq_pulse(s->irq);
> +
> +    /* hit_out to make another pit move it's counter in pre-scalar mode. */
> +    qemu_irq_pulse(s->hit_out);
> +}
> +
> +static void xlnx_iomod_pit_ps_config(void *opaque, int n, int level)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(opaque);
> +
> +    s->ps_enable = level;
> +}
> +
> +static void xlnx_iomod_pit_ps_hit_in(void *opaque, int n, int level)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(opaque);
> +
> +    if (!ARRAY_FIELD_EX32(s->regs, PIT_CONTROL, EN)) {
> +        /* PIT disabled */
> +        return;
> +    }
> +
> +    /* Count only on positive edge */
> +    if (!s->ps_level && level) {
> +        if (s->ps_counter) {
> +            s->ps_counter--;
> +        }
> +        s->ps_level = level;
> +    } else {
> +        /* Not on positive edge */
> +        s->ps_level = level;
> +        return;
> +    }

Inverting this

if (C) {A} else {B return}

as

if (!C) {B return}
A

is a bit easier to read.

> +
> +    /* If timer expires, try to preload or stop */
> +    if (s->ps_counter == 0) {
> +        xlnx_iomod_pit_timer_hit(opaque);
> +
> +        /* Check for pit preload/one-shot mode */
> +        if (ARRAY_FIELD_EX32(s->regs, PIT_CONTROL, PRELOAD)) {
> +            /* Preload Mode, Reload the ps_counter */
> +            s->ps_counter = s->regs[R_PIT_PRELOAD];
> +        } else {
> +            /* One-Shot mode, turn off the timer */
> +            s->regs[R_PIT_CONTROL] &= ~R_PIT_CONTROL_PRELOAD_MASK;
> +        }
> +    }

Ditto, if (!s->ps_counter) return;

Anyway this is fine,
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> +}
> +
> +static void xlnx_iomod_pit_reset(DeviceState *dev)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(dev);
> +    unsigned int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
> +        register_reset(&s->regs_info[i]);
> +    }
> +
> +    s->ps_level = false;
> +}
> +
> +static const MemoryRegionOps xlnx_iomod_pit_ops = {
> +    .read = register_read_memory,
> +    .write = register_write_memory,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 4,
> +        .max_access_size = 4,
> +    },
> +};
> +
> +static void xlnx_iomod_pit_realize(DeviceState *dev, Error **errp)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(dev);
> +
> +    s->bh = qemu_bh_new(xlnx_iomod_pit_timer_hit, s);
> +    s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
> +    ptimer_set_freq(s->ptimer, s->frequency_hz);
> +
> +    /* IRQ out to pulse when present timer expires/reloads */
> +    qdev_init_gpio_out_named(dev, &s->hit_out, "ps_hit_out", 1);
> +
> +    /* IRQ in to enable pre-scalar mode. Routed from gpo1 */
> +    qdev_init_gpio_in_named(dev, xlnx_iomod_pit_ps_config, "ps_config", 1);
> +
> +    /* hit_out of neighbouring PIT is received as hit_in */
> +    qdev_init_gpio_in_named(dev, xlnx_iomod_pit_ps_hit_in, "ps_hit_in", 1);
> +}
> +
> +static void xlnx_iomod_pit_init(Object *obj)
> +{
> +    XlnxPMUPIT *s = XLNX_ZYNQMP_IOMODULE_PIT(obj);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
> +
> +    memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_IOMODULE_PIT,
> +                       XLNX_ZYNQMP_IOMOD_PIT_R_MAX * 4);
> +    reg_array =
> +        register_init_block32(DEVICE(obj), xlnx_iomod_pit_regs_info,
> +                              ARRAY_SIZE(xlnx_iomod_pit_regs_info),
> +                              s->regs_info, s->regs,
> +                              &xlnx_iomod_pit_ops,
> +                              XLNX_ZYNQMP_IOMODULE_PIT_ERR_DEBUG,
> +                              XLNX_ZYNQMP_IOMOD_PIT_R_MAX * 4);
> +    memory_region_add_subregion(&s->iomem,
> +                                0x0,
> +                                &reg_array->mem);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +    sysbus_init_irq(sbd, &s->irq);
> +}
> +
> +static const VMStateDescription vmstate_xlnx_iomod_pit = {
> +    .name = TYPE_XLNX_ZYNQMP_IOMODULE_PIT,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_END_OF_LIST(),
> +    }
> +};
> +
> +static Property xlnx_iomod_pit_properties[] = {
> +    DEFINE_PROP_UINT32("frequency", XlnxPMUPIT, frequency_hz, 66000000),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void xlnx_iomod_pit_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = xlnx_iomod_pit_reset;
> +    dc->realize = xlnx_iomod_pit_realize;
> +    dc->props = xlnx_iomod_pit_properties;
> +    dc->vmsd = &vmstate_xlnx_iomod_pit;
> +}
> +
> +static const TypeInfo xlnx_iomod_pit_info = {
> +    .name          = TYPE_XLNX_ZYNQMP_IOMODULE_PIT,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(XlnxPMUPIT),
> +    .class_init    = xlnx_iomod_pit_class_init,
> +    .instance_init = xlnx_iomod_pit_init,
> +};
> +
> +static void xlnx_iomod_pit_register_types(void)
> +{
> +    type_register_static(&xlnx_iomod_pit_info);
> +}
> +
> +type_init(xlnx_iomod_pit_register_types)
> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
> index 8c19eac3b6..805c480cad 100644
> --- a/hw/timer/Makefile.objs
> +++ b/hw/timer/Makefile.objs
> @@ -43,3 +43,5 @@ common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
>  common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
>  common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
>  common-obj-$(CONFIG_MSF2) += mss-timer.o
> +
> +common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-pmu-iomod-pit.o
> 

  reply	other threads:[~2018-03-01 18:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-28 22:31 [Qemu-devel] [PATCH v2 0/5] Add and connect the PMU IOModule devices Alistair Francis
2018-02-28 22:30 ` [Qemu-devel] [PATCH v2 1/5] timer: Initial commit of xlnx-pmu-iomod-pit device Alistair Francis
2018-03-01 18:21   ` Philippe Mathieu-Daudé [this message]
2018-05-04  3:39     ` Alistair Francis
2018-02-28 22:32 ` [Qemu-devel] [PATCH v2 2/5] xlnx-zynqmp-pmu: Connect the PMU IOMOD PIT devices Alistair Francis
2018-03-01 18:22   ` Philippe Mathieu-Daudé
2018-02-28 22:32 ` [Qemu-devel] [PATCH v2 3/5] hw/gpio: Add the xlnx-pmu-iomod-gpo device Alistair Francis
2018-03-01 17:02   ` Philippe Mathieu-Daudé
2018-05-04  3:28     ` Alistair Francis
2018-02-28 22:32 ` [Qemu-devel] [PATCH v2 4/5] hw/gpio: Add support for the xlnx-pmu-iomod-gpi device Alistair Francis
2018-03-01 17:12   ` Philippe Mathieu-Daudé
2018-02-28 22:32 ` [Qemu-devel] [PATCH v2 5/5] xlnx-zynqmp-pmu: Connect the IOMOD GPI/GPO devices Alistair Francis
2018-03-01 17:17   ` Philippe Mathieu-Daudé
2018-03-01 18:03   ` Philippe Mathieu-Daudé
2018-05-04  3:54     ` Alistair Francis

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=a7c53011-5689-3cbf-09e1-ee466511467d@amsat.org \
    --to=f4bug@amsat.org \
    --cc=alistair.francis@xilinx.com \
    --cc=alistair23@gmail.com \
    --cc=edgar.iglesias@gmail.com \
    --cc=edgar.iglesias@xilinx.com \
    --cc=qemu-devel@nongnu.org \
    /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.