All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v1 0/2] Add and connet the PMU IOModule PIT device
@ 2018-02-06 22:23 Alistair Francis
  2018-02-06 22:23 ` [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device Alistair Francis
  2018-02-06 22:23 ` [Qemu-devel] [PATCH v1 2/2] xlnx-zynqmp-pmu: Connect the PMU IOMOD PIT devices Alistair Francis
  0 siblings, 2 replies; 6+ messages in thread
From: Alistair Francis @ 2018-02-06 22:23 UTC (permalink / raw)
  To: qemu-devel, edgar.iglesias, edgar.iglesias; +Cc: alistair.francis, alistair23

Alistair Francis (2):
  timer: Initial commit of xlnx-pmu-iomod-pit device
  xlnx-zynqmp-pmu: Connect the PMU IOMOD PIT devices

 include/hw/timer/xlnx-pmu-iomod-pit.h |  58 ++++++++
 hw/microblaze/xlnx-zynqmp-pmu.c       |  35 +++++
 hw/timer/xlnx-pmu-iomod-pit.c         | 241 ++++++++++++++++++++++++++++++++++
 hw/timer/Makefile.objs                |   2 +
 4 files changed, 336 insertions(+)
 create mode 100644 include/hw/timer/xlnx-pmu-iomod-pit.h
 create mode 100644 hw/timer/xlnx-pmu-iomod-pit.c

-- 
2.14.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device
  2018-02-06 22:23 [Qemu-devel] [PATCH v1 0/2] Add and connet the PMU IOModule PIT device Alistair Francis
@ 2018-02-06 22:23 ` Alistair Francis
  2018-02-07  2:18   ` Philippe Mathieu-Daudé
  2018-02-06 22:23 ` [Qemu-devel] [PATCH v1 2/2] xlnx-zynqmp-pmu: Connect the PMU IOMOD PIT devices Alistair Francis
  1 sibling, 1 reply; 6+ messages in thread
From: Alistair Francis @ 2018-02-06 22:23 UTC (permalink / raw)
  To: qemu-devel, edgar.iglesias, edgar.iglesias; +Cc: alistair.francis, alistair23

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
---

 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..15f9f0dee5
--- /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"
+
+#define XLNX_ZYNQMP_IOMODULE_PIT(obj) \
+     OBJECT_CHECK(XlnxPMUPIT, (obj), TYPE_XLNX_ZYNQMP_IOMODULE_PIT)
+
+#define XLNX_ZYNQMP_IOMODULE_PIT_R_MAX (0x08 + 1)
+
+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;
+
+    uint32_t regs[XLNX_ZYNQMP_IOMODULE_PIT_R_MAX];
+    RegisterInfo regs_info[XLNX_ZYNQMP_IOMODULE_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..cdfef1a440
--- /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);
+    uint32_t ret;
+
+    if (s->ps_enable) {
+        ret = s->ps_counter;
+    } else {
+        ret = ptimer_get_count(s->ptimer);
+    }
+
+    return ret;
+}
+
+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));
+
+        }
+    }
+}
+
+static const RegisterAccessInfo xlnx_iomod_pit_regs_info[] = {
+    { .name = "PIT_PRELOAD",  .addr = A_PIT_PRELOAD,
+        .ro = 0xffffffff,
+    },{ .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,
+        .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;
+    }
+
+    /* 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;
+        }
+    }
+}
+
+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);
+
+    /* 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_IOMODULE_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_IOMODULE_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, 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
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v1 2/2] xlnx-zynqmp-pmu: Connect the PMU IOMOD PIT devices
  2018-02-06 22:23 [Qemu-devel] [PATCH v1 0/2] Add and connet the PMU IOModule PIT device Alistair Francis
  2018-02-06 22:23 ` [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device Alistair Francis
@ 2018-02-06 22:23 ` Alistair Francis
  1 sibling, 0 replies; 6+ messages in thread
From: Alistair Francis @ 2018-02-06 22:23 UTC (permalink / raw)
  To: qemu-devel, edgar.iglesias, edgar.iglesias; +Cc: alistair.francis, alistair23

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
---

 hw/microblaze/xlnx-zynqmp-pmu.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c
index 999a5657cf..f466c56e45 100644
--- a/hw/microblaze/xlnx-zynqmp-pmu.c
+++ b/hw/microblaze/xlnx-zynqmp-pmu.c
@@ -26,6 +26,7 @@
 
 #include "hw/intc/xlnx-zynqmp-ipi.h"
 #include "hw/intc/xlnx-pmu-iomod-intc.h"
+#include "hw/timer/xlnx-pmu-iomod-pit.h"
 
 /* Define the PMU device */
 
@@ -40,6 +41,7 @@
 #define XLNX_ZYNQMP_PMU_INTC_ADDR   0xFFD40000
 
 #define XLNX_ZYNQMP_PMU_NUM_IPIS    4
+#define XLNX_ZYNQMP_PMU_NUM_PITS    4
 
 static const uint64_t ipi_addr[XLNX_ZYNQMP_PMU_NUM_IPIS] = {
     0xFF340000, 0xFF350000, 0xFF360000, 0xFF370000,
@@ -48,6 +50,13 @@ static const uint64_t ipi_irq[XLNX_ZYNQMP_PMU_NUM_IPIS] = {
     19, 20, 21, 22,
 };
 
+static const uint64_t pit_addr[XLNX_ZYNQMP_PMU_NUM_PITS] = {
+    0xFFD40040, 0xFFD40050, 0xFFD40060, 0xFFD40070,
+};
+static const uint64_t pit_irq[XLNX_ZYNQMP_PMU_NUM_PITS] = {
+    3, 4, 5, 6,
+};
+
 typedef struct XlnxZynqMPPMUSoCState {
     /*< private >*/
     DeviceState parent_obj;
@@ -147,7 +156,9 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine)
     MemoryRegion *pmu_rom = g_new(MemoryRegion, 1);
     MemoryRegion *pmu_ram = g_new(MemoryRegion, 1);
     XlnxZynqMPIPI *ipi[XLNX_ZYNQMP_PMU_NUM_IPIS];
+    XlnxPMUPIT *pit[XLNX_ZYNQMP_PMU_NUM_PITS];
     qemu_irq irq[32];
+    qemu_irq hit_in;
     int i;
 
     /* Create the ROM */
@@ -186,6 +197,30 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine)
         sysbus_connect_irq(SYS_BUS_DEVICE(ipi[i]), 0, irq[ipi_irq[i]]);
     }
 
+    /* Create and connect the IOMOD PIT devices */
+    for (i = 0; i < XLNX_ZYNQMP_PMU_NUM_PITS; i++) {
+        pit[i] = g_new0(XlnxPMUPIT, 1);
+        object_initialize(pit[i], sizeof(XlnxPMUPIT), TYPE_XLNX_ZYNQMP_IOMODULE_PIT);
+        qdev_set_parent_bus(DEVICE(pit[i]), sysbus_get_default());
+    }
+
+    for (i = 0; i < XLNX_ZYNQMP_PMU_NUM_PITS; i++) {
+        object_property_set_bool(OBJECT(pit[i]), true, "realized",
+                                 &error_abort);
+        sysbus_mmio_map(SYS_BUS_DEVICE(pit[i]), 0, pit_addr[i]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(pit[i]), 0, irq[pit_irq[i]]);
+    }
+
+    /* PIT1 hits into PIT0 */
+    hit_in = qdev_get_gpio_in_named(DEVICE(pit[0]), "ps_hit_in", 0);
+    qdev_connect_gpio_out_named(DEVICE(pit[1]), "ps_hit_out", 0, hit_in);
+
+    /* PIT3 hits into PIT2 */
+    hit_in = qdev_get_gpio_in_named(DEVICE(pit[2]), "ps_hit_in", 0);
+    qdev_connect_gpio_out_named(DEVICE(pit[3]), "ps_hit_out", 0, hit_in);
+
+    /* TODO: PIT0 and PIT2 "ps_config" GPIO goes to The GPO1 device. */
+
     /* Load the kernel */
     microblaze_load_kernel(&pmu->cpu, XLNX_ZYNQMP_PMU_RAM_ADDR,
                            machine->ram_size,
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device
  2018-02-06 22:23 ` [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device Alistair Francis
@ 2018-02-07  2:18   ` Philippe Mathieu-Daudé
  2018-02-07 19:49     ` Alistair Francis
  0 siblings, 1 reply; 6+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-02-07  2:18 UTC (permalink / raw)
  To: Alistair Francis, qemu-devel, edgar.iglesias, edgar.iglesias; +Cc: alistair23

Hi Alistair,

On 02/06/2018 07:23 PM, Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
> ---
> 
>  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..15f9f0dee5
> --- /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

I'm glad you upstream this :)

> + * 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"
> +
> +#define XLNX_ZYNQMP_IOMODULE_PIT(obj) \
> +     OBJECT_CHECK(XlnxPMUPIT, (obj), TYPE_XLNX_ZYNQMP_IOMODULE_PIT)
> +
> +#define XLNX_ZYNQMP_IOMODULE_PIT_R_MAX (0x08 + 1)

I assume this part is generated, removing 'XLNX_' shortens a bit.

> +
> +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;

I personally prefer explicit that kind of unit when possible:
"frequency_hz".

> +
> +    uint32_t regs[XLNX_ZYNQMP_IOMODULE_PIT_R_MAX];
> +    RegisterInfo regs_info[XLNX_ZYNQMP_IOMODULE_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..cdfef1a440
> --- /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);
> +    uint32_t ret;

Can you use uint64_t and return explicitly masking with UINT32_MAX?

> +
> +    if (s->ps_enable) {
> +        ret = s->ps_counter;
> +    } else {
> +        ret = ptimer_get_count(s->ptimer);
> +    }
> +
> +    return ret;
> +}
> +
> +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));
> +

> +        }
> +    }
> +}
> +
> +static const RegisterAccessInfo xlnx_iomod_pit_regs_info[] = {
> +    { .name = "PIT_PRELOAD",  .addr = A_PIT_PRELOAD,
> +        .ro = 0xffffffff,
> +    },{ .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,
> +        .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;
> +    }
> +
> +    /* 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;
> +        }
> +    }
> +}
> +
> +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);
> +
> +    /* 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_IOMODULE_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_IOMODULE_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, 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
> 

Patch looks good to me but I'm not confident with ptimers to add a R-b.

Regards,

Phil.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device
  2018-02-07  2:18   ` Philippe Mathieu-Daudé
@ 2018-02-07 19:49     ` Alistair Francis
  2018-02-07 19:56       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 6+ messages in thread
From: Alistair Francis @ 2018-02-07 19:49 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Alistair Francis, qemu-devel@nongnu.org Developers,
	Edgar Iglesias, Edgar Iglesias

On Tue, Feb 6, 2018 at 6:18 PM, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> Hi Alistair,
>
> On 02/06/2018 07:23 PM, Alistair Francis wrote:
>> Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
>> ---
>>
>>  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..15f9f0dee5
>> --- /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
>
> I'm glad you upstream this :)
>
>> + * 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"
>> +
>> +#define XLNX_ZYNQMP_IOMODULE_PIT(obj) \
>> +     OBJECT_CHECK(XlnxPMUPIT, (obj), TYPE_XLNX_ZYNQMP_IOMODULE_PIT)
>> +
>> +#define XLNX_ZYNQMP_IOMODULE_PIT_R_MAX (0x08 + 1)
>
> I assume this part is generated, removing 'XLNX_' shortens a bit.

I don't want to remove XLNX_ as this is a public macro. I'll shorten
the IOMODULE to IOMOD though.

>
>> +
>> +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;
>
> I personally prefer explicit that kind of unit when possible:
> "frequency_hz".

Good point, will fix

>
>> +
>> +    uint32_t regs[XLNX_ZYNQMP_IOMODULE_PIT_R_MAX];
>> +    RegisterInfo regs_info[XLNX_ZYNQMP_IOMODULE_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..cdfef1a440
>> --- /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);
>> +    uint32_t ret;
>
> Can you use uint64_t and return explicitly masking with UINT32_MAX?

Yep

Alistair

>
>> +
>> +    if (s->ps_enable) {
>> +        ret = s->ps_counter;
>> +    } else {
>> +        ret = ptimer_get_count(s->ptimer);
>> +    }
>> +
>> +    return ret;
>> +}
>> +
>> +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));
>> +
>
>> +        }
>> +    }
>> +}
>> +
>> +static const RegisterAccessInfo xlnx_iomod_pit_regs_info[] = {
>> +    { .name = "PIT_PRELOAD",  .addr = A_PIT_PRELOAD,
>> +        .ro = 0xffffffff,
>> +    },{ .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,
>> +        .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;
>> +    }
>> +
>> +    /* 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;
>> +        }
>> +    }
>> +}
>> +
>> +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);
>> +
>> +    /* 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_IOMODULE_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_IOMODULE_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, 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
>>
>
> Patch looks good to me but I'm not confident with ptimers to add a R-b.
>
> Regards,
>
> Phil.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device
  2018-02-07 19:49     ` Alistair Francis
@ 2018-02-07 19:56       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 6+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-02-07 19:56 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Edgar Iglesias, Edgar Iglesias

On 02/07/2018 04:49 PM, Alistair Francis wrote:
> On Tue, Feb 6, 2018 at 6:18 PM, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>> Hi Alistair,
>>
>> On 02/06/2018 07:23 PM, Alistair Francis wrote:
>>> Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
>>> ---
>>>
>>>  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..15f9f0dee5
>>> --- /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
>>
>> I'm glad you upstream this :)
>>
>>> + * 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"
>>> +
>>> +#define XLNX_ZYNQMP_IOMODULE_PIT(obj) \
>>> +     OBJECT_CHECK(XlnxPMUPIT, (obj), TYPE_XLNX_ZYNQMP_IOMODULE_PIT)
>>> +
>>> +#define XLNX_ZYNQMP_IOMODULE_PIT_R_MAX (0x08 + 1)
>>
>> I assume this part is generated, removing 'XLNX_' shortens a bit.
> 
> I don't want to remove XLNX_ as this is a public macro. I'll shorten
> the IOMODULE to IOMOD though.

Not sure this is a big win ;)

Just after sending this I realized this tag can be useful for you when
using 'git grep XLNX'

> 
>>
>>> +
>>> +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;
>>
>> I personally prefer explicit that kind of unit when possible:
>> "frequency_hz".
> 
> Good point, will fix
> 
>>
>>> +
>>> +    uint32_t regs[XLNX_ZYNQMP_IOMODULE_PIT_R_MAX];
>>> +    RegisterInfo regs_info[XLNX_ZYNQMP_IOMODULE_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..cdfef1a440
>>> --- /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);
>>> +    uint32_t ret;
>>
>> Can you use uint64_t and return explicitly masking with UINT32_MAX?
> 
> Yep
> 
> Alistair
> 
>>
>>> +
>>> +    if (s->ps_enable) {
>>> +        ret = s->ps_counter;
>>> +    } else {
>>> +        ret = ptimer_get_count(s->ptimer);
>>> +    }
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +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));
>>> +
>>
>>> +        }
>>> +    }
>>> +}
>>> +
>>> +static const RegisterAccessInfo xlnx_iomod_pit_regs_info[] = {
>>> +    { .name = "PIT_PRELOAD",  .addr = A_PIT_PRELOAD,
>>> +        .ro = 0xffffffff,
>>> +    },{ .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,
>>> +        .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;
>>> +    }
>>> +
>>> +    /* 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;
>>> +        }
>>> +    }
>>> +}
>>> +
>>> +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);
>>> +
>>> +    /* 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_IOMODULE_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_IOMODULE_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, 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
>>>
>>
>> Patch looks good to me but I'm not confident with ptimers to add a R-b.
>>
>> Regards,
>>
>> Phil.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-02-07 19:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-06 22:23 [Qemu-devel] [PATCH v1 0/2] Add and connet the PMU IOModule PIT device Alistair Francis
2018-02-06 22:23 ` [Qemu-devel] [PATCH v1 1/2] timer: Initial commit of xlnx-pmu-iomod-pit device Alistair Francis
2018-02-07  2:18   ` Philippe Mathieu-Daudé
2018-02-07 19:49     ` Alistair Francis
2018-02-07 19:56       ` Philippe Mathieu-Daudé
2018-02-06 22:23 ` [Qemu-devel] [PATCH v1 2/2] xlnx-zynqmp-pmu: Connect the PMU IOMOD PIT devices Alistair Francis

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.