From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org,
David Gibson <david@gibson.dropbear.id.au>
Subject: Re: [PATCH 2/8] ppc: Convert PPC UIC to a QOM device
Date: Sun, 13 Dec 2020 15:34:22 +0100 [thread overview]
Message-ID: <20201213143422.GC477672@toto> (raw)
In-Reply-To: <20201212001537.24520-3-peter.maydell@linaro.org>
On Sat, Dec 12, 2020 at 12:15:31AM +0000, Peter Maydell wrote:
> Currently the PPC UIC ("Universal Interrupt Controller") is implemented
> as a non-QOM device in ppc4xx_devs.c. Convert it to a proper QOM device
> in hw/intc.
>
> The ppcuic_init() function is retained for the moment with its current
> interface; in subsequent commits this will be tidied up to avoid the
> allocation of an irq array.
>
> This conversion adds VMState support.
>
> It leaves the LOG_UIC() macro as-is to maximise the extent to which
> this is simply code-movement rather than a rewrite (in new code it
> would be better to use tracepoints).
>
> The default property values for dcr-base and use-vectors are set to
> match those use by most of our boards with a UIC.
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> include/hw/intc/ppc-uic.h | 73 +++++++++
> hw/intc/ppc-uic.c | 321 ++++++++++++++++++++++++++++++++++++++
> hw/ppc/ppc4xx_devs.c | 267 ++++---------------------------
> MAINTAINERS | 2 +
> hw/intc/Kconfig | 3 +
> hw/intc/meson.build | 1 +
> hw/ppc/Kconfig | 1 +
> 7 files changed, 431 insertions(+), 237 deletions(-)
> create mode 100644 include/hw/intc/ppc-uic.h
> create mode 100644 hw/intc/ppc-uic.c
>
> diff --git a/include/hw/intc/ppc-uic.h b/include/hw/intc/ppc-uic.h
> new file mode 100644
> index 00000000000..e614e2ffd80
> --- /dev/null
> +++ b/include/hw/intc/ppc-uic.h
> @@ -0,0 +1,73 @@
> +/*
> + * "Universal" Interrupt Controller for PowerPPC 4xx embedded processors
> + *
> + * Copyright (c) 2007 Jocelyn Mayer
> + *
> + * 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.
> + */
> +
> +#ifndef HW_INTC_PPC_UIC_H
> +#define HW_INTC_PPC_UIC_H
> +
> +#include "hw/sysbus.h"
> +#include "qom/object.h"
> +
> +#define TYPE_PPC_UIC "ppc-uic"
> +OBJECT_DECLARE_SIMPLE_TYPE(PPCUIC, PPC_UIC)
> +
> +/*
> + * QEMU interface:
> + * QOM property "cpu": link to the PPC CPU
> + * (no default, must be set)
> + * QOM property "dcr-base": base of the bank of DCR registers for the UIC
> + * (default 0x30)
> + * QOM property "use-vectors": true if the UIC has vector registers
> + * (default true)
> + * unnamed GPIO inputs 0..UIC_MAX_IRQ: input IRQ lines
> + * sysbus IRQs:
> + * 0 (PPCUIC_OUTPUT_INT): output INT line to the CPU
> + * 1 (PPCUIC_OUTPUT_CINT): output CINT line to the CPU
> + */
> +
> +#define UIC_MAX_IRQ 32
> +
> +struct PPCUIC {
> + /*< private >*/
> + SysBusDevice parent_obj;
> +
> + /*< public >*/
> + qemu_irq output_int;
> + qemu_irq output_cint;
> +
> + /* properties */
> + CPUState *cpu;
> + uint32_t dcr_base;
> + bool use_vectors;
> +
> + uint32_t level; /* Remembers the state of level-triggered interrupts. */
> + uint32_t uicsr; /* Status register */
> + uint32_t uicer; /* Enable register */
> + uint32_t uiccr; /* Critical register */
> + uint32_t uicpr; /* Polarity register */
> + uint32_t uictr; /* Triggering register */
> + uint32_t uicvcr; /* Vector configuration register */
> + uint32_t uicvr;
> +};
> +
> +#endif
> diff --git a/hw/intc/ppc-uic.c b/hw/intc/ppc-uic.c
> new file mode 100644
> index 00000000000..b21951eea83
> --- /dev/null
> +++ b/hw/intc/ppc-uic.c
> @@ -0,0 +1,321 @@
> +/*
> + * "Universal" Interrupt Controller for PowerPPC 4xx embedded processors
> + *
> + * Copyright (c) 2007 Jocelyn Mayer
> + *
> + * 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 "include/hw/intc/ppc-uic.h"
> +#include "hw/irq.h"
> +#include "cpu.h"
> +#include "hw/ppc/ppc.h"
> +#include "hw/qdev-properties.h"
> +#include "migration/vmstate.h"
> +#include "qapi/error.h"
> +
> +enum {
> + DCR_UICSR = 0x000,
> + DCR_UICSRS = 0x001,
> + DCR_UICER = 0x002,
> + DCR_UICCR = 0x003,
> + DCR_UICPR = 0x004,
> + DCR_UICTR = 0x005,
> + DCR_UICMSR = 0x006,
> + DCR_UICVR = 0x007,
> + DCR_UICVCR = 0x008,
> + DCR_UICMAX = 0x009,
> +};
> +
> +/*#define DEBUG_UIC*/
> +
> +#ifdef DEBUG_UIC
> +# define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
> +#else
> +# define LOG_UIC(...) do { } while (0)
> +#endif
> +
> +static void ppcuic_trigger_irq(PPCUIC *uic)
> +{
> + uint32_t ir, cr;
> + int start, end, inc, i;
> +
> + /* Trigger interrupt if any is pending */
> + ir = uic->uicsr & uic->uicer & (~uic->uiccr);
> + cr = uic->uicsr & uic->uicer & uic->uiccr;
> + LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
> + " uiccr %08" PRIx32 "\n"
> + " %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
> + __func__, uic->uicsr, uic->uicer, uic->uiccr,
> + uic->uicsr & uic->uicer, ir, cr);
> + if (ir != 0x0000000) {
> + LOG_UIC("Raise UIC interrupt\n");
> + qemu_irq_raise(uic->output_int);
> + } else {
> + LOG_UIC("Lower UIC interrupt\n");
> + qemu_irq_lower(uic->output_int);
> + }
> + /* Trigger critical interrupt if any is pending and update vector */
> + if (cr != 0x0000000) {
> + qemu_irq_raise(uic->output_cint);
> + if (uic->use_vectors) {
> + /* Compute critical IRQ vector */
> + if (uic->uicvcr & 1) {
> + start = 31;
> + end = 0;
> + inc = -1;
> + } else {
> + start = 0;
> + end = 31;
> + inc = 1;
> + }
> + uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
> + for (i = start; i <= end; i += inc) {
> + if (cr & (1 << i)) {
> + uic->uicvr += (i - start) * 512 * inc;
> + break;
> + }
> + }
> + }
> + LOG_UIC("Raise UIC critical interrupt - "
> + "vector %08" PRIx32 "\n", uic->uicvr);
> + } else {
> + LOG_UIC("Lower UIC critical interrupt\n");
> + qemu_irq_lower(uic->output_cint);
> + uic->uicvr = 0x00000000;
> + }
> +}
> +
> +static void ppcuic_set_irq(void *opaque, int irq_num, int level)
> +{
> + PPCUIC *uic;
> + uint32_t mask, sr;
> +
> + uic = opaque;
> + mask = 1U << (31 - irq_num);
> + LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
> + " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
> + __func__, irq_num, level,
> + uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
> + if (irq_num < 0 || irq_num > 31) {
> + return;
> + }
> + sr = uic->uicsr;
> +
> + /* Update status register */
> + if (uic->uictr & mask) {
> + /* Edge sensitive interrupt */
> + if (level == 1) {
> + uic->uicsr |= mask;
> + }
> + } else {
> + /* Level sensitive interrupt */
> + if (level == 1) {
> + uic->uicsr |= mask;
> + uic->level |= mask;
> + } else {
> + uic->uicsr &= ~mask;
> + uic->level &= ~mask;
> + }
> + }
> + LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
> + "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
> + if (sr != uic->uicsr) {
> + ppcuic_trigger_irq(uic);
> + }
> +}
> +
> +static uint32_t dcr_read_uic(void *opaque, int dcrn)
> +{
> + PPCUIC *uic;
> + uint32_t ret;
> +
> + uic = opaque;
> + dcrn -= uic->dcr_base;
> + switch (dcrn) {
> + case DCR_UICSR:
> + case DCR_UICSRS:
> + ret = uic->uicsr;
> + break;
> + case DCR_UICER:
> + ret = uic->uicer;
> + break;
> + case DCR_UICCR:
> + ret = uic->uiccr;
> + break;
> + case DCR_UICPR:
> + ret = uic->uicpr;
> + break;
> + case DCR_UICTR:
> + ret = uic->uictr;
> + break;
> + case DCR_UICMSR:
> + ret = uic->uicsr & uic->uicer;
> + break;
> + case DCR_UICVR:
> + if (!uic->use_vectors) {
> + goto no_read;
> + }
> + ret = uic->uicvr;
> + break;
> + case DCR_UICVCR:
> + if (!uic->use_vectors) {
> + goto no_read;
> + }
> + ret = uic->uicvcr;
> + break;
> + default:
> + no_read:
> + ret = 0x00000000;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static void dcr_write_uic(void *opaque, int dcrn, uint32_t val)
> +{
> + PPCUIC *uic;
> +
> + uic = opaque;
> + dcrn -= uic->dcr_base;
> + LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
> + switch (dcrn) {
> + case DCR_UICSR:
> + uic->uicsr &= ~val;
> + uic->uicsr |= uic->level;
> + ppcuic_trigger_irq(uic);
> + break;
> + case DCR_UICSRS:
> + uic->uicsr |= val;
> + ppcuic_trigger_irq(uic);
> + break;
> + case DCR_UICER:
> + uic->uicer = val;
> + ppcuic_trigger_irq(uic);
> + break;
> + case DCR_UICCR:
> + uic->uiccr = val;
> + ppcuic_trigger_irq(uic);
> + break;
> + case DCR_UICPR:
> + uic->uicpr = val;
> + break;
> + case DCR_UICTR:
> + uic->uictr = val;
> + ppcuic_trigger_irq(uic);
> + break;
> + case DCR_UICMSR:
> + break;
> + case DCR_UICVR:
> + break;
> + case DCR_UICVCR:
> + uic->uicvcr = val & 0xFFFFFFFD;
> + ppcuic_trigger_irq(uic);
> + break;
> + }
> +}
> +
> +static void ppc_uic_reset(DeviceState *dev)
> +{
> + PPCUIC *uic = PPC_UIC(dev);
> +
> + uic->uiccr = 0x00000000;
> + uic->uicer = 0x00000000;
> + uic->uicpr = 0x00000000;
> + uic->uicsr = 0x00000000;
> + uic->uictr = 0x00000000;
> + if (uic->use_vectors) {
> + uic->uicvcr = 0x00000000;
> + uic->uicvr = 0x0000000;
> + }
> +}
> +
> +static void ppc_uic_realize(DeviceState *dev, Error **errp)
> +{
> + PPCUIC *uic = PPC_UIC(dev);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> + PowerPCCPU *cpu;
> + int i;
> +
> + if (!uic->cpu) {
> + /* This is a programming error in the code using this device */
> + error_setg(errp, "ppc-uic 'cpu' link property was not set");
> + return;
> + }
> +
> + cpu = POWERPC_CPU(uic->cpu);
> + for (i = 0; i < DCR_UICMAX; i++) {
> + ppc_dcr_register(&cpu->env, uic->dcr_base + i, uic,
> + &dcr_read_uic, &dcr_write_uic);
> + }
> +
> + sysbus_init_irq(sbd, &uic->output_int);
> + sysbus_init_irq(sbd, &uic->output_cint);
> + qdev_init_gpio_in(dev, ppcuic_set_irq, UIC_MAX_IRQ);
> +}
> +
> +static Property ppc_uic_properties[] = {
> + DEFINE_PROP_LINK("cpu", PPCUIC, cpu, TYPE_CPU, CPUState *),
> + DEFINE_PROP_UINT32("dcr-base", PPCUIC, dcr_base, 0x30),
> + DEFINE_PROP_BOOL("use-vectors", PPCUIC, use_vectors, true),
> + DEFINE_PROP_END_OF_LIST()
> +};
> +
> +static const VMStateDescription ppc_uic_vmstate = {
> + .name = "ppc-uic",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32(level, PPCUIC),
> + VMSTATE_UINT32(uicsr, PPCUIC),
> + VMSTATE_UINT32(uicer, PPCUIC),
> + VMSTATE_UINT32(uiccr, PPCUIC),
> + VMSTATE_UINT32(uicpr, PPCUIC),
> + VMSTATE_UINT32(uictr, PPCUIC),
> + VMSTATE_UINT32(uicvcr, PPCUIC),
> + VMSTATE_UINT32(uicvr, PPCUIC),
> + VMSTATE_END_OF_LIST()
> + },
> +};
> +
> +static void ppc_uic_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->reset = ppc_uic_reset;
> + dc->realize = ppc_uic_realize;
> + dc->vmsd = &ppc_uic_vmstate;
> + device_class_set_props(dc, ppc_uic_properties);
> +}
> +
> +static const TypeInfo ppc_uic_info = {
> + .name = TYPE_PPC_UIC,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(PPCUIC),
> + .class_init = ppc_uic_class_init,
> +};
> +
> +static void ppc_uic_register_types(void)
> +{
> + type_register_static(&ppc_uic_info);
> +}
> +
> +type_init(ppc_uic_register_types);
> diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
> index f2f9ca4ffec..ffe4cf43e88 100644
> --- a/hw/ppc/ppc4xx_devs.c
> +++ b/hw/ppc/ppc4xx_devs.c
> @@ -30,9 +30,12 @@
> #include "hw/ppc/ppc.h"
> #include "hw/ppc/ppc4xx.h"
> #include "hw/boards.h"
> +#include "hw/intc/ppc-uic.h"
> +#include "hw/qdev-properties.h"
> #include "qemu/log.h"
> #include "exec/address-spaces.h"
> #include "qemu/error-report.h"
> +#include "qapi/error.h"
>
> /*#define DEBUG_UIC*/
>
> @@ -76,250 +79,40 @@ PowerPCCPU *ppc4xx_init(const char *cpu_type,
>
> /*****************************************************************************/
> /* "Universal" Interrupt controller */
> -enum {
> - DCR_UICSR = 0x000,
> - DCR_UICSRS = 0x001,
> - DCR_UICER = 0x002,
> - DCR_UICCR = 0x003,
> - DCR_UICPR = 0x004,
> - DCR_UICTR = 0x005,
> - DCR_UICMSR = 0x006,
> - DCR_UICVR = 0x007,
> - DCR_UICVCR = 0x008,
> - DCR_UICMAX = 0x009,
> -};
> -
> -#define UIC_MAX_IRQ 32
> -typedef struct ppcuic_t ppcuic_t;
> -struct ppcuic_t {
> - uint32_t dcr_base;
> - int use_vectors;
> - uint32_t level; /* Remembers the state of level-triggered interrupts. */
> - uint32_t uicsr; /* Status register */
> - uint32_t uicer; /* Enable register */
> - uint32_t uiccr; /* Critical register */
> - uint32_t uicpr; /* Polarity register */
> - uint32_t uictr; /* Triggering register */
> - uint32_t uicvcr; /* Vector configuration register */
> - uint32_t uicvr;
> - qemu_irq *irqs;
> -};
> -
> -static void ppcuic_trigger_irq(ppcuic_t *uic)
> -{
> - uint32_t ir, cr;
> - int start, end, inc, i;
> -
> - /* Trigger interrupt if any is pending */
> - ir = uic->uicsr & uic->uicer & (~uic->uiccr);
> - cr = uic->uicsr & uic->uicer & uic->uiccr;
> - LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
> - " uiccr %08" PRIx32 "\n"
> - " %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
> - __func__, uic->uicsr, uic->uicer, uic->uiccr,
> - uic->uicsr & uic->uicer, ir, cr);
> - if (ir != 0x0000000) {
> - LOG_UIC("Raise UIC interrupt\n");
> - qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
> - } else {
> - LOG_UIC("Lower UIC interrupt\n");
> - qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
> - }
> - /* Trigger critical interrupt if any is pending and update vector */
> - if (cr != 0x0000000) {
> - qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
> - if (uic->use_vectors) {
> - /* Compute critical IRQ vector */
> - if (uic->uicvcr & 1) {
> - start = 31;
> - end = 0;
> - inc = -1;
> - } else {
> - start = 0;
> - end = 31;
> - inc = 1;
> - }
> - uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
> - for (i = start; i <= end; i += inc) {
> - if (cr & (1 << i)) {
> - uic->uicvr += (i - start) * 512 * inc;
> - break;
> - }
> - }
> - }
> - LOG_UIC("Raise UIC critical interrupt - "
> - "vector %08" PRIx32 "\n", uic->uicvr);
> - } else {
> - LOG_UIC("Lower UIC critical interrupt\n");
> - qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
> - uic->uicvr = 0x00000000;
> - }
> -}
> -
> -static void ppcuic_set_irq(void *opaque, int irq_num, int level)
> -{
> - ppcuic_t *uic;
> - uint32_t mask, sr;
> -
> - uic = opaque;
> - mask = 1U << (31 - irq_num);
> - LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
> - " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
> - __func__, irq_num, level,
> - uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
> - if (irq_num < 0 || irq_num > 31) {
> - return;
> - }
> - sr = uic->uicsr;
> -
> - /* Update status register */
> - if (uic->uictr & mask) {
> - /* Edge sensitive interrupt */
> - if (level == 1) {
> - uic->uicsr |= mask;
> - }
> - } else {
> - /* Level sensitive interrupt */
> - if (level == 1) {
> - uic->uicsr |= mask;
> - uic->level |= mask;
> - } else {
> - uic->uicsr &= ~mask;
> - uic->level &= ~mask;
> - }
> - }
> - LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
> - "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
> - if (sr != uic->uicsr) {
> - ppcuic_trigger_irq(uic);
> - }
> -}
> -
> -static uint32_t dcr_read_uic(void *opaque, int dcrn)
> -{
> - ppcuic_t *uic;
> - uint32_t ret;
> -
> - uic = opaque;
> - dcrn -= uic->dcr_base;
> - switch (dcrn) {
> - case DCR_UICSR:
> - case DCR_UICSRS:
> - ret = uic->uicsr;
> - break;
> - case DCR_UICER:
> - ret = uic->uicer;
> - break;
> - case DCR_UICCR:
> - ret = uic->uiccr;
> - break;
> - case DCR_UICPR:
> - ret = uic->uicpr;
> - break;
> - case DCR_UICTR:
> - ret = uic->uictr;
> - break;
> - case DCR_UICMSR:
> - ret = uic->uicsr & uic->uicer;
> - break;
> - case DCR_UICVR:
> - if (!uic->use_vectors) {
> - goto no_read;
> - }
> - ret = uic->uicvr;
> - break;
> - case DCR_UICVCR:
> - if (!uic->use_vectors) {
> - goto no_read;
> - }
> - ret = uic->uicvcr;
> - break;
> - default:
> - no_read:
> - ret = 0x00000000;
> - break;
> - }
> -
> - return ret;
> -}
> -
> -static void dcr_write_uic(void *opaque, int dcrn, uint32_t val)
> -{
> - ppcuic_t *uic;
> -
> - uic = opaque;
> - dcrn -= uic->dcr_base;
> - LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
> - switch (dcrn) {
> - case DCR_UICSR:
> - uic->uicsr &= ~val;
> - uic->uicsr |= uic->level;
> - ppcuic_trigger_irq(uic);
> - break;
> - case DCR_UICSRS:
> - uic->uicsr |= val;
> - ppcuic_trigger_irq(uic);
> - break;
> - case DCR_UICER:
> - uic->uicer = val;
> - ppcuic_trigger_irq(uic);
> - break;
> - case DCR_UICCR:
> - uic->uiccr = val;
> - ppcuic_trigger_irq(uic);
> - break;
> - case DCR_UICPR:
> - uic->uicpr = val;
> - break;
> - case DCR_UICTR:
> - uic->uictr = val;
> - ppcuic_trigger_irq(uic);
> - break;
> - case DCR_UICMSR:
> - break;
> - case DCR_UICVR:
> - break;
> - case DCR_UICVCR:
> - uic->uicvcr = val & 0xFFFFFFFD;
> - ppcuic_trigger_irq(uic);
> - break;
> - }
> -}
> -
> -static void ppcuic_reset (void *opaque)
> -{
> - ppcuic_t *uic;
> -
> - uic = opaque;
> - uic->uiccr = 0x00000000;
> - uic->uicer = 0x00000000;
> - uic->uicpr = 0x00000000;
> - uic->uicsr = 0x00000000;
> - uic->uictr = 0x00000000;
> - if (uic->use_vectors) {
> - uic->uicvcr = 0x00000000;
> - uic->uicvr = 0x0000000;
> - }
> -}
>
> qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
> uint32_t dcr_base, int has_ssr, int has_vr)
> {
> - ppcuic_t *uic;
> + DeviceState *uicdev = qdev_new(TYPE_PPC_UIC);
> + SysBusDevice *uicsbd = SYS_BUS_DEVICE(uicdev);
> + qemu_irq *uic_irqs;
> int i;
>
> - uic = g_malloc0(sizeof(ppcuic_t));
> - uic->dcr_base = dcr_base;
> - uic->irqs = irqs;
> - if (has_vr)
> - uic->use_vectors = 1;
> - for (i = 0; i < DCR_UICMAX; i++) {
> - ppc_dcr_register(env, dcr_base + i, uic,
> - &dcr_read_uic, &dcr_write_uic);
> - }
> - qemu_register_reset(ppcuic_reset, uic);
> + qdev_prop_set_uint32(uicdev, "dcr-base", dcr_base);
> + qdev_prop_set_bit(uicdev, "use-vectors", has_vr);
> + object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(env_cpu(env)),
> + &error_fatal);
> + sysbus_realize_and_unref(uicsbd, &error_fatal);
>
> - return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
> + sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, irqs[PPCUIC_OUTPUT_INT]);
> + sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, irqs[PPCUIC_OUTPUT_CINT]);
> +
> + /*
> + * Return an allocated array of the UIC's input IRQ lines.
> + * This is an ugly temporary API to retain compatibility with
> + * the ppcuic_init() interface from the pre-QOM-conversion UIC.
> + * None of the callers free this array, so it is leaked -- but
> + * so was the array allocated by qemu_allocate_irqs() in the
> + * old code.
> + *
> + * The callers should just instantiate the UIC and wire it up
> + * themselves rather than passing qemu_irq* in and out of this function.
> + */
> + uic_irqs = g_new0(qemu_irq, UIC_MAX_IRQ);
> + for (i = 0; i < UIC_MAX_IRQ; i++) {
> + uic_irqs[i] = qdev_get_gpio_in(uicdev, i);
> + }
> + return uic_irqs;
> }
>
> /*****************************************************************************/
> diff --git a/MAINTAINERS b/MAINTAINERS
> index aa39490a244..24218800b16 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1671,6 +1671,8 @@ F: hw/ppc/ppc4*.c
> F: hw/i2c/ppc4xx_i2c.c
> F: include/hw/ppc/ppc4xx.h
> F: include/hw/i2c/ppc4xx_i2c.h
> +F: hw/intc/ppc-uic.c
> +F: include/hw/intc/ppc-uic.h
>
> Character devices
> M: Marc-André Lureau <marcandre.lureau@redhat.com>
> diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
> index d07954086a5..468d548ca77 100644
> --- a/hw/intc/Kconfig
> +++ b/hw/intc/Kconfig
> @@ -62,6 +62,9 @@ config S390_FLIC_KVM
> config OMPIC
> bool
>
> +config PPC_UIC
> + bool
> +
> config RX_ICU
> bool
>
> diff --git a/hw/intc/meson.build b/hw/intc/meson.build
> index 3f82cc230ad..d7dadbe5034 100644
> --- a/hw/intc/meson.build
> +++ b/hw/intc/meson.build
> @@ -42,6 +42,7 @@ specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c'))
> specific_ss.add(when: 'CONFIG_OMPIC', if_true: files('ompic.c'))
> specific_ss.add(when: 'CONFIG_OPENPIC_KVM', if_true: files('openpic_kvm.c'))
> specific_ss.add(when: 'CONFIG_POWERNV', if_true: files('xics_pnv.c', 'pnv_xive.c'))
> +specific_ss.add(when: 'CONFIG_PPC_UIC', if_true: files('ppc-uic.c'))
> specific_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_ic.c', 'bcm2836_control.c'))
> specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c'))
> specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
> diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
> index dd86e664d21..982d55f5875 100644
> --- a/hw/ppc/Kconfig
> +++ b/hw/ppc/Kconfig
> @@ -53,6 +53,7 @@ config PPC4XX
> bool
> select BITBANG_I2C
> select PCI
> + select PPC_UIC
>
> config SAM460EX
> bool
> --
> 2.20.1
>
next prev parent reply other threads:[~2020-12-13 14:36 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-12 0:15 [PATCH 0/8] hw/ppc: Convert UIC device to QOM Peter Maydell
2020-12-12 0:15 ` [PATCH 1/8] hw/ppc/ppc4xx_devs: Make code style fixes to UIC code Peter Maydell
2020-12-13 12:09 ` Philippe Mathieu-Daudé
2020-12-13 14:33 ` Edgar E. Iglesias
2020-12-14 5:43 ` David Gibson
2020-12-14 9:15 ` Thomas Huth
2020-12-12 0:15 ` [PATCH 2/8] ppc: Convert PPC UIC to a QOM device Peter Maydell
2020-12-12 16:57 ` BALATON Zoltan via
2020-12-12 18:27 ` BALATON Zoltan via
2020-12-12 18:33 ` Peter Maydell
2020-12-12 19:53 ` BALATON Zoltan via
2020-12-13 14:34 ` Edgar E. Iglesias [this message]
2020-12-14 5:54 ` David Gibson
2020-12-14 9:12 ` BALATON Zoltan via
2020-12-12 0:15 ` [PATCH 3/8] hw/ppc/virtex_ml507: Drop use of ppcuic_init() Peter Maydell
2020-12-13 14:32 ` Edgar E. Iglesias
2020-12-14 5:55 ` David Gibson
2021-01-11 19:04 ` BALATON Zoltan
2020-12-12 0:15 ` [PATCH 4/8] hw/ppc/ppc440_bamboo: " Peter Maydell
2020-12-14 5:56 ` David Gibson
2021-01-11 1:00 ` Nathan Chancellor
2021-01-11 17:14 ` Peter Maydell
2021-01-11 18:22 ` Mark Cave-Ayland
2021-02-03 16:35 ` Philippe Mathieu-Daudé
2020-12-12 0:15 ` [PATCH 5/8] hw/ppc/sam460ex: " Peter Maydell
2020-12-12 17:17 ` BALATON Zoltan via
2020-12-12 18:11 ` Peter Maydell
2020-12-12 20:35 ` BALATON Zoltan via
2020-12-12 19:53 ` BALATON Zoltan via
2020-12-12 19:55 ` Peter Maydell
2020-12-12 0:15 ` [PATCH 6/8] hw/ppc: Delete unused ppc405cr_init() code Peter Maydell
2020-12-12 0:15 ` [PATCH 7/8] hw/ppc/ppc405_uc: Drop use of ppcuic_init() Peter Maydell
2021-01-11 19:09 ` BALATON Zoltan
2020-12-12 0:15 ` [PATCH 8/8] hw/ppc: Remove unused ppcuic_init() Peter Maydell
2020-12-13 14:35 ` Edgar E. Iglesias
2020-12-12 17:43 ` [PATCH 0/8] hw/ppc: Convert UIC device to QOM BALATON Zoltan via
2020-12-12 18:13 ` Peter Maydell
2020-12-14 6:00 ` David Gibson
2020-12-14 10:04 ` Peter Maydell
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=20201213143422.GC477672@toto \
--to=edgar.iglesias@gmail.com \
--cc=david@gibson.dropbear.id.au \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@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.