From patchwork Sun Mar 24 11:32:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 15560 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id A75C823E3E for ; Sun, 24 Mar 2013 11:32:47 +0000 (UTC) Received: from mail-ve0-f178.google.com (mail-ve0-f178.google.com [209.85.128.178]) by fiordland.canonical.com (Postfix) with ESMTP id 4D885A18D65 for ; Sun, 24 Mar 2013 11:32:47 +0000 (UTC) Received: by mail-ve0-f178.google.com with SMTP id db10so418506veb.37 for ; Sun, 24 Mar 2013 04:32:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state; bh=haTA6KSpveFWTgbyJiKOZfd6bHJY456GVUUAZGS3mO8=; b=glFrdWlhjgzwKtyKUADTPwjlAS824ex0yn2J+2VYjD3LJgIOZ32PuN2AbIlJh0rtdV hVtzOFO31MNAflIWSVvUISIo0Bjq9lCj3kozGYkqoMNiRCA2rbBndRdu8APwcAfi2ywX MKPRUcZXDBZFeka4EaV4fE3KMcAVHGczJ0ZnftQfMaHoPOD6g0+src2oLXC2wvaHjWKG 6VfZJruDv/qSi8rwwKcARouWTnLqdaU+8BabywzkRvoZwJCuYV9i0V5KzmVxBQ02hrn+ poMF9Cb9+wsWiGi/qKhavgmpACwVBzqYTvHaiONooYoVHW0HlW2j9TQiTDb2Yq65CuEQ ZGHQ== X-Received: by 10.52.20.239 with SMTP id q15mr9172875vde.73.1364124766769; Sun, 24 Mar 2013 04:32:46 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.59.4.204 with SMTP id cg12csp4955ved; Sun, 24 Mar 2013 04:32:46 -0700 (PDT) X-Received: by 10.15.81.136 with SMTP id x8mr23036163eey.9.1364124764425; Sun, 24 Mar 2013 04:32:44 -0700 (PDT) Received: from mnementh.archaic.org.uk (1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.1.0.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id f1si1953557eeo.101.2013.03.24.04.32.43 (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 24 Mar 2013 04:32:44 -0700 (PDT) Received-SPF: neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) client-ip=2001:8b0:1d0::1; Authentication-Results: mx.google.com; spf=neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1UJjAG-0001W9-Df; Sun, 24 Mar 2013 11:32:40 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, =?UTF-8?q?Andreas=20F=C3=A4rber?= , "Michael S. Tsirkin" , Paul Brook , Arnd Bergmann , Will Deacon Subject: [PATCH 08/10] versatile_pci: Implement the PCI controller's control registers Date: Sun, 24 Mar 2013 11:32:38 +0000 Message-Id: <1364124760-5794-9-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1364124760-5794-1-git-send-email-peter.maydell@linaro.org> References: <1364124760-5794-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQmtHdQrU3SDhJNKWDBpgs0tGZ6cKK1SdemKXfpDcceWs6TdbCz4FeSDYSzjKHG10VG4TRez The versatile_pci PCI controller has a set of control registers which handle the mapping between PCI and system address spaces. Implement these registers (though for now they have no effect since we don't implement mapping PCI space into system memory at all). The most natural order for our sysbus regions has the control registers at the start, so move all the others down one. Signed-off-by: Peter Maydell --- hw/arm/realview.c | 7 +-- hw/arm/versatilepb.c | 7 +-- hw/versatile_pci.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 138 insertions(+), 11 deletions(-) diff --git a/hw/arm/realview.c b/hw/arm/realview.c index 5fb490c..ba61d18 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -217,9 +217,10 @@ static void realview_init(QEMUMachineInitArgs *args, dev = qdev_create(NULL, "realview_pci"); busdev = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); - sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */ - sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */ - sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */ + sysbus_mmio_map(busdev, 0, 0x10019000); /* PCI controller registers */ + sysbus_mmio_map(busdev, 1, 0x61000000); /* PCI self-config */ + sysbus_mmio_map(busdev, 2, 0x62000000); /* PCI config */ + sysbus_mmio_map(busdev, 3, 0x63000000); /* PCI I/O */ sysbus_connect_irq(busdev, 0, pic[48]); sysbus_connect_irq(busdev, 1, pic[49]); sysbus_connect_irq(busdev, 2, pic[50]); diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index 0d08d15..9c9bfde 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -224,9 +224,10 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id) dev = qdev_create(NULL, "versatile_pci"); busdev = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); - sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */ - sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */ - sysbus_mmio_map(busdev, 2, 0x43000000); /* PCI I/O */ + sysbus_mmio_map(busdev, 0, 0x10001000); /* PCI controller regs */ + sysbus_mmio_map(busdev, 1, 0x41000000); /* PCI self-config */ + sysbus_mmio_map(busdev, 2, 0x42000000); /* PCI config */ + sysbus_mmio_map(busdev, 3, 0x43000000); /* PCI I/O */ sysbus_connect_irq(busdev, 0, sic[27]); sysbus_connect_irq(busdev, 1, sic[28]); sysbus_connect_irq(busdev, 2, sic[29]); diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index 7739f4c..a617675 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -17,6 +17,7 @@ typedef struct { PCIHostState parent_obj; qemu_irq irq[4]; + MemoryRegion controlregs; MemoryRegion mem_config; MemoryRegion mem_config2; MemoryRegion pci_io_space; @@ -27,8 +28,27 @@ typedef struct { /* Constant for life of device: */ int realview; uint8_t broken_irq_mapping; + + /* Register state: */ + uint32_t imap[3]; + uint32_t smap[3]; + uint32_t selfid; + uint32_t flags; } PCIVPBState; +static const VMStateDescription pci_vpb_vmstate = { + .name = "versatile-pci", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(imap, PCIVPBState, 3), + VMSTATE_UINT32_ARRAY(smap, PCIVPBState, 3), + VMSTATE_UINT32(selfid, PCIVPBState), + VMSTATE_UINT32(flags, PCIVPBState), + VMSTATE_END_OF_LIST() + } +}; + #define TYPE_VERSATILE_PCI "versatile_pci" #define PCI_VPB(obj) \ OBJECT_CHECK(PCIVPBState, (obj), TYPE_VERSATILE_PCI) @@ -37,6 +57,93 @@ typedef struct { #define PCI_VPB_HOST(obj) \ OBJECT_CHECK(PCIDevice, (obj), TYPE_VERSATILE_PCIHOST) +typedef enum { + PCI_IMAP0 = 0x0, + PCI_IMAP1 = 0x4, + PCI_IMAP2 = 0x8, + PCI_SELFID = 0xc, + PCI_FLAGS = 0x10, + PCI_SMAP0 = 0x14, + PCI_SMAP1 = 0x18, + PCI_SMAP2 = 0x1c, +} PCIVPBControlRegs; + +static void pci_vpb_reg_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + PCIVPBState *s = opaque; + + switch (addr) { + case PCI_IMAP0: + case PCI_IMAP1: + case PCI_IMAP2: + { + int win = (addr - PCI_IMAP0) >> 2; + s->imap[win] = val; + break; + } + case PCI_SELFID: + s->selfid = val; + break; + case PCI_FLAGS: + s->flags = val; + break; + case PCI_SMAP0: + case PCI_SMAP1: + case PCI_SMAP2: + { + int win = (addr - PCI_SMAP0) >> 2; + s->smap[win] = val; + break; + } + default: + qemu_log_mask(LOG_GUEST_ERROR, + "pci_vpb_reg_write: Bad offset %x\n", (int)addr); + break; + } +} + +static uint64_t pci_vpb_reg_read(void *opaque, hwaddr addr, + unsigned size) +{ + PCIVPBState *s = opaque; + + switch (addr) { + case PCI_IMAP0: + case PCI_IMAP1: + case PCI_IMAP2: + { + int win = (addr - PCI_IMAP0) >> 2; + return s->imap[win]; + } + case PCI_SELFID: + return s->selfid; + case PCI_FLAGS: + return s->flags; + case PCI_SMAP0: + case PCI_SMAP1: + case PCI_SMAP2: + { + int win = (addr - PCI_SMAP0) >> 2; + return s->smap[win]; + } + default: + qemu_log_mask(LOG_GUEST_ERROR, + "pci_vpb_reg_read: Bad offset %x\n", (int)addr); + return 0; + } +} + +static const MemoryRegionOps pci_vpb_reg_ops = { + .read = pci_vpb_reg_read, + .write = pci_vpb_reg_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static inline uint32_t vpb_pci_config_addr(hwaddr addr) { return addr & 0xffffff; @@ -115,6 +222,20 @@ static void pci_vpb_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(pic[irq_num], level); } +static void pci_vpb_reset(DeviceState *d) +{ + PCIVPBState *s = PCI_VPB(d); + + s->imap[0] = 0; + s->imap[1] = 0; + s->imap[2] = 0; + s->smap[0] = 0; + s->smap[1] = 0; + s->smap[2] = 0; + s->selfid = 0; + s->flags = 0; +} + static void pci_vpb_init(Object *obj) { PCIHostState *h = PCI_HOST_BRIDGE(obj); @@ -154,13 +275,15 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) pci_bus_irqs(&s->pci_bus, pci_vpb_set_irq, mapfn, s->irq, 4); - /* ??? Register memory space. */ - /* Our memory regions are: - * 0 : PCI self config window - * 1 : PCI config window - * 2 : PCI IO window + * 0 : our control registers + * 1 : PCI self config window + * 2 : PCI config window + * 3 : PCI IO window */ + memory_region_init_io(&s->controlregs, &pci_vpb_reg_ops, s, "pci-vpb-regs", + 0x1000); + sysbus_init_mmio(sbd, &s->controlregs); memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, &s->pci_bus, "pci-vpb-selfconfig", 0x1000000); sysbus_init_mmio(sbd, &s->mem_config); @@ -216,6 +339,8 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data) dc->realize = pci_vpb_realize; dc->props = pci_vpb_properties; + dc->reset = pci_vpb_reset; + dc->vmsd = &pci_vpb_vmstate; } static const TypeInfo pci_vpb_info = {