From patchwork Mon Oct 9 19:54:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: BALATON Zoltan X-Patchwork-Id: 1845458 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S48t65xLFz1ypX for ; Tue, 10 Oct 2023 06:56:14 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qpwLM-000140-6r; Mon, 09 Oct 2023 15:55:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpwLK-00013W-JA; Mon, 09 Oct 2023 15:55:06 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpwLH-0005DJ-V6; Mon, 09 Oct 2023 15:55:06 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 3DF767571FE; Mon, 9 Oct 2023 21:54:07 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id ECA7C74632B; Mon, 9 Oct 2023 21:54:05 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v2 1/3] via-ide: Fix legacy mode emulation To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Nicholas Piggin , Daniel Henrique Barboza , clg@kaod.org, philmd@linaro.org, Bernhard Beschow , Mark Cave-Ayland , Rene Engel , vr_qemu@t-online.de Date: Mon, 9 Oct 2023 21:54:05 +0200 (CEST) X-Spam-Probability: 8% Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 The initial value for BARs were set in reset method for emulating legacy mode at start but this does not work because PCI code resets BARs after calling device reset method. Remove this ineffective default to avoid confusion. Instead move setting the BARs to a callback on writing the PCI config regsiter that sets legacy mode (which firmwares needing this mode seem to do) and fix their values to program it to use legacy port numbers in this case. This does not fully emulate what the data sheet says (which is not very clear on this) but it implements enogh to allow both modes as used by firmwares of machines we emulate. Signed-off-by: BALATON Zoltan --- hw/ide/via.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/hw/ide/via.c b/hw/ide/via.c index fff23803a6..43e8af8d69 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -132,11 +132,6 @@ static void via_ide_reset(DeviceState *dev) pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA: 20-23h */ pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x0000010e); /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/ @@ -159,6 +154,41 @@ static void via_ide_reset(DeviceState *dev) pci_set_long(pci_conf + 0xc0, 0x00020001); } +static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr, + uint32_t val, int len) +{ + pci_default_write_config(pd, addr, val, len); + /* + * Bits 0 and 2 of the PCI programming interface register select between + * legacy and native mode for the two IDE channels. We don't emulate this + * because we cannot easily switch between ISA and PCI in QEMU so instead + * when guest selects legacy mode we set the PCI BARs to legacy ports which + * works the same. We also don't care about setting each channel separately + * as no guest is known to do or need that. We only do this when BARs are + * unset when writing this register as logs from real hardware show that + * setting legacy mode after BARs were set it will still use ports set by + * BARs not ISA ports (e.g. pegasos2 Linux does this after firmware set + * native mode and programmed BARs and calls it non-100% native mode). + * But if 0x8a is written righr after reset without setting BARs then we + * want legacy ports (this is done by the AmigaOne firmware). + */ + if (addr == PCI_CLASS_PROG && val == 0x8a && + pci_get_long(pd->config + PCI_BASE_ADDRESS_0) == + PCI_BASE_ADDRESS_SPACE_IO) { + pci_set_long(pd->config + PCI_BASE_ADDRESS_0, 0x1f0 + | PCI_BASE_ADDRESS_SPACE_IO); + pci_set_long(pd->config + PCI_BASE_ADDRESS_1, 0x3f6 + | PCI_BASE_ADDRESS_SPACE_IO); + pci_set_long(pd->config + PCI_BASE_ADDRESS_2, 0x170 + | PCI_BASE_ADDRESS_SPACE_IO); + pci_set_long(pd->config + PCI_BASE_ADDRESS_3, 0x376 + | PCI_BASE_ADDRESS_SPACE_IO); + /* BMIBA: 20-23h */ + pci_set_long(pd->config + PCI_BASE_ADDRESS_4, 0xcc00 + | PCI_BASE_ADDRESS_SPACE_IO); + } +} + static void via_ide_realize(PCIDevice *dev, Error **errp) { PCIIDEState *d = PCI_IDE(dev); @@ -221,6 +251,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data) /* Reason: only works as function of VIA southbridge */ dc->user_creatable = false; + k->config_write = via_ide_cfg_write; k->realize = via_ide_realize; k->exit = via_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_VIA; From patchwork Mon Oct 9 19:54:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: BALATON Zoltan X-Patchwork-Id: 1845462 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S48tb4Yr7z20Xn for ; Tue, 10 Oct 2023 06:56:39 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qpwLa-00018u-Te; Mon, 09 Oct 2023 15:55:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpwLY-00015d-9S; Mon, 09 Oct 2023 15:55:20 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpwLI-0005DM-1M; Mon, 09 Oct 2023 15:55:20 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 6213C757206; Mon, 9 Oct 2023 21:54:07 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 05F9F7571FA; Mon, 9 Oct 2023 21:54:07 +0200 (CEST) Message-Id: <650d41deef97df5911c87404014bfe162e989314.1696880742.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v2 2/3] hw/pci-host: Add emulation of Mai Logic Articia S To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Nicholas Piggin , Daniel Henrique Barboza , clg@kaod.org, philmd@linaro.org, Bernhard Beschow , Mark Cave-Ayland , Rene Engel , vr_qemu@t-online.de Date: Mon, 9 Oct 2023 21:54:07 +0200 (CEST) X-Spam-Probability: 8% Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 The Articia S is a generic chipset supporting several different CPUs that were among others used on some PPC boards. This is a minimal emulation of the parts needed for emulating the AmigaOne board. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 5 + hw/pci-host/articia.c | 293 ++++++++++++++++++++++++++++++++++ hw/pci-host/meson.build | 2 + include/hw/pci-host/articia.h | 17 ++ 4 files changed, 317 insertions(+) create mode 100644 hw/pci-host/articia.c create mode 100644 include/hw/pci-host/articia.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index a07070eddf..33014c80a4 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -73,6 +73,11 @@ config SH_PCI bool select PCI +config ARTICIA + bool + select PCI + select I8259 + config MV64361 bool select PCI diff --git a/hw/pci-host/articia.c b/hw/pci-host/articia.c new file mode 100644 index 0000000000..f3fcc49f81 --- /dev/null +++ b/hw/pci-host/articia.c @@ -0,0 +1,293 @@ +/* + * Mai Logic Articia S emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci_device.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/i2c/bitbang_i2c.h" +#include "hw/intc/i8259.h" +#include "hw/pci-host/articia.h" + +/* + * This is a minimal emulation of this chip as used in AmigaOne board. + * Most features are missing but those are not needed by firmware and guests. + */ + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaState, ARTICIA) + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaHostState, ARTICIA_PCI_HOST) +struct ArticiaHostState { + PCIDevice parent_obj; + + ArticiaState *as; +}; + +/* TYPE_ARTICIA */ + +struct ArticiaState { + PCIHostState parent_obj; + + qemu_irq irq[PCI_NUM_PINS]; + MemoryRegion io; + MemoryRegion mem; + MemoryRegion reg; + + bitbang_i2c_interface smbus; + uint32_t gpio; /* bits 0-7 in, 8-15 out, 16-23 direction (0 in, 1 out) */ + hwaddr gpio_base; + MemoryRegion gpio_reg; +}; + +static uint64_t articia_gpio_read(void *opaque, hwaddr addr, unsigned int size) +{ + ArticiaState *s = opaque; + + return (s->gpio >> (addr * 8)) & 0xff; +} + +static void articia_gpio_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + ArticiaState *s = opaque; + uint32_t sh = addr * 8; + + if (addr == 0) { + /* in bits read only? */ + return; + } + + if ((s->gpio & (0xff << sh)) != (val & 0xff) << sh) { + s->gpio &= ~(0xff << sh | 0xff); + s->gpio |= (val & 0xff) << sh; + s->gpio |= bitbang_i2c_set(&s->smbus, BITBANG_I2C_SDA, + s->gpio & BIT(16) ? + !!(s->gpio & BIT(8)) : 1); + if ((s->gpio & BIT(17))) { + s->gpio &= ~BIT(0); + s->gpio |= bitbang_i2c_set(&s->smbus, BITBANG_I2C_SCL, + !!(s->gpio & BIT(9))); + } + } +} + +static const MemoryRegionOps articia_gpio_ops = { + .read = articia_gpio_read, + .write = articia_gpio_write, + .valid.min_access_size = 1, + .valid.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t articia_reg_read(void *opaque, hwaddr addr, unsigned int size) +{ + ArticiaState *s = opaque; + uint64_t ret = UINT_MAX; + + switch (addr) { + case 0xc00cf8: + ret = pci_host_conf_le_ops.read(PCI_HOST_BRIDGE(s), 0, size); + break; + case 0xe00cfc ... 0xe00cff: + ret = pci_host_data_le_ops.read(PCI_HOST_BRIDGE(s), addr - 0xe00cfc, size); + break; + case 0xf00000: + ret = pic_read_irq(isa_pic); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register read 0x%" + HWADDR_PRIx " %d\n", __func__, addr, size); + break; + } + return ret; +} + +static void articia_reg_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + ArticiaState *s = opaque; + + switch (addr) { + case 0xc00cf8: + pci_host_conf_le_ops.write(PCI_HOST_BRIDGE(s), 0, val, size); + break; + case 0xe00cfc ... 0xe00cff: + pci_host_data_le_ops.write(PCI_HOST_BRIDGE(s), addr, val, size); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register write 0x%" + HWADDR_PRIx " %d <- %"PRIx64"\n", __func__, addr, size, val); + break; + } +} + +static const MemoryRegionOps articia_reg_ops = { + .read = articia_reg_read, + .write = articia_reg_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void articia_pcihost_set_irq(void *opaque, int n, int level) +{ + ArticiaState *s = opaque; + qemu_set_irq(s->irq[n], level); +} + +/* + * AmigaOne SE PCI slot to IRQ routing + * + * repository: https://source.denx.de/u-boot/custodians/u-boot-avr32.git + * refspec: v2010.06 + * file: board/MAI/AmigaOneG3SE/articiaS_pci.c + */ +static int amigaone_pcihost_bus0_map_irq(PCIDevice *pdev, int pin) +{ + int devfn_slot = PCI_SLOT(pdev->devfn); + + switch (devfn_slot) { + case 6: /* On board ethernet */ + return 3; + case 7: /* South bridge */ + return pin; + default: /* PCI Slot 1 Devfn slot 8, Slot 2 Devfn 9, Slot 3 Devfn 10 */ + return pci_swizzle(devfn_slot, pin); + } + +} + +static void articia_realize(DeviceState *dev, Error **errp) +{ + ArticiaState *s = ARTICIA(dev); + PCIHostState *h = PCI_HOST_BRIDGE(dev); + PCIDevice *pdev; + + bitbang_i2c_init(&s->smbus, i2c_init_bus(dev, "smbus")); + memory_region_init_io(&s->gpio_reg, OBJECT(s), &articia_gpio_ops, s, + TYPE_ARTICIA, 4); + + memory_region_init(&s->mem, OBJECT(dev), "pci-mem", UINT64_MAX); + memory_region_init(&s->io, OBJECT(dev), "pci-io", 0xc00000); + memory_region_init_io(&s->reg, OBJECT(s), &articia_reg_ops, s, + TYPE_ARTICIA, 0x1000000); + memory_region_add_subregion_overlap(&s->reg, 0, &s->io, 1); + + /* devfn_min is 8 that matches first PCI slot in AmigaOne */ + h->bus = pci_register_root_bus(dev, NULL, articia_pcihost_set_irq, + amigaone_pcihost_bus0_map_irq, dev, &s->mem, + &s->io, PCI_DEVFN(8, 0), 4, TYPE_PCI_BUS); + pdev = pci_create_simple_multifunction(h->bus, PCI_DEVFN(0, 0), + TYPE_ARTICIA_PCI_HOST); + ARTICIA_PCI_HOST(pdev)->as = s; + pci_create_simple(h->bus, PCI_DEVFN(0, 1), TYPE_ARTICIA_PCI_BRIDGE); + + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->reg); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mem); + qdev_init_gpio_out(dev, s->irq, ARRAY_SIZE(s->irq)); +} + +static void articia_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = articia_realize; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); +} + +/* TYPE_ARTICIA_PCI_HOST */ + +static void articia_pci_host_cfg_write(PCIDevice *d, uint32_t addr, + uint32_t val, int len) +{ + ArticiaState *s = ARTICIA_PCI_HOST(d)->as; + + pci_default_write_config(d, addr, val, len); + switch (addr) { + case 0x40: + s->gpio_base = val; + break; + case 0x44: + if (val != 0x11) { + /* FIXME what do the bits actually mean? */ + break; + } + if (memory_region_is_mapped(&s->gpio_reg)) { + memory_region_del_subregion(&s->io, &s->gpio_reg); + } + memory_region_add_subregion(&s->io, s->gpio_base + 0x38, &s->gpio_reg); + break; + } +} + +static void articia_pci_host_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->config_write = articia_pci_host_cfg_write; + k->vendor_id = 0x10cc; + k->device_id = 0x0660; + k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, + * not usable without the host-facing part + */ + dc->user_creatable = false; +} + +/* TYPE_ARTICIA_PCI_BRIDGE */ + +static void articia_pci_bridge_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->vendor_id = 0x10cc; + k->device_id = 0x0661; + k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, + * not usable without the host-facing part + */ + dc->user_creatable = false; +} + +static const TypeInfo articia_types[] = { + { + .name = TYPE_ARTICIA, + .parent = TYPE_PCI_HOST_BRIDGE, + .instance_size = sizeof(ArticiaState), + .class_init = articia_class_init, + }, + { + .name = TYPE_ARTICIA_PCI_HOST, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(ArticiaHostState), + .class_init = articia_pci_host_class_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, + }, + { + .name = TYPE_ARTICIA_PCI_BRIDGE, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIDevice), + .class_init = articia_pci_bridge_class_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, + }, +}; + +DEFINE_TYPES(articia_types) diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index 64eada76fe..40de48eb7f 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -20,6 +20,8 @@ pci_ss.add(when: 'CONFIG_GRACKLE_PCI', if_true: files('grackle.c')) pci_ss.add(when: 'CONFIG_UNIN_PCI', if_true: files('uninorth.c')) # PowerPC E500 boards pci_ss.add(when: 'CONFIG_PPCE500_PCI', if_true: files('ppce500.c')) +# AmigaOne +pci_ss.add(when: 'CONFIG_ARTICIA', if_true: files('articia.c')) # Pegasos2 pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c')) diff --git a/include/hw/pci-host/articia.h b/include/hw/pci-host/articia.h new file mode 100644 index 0000000000..529c240274 --- /dev/null +++ b/include/hw/pci-host/articia.h @@ -0,0 +1,17 @@ +/* + * Mai Logic Articia S emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#ifndef ARTICIA_H +#define ARTICIA_H + +#define TYPE_ARTICIA "articia" +#define TYPE_ARTICIA_PCI_HOST "articia-pci-host" +#define TYPE_ARTICIA_PCI_BRIDGE "articia-pci-bridge" + +#endif From patchwork Mon Oct 9 19:54:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: BALATON Zoltan X-Patchwork-Id: 1845461 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S48tY6ltGz1ypX for ; Tue, 10 Oct 2023 06:56:37 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qpwLb-00019K-77; Mon, 09 Oct 2023 15:55:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpwLY-00017C-Ub; Mon, 09 Oct 2023 15:55:20 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpwLI-0005Df-4b; Mon, 09 Oct 2023 15:55:20 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 55B8C75724D; Mon, 9 Oct 2023 21:54:09 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 0DB67757248; Mon, 9 Oct 2023 21:54:08 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v2 3/3] hw/ppc: Add emulation of AmigaOne XE board To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Nicholas Piggin , Daniel Henrique Barboza , clg@kaod.org, philmd@linaro.org, Bernhard Beschow , Mark Cave-Ayland , Rene Engel , vr_qemu@t-online.de Date: Mon, 9 Oct 2023 21:54:08 +0200 (CEST) X-Spam-Probability: 10% Received-SPF: pass client-ip=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 The AmigaOne is a rebranded MAI Teron board that uses U-Boot firmware with patches to support AmigaOS and is very similar to pegasos2 so can be easily emulated sharing most code with pegasos2. The reason to emulate it is that AmigaOS comes in different versions for AmigaOne and PegasosII which only have drivers for one machine and firmware so these only run on the specific machine. Adding this board allows another AmigaOS version to be used reusing already existing peagasos2 emulation. (The AmigaOne was the first of these boards so likely most widespread which then inspired Pegasos that was later replaced with PegasosII due to problems with Articia S, so these have a lot of similarity. Pegasos mainly ran MorphOS while the PegasosII version of AmigaOS was added later and therefore less common than the AmigaOne version.) Signed-off-by: BALATON Zoltan --- MAINTAINERS | 8 ++ configs/devices/ppc-softmmu/default.mak | 1 + hw/ppc/Kconfig | 7 + hw/ppc/amigaone.c | 164 ++++++++++++++++++++++++ hw/ppc/meson.build | 2 + 5 files changed, 182 insertions(+) create mode 100644 hw/ppc/amigaone.c diff --git a/MAINTAINERS b/MAINTAINERS index 7f0e20fde6..03f908c153 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1490,6 +1490,14 @@ F: hw/pci-host/mv64361.c F: hw/pci-host/mv643xx.h F: include/hw/pci-host/mv64361.h +amigaone +M: BALATON Zoltan +L: qemu-ppc@nongnu.org +S: Maintained +F: hw/ppc/amigaone.c +F: hw/pci-host/articia.c +F: include/hw/pci-host/articia.h + Virtual Open Firmware (VOF) M: Alexey Kardashevskiy R: David Gibson diff --git a/configs/devices/ppc-softmmu/default.mak b/configs/devices/ppc-softmmu/default.mak index a887f5438b..b85fd2bcd7 100644 --- a/configs/devices/ppc-softmmu/default.mak +++ b/configs/devices/ppc-softmmu/default.mak @@ -14,6 +14,7 @@ CONFIG_SAM460EX=y CONFIG_MAC_OLDWORLD=y CONFIG_MAC_NEWWORLD=y +CONFIG_AMIGAONE=y CONFIG_PEGASOS2=y # For PReP diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 5dfbf47ef5..56f0475a8e 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -69,6 +69,13 @@ config SAM460EX select USB_OHCI select FDT_PPC +config AMIGAONE + bool + imply ATI_VGA + select ARTICIA + select VT82C686 + select SMBUS_EEPROM + config PEGASOS2 bool imply ATI_VGA diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c new file mode 100644 index 0000000000..3589924c8a --- /dev/null +++ b/hw/ppc/amigaone.c @@ -0,0 +1,164 @@ +/* + * QEMU Eyetech AmigaOne/Mai Logic Teron emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/datadir.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/ppc/ppc.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "hw/pci-host/articia.h" +#include "hw/isa/vt82c686.h" +#include "hw/ide/pci.h" +#include "hw/i2c/smbus_eeprom.h" +#include "hw/ppc/ppc.h" +#include "sysemu/reset.h" +#include "kvm_ppc.h" + +#define BUS_FREQ_HZ 100000000 + +/* + * Firmware binary available at + * https://www.hyperion-entertainment.com/index.php/downloads?view=files&parent=28 + * then "tail -c 524288 updater.image >u-boot-amigaone.bin" + * + * BIOS emulator in firmware cannot run QEMU vgabios and hangs on it, use + * -device VGA,romfile=VGABIOS-lgpl-latest.bin + * from http://www.nongnu.org/vgabios/ instead. + */ +#define PROM_FILENAME "u-boot-amigaone.bin" +#define PROM_ADDR 0xfff00000 +#define PROM_SIZE (512 * KiB) + +static void amigaone_cpu_reset(void *opaque) +{ + PowerPCCPU *cpu = opaque; + + cpu_reset(CPU(cpu)); + cpu_ppc_tb_reset(&cpu->env); +} + +static void fix_spd_data(uint8_t *spd) +{ + uint32_t bank_size = 4 * MiB * spd[31]; + uint32_t rows = bank_size / spd[13] / spd[17]; + spd[3] = ctz32(rows) - spd[4]; +} + +static void amigaone_init(MachineState *machine) +{ + PowerPCCPU *cpu; + CPUPPCState *env; + MemoryRegion *rom, *pci_mem, *mr; + const char *fwname = machine->firmware ?: PROM_FILENAME; + char *filename; + ssize_t sz; + PCIBus *pci_bus; + Object *via; + DeviceState *dev; + I2CBus *i2c_bus; + uint8_t *spd_data; + int i; + + /* init CPU */ + cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); + env = &cpu->env; + if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { + error_report("Incompatible CPU, only 6xx bus supported"); + exit(1); + } + cpu_ppc_tb_init(env, BUS_FREQ_HZ / 4); + qemu_register_reset(amigaone_cpu_reset, cpu); + + /* RAM */ + if (machine->ram_size > 2 * GiB) { + error_report("RAM size more than 2 GiB is not supported"); + exit(1); + } + memory_region_add_subregion(get_system_memory(), 0, machine->ram); + if (machine->ram_size < 1 * GiB + 32 * KiB) { + /* Firmware uses this area for startup */ + mr = g_new(MemoryRegion, 1); + memory_region_init_ram(mr, NULL, "init-cache", 32 * KiB, &error_fatal); + memory_region_add_subregion(get_system_memory(), 0x40000000, mr); + } + + /* allocate and load firmware */ + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, fwname); + if (!filename) { + error_report("Could not find firmware '%s'", fwname); + exit(1); + } + rom = g_new(MemoryRegion, 1); + memory_region_init_rom(rom, NULL, "rom", PROM_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), PROM_ADDR, rom); + sz = load_image_targphys(filename, PROM_ADDR, PROM_SIZE); + if (sz <= 0 || sz > PROM_SIZE) { + error_report("Could not load firmware '%s'", filename); + exit(1); + } + g_free(filename); + + /* Articia S */ + dev = sysbus_create_simple(TYPE_ARTICIA, 0xfe000000, NULL); + + i2c_bus = I2C_BUS(qdev_get_child_bus(dev, "smbus")); + if (machine->ram_size > 512 * MiB) { + spd_data = spd_data_generate(SDR, machine->ram_size / 2); + } else { + spd_data = spd_data_generate(SDR, machine->ram_size); + } + fix_spd_data(spd_data); + smbus_eeprom_init_one(i2c_bus, 0x51, spd_data); + if (machine->ram_size > 512 * MiB) { + smbus_eeprom_init_one(i2c_bus, 0x52, spd_data); + } + + pci_mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + mr = g_new(MemoryRegion, 1); + memory_region_init_alias(mr, OBJECT(dev), "pci-mem-low", pci_mem, + 0, 0x1000000); + memory_region_add_subregion(get_system_memory(), 0xfd000000, mr); + mr = g_new(MemoryRegion, 1); + memory_region_init_alias(mr, OBJECT(dev), "pci-mem-high", pci_mem, + 0x80000000, 0x7d000000); + memory_region_add_subregion(get_system_memory(), 0x80000000, mr); + pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); + + /* VIA VT82c686B South Bridge (multifunction PCI device) */ + via = OBJECT(pci_create_simple_multifunction(pci_bus, PCI_DEVFN(7, 0), + TYPE_VT82C686B_ISA)); + object_property_add_alias(OBJECT(machine), "rtc-time", + object_resolve_path_component(via, "rtc"), + "date"); + qdev_connect_gpio_out(DEVICE(via), 0, + qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT)); + for (i = 0; i < PCI_NUM_PINS; i++) { + qdev_connect_gpio_out(dev, i, qdev_get_gpio_in_named(DEVICE(via), + "pirq", i)); + } + pci_ide_create_devs(PCI_DEVICE(object_resolve_path_component(via, "ide"))); + pci_vga_init(pci_bus); +} + +static void amigaone_machine_init(MachineClass *mc) +{ + mc->desc = "Eyetech AmigaOne/Mai Logic Teron"; + mc->init = amigaone_init; + mc->block_default_type = IF_IDE; + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7457_v1.2"); + mc->default_display = "std"; + mc->default_ram_id = "ram"; + mc->default_ram_size = 128 * MiB; +} + +DEFINE_MACHINE("amigaone", amigaone_machine_init) diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index 7c2c52434a..0f76f4cce4 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -81,6 +81,8 @@ ppc_ss.add(when: 'CONFIG_E500', if_true: files( )) # PowerPC 440 Xilinx ML507 reference board. ppc_ss.add(when: 'CONFIG_VIRTEX', if_true: files('virtex_ml507.c')) +# a1xe +ppc_ss.add(when: 'CONFIG_AMIGAONE', if_true: files('amigaone.c')) # Pegasos2 ppc_ss.add(when: 'CONFIG_PEGASOS2', if_true: files('pegasos2.c'))