All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Crosthwaite <crosthwaitepeter@gmail.com>
To: Andrew Baumann <Andrew.Baumann@microsoft.com>
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Grégory ESTRADE" <gregory.estrade@gmail.com>,
	"Stefan Weil" <sw@weilnetz.de>,
	"Peter Crosthwaite" <crosthwaite.peter@gmail.com>,
	"qemu-devel@nongnu.org Developers" <qemu-devel@nongnu.org>,
	qemu-arm <qemu-arm@nongnu.org>,
	"Paolo Bonzini" <pbonzini@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller
Date: Wed, 30 Dec 2015 16:33:36 -0800	[thread overview]
Message-ID: <CAPokK=qES8kJ2m6OiZ5qco877G_0azYXm5tFWyU944BZ8ndK6w@mail.gmail.com> (raw)
In-Reply-To: <1450916731-5968-4-git-send-email-Andrew.Baumann@microsoft.com>

On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
<Andrew.Baumann@microsoft.com> wrote:
> Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> ---
>
> Notes:
>     v2 changes:
>      * split inputs to named gpu_irq and arm_irq gpio inputs
>      * use 64-bit gpu_irq and 8-bit arm_irq status rather than 3*32-bit bitfields
>      * added defined names for register offsets
>      * deleted nop realize method
>      * other misc cleanup suggested in review
>
>  hw/intc/Makefile.objs        |   1 +
>  hw/intc/bcm2835_ic.c         | 233 +++++++++++++++++++++++++++++++++++++++++++
>  include/hw/intc/bcm2835_ic.h |  33 ++++++
>  3 files changed, 267 insertions(+)
>  create mode 100644 hw/intc/bcm2835_ic.c
>  create mode 100644 include/hw/intc/bcm2835_ic.h
>
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 004b0c2..2ad1204 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -24,6 +24,7 @@ obj-$(CONFIG_GRLIB) += grlib_irqmp.o
>  obj-$(CONFIG_IOAPIC) += ioapic.o
>  obj-$(CONFIG_OMAP) += omap_intc.o
>  obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
> +obj-$(CONFIG_RASPI) += bcm2835_ic.o
>  obj-$(CONFIG_SH4) += sh_intc.o
>  obj-$(CONFIG_XICS) += xics.o
>  obj-$(CONFIG_XICS_KVM) += xics_kvm.o
> diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
> new file mode 100644
> index 0000000..9624e8b
> --- /dev/null
> +++ b/hw/intc/bcm2835_ic.c
> @@ -0,0 +1,233 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + * Heavily based on pl190.c, copyright terms below:
> + *
> + * Arm PrimeCell PL190 Vector Interrupt Controller
> + *
> + * Copyright (c) 2006 CodeSourcery.
> + * Written by Paul Brook
> + *

So your own modifications are now heavy enough for you and/or an
affiliation to claim at least co-authorship.

> + * This code is licensed under the GPL.
> + */
> +
> +#include "hw/intc/bcm2835_ic.h"
> +
> +#define GPU_IRQS 64
> +#define ARM_IRQS 8
> +
> +#define IRQ_PENDING_BASIC       0x00 /* IRQ basic pending */
> +#define IRQ_PENDING_1           0x04 /* IRQ pending 1 */
> +#define IRQ_PENDING_2           0x08 /* IRQ pending 2 */
> +#define FIQ_CONTROL             0x0C /* FIQ register */
> +#define IRQ_ENABLE_1            0x10 /* Interrupt enable register 1 */
> +#define IRQ_ENABLE_2            0x14 /* Interrupt enable register 2 */
> +#define IRQ_ENABLE_BASIC        0x18 /* Base interrupt enable register */
> +#define IRQ_DISABLE_1           0x1C /* Interrupt disable register 1 */
> +#define IRQ_DISABLE_2           0x20 /* Interrupt disable register 2 */
> +#define IRQ_DISABLE_BASIC       0x24 /* Base interrupt disable register */
> +
> +/* Update interrupts.  */
> +static void bcm2835_ic_update(BCM2835ICState *s)
> +{
> +    bool set = false;
> +
> +    if (s->fiq_enable) {
> +        if (s->fiq_select >= GPU_IRQS) {
> +            /* ARM IRQ */
> +            set = extract32(s->arm_irq_level, s->fiq_select - GPU_IRQS, 1);
> +        } else {
> +            set = extract64(s->gpu_irq_level, s->fiq_select, 1);
> +        }
> +    }
> +    qemu_set_irq(s->fiq, set);
> +
> +    set = (s->gpu_irq_level & s->gpu_irq_enable)
> +        || (s->arm_irq_level & s->arm_irq_enable);
> +    qemu_set_irq(s->irq, set);
> +
> +}
> +
> +static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
> +{
> +    BCM2835ICState *s = opaque;

Blank line here.

> +    assert(irq >= 0 && irq < 64);
> +    s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
> +    bcm2835_ic_update(s);
> +}
> +
> +static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
> +{
> +    BCM2835ICState *s = opaque;

Blank line here.

> +    assert(irq >= 0 && irq < 8);
> +    s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
> +    bcm2835_ic_update(s);
> +}
> +
> +static const int irq_dups[] = { 7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62 };
> +
> +static uint64_t bcm2835_ic_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    BCM2835ICState *s = opaque;
> +    uint32_t res = 0;
> +    uint64_t gpu_pending = s->gpu_irq_level & s->gpu_irq_enable;
> +    int i;
> +
> +    switch (offset) {
> +    case IRQ_PENDING_BASIC:
> +        /* bits 0-7: ARM irqs */
> +        res = s->arm_irq_level & s->arm_irq_enable;
> +
> +        /* bits 8 & 9: pending registers 1 & 2 */
> +        res |= (((uint32_t)gpu_pending) != 0) << 8;
> +        res |= ((gpu_pending >> 32) != 0) << 9;
> +
> +        /* bits 10-20: selected GPU IRQs */
> +        for (i = 0; i < ARRAY_SIZE(irq_dups); i++) {
> +            res |= extract64(gpu_pending, irq_dups[i], 1) << (i + 10);
> +        }
> +        break;
> +    case IRQ_PENDING_1:  /* IRQ pending 1 */

Drop trailing comment here and all below.

> +        res = gpu_pending;
> +        break;
> +    case IRQ_PENDING_2:  /* IRQ pending 2 */
> +        res = gpu_pending >> 32;
> +        break;
> +    case FIQ_CONTROL:  /* FIQ register */
> +        res = (s->fiq_enable << 7) | s->fiq_select;
> +        break;
> +    case IRQ_ENABLE_1:  /* Interrupt enable register 1 */
> +        res = s->gpu_irq_enable;
> +        break;
> +    case IRQ_ENABLE_2:  /* Interrupt enable register 2 */
> +        res = s->gpu_irq_enable >> 32;
> +        break;
> +    case IRQ_ENABLE_BASIC:  /* Base interrupt enable register */
> +        res = s->arm_irq_enable;
> +        break;
> +    case IRQ_DISABLE_1:  /* Interrupt disable register 1 */
> +        res = ~s->gpu_irq_enable;
> +        break;
> +    case IRQ_DISABLE_2:  /* Interrupt disable register 2 */
> +        res = ~s->gpu_irq_enable >> 32;
> +        break;
> +    case IRQ_DISABLE_BASIC:  /* Base interrupt disable register */
> +        res = ~s->arm_irq_enable;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return 0;
> +    }
> +
> +    return res;
> +}
> +
> +static void bcm2835_ic_write(void *opaque, hwaddr offset, uint64_t val,
> +                             unsigned size)
> +{
> +    BCM2835ICState *s = opaque;
> +
> +    switch (offset) {
> +    case FIQ_CONTROL:
> +        s->fiq_select = (val & 0x7f);
> +        s->fiq_enable = (val >> 7) & 0x1;

extract32 for both (my criteria is if there is both a shift and mask
it should extract instead of be manual).

> +        break;
> +    case IRQ_ENABLE_1:
> +        s->gpu_irq_enable |= val;
> +        break;
> +    case IRQ_ENABLE_2:
> +        s->gpu_irq_enable |= val << 32;
> +        break;
> +    case IRQ_ENABLE_BASIC:
> +        s->arm_irq_enable |= val & 0xff;
> +        break;
> +    case IRQ_DISABLE_1:
> +        s->gpu_irq_enable &= ~val;
> +        break;
> +    case IRQ_DISABLE_2:
> +        s->gpu_irq_enable &= ~(val << 32);
> +        break;
> +    case IRQ_DISABLE_BASIC:
> +        s->arm_irq_enable &= ~val & 0xff;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return;
> +    }
> +    bcm2835_ic_update(s);
> +}
> +
> +static const MemoryRegionOps bcm2835_ic_ops = {
> +    .read = bcm2835_ic_read,
> +    .write = bcm2835_ic_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .valid.min_access_size = 4,
> +    .valid.max_access_size = 4,
> +};
> +
> +static void bcm2835_ic_reset(DeviceState *d)
> +{
> +    BCM2835ICState *s = BCM2835_IC(d);
> +
> +    s->gpu_irq_enable = 0;
> +    s->arm_irq_enable = 0;
> +    s->fiq_enable = false;
> +    s->fiq_select = 0;
> +}
> +
> +static void bcm2835_ic_init(Object *obj)
> +{
> +    BCM2835ICState *s = BCM2835_IC(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &bcm2835_ic_ops, s, TYPE_BCM2835_IC,
> +                          0x200);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> +
> +    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_gpu_irq,
> +                            BCM2835_IC_GPU_IRQ, GPU_IRQS);
> +    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_arm_irq,
> +                            BCM2835_IC_ARM_IRQ, ARM_IRQS);
> +
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->fiq);
> +}
> +
> +static const VMStateDescription vmstate_bcm2835_ic = {
> +    .name = TYPE_BCM2835_IC,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64(gpu_irq_level, BCM2835ICState),
> +        VMSTATE_UINT64(gpu_irq_enable, BCM2835ICState),
> +        VMSTATE_UINT8(arm_irq_level, BCM2835ICState),
> +        VMSTATE_UINT8(arm_irq_enable, BCM2835ICState),
> +        VMSTATE_BOOL(fiq_enable, BCM2835ICState),
> +        VMSTATE_UINT8(fiq_select, BCM2835ICState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void bcm2835_ic_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = bcm2835_ic_reset;
> +    dc->vmsd = &vmstate_bcm2835_ic;
> +}
> +
> +static TypeInfo bcm2835_ic_info = {
> +    .name          = TYPE_BCM2835_IC,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(BCM2835ICState),
> +    .class_init    = bcm2835_ic_class_init,
> +    .instance_init = bcm2835_ic_init,
> +};
> +
> +static void bcm2835_ic_register_types(void)
> +{
> +    type_register_static(&bcm2835_ic_info);
> +}
> +
> +type_init(bcm2835_ic_register_types)
> diff --git a/include/hw/intc/bcm2835_ic.h b/include/hw/intc/bcm2835_ic.h
> new file mode 100644
> index 0000000..d897f44
> --- /dev/null
> +++ b/include/hw/intc/bcm2835_ic.h
> @@ -0,0 +1,33 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2835_IC_H
> +#define BCM2835_IC_H
> +
> +#include "hw/sysbus.h"
> +
> +#define TYPE_BCM2835_IC "bcm2835_ic"

s/_/-

> +#define BCM2835_IC(obj) OBJECT_CHECK(BCM2835ICState, (obj), TYPE_BCM2835_IC)
> +
> +#define BCM2835_IC_GPU_IRQ "gpu-irq"
> +#define BCM2835_IC_ARM_IRQ "arm-irq"
> +
> +typedef struct BCM2835ICState {
> +    /*< private >*/
> +    SysBusDevice busdev;
> +    /*< public >*/
> +
> +    MemoryRegion iomem;
> +
> +    /* 64 GPU IRQs + 8 ARM IRQs = 72 total (GPU first) */
> +    uint64_t gpu_irq_level, gpu_irq_enable;
> +    uint8_t arm_irq_level, arm_irq_enable;
> +    bool fiq_enable;
> +    uint8_t fiq_select;

> +    qemu_irq irq;
> +    qemu_irq fiq;

Move these two up to below iomem to separate IO from internal state.

Otherwise,

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>

Regards,
Peter

> +} BCM2835ICState;
> +
> +#endif
> --
> 2.5.3
>

  reply	other threads:[~2015-12-31  0:33 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes Andrew Baumann
2015-12-31  0:12   ` Peter Crosthwaite
2015-12-31 18:06     ` Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 2/7] bcm2835_property: add bcm2835 property channel Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller Andrew Baumann
2015-12-31  0:33   ` Peter Crosthwaite [this message]
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals Andrew Baumann
2015-12-31  2:53   ` Peter Crosthwaite
2015-12-31 18:23     ` Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic Andrew Baumann
2015-12-31  3:20   ` Peter Crosthwaite
2015-12-31 18:43     ` Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 6/7] bcm2836: add bcm2836 soc device Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 7/7] raspi: add raspberry pi 2 machine Andrew Baumann
2015-12-31  1:13 ` [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Piotr Król
2016-01-06 18:27   ` Andrew Baumann
2016-01-07  0:09     ` Piotr Król
2016-01-07  0:14       ` Andrew Baumann
2016-01-07  2:46       ` Peter Crosthwaite
2016-01-07  4:47         ` Andrew Baumann
2016-01-07 10:16           ` 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='CAPokK=qES8kJ2m6OiZ5qco877G_0azYXm5tFWyU944BZ8ndK6w@mail.gmail.com' \
    --to=crosthwaitepeter@gmail.com \
    --cc=Andrew.Baumann@microsoft.com \
    --cc=crosthwaite.peter@gmail.com \
    --cc=gregory.estrade@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=sw@weilnetz.de \
    /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.