From patchwork Wed Nov 20 07:53:21 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: liguang X-Patchwork-Id: 292678 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2E9042C00C3 for ; Wed, 20 Nov 2013 18:56:13 +1100 (EST) Received: from localhost ([::1]:53295 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vj2dt-0005pV-Lp for incoming@patchwork.ozlabs.org; Wed, 20 Nov 2013 02:56:09 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38547) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vj2dL-0005p6-7w for qemu-devel@nongnu.org; Wed, 20 Nov 2013 02:55:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Vj2dG-0001W6-4i for qemu-devel@nongnu.org; Wed, 20 Nov 2013 02:55:35 -0500 Received: from [222.73.24.84] (port=3495 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vj2dF-0001Vc-68 for qemu-devel@nongnu.org; Wed, 20 Nov 2013 02:55:30 -0500 X-IronPort-AV: E=Sophos;i="4.93,735,1378828800"; d="scan'208";a="9083486" Received: from unknown (HELO tang.cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 20 Nov 2013 15:51:55 +0800 Received: from fnstmail02.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id rAK7tIdn014348; Wed, 20 Nov 2013 15:55:20 +0800 Received: from liguang.fnst.cn.fujitsu.com ([10.167.226.116]) by fnstmail02.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.3) with ESMTP id 2013112015532188-266190 ; Wed, 20 Nov 2013 15:53:21 +0800 From: liguang To: qemu-devel@nongnu.org Date: Wed, 20 Nov 2013 15:53:21 +0800 Message-Id: <1384934003-26036-3-git-send-email-lig.fnst@cn.fujitsu.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1384934003-26036-1-git-send-email-lig.fnst@cn.fujitsu.com> References: <1384934003-26036-1-git-send-email-lig.fnst@cn.fujitsu.com> X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/11/20 15:53:21, Serialize by Router on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/11/20 15:53:25, Serialize complete at 2013/11/20 15:53:25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 222.73.24.84 Cc: Peter Maydell , liguang Subject: [Qemu-devel] [PATCH 2/4] hw/arm/sunxi-soc: add interrupt controller X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: liguang --- hw/arm/sunxi-soc.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 290 insertions(+), 0 deletions(-) diff --git a/hw/arm/sunxi-soc.c b/hw/arm/sunxi-soc.c index f6849eb..1b369ba 100644 --- a/hw/arm/sunxi-soc.c +++ b/hw/arm/sunxi-soc.c @@ -5,6 +5,296 @@ #include "sysemu/sysemu.h" +#define TYPE_SUNXI_PIC "sunxi_PIC" +#define SUNXI_PIC(obj) OBJECT_CHECK(SunxiPICState, (obj), TYPE_SUNXI_PIC) + +#define PIC_VECTOR 0 +#define PIC_BASE_ADDR 4 +#define PIC_PROTECT 8 +#define PIC_NMI 0xc +#define PIC_IRQ_PENDING0 0x10 +#define PIC_IRQ_PENDING1 0x14 +#define PIC_IRQ_PENDING2 0x18 +#define PIC_FIQ_PENDING0 0x20 +#define PIC_FIQ_PENDING1 0x24 +#define PIC_FIQ_PENDING2 0x28 +#define PIC_SELECT0 0x30 +#define PIC_SELECT1 0x34 +#define PIC_SELECT2 0x38 +#define PIC_ENABLE0 0x40 +#define PIC_ENABLE1 0x44 +#define PIC_ENABLE2 0x48 +#define PIC_MASK0 0x50 +#define PIC_MASK1 0x54 +#define PIC_MASK2 0x58 + +typedef struct SunxiPICState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + MemoryRegion iomem; + qemu_irq parent_fiq; + qemu_irq parent_irq; + uint32_t vector; + uint32_t base_addr; + uint32_t protect; + uint32_t nmi; + uint32_t irq_pending0; + uint32_t irq_pending1; + uint32_t irq_pending2; + uint32_t select0; + uint32_t select1; + uint32_t select2; + uint32_t enable0; + uint32_t enable1; + uint32_t enable2; + uint32_t mask0; + uint32_t mask1; + uint32_t mask2; + /*priority setting here*/ +} SunxiPICState; + +static void sunxi_pic_update(SunxiPICState *s) +{ + uint32_t flags = 0; + + flags = s->irq_pending0 & s->irq_pending1 & s->irq_pending0; + qemu_set_irq(s->parent_irq, flags != 0); + flags = s->select0 & s->select1 & s->select2; + qemu_set_irq(s->parent_fiq, flags != 0); +} + +static void sunxi_pic_set_irq(void *opaque, int irq, int level) +{ + SunxiPICState *s = opaque; + bool allow_irq = false; + + if (level) { + if (irq < 32) { + set_bit(irq, (void *)&s->irq_pending0); + if (test_bit(irq, (void *)&s->enable0) && + !test_bit(irq, (void *)&s->mask0)) { + allow_irq = true; + } + } else if (irq < 64) { + set_bit(irq, (void *)&s->irq_pending1); + if (test_bit(irq, (void *)&s->enable1) && + !test_bit(irq, (void *)&s->mask1)) { + allow_irq = true; + } + } else if (irq < 95) { + set_bit(irq, (void *)&s->irq_pending2); + if (test_bit(irq, (void *)&s->enable2) && + !test_bit(irq, (void *)&s->mask2)) { + allow_irq = true; + } + } + } else { + if (irq < 32) { + clear_bit(irq, (void *)&s->irq_pending0); + } else if (irq < 64) { + clear_bit(irq, (void *)&s->irq_pending1); + } else if (irq < 95) { + clear_bit(irq, (void *)&s->irq_pending2); + } + } + if (allow_irq) { + sunxi_pic_update(s); + } +} + +static uint64_t sunxi_pic_read(void *opaque, hwaddr offset, unsigned size) +{ + SunxiPICState *s = opaque; + + switch (offset) { + case PIC_VECTOR: + return s->vector; + break; + case PIC_BASE_ADDR: + return s->base_addr; + break; + case PIC_PROTECT: + return s->protect; + break; + case PIC_NMI: + return s->nmi; + break; + case PIC_IRQ_PENDING0: + case PIC_FIQ_PENDING0: + return s->irq_pending0; + break; + case PIC_IRQ_PENDING1: + case PIC_FIQ_PENDING1: + return s->irq_pending1; + break; + case PIC_IRQ_PENDING2: + case PIC_FIQ_PENDING2: + return s->irq_pending2; + break; + case PIC_SELECT0: + return s->select0; + break; + case PIC_SELECT1: + return s->select1; + break; + case PIC_SELECT2: + return s->select2; + break; + case PIC_ENABLE0: + return s->enable0; + break; + case PIC_ENABLE1: + return s->enable1; + break; + case PIC_ENABLE2: + return s->enable2; + break; + case PIC_MASK0: + return s->mask0; + break; + case PIC_MASK1: + return s->mask1; + break; + case PIC_MASK2: + return s->mask2; + break; + default: + break; + } + + return 0; +} + +static void sunxi_pic_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + SunxiPICState *s = opaque; + uint8_t index = 0; + + switch (offset) { + case PIC_VECTOR: + s->vector = value & ~0x3; + break; + case PIC_BASE_ADDR: + s->base_addr = value & ~0x3; + case PIC_PROTECT: + case PIC_NMI: + break; + case PIC_IRQ_PENDING0: + case PIC_FIQ_PENDING0: + for (index = 0; index < sizeof(uint32_t); index++) { + if (test_bit(index, (void *)&value)) { + clear_bit(index, (void *)&s->irq_pending0); + } + } + break; + case PIC_IRQ_PENDING1: + case PIC_FIQ_PENDING1: + for (index = 0; index < sizeof(uint32_t); index++) { + if (test_bit(index, (void *)&value)) { + clear_bit(index, (void *)&s->irq_pending1); + } + } + break; + case PIC_IRQ_PENDING2: + case PIC_FIQ_PENDING2: + for (index = 0; index < sizeof(uint32_t); index++) { + if (test_bit(index, (void *)&value)) { + clear_bit(index, (void *)&s->irq_pending2); + } + } + break; + case PIC_SELECT0: + s->select0 = value; + break; + case PIC_SELECT1: + s->select1 = value; + break; + case PIC_SELECT2: + s->select2 = value; + break; + case PIC_ENABLE0: + s->enable0 = value; + break; + case PIC_ENABLE1: + s->enable1 = value; + break; + case PIC_ENABLE2: + s->enable2 = value; + break; + case PIC_MASK0: + s->mask0 = value; + break; + case PIC_MASK1: + s->mask1 = value; + break; + case PIC_MASK2: + s->mask2 = value; + default: + break; + } + + sunxi_pic_update(s); +} + +static const MemoryRegionOps sunxi_pic_ops = { + .read = sunxi_pic_read, + .write = sunxi_pic_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static int sunxi_pic_init(SysBusDevice *dev) +{ + SunxiPICState *s = SUNXI_PIC(dev); + + qdev_init_gpio_in(DEVICE(dev), sunxi_pic_set_irq, 95); + sysbus_init_irq(dev, &s->parent_irq); + sysbus_init_irq(dev, &s->parent_fiq); + memory_region_init_io(&s->iomem, OBJECT(s), &sunxi_pic_ops, s, + "sunxi-pic", 0x400); + sysbus_init_mmio(dev, &s->iomem); + + return 0; +} + +static void sunxi_pic_reset(DeviceState *d) +{ + SunxiPICState *s = SUNXI_PIC(d); + + s->base_addr = 0; + s->protect = 0; + s->nmi = 0; + s->vector = 0; + s->irq_pending0 = 0; + s->irq_pending1 = 0; + s->irq_pending2 = 0; + s->select0 = 0; + s->select1 = 0; + s->select2 = 0; + s->enable0 = 0; + s->enable1 = 0; + s->enable2 = 0; + s->mask0 = 0; + s->mask1 = 0; + s->mask2 = 0; +} + +static void sunxi_pic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = sunxi_pic_init; + dc->reset = sunxi_pic_reset; + } + +static const TypeInfo sunxi_pic_info = { + .name = TYPE_SUNXI_PIC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SunxiPICState), + .class_init = sunxi_pic_class_init, +}; static void sunxi_init(QEMUMachineInitArgs *args) {