diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/hw/misc | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/hw/misc')
48 files changed, 0 insertions, 17029 deletions
diff --git a/qemu/hw/misc/Makefile.objs b/qemu/hw/misc/Makefile.objs deleted file mode 100644 index 93f952880..000000000 --- a/qemu/hw/misc/Makefile.objs +++ /dev/null @@ -1,52 +0,0 @@ -common-obj-$(CONFIG_APPLESMC) += applesmc.o -common-obj-$(CONFIG_MAX111X) += max111x.o -common-obj-$(CONFIG_TMP105) += tmp105.o -common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o -common-obj-$(CONFIG_SGA) += sga.o -common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o -common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o - -obj-$(CONFIG_VMPORT) += vmport.o - -# ARM devices -common-obj-$(CONFIG_PL310) += arm_l2x0.o -common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o -common-obj-$(CONFIG_A9SCU) += a9scu.o -common-obj-$(CONFIG_ARM11SCU) += arm11scu.o - -# PKUnity SoC devices -common-obj-$(CONFIG_PUV3) += puv3_pm.o - -common-obj-$(CONFIG_MACIO) += macio/ - -obj-$(CONFIG_IVSHMEM) += ivshmem.o - -obj-$(CONFIG_REALVIEW) += arm_sysctl.o -obj-$(CONFIG_NSERIES) += cbus.o -obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o -obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o -obj-$(CONFIG_IMX) += imx_ccm.o -obj-$(CONFIG_IMX) += imx31_ccm.o -obj-$(CONFIG_IMX) += imx25_ccm.o -obj-$(CONFIG_IMX) += imx6_ccm.o -obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o -obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o -obj-$(CONFIG_MAINSTONE) += mst_fpga.o -obj-$(CONFIG_OMAP) += omap_clk.o -obj-$(CONFIG_OMAP) += omap_gpmc.o -obj-$(CONFIG_OMAP) += omap_l4.o -obj-$(CONFIG_OMAP) += omap_sdrc.o -obj-$(CONFIG_OMAP) += omap_tap.o -obj-$(CONFIG_RASPI) += bcm2835_mbox.o -obj-$(CONFIG_RASPI) += bcm2835_property.o -obj-$(CONFIG_SLAVIO) += slavio_misc.o -obj-$(CONFIG_ZYNQ) += zynq_slcr.o -obj-$(CONFIG_ZYNQ) += zynq-xadc.o -obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o -obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o -obj-$(CONFIG_MIPS_CPS) += mips_cpc.o -obj-$(CONFIG_MIPS_ITU) += mips_itu.o - -obj-$(CONFIG_PVPANIC) += pvpanic.o -obj-$(CONFIG_EDU) += edu.o -obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o diff --git a/qemu/hw/misc/a9scu.c b/qemu/hw/misc/a9scu.c deleted file mode 100644 index 3e8ad8cd7..000000000 --- a/qemu/hw/misc/a9scu.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Cortex-A9MPCore Snoop Control Unit (SCU) emulation. - * - * Copyright (c) 2009 CodeSourcery. - * Copyright (c) 2011 Linaro Limited. - * Written by Paul Brook, Peter Maydell. - * - * This code is licensed under the GPL. - */ - -#include "qemu/osdep.h" -#include "hw/misc/a9scu.h" - -static uint64_t a9_scu_read(void *opaque, hwaddr offset, - unsigned size) -{ - A9SCUState *s = (A9SCUState *)opaque; - switch (offset) { - case 0x00: /* Control */ - return s->control; - case 0x04: /* Configuration */ - return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1); - case 0x08: /* CPU Power Status */ - return s->status; - case 0x09: /* CPU status. */ - return s->status >> 8; - case 0x0a: /* CPU status. */ - return s->status >> 16; - case 0x0b: /* CPU status. */ - return s->status >> 24; - case 0x0c: /* Invalidate All Registers In Secure State */ - return 0; - case 0x40: /* Filtering Start Address Register */ - case 0x44: /* Filtering End Address Register */ - /* RAZ/WI, like an implementation with only one AXI master */ - return 0; - case 0x50: /* SCU Access Control Register */ - case 0x54: /* SCU Non-secure Access Control Register */ - /* unimplemented, fall through */ - default: - return 0; - } -} - -static void a9_scu_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - A9SCUState *s = (A9SCUState *)opaque; - uint32_t mask; - uint32_t shift; - switch (size) { - case 1: - mask = 0xff; - break; - case 2: - mask = 0xffff; - break; - case 4: - mask = 0xffffffff; - break; - default: - fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n", - size, (unsigned)offset); - return; - } - - switch (offset) { - case 0x00: /* Control */ - s->control = value & 1; - break; - case 0x4: /* Configuration: RO */ - break; - case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */ - shift = (offset - 0x8) * 8; - s->status &= ~(mask << shift); - s->status |= ((value & mask) << shift); - break; - case 0x0c: /* Invalidate All Registers In Secure State */ - /* no-op as we do not implement caches */ - break; - case 0x40: /* Filtering Start Address Register */ - case 0x44: /* Filtering End Address Register */ - /* RAZ/WI, like an implementation with only one AXI master */ - break; - case 0x50: /* SCU Access Control Register */ - case 0x54: /* SCU Non-secure Access Control Register */ - /* unimplemented, fall through */ - default: - break; - } -} - -static const MemoryRegionOps a9_scu_ops = { - .read = a9_scu_read, - .write = a9_scu_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void a9_scu_reset(DeviceState *dev) -{ - A9SCUState *s = A9_SCU(dev); - s->control = 0; -} - -static void a9_scu_init(Object *obj) -{ - A9SCUState *s = A9_SCU(obj); - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - - memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s, - "a9-scu", 0x100); - sysbus_init_mmio(sbd, &s->iomem); -} - -static const VMStateDescription vmstate_a9_scu = { - .name = "a9-scu", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(control, A9SCUState), - VMSTATE_UINT32(status, A9SCUState), - VMSTATE_END_OF_LIST() - } -}; - -static Property a9_scu_properties[] = { - DEFINE_PROP_UINT32("num-cpu", A9SCUState, num_cpu, 1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void a9_scu_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->props = a9_scu_properties; - dc->vmsd = &vmstate_a9_scu; - dc->reset = a9_scu_reset; -} - -static const TypeInfo a9_scu_info = { - .name = TYPE_A9_SCU, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(A9SCUState), - .instance_init = a9_scu_init, - .class_init = a9_scu_class_init, -}; - -static void a9mp_register_types(void) -{ - type_register_static(&a9_scu_info); -} - -type_init(a9mp_register_types) diff --git a/qemu/hw/misc/applesmc.c b/qemu/hw/misc/applesmc.c deleted file mode 100644 index 77fab5b9d..000000000 --- a/qemu/hw/misc/applesmc.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Apple SMC controller - * - * Copyright (c) 2007 Alexander Graf - * - * Authors: Alexander Graf <agraf@suse.de> - * Susanne Graf <suse@csgraf.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - * ***************************************************************** - * - * In all Intel-based Apple hardware there is an SMC chip to control the - * backlight, fans and several other generic device parameters. It also - * contains the magic keys used to dongle Mac OS X to the device. - * - * This driver was mostly created by looking at the Linux AppleSMC driver - * implementation and does not support IRQ. - * - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/isa/isa.h" -#include "ui/console.h" -#include "qemu/timer.h" - -/* #define DEBUG_SMC */ - -#define APPLESMC_DEFAULT_IOBASE 0x300 -/* data port used by Apple SMC */ -#define APPLESMC_DATA_PORT 0x0 -/* command/status port used by Apple SMC */ -#define APPLESMC_CMD_PORT 0x4 -#define APPLESMC_NR_PORTS 32 - -#define APPLESMC_READ_CMD 0x10 -#define APPLESMC_WRITE_CMD 0x11 -#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 -#define APPLESMC_GET_KEY_TYPE_CMD 0x13 - -#ifdef DEBUG_SMC -#define smc_debug(...) fprintf(stderr, "AppleSMC: " __VA_ARGS__) -#else -#define smc_debug(...) do { } while(0) -#endif - -static char default_osk[64] = "This is a dummy key. Enter the real key " - "using the -osk parameter"; - -struct AppleSMCData { - uint8_t len; - const char *key; - const char *data; - QLIST_ENTRY(AppleSMCData) node; -}; - -#define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC) - -typedef struct AppleSMCState AppleSMCState; -struct AppleSMCState { - ISADevice parent_obj; - - MemoryRegion io_data; - MemoryRegion io_cmd; - uint32_t iobase; - uint8_t cmd; - uint8_t status; - uint8_t key[4]; - uint8_t read_pos; - uint8_t data_len; - uint8_t data_pos; - uint8_t data[255]; - uint8_t charactic[4]; - char *osk; - QLIST_HEAD(, AppleSMCData) data_def; -}; - -static void applesmc_io_cmd_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - AppleSMCState *s = opaque; - - smc_debug("CMD Write B: %#x = %#x\n", addr, val); - switch(val) { - case APPLESMC_READ_CMD: - s->status = 0x0c; - break; - } - s->cmd = val; - s->read_pos = 0; - s->data_pos = 0; -} - -static void applesmc_fill_data(AppleSMCState *s) -{ - struct AppleSMCData *d; - - QLIST_FOREACH(d, &s->data_def, node) { - if (!memcmp(d->key, s->key, 4)) { - smc_debug("Key matched (%s Len=%d Data=%s)\n", d->key, - d->len, d->data); - memcpy(s->data, d->data, d->len); - return; - } - } -} - -static void applesmc_io_data_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - AppleSMCState *s = opaque; - - smc_debug("DATA Write B: %#x = %#x\n", addr, val); - switch(s->cmd) { - case APPLESMC_READ_CMD: - if(s->read_pos < 4) { - s->key[s->read_pos] = val; - s->status = 0x04; - } else if(s->read_pos == 4) { - s->data_len = val; - s->status = 0x05; - s->data_pos = 0; - smc_debug("Key = %c%c%c%c Len = %d\n", s->key[0], - s->key[1], s->key[2], s->key[3], val); - applesmc_fill_data(s); - } - s->read_pos++; - break; - } -} - -static uint64_t applesmc_io_data_read(void *opaque, hwaddr addr1, - unsigned size) -{ - AppleSMCState *s = opaque; - uint8_t retval = 0; - - switch(s->cmd) { - case APPLESMC_READ_CMD: - if(s->data_pos < s->data_len) { - retval = s->data[s->data_pos]; - smc_debug("READ_DATA[%d] = %#hhx\n", s->data_pos, - retval); - s->data_pos++; - if(s->data_pos == s->data_len) { - s->status = 0x00; - smc_debug("EOF\n"); - } else - s->status = 0x05; - } - } - smc_debug("DATA Read b: %#x = %#x\n", addr1, retval); - - return retval; -} - -static uint64_t applesmc_io_cmd_read(void *opaque, hwaddr addr1, unsigned size) -{ - AppleSMCState *s = opaque; - - smc_debug("CMD Read B: %#x\n", addr1); - return s->status; -} - -static void applesmc_add_key(AppleSMCState *s, const char *key, - int len, const char *data) -{ - struct AppleSMCData *def; - - def = g_malloc0(sizeof(struct AppleSMCData)); - def->key = key; - def->len = len; - def->data = data; - - QLIST_INSERT_HEAD(&s->data_def, def, node); -} - -static void qdev_applesmc_isa_reset(DeviceState *dev) -{ - AppleSMCState *s = APPLE_SMC(dev); - struct AppleSMCData *d, *next; - - /* Remove existing entries */ - QLIST_FOREACH_SAFE(d, &s->data_def, node, next) { - QLIST_REMOVE(d, node); - } - - applesmc_add_key(s, "REV ", 6, "\x01\x13\x0f\x00\x00\x03"); - applesmc_add_key(s, "OSK0", 32, s->osk); - applesmc_add_key(s, "OSK1", 32, s->osk + 32); - applesmc_add_key(s, "NATJ", 1, "\0"); - applesmc_add_key(s, "MSSP", 1, "\0"); - applesmc_add_key(s, "MSSD", 1, "\0x3"); -} - -static const MemoryRegionOps applesmc_data_io_ops = { - .write = applesmc_io_data_write, - .read = applesmc_io_data_read, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static const MemoryRegionOps applesmc_cmd_io_ops = { - .write = applesmc_io_cmd_write, - .read = applesmc_io_cmd_read, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void applesmc_isa_realize(DeviceState *dev, Error **errp) -{ - AppleSMCState *s = APPLE_SMC(dev); - - memory_region_init_io(&s->io_data, OBJECT(s), &applesmc_data_io_ops, s, - "applesmc-data", 4); - isa_register_ioport(&s->parent_obj, &s->io_data, - s->iobase + APPLESMC_DATA_PORT); - - memory_region_init_io(&s->io_cmd, OBJECT(s), &applesmc_cmd_io_ops, s, - "applesmc-cmd", 4); - isa_register_ioport(&s->parent_obj, &s->io_cmd, - s->iobase + APPLESMC_CMD_PORT); - - if (!s->osk || (strlen(s->osk) != 64)) { - fprintf(stderr, "WARNING: Using AppleSMC with invalid key\n"); - s->osk = default_osk; - } - - QLIST_INIT(&s->data_def); - qdev_applesmc_isa_reset(dev); -} - -static Property applesmc_isa_properties[] = { - DEFINE_PROP_UINT32(APPLESMC_PROP_IO_BASE, AppleSMCState, iobase, - APPLESMC_DEFAULT_IOBASE), - DEFINE_PROP_STRING("osk", AppleSMCState, osk), - DEFINE_PROP_END_OF_LIST(), -}; - -static void qdev_applesmc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = applesmc_isa_realize; - dc->reset = qdev_applesmc_isa_reset; - dc->props = applesmc_isa_properties; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); -} - -static const TypeInfo applesmc_isa_info = { - .name = TYPE_APPLE_SMC, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(AppleSMCState), - .class_init = qdev_applesmc_class_init, -}; - -static void applesmc_register_types(void) -{ - type_register_static(&applesmc_isa_info); -} - -type_init(applesmc_register_types) diff --git a/qemu/hw/misc/arm11scu.c b/qemu/hw/misc/arm11scu.c deleted file mode 100644 index 5e54b494b..000000000 --- a/qemu/hw/misc/arm11scu.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * ARM11MPCore Snoop Control Unit (SCU) emulation - * - * Copyright (c) 2006-2007 CodeSourcery. - * Copyright (c) 2013 SUSE LINUX Products GmbH - * Written by Paul Brook and Andreas Färber - * - * This code is licensed under the GPL. - */ - -#include "qemu/osdep.h" -#include "hw/misc/arm11scu.h" - -static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, - unsigned size) -{ - ARM11SCUState *s = (ARM11SCUState *)opaque; - int id; - /* SCU */ - switch (offset) { - case 0x00: /* Control. */ - return s->control; - case 0x04: /* Configuration. */ - id = ((1 << s->num_cpu) - 1) << 4; - return id | (s->num_cpu - 1); - case 0x08: /* CPU status. */ - return 0; - case 0x0c: /* Invalidate all. */ - return 0; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "mpcore_priv_read: Bad offset %x\n", (int)offset); - return 0; - } -} - -static void mpcore_scu_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - ARM11SCUState *s = (ARM11SCUState *)opaque; - /* SCU */ - switch (offset) { - case 0: /* Control register. */ - s->control = value & 1; - break; - case 0x0c: /* Invalidate all. */ - /* This is a no-op as cache is not emulated. */ - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "mpcore_priv_read: Bad offset %x\n", (int)offset); - } -} - -static const MemoryRegionOps mpcore_scu_ops = { - .read = mpcore_scu_read, - .write = mpcore_scu_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void arm11_scu_realize(DeviceState *dev, Error **errp) -{ -} - -static void arm11_scu_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - ARM11SCUState *s = ARM11_SCU(obj); - - memory_region_init_io(&s->iomem, OBJECT(s), - &mpcore_scu_ops, s, "mpcore-scu", 0x100); - sysbus_init_mmio(sbd, &s->iomem); -} - -static Property arm11_scu_properties[] = { - DEFINE_PROP_UINT32("num-cpu", ARM11SCUState, num_cpu, 1), - DEFINE_PROP_END_OF_LIST() -}; - -static void arm11_scu_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - dc->realize = arm11_scu_realize; - dc->props = arm11_scu_properties; -} - -static const TypeInfo arm11_scu_type_info = { - .name = TYPE_ARM11_SCU, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(ARM11SCUState), - .instance_init = arm11_scu_init, - .class_init = arm11_scu_class_init, -}; - -static void arm11_scu_register_types(void) -{ - type_register_static(&arm11_scu_type_info); -} - -type_init(arm11_scu_register_types) diff --git a/qemu/hw/misc/arm_integrator_debug.c b/qemu/hw/misc/arm_integrator_debug.c deleted file mode 100644 index 902605fef..000000000 --- a/qemu/hw/misc/arm_integrator_debug.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * LED, Switch and Debug control registers for ARM Integrator Boards - * - * This is currently a stub for this functionality but at least - * ensures something other than unassigned_mem_read() handles access - * to this area. - * - * The real h/w is described at: - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0159b/Babbfijf.html - * - * Copyright (c) 2013 Alex Bennée <alex@bennee.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "exec/address-spaces.h" -#include "hw/misc/arm_integrator_debug.h" - -#define INTEGRATOR_DEBUG(obj) \ - OBJECT_CHECK(IntegratorDebugState, (obj), TYPE_INTEGRATOR_DEBUG) - -typedef struct { - SysBusDevice parent_obj; - - MemoryRegion iomem; -} IntegratorDebugState; - -static uint64_t intdbg_control_read(void *opaque, hwaddr offset, - unsigned size) -{ - switch (offset >> 2) { - case 0: /* ALPHA */ - case 1: /* LEDS */ - case 2: /* SWITCHES */ - qemu_log_mask(LOG_UNIMP, - "%s: returning zero from %" HWADDR_PRIx ":%u\n", - __func__, offset, size); - return 0; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Bad offset %" HWADDR_PRIx, - __func__, offset); - return 0; - } -} - -static void intdbg_control_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - switch (offset >> 2) { - case 1: /* ALPHA */ - case 2: /* LEDS */ - case 3: /* SWITCHES */ - /* Nothing interesting implemented yet. */ - qemu_log_mask(LOG_UNIMP, - "%s: ignoring write of %" PRIu64 - " to %" HWADDR_PRIx ":%u\n", - __func__, value, offset, size); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: write of %" PRIu64 - " to bad offset %" HWADDR_PRIx "\n", - __func__, value, offset); - } -} - -static const MemoryRegionOps intdbg_control_ops = { - .read = intdbg_control_read, - .write = intdbg_control_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void intdbg_control_init(Object *obj) -{ - SysBusDevice *sd = SYS_BUS_DEVICE(obj); - IntegratorDebugState *s = INTEGRATOR_DEBUG(obj); - - memory_region_init_io(&s->iomem, obj, &intdbg_control_ops, - NULL, "dbg-leds", 0x1000000); - sysbus_init_mmio(sd, &s->iomem); -} - -static const TypeInfo intdbg_info = { - .name = TYPE_INTEGRATOR_DEBUG, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(IntegratorDebugState), - .instance_init = intdbg_control_init, -}; - -static void intdbg_register_types(void) -{ - type_register_static(&intdbg_info); -} - -type_init(intdbg_register_types) diff --git a/qemu/hw/misc/arm_l2x0.c b/qemu/hw/misc/arm_l2x0.c deleted file mode 100644 index 7e179f1a4..000000000 --- a/qemu/hw/misc/arm_l2x0.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * ARM dummy L210, L220, PL310 cache controller. - * - * Copyright (c) 2010-2012 Calxeda - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2 or any later version, as published by the Free Software - * Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" - -/* L2C-310 r3p2 */ -#define CACHE_ID 0x410000c8 - -#define TYPE_ARM_L2X0 "l2x0" -#define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0) - -typedef struct L2x0State { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint32_t cache_type; - uint32_t ctrl; - uint32_t aux_ctrl; - uint32_t data_ctrl; - uint32_t tag_ctrl; - uint32_t filter_start; - uint32_t filter_end; -} L2x0State; - -static const VMStateDescription vmstate_l2x0 = { - .name = "l2x0", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(ctrl, L2x0State), - VMSTATE_UINT32(aux_ctrl, L2x0State), - VMSTATE_UINT32(data_ctrl, L2x0State), - VMSTATE_UINT32(tag_ctrl, L2x0State), - VMSTATE_UINT32(filter_start, L2x0State), - VMSTATE_UINT32(filter_end, L2x0State), - VMSTATE_END_OF_LIST() - } -}; - - -static uint64_t l2x0_priv_read(void *opaque, hwaddr offset, - unsigned size) -{ - uint32_t cache_data; - L2x0State *s = (L2x0State *)opaque; - offset &= 0xfff; - if (offset >= 0x730 && offset < 0x800) { - return 0; /* cache ops complete */ - } - switch (offset) { - case 0: - return CACHE_ID; - case 0x4: - /* aux_ctrl values affect cache_type values */ - cache_data = (s->aux_ctrl & (7 << 17)) >> 15; - cache_data |= (s->aux_ctrl & (1 << 16)) >> 16; - return s->cache_type |= (cache_data << 18) | (cache_data << 6); - case 0x100: - return s->ctrl; - case 0x104: - return s->aux_ctrl; - case 0x108: - return s->tag_ctrl; - case 0x10C: - return s->data_ctrl; - case 0xC00: - return s->filter_start; - case 0xC04: - return s->filter_end; - case 0xF40: - return 0; - case 0xF60: - return 0; - case 0xF80: - return 0; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "l2x0_priv_read: Bad offset %x\n", (int)offset); - break; - } - return 0; -} - -static void l2x0_priv_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - L2x0State *s = (L2x0State *)opaque; - offset &= 0xfff; - if (offset >= 0x730 && offset < 0x800) { - /* ignore */ - return; - } - switch (offset) { - case 0x100: - s->ctrl = value & 1; - break; - case 0x104: - s->aux_ctrl = value; - break; - case 0x108: - s->tag_ctrl = value; - break; - case 0x10C: - s->data_ctrl = value; - break; - case 0xC00: - s->filter_start = value; - break; - case 0xC04: - s->filter_end = value; - break; - case 0xF40: - return; - case 0xF60: - return; - case 0xF80: - return; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "l2x0_priv_write: Bad offset %x\n", (int)offset); - break; - } -} - -static void l2x0_priv_reset(DeviceState *dev) -{ - L2x0State *s = ARM_L2X0(dev); - - s->ctrl = 0; - s->aux_ctrl = 0x02020000; - s->tag_ctrl = 0; - s->data_ctrl = 0; - s->filter_start = 0; - s->filter_end = 0; -} - -static const MemoryRegionOps l2x0_mem_ops = { - .read = l2x0_priv_read, - .write = l2x0_priv_write, - .endianness = DEVICE_NATIVE_ENDIAN, - }; - -static int l2x0_priv_init(SysBusDevice *dev) -{ - L2x0State *s = ARM_L2X0(dev); - - memory_region_init_io(&s->iomem, OBJECT(dev), &l2x0_mem_ops, s, - "l2x0_cc", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - return 0; -} - -static Property l2x0_properties[] = { - DEFINE_PROP_UINT32("cache-type", L2x0State, cache_type, 0x1c100100), - DEFINE_PROP_END_OF_LIST(), -}; - -static void l2x0_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->init = l2x0_priv_init; - dc->vmsd = &vmstate_l2x0; - dc->props = l2x0_properties; - dc->reset = l2x0_priv_reset; -} - -static const TypeInfo l2x0_info = { - .name = TYPE_ARM_L2X0, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(L2x0State), - .class_init = l2x0_class_init, -}; - -static void l2x0_register_types(void) -{ - type_register_static(&l2x0_info); -} - -type_init(l2x0_register_types) diff --git a/qemu/hw/misc/arm_sysctl.c b/qemu/hw/misc/arm_sysctl.c deleted file mode 100644 index 34d90d523..000000000 --- a/qemu/hw/misc/arm_sysctl.c +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Status and system control registers for ARM RealView/Versatile boards. - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GPL. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "qemu/timer.h" -#include "qemu/bitops.h" -#include "hw/sysbus.h" -#include "hw/arm/primecell.h" -#include "sysemu/sysemu.h" - -#define LOCK_VALUE 0xa05f - -#define TYPE_ARM_SYSCTL "realview_sysctl" -#define ARM_SYSCTL(obj) \ - OBJECT_CHECK(arm_sysctl_state, (obj), TYPE_ARM_SYSCTL) - -typedef struct { - SysBusDevice parent_obj; - - MemoryRegion iomem; - qemu_irq pl110_mux_ctrl; - - uint32_t sys_id; - uint32_t leds; - uint16_t lockval; - uint32_t cfgdata1; - uint32_t cfgdata2; - uint32_t flags; - uint32_t nvflags; - uint32_t resetlevel; - uint32_t proc_id; - uint32_t sys_mci; - uint32_t sys_cfgdata; - uint32_t sys_cfgctrl; - uint32_t sys_cfgstat; - uint32_t sys_clcd; - uint32_t mb_clock[6]; - uint32_t *db_clock; - uint32_t db_num_vsensors; - uint32_t *db_voltage; - uint32_t db_num_clocks; - uint32_t *db_clock_reset; -} arm_sysctl_state; - -static const VMStateDescription vmstate_arm_sysctl = { - .name = "realview_sysctl", - .version_id = 4, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(leds, arm_sysctl_state), - VMSTATE_UINT16(lockval, arm_sysctl_state), - VMSTATE_UINT32(cfgdata1, arm_sysctl_state), - VMSTATE_UINT32(cfgdata2, arm_sysctl_state), - VMSTATE_UINT32(flags, arm_sysctl_state), - VMSTATE_UINT32(nvflags, arm_sysctl_state), - VMSTATE_UINT32(resetlevel, arm_sysctl_state), - VMSTATE_UINT32_V(sys_mci, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3), - VMSTATE_UINT32_ARRAY_V(mb_clock, arm_sysctl_state, 6, 4), - VMSTATE_VARRAY_UINT32(db_clock, arm_sysctl_state, db_num_clocks, - 4, vmstate_info_uint32, uint32_t), - VMSTATE_END_OF_LIST() - } -}; - -/* The PB926 actually uses a different format for - * its SYS_ID register. Fortunately the bits which are - * board type on later boards are distinct. - */ -#define BOARD_ID_PB926 0x100 -#define BOARD_ID_EB 0x140 -#define BOARD_ID_PBA8 0x178 -#define BOARD_ID_PBX 0x182 -#define BOARD_ID_VEXPRESS 0x190 - -static int board_id(arm_sysctl_state *s) -{ - /* Extract the board ID field from the SYS_ID register value */ - return (s->sys_id >> 16) & 0xfff; -} - -static void arm_sysctl_reset(DeviceState *d) -{ - arm_sysctl_state *s = ARM_SYSCTL(d); - int i; - - s->leds = 0; - s->lockval = 0; - s->cfgdata1 = 0; - s->cfgdata2 = 0; - s->flags = 0; - s->resetlevel = 0; - /* Motherboard oscillators (in Hz) */ - s->mb_clock[0] = 50000000; /* Static memory clock: 50MHz */ - s->mb_clock[1] = 23750000; /* motherboard CLCD clock: 23.75MHz */ - s->mb_clock[2] = 24000000; /* IO FPGA peripheral clock: 24MHz */ - s->mb_clock[3] = 24000000; /* IO FPGA reserved clock: 24MHz */ - s->mb_clock[4] = 24000000; /* System bus global clock: 24MHz */ - s->mb_clock[5] = 24000000; /* IO FPGA reserved clock: 24MHz */ - /* Daughterboard oscillators: reset from property values */ - for (i = 0; i < s->db_num_clocks; i++) { - s->db_clock[i] = s->db_clock_reset[i]; - } - if (board_id(s) == BOARD_ID_VEXPRESS) { - /* On VExpress this register will RAZ/WI */ - s->sys_clcd = 0; - } else { - /* All others: CLCDID 0x1f, indicating VGA */ - s->sys_clcd = 0x1f00; - } -} - -static uint64_t arm_sysctl_read(void *opaque, hwaddr offset, - unsigned size) -{ - arm_sysctl_state *s = (arm_sysctl_state *)opaque; - - switch (offset) { - case 0x00: /* ID */ - return s->sys_id; - case 0x04: /* SW */ - /* General purpose hardware switches. - We don't have a useful way of exposing these to the user. */ - return 0; - case 0x08: /* LED */ - return s->leds; - case 0x20: /* LOCK */ - return s->lockval; - case 0x0c: /* OSC0 */ - case 0x10: /* OSC1 */ - case 0x14: /* OSC2 */ - case 0x18: /* OSC3 */ - case 0x1c: /* OSC4 */ - case 0x24: /* 100HZ */ - /* ??? Implement these. */ - return 0; - case 0x28: /* CFGDATA1 */ - return s->cfgdata1; - case 0x2c: /* CFGDATA2 */ - return s->cfgdata2; - case 0x30: /* FLAGS */ - return s->flags; - case 0x38: /* NVFLAGS */ - return s->nvflags; - case 0x40: /* RESETCTL */ - if (board_id(s) == BOARD_ID_VEXPRESS) { - /* reserved: RAZ/WI */ - return 0; - } - return s->resetlevel; - case 0x44: /* PCICTL */ - return 1; - case 0x48: /* MCI */ - return s->sys_mci; - case 0x4c: /* FLASH */ - return 0; - case 0x50: /* CLCD */ - return s->sys_clcd; - case 0x54: /* CLCDSER */ - return 0; - case 0x58: /* BOOTCS */ - return 0; - case 0x5c: /* 24MHz */ - return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24000000, - NANOSECONDS_PER_SECOND); - case 0x60: /* MISC */ - return 0; - case 0x84: /* PROCID0 */ - return s->proc_id; - case 0x88: /* PROCID1 */ - return 0xff000000; - case 0x64: /* DMAPSR0 */ - case 0x68: /* DMAPSR1 */ - case 0x6c: /* DMAPSR2 */ - case 0x70: /* IOSEL */ - case 0x74: /* PLDCTL */ - case 0x80: /* BUSID */ - case 0x8c: /* OSCRESET0 */ - case 0x90: /* OSCRESET1 */ - case 0x94: /* OSCRESET2 */ - case 0x98: /* OSCRESET3 */ - case 0x9c: /* OSCRESET4 */ - case 0xc0: /* SYS_TEST_OSC0 */ - case 0xc4: /* SYS_TEST_OSC1 */ - case 0xc8: /* SYS_TEST_OSC2 */ - case 0xcc: /* SYS_TEST_OSC3 */ - case 0xd0: /* SYS_TEST_OSC4 */ - return 0; - case 0xa0: /* SYS_CFGDATA */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - return s->sys_cfgdata; - case 0xa4: /* SYS_CFGCTRL */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - return s->sys_cfgctrl; - case 0xa8: /* SYS_CFGSTAT */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - return s->sys_cfgstat; - default: - bad_reg: - qemu_log_mask(LOG_GUEST_ERROR, - "arm_sysctl_read: Bad register offset 0x%x\n", - (int)offset); - return 0; - } -} - -/* SYS_CFGCTRL functions */ -#define SYS_CFG_OSC 1 -#define SYS_CFG_VOLT 2 -#define SYS_CFG_AMP 3 -#define SYS_CFG_TEMP 4 -#define SYS_CFG_RESET 5 -#define SYS_CFG_SCC 6 -#define SYS_CFG_MUXFPGA 7 -#define SYS_CFG_SHUTDOWN 8 -#define SYS_CFG_REBOOT 9 -#define SYS_CFG_DVIMODE 11 -#define SYS_CFG_POWER 12 -#define SYS_CFG_ENERGY 13 - -/* SYS_CFGCTRL site field values */ -#define SYS_CFG_SITE_MB 0 -#define SYS_CFG_SITE_DB1 1 -#define SYS_CFG_SITE_DB2 2 - -/** - * vexpress_cfgctrl_read: - * @s: arm_sysctl_state pointer - * @dcc, @function, @site, @position, @device: split out values from - * SYS_CFGCTRL register - * @val: pointer to where to put the read data on success - * - * Handle a VExpress SYS_CFGCTRL register read. On success, return true and - * write the read value to *val. On failure, return false (and val may - * or may not be written to). - */ -static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc, - unsigned int function, unsigned int site, - unsigned int position, unsigned int device, - uint32_t *val) -{ - /* We don't support anything other than DCC 0, board stack position 0 - * or sites other than motherboard/daughterboard: - */ - if (dcc != 0 || position != 0 || - (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) { - goto cfgctrl_unimp; - } - - switch (function) { - case SYS_CFG_VOLT: - if (site == SYS_CFG_SITE_DB1 && device < s->db_num_vsensors) { - *val = s->db_voltage[device]; - return true; - } - if (site == SYS_CFG_SITE_MB && device == 0) { - /* There is only one motherboard voltage sensor: - * VIO : 3.3V : bus voltage between mother and daughterboard - */ - *val = 3300000; - return true; - } - break; - case SYS_CFG_OSC: - if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) { - /* motherboard clock */ - *val = s->mb_clock[device]; - return true; - } - if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) { - /* daughterboard clock */ - *val = s->db_clock[device]; - return true; - } - break; - default: - break; - } - -cfgctrl_unimp: - qemu_log_mask(LOG_UNIMP, - "arm_sysctl: Unimplemented SYS_CFGCTRL read of function " - "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n", - function, dcc, site, position, device); - return false; -} - -/** - * vexpress_cfgctrl_write: - * @s: arm_sysctl_state pointer - * @dcc, @function, @site, @position, @device: split out values from - * SYS_CFGCTRL register - * @val: data to write - * - * Handle a VExpress SYS_CFGCTRL register write. On success, return true. - * On failure, return false. - */ -static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc, - unsigned int function, unsigned int site, - unsigned int position, unsigned int device, - uint32_t val) -{ - /* We don't support anything other than DCC 0, board stack position 0 - * or sites other than motherboard/daughterboard: - */ - if (dcc != 0 || position != 0 || - (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) { - goto cfgctrl_unimp; - } - - switch (function) { - case SYS_CFG_OSC: - if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) { - /* motherboard clock */ - s->mb_clock[device] = val; - return true; - } - if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) { - /* daughterboard clock */ - s->db_clock[device] = val; - return true; - } - break; - case SYS_CFG_MUXFPGA: - if (site == SYS_CFG_SITE_MB && device == 0) { - /* Select whether video output comes from motherboard - * or daughterboard: log and ignore as QEMU doesn't - * support this. - */ - qemu_log_mask(LOG_UNIMP, "arm_sysctl: selection of video output " - "not supported, ignoring\n"); - return true; - } - break; - case SYS_CFG_SHUTDOWN: - if (site == SYS_CFG_SITE_MB && device == 0) { - qemu_system_shutdown_request(); - return true; - } - break; - case SYS_CFG_REBOOT: - if (site == SYS_CFG_SITE_MB && device == 0) { - qemu_system_reset_request(); - return true; - } - break; - case SYS_CFG_DVIMODE: - if (site == SYS_CFG_SITE_MB && device == 0) { - /* Selecting DVI mode is meaningless for QEMU: we will - * always display the output correctly according to the - * pixel height/width programmed into the CLCD controller. - */ - return true; - } - default: - break; - } - -cfgctrl_unimp: - qemu_log_mask(LOG_UNIMP, - "arm_sysctl: Unimplemented SYS_CFGCTRL write of function " - "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n", - function, dcc, site, position, device); - return false; -} - -static void arm_sysctl_write(void *opaque, hwaddr offset, - uint64_t val, unsigned size) -{ - arm_sysctl_state *s = (arm_sysctl_state *)opaque; - - switch (offset) { - case 0x08: /* LED */ - s->leds = val; - break; - case 0x0c: /* OSC0 */ - case 0x10: /* OSC1 */ - case 0x14: /* OSC2 */ - case 0x18: /* OSC3 */ - case 0x1c: /* OSC4 */ - /* ??? */ - break; - case 0x20: /* LOCK */ - if (val == LOCK_VALUE) - s->lockval = val; - else - s->lockval = val & 0x7fff; - break; - case 0x28: /* CFGDATA1 */ - /* ??? Need to implement this. */ - s->cfgdata1 = val; - break; - case 0x2c: /* CFGDATA2 */ - /* ??? Need to implement this. */ - s->cfgdata2 = val; - break; - case 0x30: /* FLAGSSET */ - s->flags |= val; - break; - case 0x34: /* FLAGSCLR */ - s->flags &= ~val; - break; - case 0x38: /* NVFLAGSSET */ - s->nvflags |= val; - break; - case 0x3c: /* NVFLAGSCLR */ - s->nvflags &= ~val; - break; - case 0x40: /* RESETCTL */ - switch (board_id(s)) { - case BOARD_ID_PB926: - if (s->lockval == LOCK_VALUE) { - s->resetlevel = val; - if (val & 0x100) { - qemu_system_reset_request(); - } - } - break; - case BOARD_ID_PBX: - case BOARD_ID_PBA8: - if (s->lockval == LOCK_VALUE) { - s->resetlevel = val; - if (val & 0x04) { - qemu_system_reset_request(); - } - } - break; - case BOARD_ID_VEXPRESS: - case BOARD_ID_EB: - default: - /* reserved: RAZ/WI */ - break; - } - break; - case 0x44: /* PCICTL */ - /* nothing to do. */ - break; - case 0x4c: /* FLASH */ - break; - case 0x50: /* CLCD */ - switch (board_id(s)) { - case BOARD_ID_PB926: - /* On 926 bits 13:8 are R/O, bits 1:0 control - * the mux that defines how to interpret the PL110 - * graphics format, and other bits are r/w but we - * don't implement them to do anything. - */ - s->sys_clcd &= 0x3f00; - s->sys_clcd |= val & ~0x3f00; - qemu_set_irq(s->pl110_mux_ctrl, val & 3); - break; - case BOARD_ID_EB: - /* The EB is the same except that there is no mux since - * the EB has a PL111. - */ - s->sys_clcd &= 0x3f00; - s->sys_clcd |= val & ~0x3f00; - break; - case BOARD_ID_PBA8: - case BOARD_ID_PBX: - /* On PBA8 and PBX bit 7 is r/w and all other bits - * are either r/o or RAZ/WI. - */ - s->sys_clcd &= (1 << 7); - s->sys_clcd |= val & ~(1 << 7); - break; - case BOARD_ID_VEXPRESS: - default: - /* On VExpress this register is unimplemented and will RAZ/WI */ - break; - } - break; - case 0x54: /* CLCDSER */ - case 0x64: /* DMAPSR0 */ - case 0x68: /* DMAPSR1 */ - case 0x6c: /* DMAPSR2 */ - case 0x70: /* IOSEL */ - case 0x74: /* PLDCTL */ - case 0x80: /* BUSID */ - case 0x84: /* PROCID0 */ - case 0x88: /* PROCID1 */ - case 0x8c: /* OSCRESET0 */ - case 0x90: /* OSCRESET1 */ - case 0x94: /* OSCRESET2 */ - case 0x98: /* OSCRESET3 */ - case 0x9c: /* OSCRESET4 */ - break; - case 0xa0: /* SYS_CFGDATA */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - s->sys_cfgdata = val; - return; - case 0xa4: /* SYS_CFGCTRL */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - /* Undefined bits [19:18] are RAZ/WI, and writing to - * the start bit just triggers the action; it always reads - * as zero. - */ - s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31)); - if (val & (1 << 31)) { - /* Start bit set -- actually do something */ - unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4); - unsigned int function = extract32(s->sys_cfgctrl, 20, 6); - unsigned int site = extract32(s->sys_cfgctrl, 16, 2); - unsigned int position = extract32(s->sys_cfgctrl, 12, 4); - unsigned int device = extract32(s->sys_cfgctrl, 0, 12); - s->sys_cfgstat = 1; /* complete */ - if (s->sys_cfgctrl & (1 << 30)) { - if (!vexpress_cfgctrl_write(s, dcc, function, site, position, - device, s->sys_cfgdata)) { - s->sys_cfgstat |= 2; /* error */ - } - } else { - uint32_t val; - if (!vexpress_cfgctrl_read(s, dcc, function, site, position, - device, &val)) { - s->sys_cfgstat |= 2; /* error */ - } else { - s->sys_cfgdata = val; - } - } - } - s->sys_cfgctrl &= ~(1 << 31); - return; - case 0xa8: /* SYS_CFGSTAT */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - s->sys_cfgstat = val & 3; - return; - default: - bad_reg: - qemu_log_mask(LOG_GUEST_ERROR, - "arm_sysctl_write: Bad register offset 0x%x\n", - (int)offset); - return; - } -} - -static const MemoryRegionOps arm_sysctl_ops = { - .read = arm_sysctl_read, - .write = arm_sysctl_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void arm_sysctl_gpio_set(void *opaque, int line, int level) -{ - arm_sysctl_state *s = (arm_sysctl_state *)opaque; - switch (line) { - case ARM_SYSCTL_GPIO_MMC_WPROT: - { - /* For PB926 and EB write-protect is bit 2 of SYS_MCI; - * for all later boards it is bit 1. - */ - int bit = 2; - if ((board_id(s) == BOARD_ID_PB926) || (board_id(s) == BOARD_ID_EB)) { - bit = 4; - } - s->sys_mci &= ~bit; - if (level) { - s->sys_mci |= bit; - } - break; - } - case ARM_SYSCTL_GPIO_MMC_CARDIN: - s->sys_mci &= ~1; - if (level) { - s->sys_mci |= 1; - } - break; - } -} - -static void arm_sysctl_init(Object *obj) -{ - DeviceState *dev = DEVICE(obj); - SysBusDevice *sd = SYS_BUS_DEVICE(obj); - arm_sysctl_state *s = ARM_SYSCTL(obj); - - memory_region_init_io(&s->iomem, OBJECT(dev), &arm_sysctl_ops, s, - "arm-sysctl", 0x1000); - sysbus_init_mmio(sd, &s->iomem); - qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2); - qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1); -} - -static void arm_sysctl_realize(DeviceState *d, Error **errp) -{ - arm_sysctl_state *s = ARM_SYSCTL(d); - - s->db_clock = g_new0(uint32_t, s->db_num_clocks); -} - -static void arm_sysctl_finalize(Object *obj) -{ - arm_sysctl_state *s = ARM_SYSCTL(obj); - - g_free(s->db_voltage); - g_free(s->db_clock); - g_free(s->db_clock_reset); -} - -static Property arm_sysctl_properties[] = { - DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0), - DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0), - /* Daughterboard power supply voltages (as reported via SYS_CFG) */ - DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors, - db_voltage, qdev_prop_uint32, uint32_t), - /* Daughterboard clock reset values (as reported via SYS_CFG) */ - DEFINE_PROP_ARRAY("db-clock", arm_sysctl_state, db_num_clocks, - db_clock_reset, qdev_prop_uint32, uint32_t), - DEFINE_PROP_END_OF_LIST(), -}; - -static void arm_sysctl_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = arm_sysctl_realize; - dc->reset = arm_sysctl_reset; - dc->vmsd = &vmstate_arm_sysctl; - dc->props = arm_sysctl_properties; -} - -static const TypeInfo arm_sysctl_info = { - .name = TYPE_ARM_SYSCTL, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(arm_sysctl_state), - .instance_init = arm_sysctl_init, - .instance_finalize = arm_sysctl_finalize, - .class_init = arm_sysctl_class_init, -}; - -static void arm_sysctl_register_types(void) -{ - type_register_static(&arm_sysctl_info); -} - -type_init(arm_sysctl_register_types) diff --git a/qemu/hw/misc/bcm2835_mbox.c b/qemu/hw/misc/bcm2835_mbox.c deleted file mode 100644 index 263280fd4..000000000 --- a/qemu/hw/misc/bcm2835_mbox.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Raspberry Pi emulation (c) 2012 Gregory Estrade - * This code is licensed under the GNU GPLv2 and later. - * - * This file models the system mailboxes, which are used for - * communication with low-bandwidth GPU peripherals. Refs: - * https://github.com/raspberrypi/firmware/wiki/Mailboxes - * https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/misc/bcm2835_mbox.h" - -#define MAIL0_PEEK 0x90 -#define MAIL0_SENDER 0x94 -#define MAIL1_STATUS 0xb8 - -/* Mailbox status register */ -#define MAIL0_STATUS 0x98 -#define ARM_MS_FULL 0x80000000 -#define ARM_MS_EMPTY 0x40000000 -#define ARM_MS_LEVEL 0x400000FF /* Max. value depends on mailbox depth */ - -/* MAILBOX config/status register */ -#define MAIL0_CONFIG 0x9c -/* ANY write to this register clears the error bits! */ -#define ARM_MC_IHAVEDATAIRQEN 0x00000001 /* mbox irq enable: has data */ -#define ARM_MC_IHAVESPACEIRQEN 0x00000002 /* mbox irq enable: has space */ -#define ARM_MC_OPPISEMPTYIRQEN 0x00000004 /* mbox irq enable: Opp is empty */ -#define ARM_MC_MAIL_CLEAR 0x00000008 /* mbox clear write 1, then 0 */ -#define ARM_MC_IHAVEDATAIRQPEND 0x00000010 /* mbox irq pending: has space */ -#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mbox irq pending: Opp is empty */ -#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mbox irq pending */ -/* Bit 7 is unused */ -#define ARM_MC_ERRNOOWN 0x00000100 /* error : none owner read from mailbox */ -#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */ -#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */ - -static void mbox_update_status(BCM2835Mbox *mb) -{ - mb->status &= ~(ARM_MS_EMPTY | ARM_MS_FULL); - if (mb->count == 0) { - mb->status |= ARM_MS_EMPTY; - } else if (mb->count == MBOX_SIZE) { - mb->status |= ARM_MS_FULL; - } -} - -static void mbox_reset(BCM2835Mbox *mb) -{ - int n; - - mb->count = 0; - mb->config = 0; - for (n = 0; n < MBOX_SIZE; n++) { - mb->reg[n] = MBOX_INVALID_DATA; - } - mbox_update_status(mb); -} - -static uint32_t mbox_pull(BCM2835Mbox *mb, int index) -{ - int n; - uint32_t val; - - assert(mb->count > 0); - assert(index < mb->count); - - val = mb->reg[index]; - for (n = index + 1; n < mb->count; n++) { - mb->reg[n - 1] = mb->reg[n]; - } - mb->count--; - mb->reg[mb->count] = MBOX_INVALID_DATA; - - mbox_update_status(mb); - - return val; -} - -static void mbox_push(BCM2835Mbox *mb, uint32_t val) -{ - assert(mb->count < MBOX_SIZE); - mb->reg[mb->count++] = val; - mbox_update_status(mb); -} - -static void bcm2835_mbox_update(BCM2835MboxState *s) -{ - uint32_t value; - bool set; - int n; - - s->mbox_irq_disabled = true; - - /* Get pending responses and put them in the vc->arm mbox, - * as long as it's not full - */ - for (n = 0; n < MBOX_CHAN_COUNT; n++) { - while (s->available[n] && !(s->mbox[0].status & ARM_MS_FULL)) { - value = ldl_le_phys(&s->mbox_as, n << MBOX_AS_CHAN_SHIFT); - assert(value != MBOX_INVALID_DATA); /* Pending interrupt but no data */ - mbox_push(&s->mbox[0], value); - } - } - - /* TODO (?): Try to push pending requests from the arm->vc mbox */ - - /* Re-enable calls from the IRQ routine */ - s->mbox_irq_disabled = false; - - /* Update ARM IRQ status */ - set = false; - s->mbox[0].config &= ~ARM_MC_IHAVEDATAIRQPEND; - if (!(s->mbox[0].status & ARM_MS_EMPTY)) { - s->mbox[0].config |= ARM_MC_IHAVEDATAIRQPEND; - if (s->mbox[0].config & ARM_MC_IHAVEDATAIRQEN) { - set = true; - } - } - qemu_set_irq(s->arm_irq, set); -} - -static void bcm2835_mbox_set_irq(void *opaque, int irq, int level) -{ - BCM2835MboxState *s = opaque; - - s->available[irq] = level; - - /* avoid recursively calling bcm2835_mbox_update when the interrupt - * status changes due to the ldl_phys call within that function - */ - if (!s->mbox_irq_disabled) { - bcm2835_mbox_update(s); - } -} - -static uint64_t bcm2835_mbox_read(void *opaque, hwaddr offset, unsigned size) -{ - BCM2835MboxState *s = opaque; - uint32_t res = 0; - - offset &= 0xff; - - switch (offset) { - case 0x80 ... 0x8c: /* MAIL0_READ */ - if (s->mbox[0].status & ARM_MS_EMPTY) { - res = MBOX_INVALID_DATA; - } else { - res = mbox_pull(&s->mbox[0], 0); - } - break; - - case MAIL0_PEEK: - res = s->mbox[0].reg[0]; - break; - - case MAIL0_SENDER: - break; - - case MAIL0_STATUS: - res = s->mbox[0].status; - break; - - case MAIL0_CONFIG: - res = s->mbox[0].config; - break; - - case MAIL1_STATUS: - res = s->mbox[1].status; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); - return 0; - } - - bcm2835_mbox_update(s); - - return res; -} - -static void bcm2835_mbox_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - BCM2835MboxState *s = opaque; - hwaddr childaddr; - uint8_t ch; - - offset &= 0xff; - - switch (offset) { - case MAIL0_SENDER: - break; - - case MAIL0_CONFIG: - s->mbox[0].config &= ~ARM_MC_IHAVEDATAIRQEN; - s->mbox[0].config |= value & ARM_MC_IHAVEDATAIRQEN; - break; - - case 0xa0 ... 0xac: /* MAIL1_WRITE */ - if (s->mbox[1].status & ARM_MS_FULL) { - /* Mailbox full */ - qemu_log_mask(LOG_GUEST_ERROR, "%s: mailbox full\n", __func__); - } else { - ch = value & 0xf; - if (ch < MBOX_CHAN_COUNT) { - childaddr = ch << MBOX_AS_CHAN_SHIFT; - if (ldl_le_phys(&s->mbox_as, childaddr + MBOX_AS_PENDING)) { - /* Child busy, push delayed. Push it in the arm->vc mbox */ - mbox_push(&s->mbox[1], value); - } else { - /* Push it directly to the child device */ - stl_le_phys(&s->mbox_as, childaddr, value); - } - } else { - /* Invalid channel number */ - qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid channel %u\n", - __func__, ch); - } - } - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); - return; - } - - bcm2835_mbox_update(s); -} - -static const MemoryRegionOps bcm2835_mbox_ops = { - .read = bcm2835_mbox_read, - .write = bcm2835_mbox_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid.min_access_size = 4, - .valid.max_access_size = 4, -}; - -/* vmstate of a single mailbox */ -static const VMStateDescription vmstate_bcm2835_mbox_box = { - .name = TYPE_BCM2835_MBOX "_box", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(reg, BCM2835Mbox, MBOX_SIZE), - VMSTATE_UINT32(count, BCM2835Mbox), - VMSTATE_UINT32(status, BCM2835Mbox), - VMSTATE_UINT32(config, BCM2835Mbox), - VMSTATE_END_OF_LIST() - } -}; - -/* vmstate of the entire device */ -static const VMStateDescription vmstate_bcm2835_mbox = { - .name = TYPE_BCM2835_MBOX, - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_BOOL_ARRAY(available, BCM2835MboxState, MBOX_CHAN_COUNT), - VMSTATE_STRUCT_ARRAY(mbox, BCM2835MboxState, 2, 1, - vmstate_bcm2835_mbox_box, BCM2835Mbox), - VMSTATE_END_OF_LIST() - } -}; - -static void bcm2835_mbox_init(Object *obj) -{ - BCM2835MboxState *s = BCM2835_MBOX(obj); - - memory_region_init_io(&s->iomem, obj, &bcm2835_mbox_ops, s, - TYPE_BCM2835_MBOX, 0x400); - sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); - sysbus_init_irq(SYS_BUS_DEVICE(s), &s->arm_irq); - qdev_init_gpio_in(DEVICE(s), bcm2835_mbox_set_irq, MBOX_CHAN_COUNT); -} - -static void bcm2835_mbox_reset(DeviceState *dev) -{ - BCM2835MboxState *s = BCM2835_MBOX(dev); - int n; - - mbox_reset(&s->mbox[0]); - mbox_reset(&s->mbox[1]); - s->mbox_irq_disabled = false; - for (n = 0; n < MBOX_CHAN_COUNT; n++) { - s->available[n] = false; - } -} - -static void bcm2835_mbox_realize(DeviceState *dev, Error **errp) -{ - BCM2835MboxState *s = BCM2835_MBOX(dev); - Object *obj; - Error *err = NULL; - - obj = object_property_get_link(OBJECT(dev), "mbox-mr", &err); - if (obj == NULL) { - error_setg(errp, "%s: required mbox-mr link not found: %s", - __func__, error_get_pretty(err)); - return; - } - - s->mbox_mr = MEMORY_REGION(obj); - address_space_init(&s->mbox_as, s->mbox_mr, NULL); - bcm2835_mbox_reset(dev); -} - -static void bcm2835_mbox_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = bcm2835_mbox_realize; - dc->reset = bcm2835_mbox_reset; - dc->vmsd = &vmstate_bcm2835_mbox; -} - -static TypeInfo bcm2835_mbox_info = { - .name = TYPE_BCM2835_MBOX, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(BCM2835MboxState), - .class_init = bcm2835_mbox_class_init, - .instance_init = bcm2835_mbox_init, -}; - -static void bcm2835_mbox_register_types(void) -{ - type_register_static(&bcm2835_mbox_info); -} - -type_init(bcm2835_mbox_register_types) diff --git a/qemu/hw/misc/bcm2835_property.c b/qemu/hw/misc/bcm2835_property.c deleted file mode 100644 index 530411f84..000000000 --- a/qemu/hw/misc/bcm2835_property.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Raspberry Pi emulation (c) 2012 Gregory Estrade - * This code is licensed under the GNU GPLv2 and later. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/misc/bcm2835_property.h" -#include "hw/misc/bcm2835_mbox_defs.h" -#include "sysemu/dma.h" - -/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */ - -static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) -{ - uint32_t tag; - uint32_t bufsize; - uint32_t tot_len; - size_t resplen; - uint32_t tmp; - int n; - uint32_t offset, length, color; - uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha; - uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL, - *newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL; - - value &= ~0xf; - - s->addr = value; - - tot_len = ldl_le_phys(&s->dma_as, value); - - /* @(addr + 4) : Buffer response code */ - value = s->addr + 8; - while (value + 8 <= s->addr + tot_len) { - tag = ldl_le_phys(&s->dma_as, value); - bufsize = ldl_le_phys(&s->dma_as, value + 4); - /* @(value + 8) : Request/response indicator */ - resplen = 0; - switch (tag) { - case 0x00000000: /* End tag */ - break; - case 0x00000001: /* Get firmware revision */ - stl_le_phys(&s->dma_as, value + 12, 346337); - resplen = 4; - break; - case 0x00010001: /* Get board model */ - qemu_log_mask(LOG_UNIMP, - "bcm2835_property: %x get board model NYI\n", tag); - resplen = 4; - break; - case 0x00010002: /* Get board revision */ - stl_le_phys(&s->dma_as, value + 12, s->board_rev); - resplen = 4; - break; - case 0x00010003: /* Get board MAC address */ - resplen = sizeof(s->macaddr.a); - dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen); - break; - case 0x00010004: /* Get board serial */ - qemu_log_mask(LOG_UNIMP, - "bcm2835_property: %x get board serial NYI\n", tag); - resplen = 8; - break; - case 0x00010005: /* Get ARM memory */ - /* base */ - stl_le_phys(&s->dma_as, value + 12, 0); - /* size */ - stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base); - resplen = 8; - break; - case 0x00010006: /* Get VC memory */ - /* base */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base); - /* size */ - stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size); - resplen = 8; - break; - case 0x00028001: /* Set power state */ - /* Assume that whatever device they asked for exists, - * and we'll just claim we set it to the desired state - */ - tmp = ldl_le_phys(&s->dma_as, value + 16); - stl_le_phys(&s->dma_as, value + 16, (tmp & 1)); - resplen = 8; - break; - - /* Clocks */ - - case 0x00030001: /* Get clock state */ - stl_le_phys(&s->dma_as, value + 16, 0x1); - resplen = 8; - break; - - case 0x00038001: /* Set clock state */ - qemu_log_mask(LOG_UNIMP, - "bcm2835_property: %x set clock state NYI\n", tag); - resplen = 8; - break; - - case 0x00030002: /* Get clock rate */ - case 0x00030004: /* Get max clock rate */ - case 0x00030007: /* Get min clock rate */ - switch (ldl_le_phys(&s->dma_as, value + 12)) { - case 1: /* EMMC */ - stl_le_phys(&s->dma_as, value + 16, 50000000); - break; - case 2: /* UART */ - stl_le_phys(&s->dma_as, value + 16, 3000000); - break; - default: - stl_le_phys(&s->dma_as, value + 16, 700000000); - break; - } - resplen = 8; - break; - - case 0x00038002: /* Set clock rate */ - case 0x00038004: /* Set max clock rate */ - case 0x00038007: /* Set min clock rate */ - qemu_log_mask(LOG_UNIMP, - "bcm2835_property: %x set clock rates NYI\n", tag); - resplen = 8; - break; - - /* Temperature */ - - case 0x00030006: /* Get temperature */ - stl_le_phys(&s->dma_as, value + 16, 25000); - resplen = 8; - break; - - case 0x0003000A: /* Get max temperature */ - stl_le_phys(&s->dma_as, value + 16, 99000); - resplen = 8; - break; - - /* Frame buffer */ - - case 0x00040001: /* Allocate buffer */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->base); - stl_le_phys(&s->dma_as, value + 16, s->fbdev->size); - resplen = 8; - break; - case 0x00048001: /* Release buffer */ - resplen = 0; - break; - case 0x00040002: /* Blank screen */ - resplen = 4; - break; - case 0x00040003: /* Get display width/height */ - case 0x00040004: - stl_le_phys(&s->dma_as, value + 12, s->fbdev->xres); - stl_le_phys(&s->dma_as, value + 16, s->fbdev->yres); - resplen = 8; - break; - case 0x00044003: /* Test display width/height */ - case 0x00044004: - resplen = 8; - break; - case 0x00048003: /* Set display width/height */ - case 0x00048004: - xres = ldl_le_phys(&s->dma_as, value + 12); - newxres = &xres; - yres = ldl_le_phys(&s->dma_as, value + 16); - newyres = &yres; - resplen = 8; - break; - case 0x00040005: /* Get depth */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->bpp); - resplen = 4; - break; - case 0x00044005: /* Test depth */ - resplen = 4; - break; - case 0x00048005: /* Set depth */ - bpp = ldl_le_phys(&s->dma_as, value + 12); - newbpp = &bpp; - resplen = 4; - break; - case 0x00040006: /* Get pixel order */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->pixo); - resplen = 4; - break; - case 0x00044006: /* Test pixel order */ - resplen = 4; - break; - case 0x00048006: /* Set pixel order */ - pixo = ldl_le_phys(&s->dma_as, value + 12); - newpixo = &pixo; - resplen = 4; - break; - case 0x00040007: /* Get alpha */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->alpha); - resplen = 4; - break; - case 0x00044007: /* Test pixel alpha */ - resplen = 4; - break; - case 0x00048007: /* Set alpha */ - alpha = ldl_le_phys(&s->dma_as, value + 12); - newalpha = α - resplen = 4; - break; - case 0x00040008: /* Get pitch */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->pitch); - resplen = 4; - break; - case 0x00040009: /* Get virtual offset */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->xoffset); - stl_le_phys(&s->dma_as, value + 16, s->fbdev->yoffset); - resplen = 8; - break; - case 0x00044009: /* Test virtual offset */ - resplen = 8; - break; - case 0x00048009: /* Set virtual offset */ - xoffset = ldl_le_phys(&s->dma_as, value + 12); - newxoffset = &xoffset; - yoffset = ldl_le_phys(&s->dma_as, value + 16); - newyoffset = &yoffset; - resplen = 8; - break; - case 0x0004000a: /* Get/Test/Set overscan */ - case 0x0004400a: - case 0x0004800a: - stl_le_phys(&s->dma_as, value + 12, 0); - stl_le_phys(&s->dma_as, value + 16, 0); - stl_le_phys(&s->dma_as, value + 20, 0); - stl_le_phys(&s->dma_as, value + 24, 0); - resplen = 16; - break; - case 0x0004800b: /* Set palette */ - offset = ldl_le_phys(&s->dma_as, value + 12); - length = ldl_le_phys(&s->dma_as, value + 16); - n = 0; - while (n < length - offset) { - color = ldl_le_phys(&s->dma_as, value + 20 + (n << 2)); - stl_le_phys(&s->dma_as, - s->fbdev->vcram_base + ((offset + n) << 2), color); - n++; - } - stl_le_phys(&s->dma_as, value + 12, 0); - resplen = 4; - break; - - case 0x00060001: /* Get DMA channels */ - /* channels 2-5 */ - stl_le_phys(&s->dma_as, value + 12, 0x003C); - resplen = 4; - break; - - case 0x00050001: /* Get command line */ - resplen = 0; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, - "bcm2835_property: unhandled tag %08x\n", tag); - break; - } - - if (tag == 0) { - break; - } - - stl_le_phys(&s->dma_as, value + 8, (1 << 31) | resplen); - value += bufsize + 12; - } - - /* Reconfigure framebuffer if required */ - if (newxres || newyres || newxoffset || newyoffset || newbpp || newpixo - || newalpha) { - bcm2835_fb_reconfigure(s->fbdev, newxres, newyres, newxoffset, - newyoffset, newbpp, newpixo, newalpha); - } - - /* Buffer response code */ - stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31)); -} - -static uint64_t bcm2835_property_read(void *opaque, hwaddr offset, - unsigned size) -{ - BCM2835PropertyState *s = opaque; - uint32_t res = 0; - - switch (offset) { - case MBOX_AS_DATA: - res = MBOX_CHAN_PROPERTY | s->addr; - s->pending = false; - qemu_set_irq(s->mbox_irq, 0); - break; - - case MBOX_AS_PENDING: - res = s->pending; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); - return 0; - } - - return res; -} - -static void bcm2835_property_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - BCM2835PropertyState *s = opaque; - - switch (offset) { - case MBOX_AS_DATA: - /* bcm2835_mbox should check our pending status before pushing */ - assert(!s->pending); - s->pending = true; - bcm2835_property_mbox_push(s, value); - qemu_set_irq(s->mbox_irq, 1); - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); - return; - } -} - -static const MemoryRegionOps bcm2835_property_ops = { - .read = bcm2835_property_read, - .write = bcm2835_property_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid.min_access_size = 4, - .valid.max_access_size = 4, -}; - -static const VMStateDescription vmstate_bcm2835_property = { - .name = TYPE_BCM2835_PROPERTY, - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_MACADDR(macaddr, BCM2835PropertyState), - VMSTATE_UINT32(addr, BCM2835PropertyState), - VMSTATE_BOOL(pending, BCM2835PropertyState), - VMSTATE_END_OF_LIST() - } -}; - -static void bcm2835_property_init(Object *obj) -{ - BCM2835PropertyState *s = BCM2835_PROPERTY(obj); - - memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_property_ops, s, - TYPE_BCM2835_PROPERTY, 0x10); - sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); - sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq); -} - -static void bcm2835_property_reset(DeviceState *dev) -{ - BCM2835PropertyState *s = BCM2835_PROPERTY(dev); - - s->pending = false; -} - -static void bcm2835_property_realize(DeviceState *dev, Error **errp) -{ - BCM2835PropertyState *s = BCM2835_PROPERTY(dev); - Object *obj; - Error *err = NULL; - - obj = object_property_get_link(OBJECT(dev), "fb", &err); - if (obj == NULL) { - error_setg(errp, "%s: required fb link not found: %s", - __func__, error_get_pretty(err)); - return; - } - - s->fbdev = BCM2835_FB(obj); - - obj = object_property_get_link(OBJECT(dev), "dma-mr", &err); - if (obj == NULL) { - error_setg(errp, "%s: required dma-mr link not found: %s", - __func__, error_get_pretty(err)); - return; - } - - s->dma_mr = MEMORY_REGION(obj); - address_space_init(&s->dma_as, s->dma_mr, NULL); - - /* TODO: connect to MAC address of USB NIC device, once we emulate it */ - qemu_macaddr_default_if_unset(&s->macaddr); - - bcm2835_property_reset(dev); -} - -static Property bcm2835_property_props[] = { - DEFINE_PROP_UINT32("board-rev", BCM2835PropertyState, board_rev, 0), - DEFINE_PROP_END_OF_LIST() -}; - -static void bcm2835_property_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->props = bcm2835_property_props; - dc->realize = bcm2835_property_realize; - dc->vmsd = &vmstate_bcm2835_property; -} - -static TypeInfo bcm2835_property_info = { - .name = TYPE_BCM2835_PROPERTY, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(BCM2835PropertyState), - .class_init = bcm2835_property_class_init, - .instance_init = bcm2835_property_init, -}; - -static void bcm2835_property_register_types(void) -{ - type_register_static(&bcm2835_property_info); -} - -type_init(bcm2835_property_register_types) diff --git a/qemu/hw/misc/cbus.c b/qemu/hw/misc/cbus.c deleted file mode 100644 index 0c207e310..000000000 --- a/qemu/hw/misc/cbus.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma / - * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms. - * Based on reverse-engineering of a linux driver. - * - * Copyright (C) 2008 Nokia Corporation - * Written by Andrzej Zaborowski <andrew@openedhand.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/irq.h" -#include "hw/devices.h" -#include "sysemu/sysemu.h" - -//#define DEBUG - -typedef struct { - void *opaque; - void (*io)(void *opaque, int rw, int reg, uint16_t *val); - int addr; -} CBusSlave; - -typedef struct { - CBus cbus; - - int sel; - int dat; - int clk; - int bit; - int dir; - uint16_t val; - qemu_irq dat_out; - - int addr; - int reg; - int rw; - enum { - cbus_address, - cbus_value, - } cycle; - - CBusSlave *slave[8]; -} CBusPriv; - -static void cbus_io(CBusPriv *s) -{ - if (s->slave[s->addr]) - s->slave[s->addr]->io(s->slave[s->addr]->opaque, - s->rw, s->reg, &s->val); - else - hw_error("%s: bad slave address %i\n", __FUNCTION__, s->addr); -} - -static void cbus_cycle(CBusPriv *s) -{ - switch (s->cycle) { - case cbus_address: - s->addr = (s->val >> 6) & 7; - s->rw = (s->val >> 5) & 1; - s->reg = (s->val >> 0) & 0x1f; - - s->cycle = cbus_value; - s->bit = 15; - s->dir = !s->rw; - s->val = 0; - - if (s->rw) - cbus_io(s); - break; - - case cbus_value: - if (!s->rw) - cbus_io(s); - - s->cycle = cbus_address; - s->bit = 8; - s->dir = 1; - s->val = 0; - break; - } -} - -static void cbus_clk(void *opaque, int line, int level) -{ - CBusPriv *s = (CBusPriv *) opaque; - - if (!s->sel && level && !s->clk) { - if (s->dir) - s->val |= s->dat << (s->bit --); - else - qemu_set_irq(s->dat_out, (s->val >> (s->bit --)) & 1); - - if (s->bit < 0) - cbus_cycle(s); - } - - s->clk = level; -} - -static void cbus_dat(void *opaque, int line, int level) -{ - CBusPriv *s = (CBusPriv *) opaque; - - s->dat = level; -} - -static void cbus_sel(void *opaque, int line, int level) -{ - CBusPriv *s = (CBusPriv *) opaque; - - if (!level) { - s->dir = 1; - s->bit = 8; - s->val = 0; - } - - s->sel = level; -} - -CBus *cbus_init(qemu_irq dat) -{ - CBusPriv *s = (CBusPriv *) g_malloc0(sizeof(*s)); - - s->dat_out = dat; - s->cbus.clk = qemu_allocate_irq(cbus_clk, s, 0); - s->cbus.dat = qemu_allocate_irq(cbus_dat, s, 0); - s->cbus.sel = qemu_allocate_irq(cbus_sel, s, 0); - - s->sel = 1; - s->clk = 0; - s->dat = 0; - - return &s->cbus; -} - -void cbus_attach(CBus *bus, void *slave_opaque) -{ - CBusSlave *slave = (CBusSlave *) slave_opaque; - CBusPriv *s = (CBusPriv *) bus; - - s->slave[slave->addr] = slave; -} - -/* Retu/Vilma */ -typedef struct { - uint16_t irqst; - uint16_t irqen; - uint16_t cc[2]; - int channel; - uint16_t result[16]; - uint16_t sample; - uint16_t status; - - struct { - uint16_t cal; - } rtc; - - int is_vilma; - qemu_irq irq; - CBusSlave cbus; -} CBusRetu; - -static void retu_interrupt_update(CBusRetu *s) -{ - qemu_set_irq(s->irq, s->irqst & ~s->irqen); -} - -#define RETU_REG_ASICR 0x00 /* (RO) ASIC ID & revision */ -#define RETU_REG_IDR 0x01 /* (T) Interrupt ID */ -#define RETU_REG_IMR 0x02 /* (RW) Interrupt mask */ -#define RETU_REG_RTCDSR 0x03 /* (RW) RTC seconds register */ -#define RETU_REG_RTCHMR 0x04 /* (RO) RTC hours and minutes reg */ -#define RETU_REG_RTCHMAR 0x05 /* (RW) RTC hours and minutes set reg */ -#define RETU_REG_RTCCALR 0x06 /* (RW) RTC calibration register */ -#define RETU_REG_ADCR 0x08 /* (RW) ADC result register */ -#define RETU_REG_ADCSCR 0x09 /* (RW) ADC sample control register */ -#define RETU_REG_AFCR 0x0a /* (RW) AFC register */ -#define RETU_REG_ANTIFR 0x0b /* (RW) AntiF register */ -#define RETU_REG_CALIBR 0x0c /* (RW) CalibR register*/ -#define RETU_REG_CCR1 0x0d /* (RW) Common control register 1 */ -#define RETU_REG_CCR2 0x0e /* (RW) Common control register 2 */ -#define RETU_REG_RCTRL_CLR 0x0f /* (T) Regulator clear register */ -#define RETU_REG_RCTRL_SET 0x10 /* (T) Regulator set register */ -#define RETU_REG_TXCR 0x11 /* (RW) TxC register */ -#define RETU_REG_STATUS 0x16 /* (RO) Status register */ -#define RETU_REG_WATCHDOG 0x17 /* (RW) Watchdog register */ -#define RETU_REG_AUDTXR 0x18 /* (RW) Audio Codec Tx register */ -#define RETU_REG_AUDPAR 0x19 /* (RW) AudioPA register */ -#define RETU_REG_AUDRXR1 0x1a /* (RW) Audio receive register 1 */ -#define RETU_REG_AUDRXR2 0x1b /* (RW) Audio receive register 2 */ -#define RETU_REG_SGR1 0x1c /* (RW) */ -#define RETU_REG_SCR1 0x1d /* (RW) */ -#define RETU_REG_SGR2 0x1e /* (RW) */ -#define RETU_REG_SCR2 0x1f /* (RW) */ - -/* Retu Interrupt sources */ -enum { - retu_int_pwr = 0, /* Power button */ - retu_int_char = 1, /* Charger */ - retu_int_rtcs = 2, /* Seconds */ - retu_int_rtcm = 3, /* Minutes */ - retu_int_rtcd = 4, /* Days */ - retu_int_rtca = 5, /* Alarm */ - retu_int_hook = 6, /* Hook */ - retu_int_head = 7, /* Headset */ - retu_int_adcs = 8, /* ADC sample */ -}; - -/* Retu ADC channel wiring */ -enum { - retu_adc_bsi = 1, /* BSI */ - retu_adc_batt_temp = 2, /* Battery temperature */ - retu_adc_chg_volt = 3, /* Charger voltage */ - retu_adc_head_det = 4, /* Headset detection */ - retu_adc_hook_det = 5, /* Hook detection */ - retu_adc_rf_gp = 6, /* RF GP */ - retu_adc_tx_det = 7, /* Wideband Tx detection */ - retu_adc_batt_volt = 8, /* Battery voltage */ - retu_adc_sens = 10, /* Light sensor */ - retu_adc_sens_temp = 11, /* Light sensor temperature */ - retu_adc_bbatt_volt = 12, /* Backup battery voltage */ - retu_adc_self_temp = 13, /* RETU temperature */ -}; - -static inline uint16_t retu_read(CBusRetu *s, int reg) -{ -#ifdef DEBUG - printf("RETU read at %02x\n", reg); -#endif - - switch (reg) { - case RETU_REG_ASICR: - return 0x0215 | (s->is_vilma << 7); - - case RETU_REG_IDR: /* TODO: Or is this ffs(s->irqst)? */ - return s->irqst; - - case RETU_REG_IMR: - return s->irqen; - - case RETU_REG_RTCDSR: - case RETU_REG_RTCHMR: - case RETU_REG_RTCHMAR: - /* TODO */ - return 0x0000; - - case RETU_REG_RTCCALR: - return s->rtc.cal; - - case RETU_REG_ADCR: - return (s->channel << 10) | s->result[s->channel]; - case RETU_REG_ADCSCR: - return s->sample; - - case RETU_REG_AFCR: - case RETU_REG_ANTIFR: - case RETU_REG_CALIBR: - /* TODO */ - return 0x0000; - - case RETU_REG_CCR1: - return s->cc[0]; - case RETU_REG_CCR2: - return s->cc[1]; - - case RETU_REG_RCTRL_CLR: - case RETU_REG_RCTRL_SET: - case RETU_REG_TXCR: - /* TODO */ - return 0x0000; - - case RETU_REG_STATUS: - return s->status; - - case RETU_REG_WATCHDOG: - case RETU_REG_AUDTXR: - case RETU_REG_AUDPAR: - case RETU_REG_AUDRXR1: - case RETU_REG_AUDRXR2: - case RETU_REG_SGR1: - case RETU_REG_SCR1: - case RETU_REG_SGR2: - case RETU_REG_SCR2: - /* TODO */ - return 0x0000; - - default: - hw_error("%s: bad register %02x\n", __FUNCTION__, reg); - } -} - -static inline void retu_write(CBusRetu *s, int reg, uint16_t val) -{ -#ifdef DEBUG - printf("RETU write of %04x at %02x\n", val, reg); -#endif - - switch (reg) { - case RETU_REG_IDR: - s->irqst ^= val; - retu_interrupt_update(s); - break; - - case RETU_REG_IMR: - s->irqen = val; - retu_interrupt_update(s); - break; - - case RETU_REG_RTCDSR: - case RETU_REG_RTCHMAR: - /* TODO */ - break; - - case RETU_REG_RTCCALR: - s->rtc.cal = val; - break; - - case RETU_REG_ADCR: - s->channel = (val >> 10) & 0xf; - s->irqst |= 1 << retu_int_adcs; - retu_interrupt_update(s); - break; - case RETU_REG_ADCSCR: - s->sample &= ~val; - break; - - case RETU_REG_AFCR: - case RETU_REG_ANTIFR: - case RETU_REG_CALIBR: - - case RETU_REG_CCR1: - s->cc[0] = val; - break; - case RETU_REG_CCR2: - s->cc[1] = val; - break; - - case RETU_REG_RCTRL_CLR: - case RETU_REG_RCTRL_SET: - /* TODO */ - break; - - case RETU_REG_WATCHDOG: - if (val == 0 && (s->cc[0] & 2)) - qemu_system_shutdown_request(); - break; - - case RETU_REG_TXCR: - case RETU_REG_AUDTXR: - case RETU_REG_AUDPAR: - case RETU_REG_AUDRXR1: - case RETU_REG_AUDRXR2: - case RETU_REG_SGR1: - case RETU_REG_SCR1: - case RETU_REG_SGR2: - case RETU_REG_SCR2: - /* TODO */ - break; - - default: - hw_error("%s: bad register %02x\n", __FUNCTION__, reg); - } -} - -static void retu_io(void *opaque, int rw, int reg, uint16_t *val) -{ - CBusRetu *s = (CBusRetu *) opaque; - - if (rw) - *val = retu_read(s, reg); - else - retu_write(s, reg, *val); -} - -void *retu_init(qemu_irq irq, int vilma) -{ - CBusRetu *s = (CBusRetu *) g_malloc0(sizeof(*s)); - - s->irq = irq; - s->irqen = 0xffff; - s->irqst = 0x0000; - s->status = 0x0020; - s->is_vilma = !!vilma; - s->rtc.cal = 0x01; - s->result[retu_adc_bsi] = 0x3c2; - s->result[retu_adc_batt_temp] = 0x0fc; - s->result[retu_adc_chg_volt] = 0x165; - s->result[retu_adc_head_det] = 123; - s->result[retu_adc_hook_det] = 1023; - s->result[retu_adc_rf_gp] = 0x11; - s->result[retu_adc_tx_det] = 0x11; - s->result[retu_adc_batt_volt] = 0x250; - s->result[retu_adc_sens] = 2; - s->result[retu_adc_sens_temp] = 0x11; - s->result[retu_adc_bbatt_volt] = 0x3d0; - s->result[retu_adc_self_temp] = 0x330; - - s->cbus.opaque = s; - s->cbus.io = retu_io; - s->cbus.addr = 1; - - return &s->cbus; -} - -void retu_key_event(void *retu, int state) -{ - CBusSlave *slave = (CBusSlave *) retu; - CBusRetu *s = (CBusRetu *) slave->opaque; - - s->irqst |= 1 << retu_int_pwr; - retu_interrupt_update(s); - - if (state) - s->status &= ~(1 << 5); - else - s->status |= 1 << 5; -} - -#if 0 -static void retu_head_event(void *retu, int state) -{ - CBusSlave *slave = (CBusSlave *) retu; - CBusRetu *s = (CBusRetu *) slave->opaque; - - if ((s->cc[0] & 0x500) == 0x500) { /* TODO: Which bits? */ - /* TODO: reissue the interrupt every 100ms or so. */ - s->irqst |= 1 << retu_int_head; - retu_interrupt_update(s); - } - - if (state) - s->result[retu_adc_head_det] = 50; - else - s->result[retu_adc_head_det] = 123; -} - -static void retu_hook_event(void *retu, int state) -{ - CBusSlave *slave = (CBusSlave *) retu; - CBusRetu *s = (CBusRetu *) slave->opaque; - - if ((s->cc[0] & 0x500) == 0x500) { - /* TODO: reissue the interrupt every 100ms or so. */ - s->irqst |= 1 << retu_int_hook; - retu_interrupt_update(s); - } - - if (state) - s->result[retu_adc_hook_det] = 50; - else - s->result[retu_adc_hook_det] = 123; -} -#endif - -/* Tahvo/Betty */ -typedef struct { - uint16_t irqst; - uint16_t irqen; - uint8_t charger; - uint8_t backlight; - uint16_t usbr; - uint16_t power; - - int is_betty; - qemu_irq irq; - CBusSlave cbus; -} CBusTahvo; - -static void tahvo_interrupt_update(CBusTahvo *s) -{ - qemu_set_irq(s->irq, s->irqst & ~s->irqen); -} - -#define TAHVO_REG_ASICR 0x00 /* (RO) ASIC ID & revision */ -#define TAHVO_REG_IDR 0x01 /* (T) Interrupt ID */ -#define TAHVO_REG_IDSR 0x02 /* (RO) Interrupt status */ -#define TAHVO_REG_IMR 0x03 /* (RW) Interrupt mask */ -#define TAHVO_REG_CHAPWMR 0x04 /* (RW) Charger PWM */ -#define TAHVO_REG_LEDPWMR 0x05 /* (RW) LED PWM */ -#define TAHVO_REG_USBR 0x06 /* (RW) USB control */ -#define TAHVO_REG_RCR 0x07 /* (RW) Some kind of power management */ -#define TAHVO_REG_CCR1 0x08 /* (RW) Common control register 1 */ -#define TAHVO_REG_CCR2 0x09 /* (RW) Common control register 2 */ -#define TAHVO_REG_TESTR1 0x0a /* (RW) Test register 1 */ -#define TAHVO_REG_TESTR2 0x0b /* (RW) Test register 2 */ -#define TAHVO_REG_NOPR 0x0c /* (RW) Number of periods */ -#define TAHVO_REG_FRR 0x0d /* (RO) FR */ - -static inline uint16_t tahvo_read(CBusTahvo *s, int reg) -{ -#ifdef DEBUG - printf("TAHVO read at %02x\n", reg); -#endif - - switch (reg) { - case TAHVO_REG_ASICR: - return 0x0021 | (s->is_betty ? 0x0b00 : 0x0300); /* 22 in N810 */ - - case TAHVO_REG_IDR: - case TAHVO_REG_IDSR: /* XXX: what does this do? */ - return s->irqst; - - case TAHVO_REG_IMR: - return s->irqen; - - case TAHVO_REG_CHAPWMR: - return s->charger; - - case TAHVO_REG_LEDPWMR: - return s->backlight; - - case TAHVO_REG_USBR: - return s->usbr; - - case TAHVO_REG_RCR: - return s->power; - - case TAHVO_REG_CCR1: - case TAHVO_REG_CCR2: - case TAHVO_REG_TESTR1: - case TAHVO_REG_TESTR2: - case TAHVO_REG_NOPR: - case TAHVO_REG_FRR: - return 0x0000; - - default: - hw_error("%s: bad register %02x\n", __FUNCTION__, reg); - } -} - -static inline void tahvo_write(CBusTahvo *s, int reg, uint16_t val) -{ -#ifdef DEBUG - printf("TAHVO write of %04x at %02x\n", val, reg); -#endif - - switch (reg) { - case TAHVO_REG_IDR: - s->irqst ^= val; - tahvo_interrupt_update(s); - break; - - case TAHVO_REG_IMR: - s->irqen = val; - tahvo_interrupt_update(s); - break; - - case TAHVO_REG_CHAPWMR: - s->charger = val; - break; - - case TAHVO_REG_LEDPWMR: - if (s->backlight != (val & 0x7f)) { - s->backlight = val & 0x7f; - printf("%s: LCD backlight now at %i / 127\n", - __FUNCTION__, s->backlight); - } - break; - - case TAHVO_REG_USBR: - s->usbr = val; - break; - - case TAHVO_REG_RCR: - s->power = val; - break; - - case TAHVO_REG_CCR1: - case TAHVO_REG_CCR2: - case TAHVO_REG_TESTR1: - case TAHVO_REG_TESTR2: - case TAHVO_REG_NOPR: - case TAHVO_REG_FRR: - break; - - default: - hw_error("%s: bad register %02x\n", __FUNCTION__, reg); - } -} - -static void tahvo_io(void *opaque, int rw, int reg, uint16_t *val) -{ - CBusTahvo *s = (CBusTahvo *) opaque; - - if (rw) - *val = tahvo_read(s, reg); - else - tahvo_write(s, reg, *val); -} - -void *tahvo_init(qemu_irq irq, int betty) -{ - CBusTahvo *s = (CBusTahvo *) g_malloc0(sizeof(*s)); - - s->irq = irq; - s->irqen = 0xffff; - s->irqst = 0x0000; - s->is_betty = !!betty; - - s->cbus.opaque = s; - s->cbus.io = tahvo_io; - s->cbus.addr = 2; - - return &s->cbus; -} diff --git a/qemu/hw/misc/debugexit.c b/qemu/hw/misc/debugexit.c deleted file mode 100644 index 84fa1a5b9..000000000 --- a/qemu/hw/misc/debugexit.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * debug exit port emulation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/isa/isa.h" - -#define TYPE_ISA_DEBUG_EXIT_DEVICE "isa-debug-exit" -#define ISA_DEBUG_EXIT_DEVICE(obj) \ - OBJECT_CHECK(ISADebugExitState, (obj), TYPE_ISA_DEBUG_EXIT_DEVICE) - -typedef struct ISADebugExitState { - ISADevice parent_obj; - - uint32_t iobase; - uint32_t iosize; - MemoryRegion io; -} ISADebugExitState; - -static void debug_exit_write(void *opaque, hwaddr addr, uint64_t val, - unsigned width) -{ - exit((val << 1) | 1); -} - -static const MemoryRegionOps debug_exit_ops = { - .write = debug_exit_write, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void debug_exit_realizefn(DeviceState *d, Error **errp) -{ - ISADevice *dev = ISA_DEVICE(d); - ISADebugExitState *isa = ISA_DEBUG_EXIT_DEVICE(d); - - memory_region_init_io(&isa->io, OBJECT(dev), &debug_exit_ops, isa, - TYPE_ISA_DEBUG_EXIT_DEVICE, isa->iosize); - memory_region_add_subregion(isa_address_space_io(dev), - isa->iobase, &isa->io); -} - -static Property debug_exit_properties[] = { - DEFINE_PROP_UINT32("iobase", ISADebugExitState, iobase, 0x501), - DEFINE_PROP_UINT32("iosize", ISADebugExitState, iosize, 0x02), - DEFINE_PROP_END_OF_LIST(), -}; - -static void debug_exit_class_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = debug_exit_realizefn; - dc->props = debug_exit_properties; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); -} - -static const TypeInfo debug_exit_info = { - .name = TYPE_ISA_DEBUG_EXIT_DEVICE, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(ISADebugExitState), - .class_init = debug_exit_class_initfn, -}; - -static void debug_exit_register_types(void) -{ - type_register_static(&debug_exit_info); -} - -type_init(debug_exit_register_types) diff --git a/qemu/hw/misc/eccmemctl.c b/qemu/hw/misc/eccmemctl.c deleted file mode 100644 index a0071f3ea..000000000 --- a/qemu/hw/misc/eccmemctl.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * QEMU Sparc Sun4m ECC memory controller emulation - * - * Copyright (c) 2007 Robert Reif - * - * 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 "hw/sysbus.h" -#include "trace.h" - -/* There are 3 versions of this chip used in SMP sun4m systems: - * MCC (version 0, implementation 0) SS-600MP - * EMC (version 0, implementation 1) SS-10 - * SMC (version 0, implementation 2) SS-10SX and SS-20 - * - * Chipset docs: - * "Sun-4M System Architecture (revision 2.0) by Chuck Narad", 950-1373-01, - * http://mediacast.sun.com/users/Barton808/media/Sun4M_SystemArchitecture_edited2.pdf - */ - -#define ECC_MCC 0x00000000 -#define ECC_EMC 0x10000000 -#define ECC_SMC 0x20000000 - -/* Register indexes */ -#define ECC_MER 0 /* Memory Enable Register */ -#define ECC_MDR 1 /* Memory Delay Register */ -#define ECC_MFSR 2 /* Memory Fault Status Register */ -#define ECC_VCR 3 /* Video Configuration Register */ -#define ECC_MFAR0 4 /* Memory Fault Address Register 0 */ -#define ECC_MFAR1 5 /* Memory Fault Address Register 1 */ -#define ECC_DR 6 /* Diagnostic Register */ -#define ECC_ECR0 7 /* Event Count Register 0 */ -#define ECC_ECR1 8 /* Event Count Register 1 */ - -/* ECC fault control register */ -#define ECC_MER_EE 0x00000001 /* Enable ECC checking */ -#define ECC_MER_EI 0x00000002 /* Enable Interrupts on - correctable errors */ -#define ECC_MER_MRR0 0x00000004 /* SIMM 0 */ -#define ECC_MER_MRR1 0x00000008 /* SIMM 1 */ -#define ECC_MER_MRR2 0x00000010 /* SIMM 2 */ -#define ECC_MER_MRR3 0x00000020 /* SIMM 3 */ -#define ECC_MER_MRR4 0x00000040 /* SIMM 4 */ -#define ECC_MER_MRR5 0x00000080 /* SIMM 5 */ -#define ECC_MER_MRR6 0x00000100 /* SIMM 6 */ -#define ECC_MER_MRR7 0x00000200 /* SIMM 7 */ -#define ECC_MER_REU 0x00000100 /* Memory Refresh Enable (600MP) */ -#define ECC_MER_MRR 0x000003fc /* MRR mask */ -#define ECC_MER_A 0x00000400 /* Memory controller addr map select */ -#define ECC_MER_DCI 0x00000800 /* Disables Coherent Invalidate ACK */ -#define ECC_MER_VER 0x0f000000 /* Version */ -#define ECC_MER_IMPL 0xf0000000 /* Implementation */ -#define ECC_MER_MASK_0 0x00000103 /* Version 0 (MCC) mask */ -#define ECC_MER_MASK_1 0x00000bff /* Version 1 (EMC) mask */ -#define ECC_MER_MASK_2 0x00000bff /* Version 2 (SMC) mask */ - -/* ECC memory delay register */ -#define ECC_MDR_RRI 0x000003ff /* Refresh Request Interval */ -#define ECC_MDR_MI 0x00001c00 /* MIH Delay */ -#define ECC_MDR_CI 0x0000e000 /* Coherent Invalidate Delay */ -#define ECC_MDR_MDL 0x001f0000 /* MBus Master arbitration delay */ -#define ECC_MDR_MDH 0x03e00000 /* MBus Master arbitration delay */ -#define ECC_MDR_GAD 0x7c000000 /* Graphics Arbitration Delay */ -#define ECC_MDR_RSC 0x80000000 /* Refresh load control */ -#define ECC_MDR_MASK 0x7fffffff - -/* ECC fault status register */ -#define ECC_MFSR_CE 0x00000001 /* Correctable error */ -#define ECC_MFSR_BS 0x00000002 /* C2 graphics bad slot access */ -#define ECC_MFSR_TO 0x00000004 /* Timeout on write */ -#define ECC_MFSR_UE 0x00000008 /* Uncorrectable error */ -#define ECC_MFSR_DW 0x000000f0 /* Index of double word in block */ -#define ECC_MFSR_SYND 0x0000ff00 /* Syndrome for correctable error */ -#define ECC_MFSR_ME 0x00010000 /* Multiple errors */ -#define ECC_MFSR_C2ERR 0x00020000 /* C2 graphics error */ - -/* ECC fault address register 0 */ -#define ECC_MFAR0_PADDR 0x0000000f /* PA[32-35] */ -#define ECC_MFAR0_TYPE 0x000000f0 /* Transaction type */ -#define ECC_MFAR0_SIZE 0x00000700 /* Transaction size */ -#define ECC_MFAR0_CACHE 0x00000800 /* Mapped cacheable */ -#define ECC_MFAR0_LOCK 0x00001000 /* Error occurred in atomic cycle */ -#define ECC_MFAR0_BMODE 0x00002000 /* Boot mode */ -#define ECC_MFAR0_VADDR 0x003fc000 /* VA[12-19] (superset bits) */ -#define ECC_MFAR0_S 0x08000000 /* Supervisor mode */ -#define ECC_MFARO_MID 0xf0000000 /* Module ID */ - -/* ECC diagnostic register */ -#define ECC_DR_CBX 0x00000001 -#define ECC_DR_CB0 0x00000002 -#define ECC_DR_CB1 0x00000004 -#define ECC_DR_CB2 0x00000008 -#define ECC_DR_CB4 0x00000010 -#define ECC_DR_CB8 0x00000020 -#define ECC_DR_CB16 0x00000040 -#define ECC_DR_CB32 0x00000080 -#define ECC_DR_DMODE 0x00000c00 - -#define ECC_NREGS 9 -#define ECC_SIZE (ECC_NREGS * sizeof(uint32_t)) - -#define ECC_DIAG_SIZE 4 -#define ECC_DIAG_MASK (ECC_DIAG_SIZE - 1) - -#define TYPE_ECC_MEMCTL "eccmemctl" -#define ECC_MEMCTL(obj) OBJECT_CHECK(ECCState, (obj), TYPE_ECC_MEMCTL) - -typedef struct ECCState { - SysBusDevice parent_obj; - - MemoryRegion iomem, iomem_diag; - qemu_irq irq; - uint32_t regs[ECC_NREGS]; - uint8_t diag[ECC_DIAG_SIZE]; - uint32_t version; -} ECCState; - -static void ecc_mem_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - ECCState *s = opaque; - - switch (addr >> 2) { - case ECC_MER: - if (s->version == ECC_MCC) - s->regs[ECC_MER] = (val & ECC_MER_MASK_0); - else if (s->version == ECC_EMC) - s->regs[ECC_MER] = s->version | (val & ECC_MER_MASK_1); - else if (s->version == ECC_SMC) - s->regs[ECC_MER] = s->version | (val & ECC_MER_MASK_2); - trace_ecc_mem_writel_mer(val); - break; - case ECC_MDR: - s->regs[ECC_MDR] = val & ECC_MDR_MASK; - trace_ecc_mem_writel_mdr(val); - break; - case ECC_MFSR: - s->regs[ECC_MFSR] = val; - qemu_irq_lower(s->irq); - trace_ecc_mem_writel_mfsr(val); - break; - case ECC_VCR: - s->regs[ECC_VCR] = val; - trace_ecc_mem_writel_vcr(val); - break; - case ECC_DR: - s->regs[ECC_DR] = val; - trace_ecc_mem_writel_dr(val); - break; - case ECC_ECR0: - s->regs[ECC_ECR0] = val; - trace_ecc_mem_writel_ecr0(val); - break; - case ECC_ECR1: - s->regs[ECC_ECR0] = val; - trace_ecc_mem_writel_ecr1(val); - break; - } -} - -static uint64_t ecc_mem_read(void *opaque, hwaddr addr, - unsigned size) -{ - ECCState *s = opaque; - uint32_t ret = 0; - - switch (addr >> 2) { - case ECC_MER: - ret = s->regs[ECC_MER]; - trace_ecc_mem_readl_mer(ret); - break; - case ECC_MDR: - ret = s->regs[ECC_MDR]; - trace_ecc_mem_readl_mdr(ret); - break; - case ECC_MFSR: - ret = s->regs[ECC_MFSR]; - trace_ecc_mem_readl_mfsr(ret); - break; - case ECC_VCR: - ret = s->regs[ECC_VCR]; - trace_ecc_mem_readl_vcr(ret); - break; - case ECC_MFAR0: - ret = s->regs[ECC_MFAR0]; - trace_ecc_mem_readl_mfar0(ret); - break; - case ECC_MFAR1: - ret = s->regs[ECC_MFAR1]; - trace_ecc_mem_readl_mfar1(ret); - break; - case ECC_DR: - ret = s->regs[ECC_DR]; - trace_ecc_mem_readl_dr(ret); - break; - case ECC_ECR0: - ret = s->regs[ECC_ECR0]; - trace_ecc_mem_readl_ecr0(ret); - break; - case ECC_ECR1: - ret = s->regs[ECC_ECR0]; - trace_ecc_mem_readl_ecr1(ret); - break; - } - return ret; -} - -static const MemoryRegionOps ecc_mem_ops = { - .read = ecc_mem_read, - .write = ecc_mem_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static void ecc_diag_mem_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - ECCState *s = opaque; - - trace_ecc_diag_mem_writeb(addr, val); - s->diag[addr & ECC_DIAG_MASK] = val; -} - -static uint64_t ecc_diag_mem_read(void *opaque, hwaddr addr, - unsigned size) -{ - ECCState *s = opaque; - uint32_t ret = s->diag[(int)addr]; - - trace_ecc_diag_mem_readb(addr, ret); - return ret; -} - -static const MemoryRegionOps ecc_diag_mem_ops = { - .read = ecc_diag_mem_read, - .write = ecc_diag_mem_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static const VMStateDescription vmstate_ecc = { - .name ="ECC", - .version_id = 3, - .minimum_version_id = 3, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, ECCState, ECC_NREGS), - VMSTATE_BUFFER(diag, ECCState), - VMSTATE_UINT32(version, ECCState), - VMSTATE_END_OF_LIST() - } -}; - -static void ecc_reset(DeviceState *d) -{ - ECCState *s = ECC_MEMCTL(d); - - if (s->version == ECC_MCC) { - s->regs[ECC_MER] &= ECC_MER_REU; - } else { - s->regs[ECC_MER] &= (ECC_MER_VER | ECC_MER_IMPL | ECC_MER_MRR | - ECC_MER_DCI); - } - s->regs[ECC_MDR] = 0x20; - s->regs[ECC_MFSR] = 0; - s->regs[ECC_VCR] = 0; - s->regs[ECC_MFAR0] = 0x07c00000; - s->regs[ECC_MFAR1] = 0; - s->regs[ECC_DR] = 0; - s->regs[ECC_ECR0] = 0; - s->regs[ECC_ECR1] = 0; -} - -static int ecc_init1(SysBusDevice *dev) -{ - ECCState *s = ECC_MEMCTL(dev); - - sysbus_init_irq(dev, &s->irq); - s->regs[0] = s->version; - memory_region_init_io(&s->iomem, OBJECT(dev), &ecc_mem_ops, s, "ecc", ECC_SIZE); - sysbus_init_mmio(dev, &s->iomem); - - if (s->version == ECC_MCC) { // SS-600MP only - memory_region_init_io(&s->iomem_diag, OBJECT(dev), &ecc_diag_mem_ops, s, - "ecc.diag", ECC_DIAG_SIZE); - sysbus_init_mmio(dev, &s->iomem_diag); - } - - return 0; -} - -static Property ecc_properties[] = { - DEFINE_PROP_UINT32("version", ECCState, version, -1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ecc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = ecc_init1; - dc->reset = ecc_reset; - dc->vmsd = &vmstate_ecc; - dc->props = ecc_properties; -} - -static const TypeInfo ecc_info = { - .name = TYPE_ECC_MEMCTL, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(ECCState), - .class_init = ecc_class_init, -}; - - -static void ecc_register_types(void) -{ - type_register_static(&ecc_info); -} - -type_init(ecc_register_types) diff --git a/qemu/hw/misc/edu.c b/qemu/hw/misc/edu.c deleted file mode 100644 index 888ba49a0..000000000 --- a/qemu/hw/misc/edu.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * QEMU educational PCI device - * - * Copyright (c) 2012-2015 Jiri Slaby - * - * 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 "hw/pci/pci.h" -#include "qemu/timer.h" -#include "qemu/main-loop.h" /* iothread mutex */ -#include "qapi/visitor.h" - -#define EDU(obj) OBJECT_CHECK(EduState, obj, "edu") - -#define FACT_IRQ 0x00000001 -#define DMA_IRQ 0x00000100 - -#define DMA_START 0x40000 -#define DMA_SIZE 4096 - -typedef struct { - PCIDevice pdev; - MemoryRegion mmio; - - QemuThread thread; - QemuMutex thr_mutex; - QemuCond thr_cond; - bool stopping; - - uint32_t addr4; - uint32_t fact; -#define EDU_STATUS_COMPUTING 0x01 -#define EDU_STATUS_IRQFACT 0x80 - uint32_t status; - - uint32_t irq_status; - -#define EDU_DMA_RUN 0x1 -#define EDU_DMA_DIR(cmd) (((cmd) & 0x2) >> 1) -# define EDU_DMA_FROM_PCI 0 -# define EDU_DMA_TO_PCI 1 -#define EDU_DMA_IRQ 0x4 - struct dma_state { - dma_addr_t src; - dma_addr_t dst; - dma_addr_t cnt; - dma_addr_t cmd; - } dma; - QEMUTimer dma_timer; - char dma_buf[DMA_SIZE]; - uint64_t dma_mask; -} EduState; - -static void edu_raise_irq(EduState *edu, uint32_t val) -{ - edu->irq_status |= val; - if (edu->irq_status) { - pci_set_irq(&edu->pdev, 1); - } -} - -static void edu_lower_irq(EduState *edu, uint32_t val) -{ - edu->irq_status &= ~val; - - if (!edu->irq_status) { - pci_set_irq(&edu->pdev, 0); - } -} - -static bool within(uint32_t addr, uint32_t start, uint32_t end) -{ - return start <= addr && addr < end; -} - -static void edu_check_range(uint32_t addr, uint32_t size1, uint32_t start, - uint32_t size2) -{ - uint32_t end1 = addr + size1; - uint32_t end2 = start + size2; - - if (within(addr, start, end2) && - end1 > addr && within(end1, start, end2)) { - return; - } - - hw_error("EDU: DMA range 0x%.8x-0x%.8x out of bounds (0x%.8x-0x%.8x)!", - addr, end1 - 1, start, end2 - 1); -} - -static dma_addr_t edu_clamp_addr(const EduState *edu, dma_addr_t addr) -{ - dma_addr_t res = addr & edu->dma_mask; - - if (addr != res) { - printf("EDU: clamping DMA %#.16"PRIx64" to %#.16"PRIx64"!\n", addr, res); - } - - return res; -} - -static void edu_dma_timer(void *opaque) -{ - EduState *edu = opaque; - bool raise_irq = false; - - if (!(edu->dma.cmd & EDU_DMA_RUN)) { - return; - } - - if (EDU_DMA_DIR(edu->dma.cmd) == EDU_DMA_FROM_PCI) { - uint32_t dst = edu->dma.dst; - edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE); - dst -= DMA_START; - pci_dma_read(&edu->pdev, edu_clamp_addr(edu, edu->dma.src), - edu->dma_buf + dst, edu->dma.cnt); - } else { - uint32_t src = edu->dma.src; - edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE); - src -= DMA_START; - pci_dma_write(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst), - edu->dma_buf + src, edu->dma.cnt); - } - - edu->dma.cmd &= ~EDU_DMA_RUN; - if (edu->dma.cmd & EDU_DMA_IRQ) { - raise_irq = true; - } - - if (raise_irq) { - edu_raise_irq(edu, DMA_IRQ); - } -} - -static void dma_rw(EduState *edu, bool write, dma_addr_t *val, dma_addr_t *dma, - bool timer) -{ - if (write && (edu->dma.cmd & EDU_DMA_RUN)) { - return; - } - - if (write) { - *dma = *val; - } else { - *val = *dma; - } - - if (timer) { - timer_mod(&edu->dma_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100); - } -} - -static uint64_t edu_mmio_read(void *opaque, hwaddr addr, unsigned size) -{ - EduState *edu = opaque; - uint64_t val = ~0ULL; - - if (size != 4) { - return val; - } - - switch (addr) { - case 0x00: - val = 0x010000edu; - break; - case 0x04: - val = edu->addr4; - break; - case 0x08: - qemu_mutex_lock(&edu->thr_mutex); - val = edu->fact; - qemu_mutex_unlock(&edu->thr_mutex); - break; - case 0x20: - val = atomic_read(&edu->status); - break; - case 0x24: - val = edu->irq_status; - break; - case 0x80: - dma_rw(edu, false, &val, &edu->dma.src, false); - break; - case 0x88: - dma_rw(edu, false, &val, &edu->dma.dst, false); - break; - case 0x90: - dma_rw(edu, false, &val, &edu->dma.cnt, false); - break; - case 0x98: - dma_rw(edu, false, &val, &edu->dma.cmd, false); - break; - } - - return val; -} - -static void edu_mmio_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - EduState *edu = opaque; - - if (addr < 0x80 && size != 4) { - return; - } - - if (addr >= 0x80 && size != 4 && size != 8) { - return; - } - - switch (addr) { - case 0x04: - edu->addr4 = ~val; - break; - case 0x08: - if (atomic_read(&edu->status) & EDU_STATUS_COMPUTING) { - break; - } - /* EDU_STATUS_COMPUTING cannot go 0->1 concurrently, because it is only - * set in this function and it is under the iothread mutex. - */ - qemu_mutex_lock(&edu->thr_mutex); - edu->fact = val; - atomic_or(&edu->status, EDU_STATUS_COMPUTING); - qemu_cond_signal(&edu->thr_cond); - qemu_mutex_unlock(&edu->thr_mutex); - break; - case 0x20: - if (val & EDU_STATUS_IRQFACT) { - atomic_or(&edu->status, EDU_STATUS_IRQFACT); - } else { - atomic_and(&edu->status, ~EDU_STATUS_IRQFACT); - } - break; - case 0x60: - edu_raise_irq(edu, val); - break; - case 0x64: - edu_lower_irq(edu, val); - break; - case 0x80: - dma_rw(edu, true, &val, &edu->dma.src, false); - break; - case 0x88: - dma_rw(edu, true, &val, &edu->dma.dst, false); - break; - case 0x90: - dma_rw(edu, true, &val, &edu->dma.cnt, false); - break; - case 0x98: - if (!(val & EDU_DMA_RUN)) { - break; - } - dma_rw(edu, true, &val, &edu->dma.cmd, true); - break; - } -} - -static const MemoryRegionOps edu_mmio_ops = { - .read = edu_mmio_read, - .write = edu_mmio_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -/* - * We purposely use a thread, so that users are forced to wait for the status - * register. - */ -static void *edu_fact_thread(void *opaque) -{ - EduState *edu = opaque; - - while (1) { - uint32_t val, ret = 1; - - qemu_mutex_lock(&edu->thr_mutex); - while ((atomic_read(&edu->status) & EDU_STATUS_COMPUTING) == 0 && - !edu->stopping) { - qemu_cond_wait(&edu->thr_cond, &edu->thr_mutex); - } - - if (edu->stopping) { - qemu_mutex_unlock(&edu->thr_mutex); - break; - } - - val = edu->fact; - qemu_mutex_unlock(&edu->thr_mutex); - - while (val > 0) { - ret *= val--; - } - - /* - * We should sleep for a random period here, so that students are - * forced to check the status properly. - */ - - qemu_mutex_lock(&edu->thr_mutex); - edu->fact = ret; - qemu_mutex_unlock(&edu->thr_mutex); - atomic_and(&edu->status, ~EDU_STATUS_COMPUTING); - - if (atomic_read(&edu->status) & EDU_STATUS_IRQFACT) { - qemu_mutex_lock_iothread(); - edu_raise_irq(edu, FACT_IRQ); - qemu_mutex_unlock_iothread(); - } - } - - return NULL; -} - -static void pci_edu_realize(PCIDevice *pdev, Error **errp) -{ - EduState *edu = DO_UPCAST(EduState, pdev, pdev); - uint8_t *pci_conf = pdev->config; - - timer_init_ms(&edu->dma_timer, QEMU_CLOCK_VIRTUAL, edu_dma_timer, edu); - - qemu_mutex_init(&edu->thr_mutex); - qemu_cond_init(&edu->thr_cond); - qemu_thread_create(&edu->thread, "edu", edu_fact_thread, - edu, QEMU_THREAD_JOINABLE); - - pci_config_set_interrupt_pin(pci_conf, 1); - - memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu, - "edu-mmio", 1 << 20); - pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &edu->mmio); -} - -static void pci_edu_uninit(PCIDevice *pdev) -{ - EduState *edu = DO_UPCAST(EduState, pdev, pdev); - - qemu_mutex_lock(&edu->thr_mutex); - edu->stopping = true; - qemu_mutex_unlock(&edu->thr_mutex); - qemu_cond_signal(&edu->thr_cond); - qemu_thread_join(&edu->thread); - - qemu_cond_destroy(&edu->thr_cond); - qemu_mutex_destroy(&edu->thr_mutex); - - timer_del(&edu->dma_timer); -} - -static void edu_obj_uint64(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - uint64_t *val = opaque; - - visit_type_uint64(v, name, val, errp); -} - -static void edu_instance_init(Object *obj) -{ - EduState *edu = EDU(obj); - - edu->dma_mask = (1UL << 28) - 1; - object_property_add(obj, "dma_mask", "uint64", edu_obj_uint64, - edu_obj_uint64, NULL, &edu->dma_mask, NULL); -} - -static void edu_class_init(ObjectClass *class, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(class); - - k->realize = pci_edu_realize; - k->exit = pci_edu_uninit; - k->vendor_id = PCI_VENDOR_ID_QEMU; - k->device_id = 0x11e8; - k->revision = 0x10; - k->class_id = PCI_CLASS_OTHERS; -} - -static void pci_edu_register_types(void) -{ - static const TypeInfo edu_info = { - .name = "edu", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EduState), - .instance_init = edu_instance_init, - .class_init = edu_class_init, - }; - - type_register_static(&edu_info); -} -type_init(pci_edu_register_types) diff --git a/qemu/hw/misc/exynos4210_pmu.c b/qemu/hw/misc/exynos4210_pmu.c deleted file mode 100644 index 889abadfe..000000000 --- a/qemu/hw/misc/exynos4210_pmu.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Exynos4210 Power Management Unit (PMU) Emulation - * - * Copyright (C) 2011 Samsung Electronics Co Ltd. - * Maksim Kozlov <m.kozlov@samsung.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -/* - * This model implements PMU registers just as a bulk of memory. Currently, - * the only reason this device exists is that secondary CPU boot loader - * uses PMU INFORM5 register as a holding pen. - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" - -#ifndef DEBUG_PMU -#define DEBUG_PMU 0 -#endif - -#ifndef DEBUG_PMU_EXTEND -#define DEBUG_PMU_EXTEND 0 -#endif - -#if DEBUG_PMU -#define PRINT_DEBUG(fmt, args...) \ - do { \ - fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__, ##args); \ - } while (0) - -#if DEBUG_PMU_EXTEND -#define PRINT_DEBUG_EXTEND(fmt, args...) \ - do { \ - fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__, ##args); \ - } while (0) -#else -#define PRINT_DEBUG_EXTEND(fmt, args...) do {} while (0) -#endif /* EXTEND */ - -#else -#define PRINT_DEBUG(fmt, args...) do {} while (0) -#define PRINT_DEBUG_EXTEND(fmt, args...) do {} while (0) -#endif - -/* - * Offsets for PMU registers - */ -#define OM_STAT 0x0000 /* OM status register */ -#define RTC_CLKO_SEL 0x000C /* Controls RTCCLKOUT */ -#define GNSS_RTC_OUT_CTRL 0x0010 /* Controls GNSS_RTC_OUT */ -/* Decides whether system-level low-power mode is used. */ -#define SYSTEM_POWER_DOWN_CTRL 0x0200 -/* Sets control options for CENTRAL_SEQ */ -#define SYSTEM_POWER_DOWN_OPTION 0x0208 -#define SWRESET 0x0400 /* Generate software reset */ -#define RST_STAT 0x0404 /* Reset status register */ -#define WAKEUP_STAT 0x0600 /* Wakeup status register */ -#define EINT_WAKEUP_MASK 0x0604 /* Configure External INTerrupt mask */ -#define WAKEUP_MASK 0x0608 /* Configure wakeup source mask */ -#define HDMI_PHY_CONTROL 0x0700 /* HDMI PHY control register */ -#define USBDEVICE_PHY_CONTROL 0x0704 /* USB Device PHY control register */ -#define USBHOST_PHY_CONTROL 0x0708 /* USB HOST PHY control register */ -#define DAC_PHY_CONTROL 0x070C /* DAC control register */ -#define MIPI_PHY0_CONTROL 0x0710 /* MIPI PHY control register */ -#define MIPI_PHY1_CONTROL 0x0714 /* MIPI PHY control register */ -#define ADC_PHY_CONTROL 0x0718 /* TS-ADC control register */ -#define PCIe_PHY_CONTROL 0x071C /* TS-PCIe control register */ -#define SATA_PHY_CONTROL 0x0720 /* TS-SATA control register */ -#define INFORM0 0x0800 /* Information register 0 */ -#define INFORM1 0x0804 /* Information register 1 */ -#define INFORM2 0x0808 /* Information register 2 */ -#define INFORM3 0x080C /* Information register 3 */ -#define INFORM4 0x0810 /* Information register 4 */ -#define INFORM5 0x0814 /* Information register 5 */ -#define INFORM6 0x0818 /* Information register 6 */ -#define INFORM7 0x081C /* Information register 7 */ -#define PMU_DEBUG 0x0A00 /* PMU debug register */ -/* Registers to set system-level low-power option */ -#define ARM_CORE0_SYS_PWR_REG 0x1000 -#define ARM_CORE1_SYS_PWR_REG 0x1010 -#define ARM_COMMON_SYS_PWR_REG 0x1080 -#define ARM_CPU_L2_0_SYS_PWR_REG 0x10C0 -#define ARM_CPU_L2_1_SYS_PWR_REG 0x10C4 -#define CMU_ACLKSTOP_SYS_PWR_REG 0x1100 -#define CMU_SCLKSTOP_SYS_PWR_REG 0x1104 -#define CMU_RESET_SYS_PWR_REG 0x110C -#define APLL_SYSCLK_SYS_PWR_REG 0x1120 -#define MPLL_SYSCLK_SYS_PWR_REG 0x1124 -#define VPLL_SYSCLK_SYS_PWR_REG 0x1128 -#define EPLL_SYSCLK_SYS_PWR_REG 0x112C -#define CMU_CLKSTOP_GPS_ALIVE_SYS_PWR_REG 0x1138 -#define CMU_RESET_GPS_ALIVE_SYS_PWR_REG 0x113C -#define CMU_CLKSTOP_CAM_SYS_PWR_REG 0x1140 -#define CMU_CLKSTOP_TV_SYS_PWR_REG 0x1144 -#define CMU_CLKSTOP_MFC_SYS_PWR_REG 0x1148 -#define CMU_CLKSTOP_G3D_SYS_PWR_REG 0x114C -#define CMU_CLKSTOP_LCD0_SYS_PWR_REG 0x1150 -#define CMU_CLKSTOP_LCD1_SYS_PWR_REG 0x1154 -#define CMU_CLKSTOP_MAUDIO_SYS_PWR_REG 0x1158 -#define CMU_CLKSTOP_GPS_SYS_PWR_REG 0x115C -#define CMU_RESET_CAM_SYS_PWR_REG 0x1160 -#define CMU_RESET_TV_SYS_PWR_REG 0x1164 -#define CMU_RESET_MFC_SYS_PWR_REG 0x1168 -#define CMU_RESET_G3D_SYS_PWR_REG 0x116C -#define CMU_RESET_LCD0_SYS_PWR_REG 0x1170 -#define CMU_RESET_LCD1_SYS_PWR_REG 0x1174 -#define CMU_RESET_MAUDIO_SYS_PWR_REG 0x1178 -#define CMU_RESET_GPS_SYS_PWR_REG 0x117C -#define TOP_BUS_SYS_PWR_REG 0x1180 -#define TOP_RETENTION_SYS_PWR_REG 0x1184 -#define TOP_PWR_SYS_PWR_REG 0x1188 -#define LOGIC_RESET_SYS_PWR_REG 0x11A0 -#define OneNANDXL_MEM_SYS_PWR_REG 0x11C0 -#define MODEMIF_MEM_SYS_PWR_REG 0x11C4 -#define USBDEVICE_MEM_SYS_PWR_REG 0x11CC -#define SDMMC_MEM_SYS_PWR_REG 0x11D0 -#define CSSYS_MEM_SYS_PWR_REG 0x11D4 -#define SECSS_MEM_SYS_PWR_REG 0x11D8 -#define PCIe_MEM_SYS_PWR_REG 0x11E0 -#define SATA_MEM_SYS_PWR_REG 0x11E4 -#define PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200 -#define PAD_RETENTION_MAUDIO_SYS_PWR_REG 0x1204 -#define PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220 -#define PAD_RETENTION_UART_SYS_PWR_REG 0x1224 -#define PAD_RETENTION_MMCA_SYS_PWR_REG 0x1228 -#define PAD_RETENTION_MMCB_SYS_PWR_REG 0x122C -#define PAD_RETENTION_EBIA_SYS_PWR_REG 0x1230 -#define PAD_RETENTION_EBIB_SYS_PWR_REG 0x1234 -#define PAD_ISOLATION_SYS_PWR_REG 0x1240 -#define PAD_ALV_SEL_SYS_PWR_REG 0x1260 -#define XUSBXTI_SYS_PWR_REG 0x1280 -#define XXTI_SYS_PWR_REG 0x1284 -#define EXT_REGULATOR_SYS_PWR_REG 0x12C0 -#define GPIO_MODE_SYS_PWR_REG 0x1300 -#define GPIO_MODE_MAUDIO_SYS_PWR_REG 0x1340 -#define CAM_SYS_PWR_REG 0x1380 -#define TV_SYS_PWR_REG 0x1384 -#define MFC_SYS_PWR_REG 0x1388 -#define G3D_SYS_PWR_REG 0x138C -#define LCD0_SYS_PWR_REG 0x1390 -#define LCD1_SYS_PWR_REG 0x1394 -#define MAUDIO_SYS_PWR_REG 0x1398 -#define GPS_SYS_PWR_REG 0x139C -#define GPS_ALIVE_SYS_PWR_REG 0x13A0 -#define ARM_CORE0_CONFIGURATION 0x2000 /* Configure power mode of ARM_CORE0 */ -#define ARM_CORE0_STATUS 0x2004 /* Check power mode of ARM_CORE0 */ -#define ARM_CORE0_OPTION 0x2008 /* Sets control options for ARM_CORE0 */ -#define ARM_CORE1_CONFIGURATION 0x2080 /* Configure power mode of ARM_CORE1 */ -#define ARM_CORE1_STATUS 0x2084 /* Check power mode of ARM_CORE1 */ -#define ARM_CORE1_OPTION 0x2088 /* Sets control options for ARM_CORE0 */ -#define ARM_COMMON_OPTION 0x2408 /* Sets control options for ARM_COMMON */ -/* Configure power mode of ARM_CPU_L2_0 */ -#define ARM_CPU_L2_0_CONFIGURATION 0x2600 -#define ARM_CPU_L2_0_STATUS 0x2604 /* Check power mode of ARM_CPU_L2_0 */ -/* Configure power mode of ARM_CPU_L2_1 */ -#define ARM_CPU_L2_1_CONFIGURATION 0x2620 -#define ARM_CPU_L2_1_STATUS 0x2624 /* Check power mode of ARM_CPU_L2_1 */ -/* Sets control options for PAD_RETENTION_MAUDIO */ -#define PAD_RETENTION_MAUDIO_OPTION 0x3028 -/* Sets control options for PAD_RETENTION_GPIO */ -#define PAD_RETENTION_GPIO_OPTION 0x3108 -/* Sets control options for PAD_RETENTION_UART */ -#define PAD_RETENTION_UART_OPTION 0x3128 -/* Sets control options for PAD_RETENTION_MMCA */ -#define PAD_RETENTION_MMCA_OPTION 0x3148 -/* Sets control options for PAD_RETENTION_MMCB */ -#define PAD_RETENTION_MMCB_OPTION 0x3168 -/* Sets control options for PAD_RETENTION_EBIA */ -#define PAD_RETENTION_EBIA_OPTION 0x3188 -/* Sets control options for PAD_RETENTION_EBIB */ -#define PAD_RETENTION_EBIB_OPTION 0x31A8 -#define PS_HOLD_CONTROL 0x330C /* PS_HOLD control register */ -#define XUSBXTI_CONFIGURATION 0x3400 /* Configure the pad of XUSBXTI */ -#define XUSBXTI_STATUS 0x3404 /* Check the pad of XUSBXTI */ -/* Sets time required for XUSBXTI to be stabilized */ -#define XUSBXTI_DURATION 0x341C -#define XXTI_CONFIGURATION 0x3420 /* Configure the pad of XXTI */ -#define XXTI_STATUS 0x3424 /* Check the pad of XXTI */ -/* Sets time required for XXTI to be stabilized */ -#define XXTI_DURATION 0x343C -/* Sets time required for EXT_REGULATOR to be stabilized */ -#define EXT_REGULATOR_DURATION 0x361C -#define CAM_CONFIGURATION 0x3C00 /* Configure power mode of CAM */ -#define CAM_STATUS 0x3C04 /* Check power mode of CAM */ -#define CAM_OPTION 0x3C08 /* Sets control options for CAM */ -#define TV_CONFIGURATION 0x3C20 /* Configure power mode of TV */ -#define TV_STATUS 0x3C24 /* Check power mode of TV */ -#define TV_OPTION 0x3C28 /* Sets control options for TV */ -#define MFC_CONFIGURATION 0x3C40 /* Configure power mode of MFC */ -#define MFC_STATUS 0x3C44 /* Check power mode of MFC */ -#define MFC_OPTION 0x3C48 /* Sets control options for MFC */ -#define G3D_CONFIGURATION 0x3C60 /* Configure power mode of G3D */ -#define G3D_STATUS 0x3C64 /* Check power mode of G3D */ -#define G3D_OPTION 0x3C68 /* Sets control options for G3D */ -#define LCD0_CONFIGURATION 0x3C80 /* Configure power mode of LCD0 */ -#define LCD0_STATUS 0x3C84 /* Check power mode of LCD0 */ -#define LCD0_OPTION 0x3C88 /* Sets control options for LCD0 */ -#define LCD1_CONFIGURATION 0x3CA0 /* Configure power mode of LCD1 */ -#define LCD1_STATUS 0x3CA4 /* Check power mode of LCD1 */ -#define LCD1_OPTION 0x3CA8 /* Sets control options for LCD1 */ -#define GPS_CONFIGURATION 0x3CE0 /* Configure power mode of GPS */ -#define GPS_STATUS 0x3CE4 /* Check power mode of GPS */ -#define GPS_OPTION 0x3CE8 /* Sets control options for GPS */ -#define GPS_ALIVE_CONFIGURATION 0x3D00 /* Configure power mode of GPS */ -#define GPS_ALIVE_STATUS 0x3D04 /* Check power mode of GPS */ -#define GPS_ALIVE_OPTION 0x3D08 /* Sets control options for GPS */ - -#define EXYNOS4210_PMU_REGS_MEM_SIZE 0x3d0c - -typedef struct Exynos4210PmuReg { - const char *name; /* for debug only */ - uint32_t offset; - uint32_t reset_value; -} Exynos4210PmuReg; - -static const Exynos4210PmuReg exynos4210_pmu_regs[] = { - {"OM_STAT", OM_STAT, 0x00000000}, - {"RTC_CLKO_SEL", RTC_CLKO_SEL, 0x00000000}, - {"GNSS_RTC_OUT_CTRL", GNSS_RTC_OUT_CTRL, 0x00000001}, - {"SYSTEM_POWER_DOWN_CTRL", SYSTEM_POWER_DOWN_CTRL, 0x00010000}, - {"SYSTEM_POWER_DOWN_OPTION", SYSTEM_POWER_DOWN_OPTION, 0x03030000}, - {"SWRESET", SWRESET, 0x00000000}, - {"RST_STAT", RST_STAT, 0x00000000}, - {"WAKEUP_STAT", WAKEUP_STAT, 0x00000000}, - {"EINT_WAKEUP_MASK", EINT_WAKEUP_MASK, 0x00000000}, - {"WAKEUP_MASK", WAKEUP_MASK, 0x00000000}, - {"HDMI_PHY_CONTROL", HDMI_PHY_CONTROL, 0x00960000}, - {"USBDEVICE_PHY_CONTROL", USBDEVICE_PHY_CONTROL, 0x00000000}, - {"USBHOST_PHY_CONTROL", USBHOST_PHY_CONTROL, 0x00000000}, - {"DAC_PHY_CONTROL", DAC_PHY_CONTROL, 0x00000000}, - {"MIPI_PHY0_CONTROL", MIPI_PHY0_CONTROL, 0x00000000}, - {"MIPI_PHY1_CONTROL", MIPI_PHY1_CONTROL, 0x00000000}, - {"ADC_PHY_CONTROL", ADC_PHY_CONTROL, 0x00000001}, - {"PCIe_PHY_CONTROL", PCIe_PHY_CONTROL, 0x00000000}, - {"SATA_PHY_CONTROL", SATA_PHY_CONTROL, 0x00000000}, - {"INFORM0", INFORM0, 0x00000000}, - {"INFORM1", INFORM1, 0x00000000}, - {"INFORM2", INFORM2, 0x00000000}, - {"INFORM3", INFORM3, 0x00000000}, - {"INFORM4", INFORM4, 0x00000000}, - {"INFORM5", INFORM5, 0x00000000}, - {"INFORM6", INFORM6, 0x00000000}, - {"INFORM7", INFORM7, 0x00000000}, - {"PMU_DEBUG", PMU_DEBUG, 0x00000000}, - {"ARM_CORE0_SYS_PWR_REG", ARM_CORE0_SYS_PWR_REG, 0xFFFFFFFF}, - {"ARM_CORE1_SYS_PWR_REG", ARM_CORE1_SYS_PWR_REG, 0xFFFFFFFF}, - {"ARM_COMMON_SYS_PWR_REG", ARM_COMMON_SYS_PWR_REG, 0xFFFFFFFF}, - {"ARM_CPU_L2_0_SYS_PWR_REG", ARM_CPU_L2_0_SYS_PWR_REG, 0xFFFFFFFF}, - {"ARM_CPU_L2_1_SYS_PWR_REG", ARM_CPU_L2_1_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_ACLKSTOP_SYS_PWR_REG", CMU_ACLKSTOP_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_SCLKSTOP_SYS_PWR_REG", CMU_SCLKSTOP_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_SYS_PWR_REG", CMU_RESET_SYS_PWR_REG, 0xFFFFFFFF}, - {"APLL_SYSCLK_SYS_PWR_REG", APLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF}, - {"MPLL_SYSCLK_SYS_PWR_REG", MPLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF}, - {"VPLL_SYSCLK_SYS_PWR_REG", VPLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF}, - {"EPLL_SYSCLK_SYS_PWR_REG", EPLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_CLKSTOP_GPS_ALIVE_SYS_PWR_REG", CMU_CLKSTOP_GPS_ALIVE_SYS_PWR_REG, - 0xFFFFFFFF}, - {"CMU_RESET_GPS_ALIVE_SYS_PWR_REG", CMU_RESET_GPS_ALIVE_SYS_PWR_REG, - 0xFFFFFFFF}, - {"CMU_CLKSTOP_CAM_SYS_PWR_REG", CMU_CLKSTOP_CAM_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_CLKSTOP_TV_SYS_PWR_REG", CMU_CLKSTOP_TV_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_CLKSTOP_MFC_SYS_PWR_REG", CMU_CLKSTOP_MFC_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_CLKSTOP_G3D_SYS_PWR_REG", CMU_CLKSTOP_G3D_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_CLKSTOP_LCD0_SYS_PWR_REG", CMU_CLKSTOP_LCD0_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_CLKSTOP_LCD1_SYS_PWR_REG", CMU_CLKSTOP_LCD1_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_CLKSTOP_MAUDIO_SYS_PWR_REG", CMU_CLKSTOP_MAUDIO_SYS_PWR_REG, - 0xFFFFFFFF}, - {"CMU_CLKSTOP_GPS_SYS_PWR_REG", CMU_CLKSTOP_GPS_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_CAM_SYS_PWR_REG", CMU_RESET_CAM_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_TV_SYS_PWR_REG", CMU_RESET_TV_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_MFC_SYS_PWR_REG", CMU_RESET_MFC_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_G3D_SYS_PWR_REG", CMU_RESET_G3D_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_LCD0_SYS_PWR_REG", CMU_RESET_LCD0_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_LCD1_SYS_PWR_REG", CMU_RESET_LCD1_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_MAUDIO_SYS_PWR_REG", CMU_RESET_MAUDIO_SYS_PWR_REG, 0xFFFFFFFF}, - {"CMU_RESET_GPS_SYS_PWR_REG", CMU_RESET_GPS_SYS_PWR_REG, 0xFFFFFFFF}, - {"TOP_BUS_SYS_PWR_REG", TOP_BUS_SYS_PWR_REG, 0xFFFFFFFF}, - {"TOP_RETENTION_SYS_PWR_REG", TOP_RETENTION_SYS_PWR_REG, 0xFFFFFFFF}, - {"TOP_PWR_SYS_PWR_REG", TOP_PWR_SYS_PWR_REG, 0xFFFFFFFF}, - {"LOGIC_RESET_SYS_PWR_REG", LOGIC_RESET_SYS_PWR_REG, 0xFFFFFFFF}, - {"OneNANDXL_MEM_SYS_PWR_REG", OneNANDXL_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"MODEMIF_MEM_SYS_PWR_REG", MODEMIF_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"USBDEVICE_MEM_SYS_PWR_REG", USBDEVICE_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"SDMMC_MEM_SYS_PWR_REG", SDMMC_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"CSSYS_MEM_SYS_PWR_REG", CSSYS_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"SECSS_MEM_SYS_PWR_REG", SECSS_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"PCIe_MEM_SYS_PWR_REG", PCIe_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"SATA_MEM_SYS_PWR_REG", SATA_MEM_SYS_PWR_REG, 0xFFFFFFFF}, - {"PAD_RETENTION_DRAM_SYS_PWR_REG", PAD_RETENTION_DRAM_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_RETENTION_MAUDIO_SYS_PWR_REG", PAD_RETENTION_MAUDIO_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_RETENTION_GPIO_SYS_PWR_REG", PAD_RETENTION_GPIO_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_RETENTION_UART_SYS_PWR_REG", PAD_RETENTION_UART_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_RETENTION_MMCA_SYS_PWR_REG", PAD_RETENTION_MMCA_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_RETENTION_MMCB_SYS_PWR_REG", PAD_RETENTION_MMCB_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_RETENTION_EBIA_SYS_PWR_REG", PAD_RETENTION_EBIA_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_RETENTION_EBIB_SYS_PWR_REG", PAD_RETENTION_EBIB_SYS_PWR_REG, - 0xFFFFFFFF}, - {"PAD_ISOLATION_SYS_PWR_REG", PAD_ISOLATION_SYS_PWR_REG, 0xFFFFFFFF}, - {"PAD_ALV_SEL_SYS_PWR_REG", PAD_ALV_SEL_SYS_PWR_REG, 0xFFFFFFFF}, - {"XUSBXTI_SYS_PWR_REG", XUSBXTI_SYS_PWR_REG, 0xFFFFFFFF}, - {"XXTI_SYS_PWR_REG", XXTI_SYS_PWR_REG, 0xFFFFFFFF}, - {"EXT_REGULATOR_SYS_PWR_REG", EXT_REGULATOR_SYS_PWR_REG, 0xFFFFFFFF}, - {"GPIO_MODE_SYS_PWR_REG", GPIO_MODE_SYS_PWR_REG, 0xFFFFFFFF}, - {"GPIO_MODE_MAUDIO_SYS_PWR_REG", GPIO_MODE_MAUDIO_SYS_PWR_REG, 0xFFFFFFFF}, - {"CAM_SYS_PWR_REG", CAM_SYS_PWR_REG, 0xFFFFFFFF}, - {"TV_SYS_PWR_REG", TV_SYS_PWR_REG, 0xFFFFFFFF}, - {"MFC_SYS_PWR_REG", MFC_SYS_PWR_REG, 0xFFFFFFFF}, - {"G3D_SYS_PWR_REG", G3D_SYS_PWR_REG, 0xFFFFFFFF}, - {"LCD0_SYS_PWR_REG", LCD0_SYS_PWR_REG, 0xFFFFFFFF}, - {"LCD1_SYS_PWR_REG", LCD1_SYS_PWR_REG, 0xFFFFFFFF}, - {"MAUDIO_SYS_PWR_REG", MAUDIO_SYS_PWR_REG, 0xFFFFFFFF}, - {"GPS_SYS_PWR_REG", GPS_SYS_PWR_REG, 0xFFFFFFFF}, - {"GPS_ALIVE_SYS_PWR_REG", GPS_ALIVE_SYS_PWR_REG, 0xFFFFFFFF}, - {"ARM_CORE0_CONFIGURATION", ARM_CORE0_CONFIGURATION, 0x00000003}, - {"ARM_CORE0_STATUS", ARM_CORE0_STATUS, 0x00030003}, - {"ARM_CORE0_OPTION", ARM_CORE0_OPTION, 0x01010001}, - {"ARM_CORE1_CONFIGURATION", ARM_CORE1_CONFIGURATION, 0x00000003}, - {"ARM_CORE1_STATUS", ARM_CORE1_STATUS, 0x00030003}, - {"ARM_CORE1_OPTION", ARM_CORE1_OPTION, 0x01010001}, - {"ARM_COMMON_OPTION", ARM_COMMON_OPTION, 0x00000001}, - {"ARM_CPU_L2_0_CONFIGURATION", ARM_CPU_L2_0_CONFIGURATION, 0x00000003}, - {"ARM_CPU_L2_0_STATUS", ARM_CPU_L2_0_STATUS, 0x00000003}, - {"ARM_CPU_L2_1_CONFIGURATION", ARM_CPU_L2_1_CONFIGURATION, 0x00000003}, - {"ARM_CPU_L2_1_STATUS", ARM_CPU_L2_1_STATUS, 0x00000003}, - {"PAD_RETENTION_MAUDIO_OPTION", PAD_RETENTION_MAUDIO_OPTION, 0x00000000}, - {"PAD_RETENTION_GPIO_OPTION", PAD_RETENTION_GPIO_OPTION, 0x00000000}, - {"PAD_RETENTION_UART_OPTION", PAD_RETENTION_UART_OPTION, 0x00000000}, - {"PAD_RETENTION_MMCA_OPTION", PAD_RETENTION_MMCA_OPTION, 0x00000000}, - {"PAD_RETENTION_MMCB_OPTION", PAD_RETENTION_MMCB_OPTION, 0x00000000}, - {"PAD_RETENTION_EBIA_OPTION", PAD_RETENTION_EBIA_OPTION, 0x00000000}, - {"PAD_RETENTION_EBIB_OPTION", PAD_RETENTION_EBIB_OPTION, 0x00000000}, - {"PS_HOLD_CONTROL", PS_HOLD_CONTROL, 0x00005200}, - {"XUSBXTI_CONFIGURATION", XUSBXTI_CONFIGURATION, 0x00000001}, - {"XUSBXTI_STATUS", XUSBXTI_STATUS, 0x00000001}, - {"XUSBXTI_DURATION", XUSBXTI_DURATION, 0xFFF00000}, - {"XXTI_CONFIGURATION", XXTI_CONFIGURATION, 0x00000001}, - {"XXTI_STATUS", XXTI_STATUS, 0x00000001}, - {"XXTI_DURATION", XXTI_DURATION, 0xFFF00000}, - {"EXT_REGULATOR_DURATION", EXT_REGULATOR_DURATION, 0xFFF03FFF}, - {"CAM_CONFIGURATION", CAM_CONFIGURATION, 0x00000007}, - {"CAM_STATUS", CAM_STATUS, 0x00060007}, - {"CAM_OPTION", CAM_OPTION, 0x00000001}, - {"TV_CONFIGURATION", TV_CONFIGURATION, 0x00000007}, - {"TV_STATUS", TV_STATUS, 0x00060007}, - {"TV_OPTION", TV_OPTION, 0x00000001}, - {"MFC_CONFIGURATION", MFC_CONFIGURATION, 0x00000007}, - {"MFC_STATUS", MFC_STATUS, 0x00060007}, - {"MFC_OPTION", MFC_OPTION, 0x00000001}, - {"G3D_CONFIGURATION", G3D_CONFIGURATION, 0x00000007}, - {"G3D_STATUS", G3D_STATUS, 0x00060007}, - {"G3D_OPTION", G3D_OPTION, 0x00000001}, - {"LCD0_CONFIGURATION", LCD0_CONFIGURATION, 0x00000007}, - {"LCD0_STATUS", LCD0_STATUS, 0x00060007}, - {"LCD0_OPTION", LCD0_OPTION, 0x00000001}, - {"LCD1_CONFIGURATION", LCD1_CONFIGURATION, 0x00000007}, - {"LCD1_STATUS", LCD1_STATUS, 0x00060007}, - {"LCD1_OPTION", LCD1_OPTION, 0x00000001}, - {"GPS_CONFIGURATION", GPS_CONFIGURATION, 0x00000007}, - {"GPS_STATUS", GPS_STATUS, 0x00060007}, - {"GPS_OPTION", GPS_OPTION, 0x00000001}, - {"GPS_ALIVE_CONFIGURATION", GPS_ALIVE_CONFIGURATION, 0x00000007}, - {"GPS_ALIVE_STATUS", GPS_ALIVE_STATUS, 0x00060007}, - {"GPS_ALIVE_OPTION", GPS_ALIVE_OPTION, 0x00000001}, -}; - -#define PMU_NUM_OF_REGISTERS ARRAY_SIZE(exynos4210_pmu_regs) - -#define TYPE_EXYNOS4210_PMU "exynos4210.pmu" -#define EXYNOS4210_PMU(obj) \ - OBJECT_CHECK(Exynos4210PmuState, (obj), TYPE_EXYNOS4210_PMU) - -typedef struct Exynos4210PmuState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint32_t reg[PMU_NUM_OF_REGISTERS]; -} Exynos4210PmuState; - -static uint64_t exynos4210_pmu_read(void *opaque, hwaddr offset, - unsigned size) -{ - Exynos4210PmuState *s = (Exynos4210PmuState *)opaque; - unsigned i; - const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs; - - for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) { - if (reg_p->offset == offset) { - PRINT_DEBUG_EXTEND("%s [0x%04x] -> 0x%04x\n", reg_p->name, - (uint32_t)offset, s->reg[i]); - return s->reg[i]; - } - reg_p++; - } - PRINT_DEBUG("QEMU PMU ERROR: bad read offset 0x%04x\n", (uint32_t)offset); - return 0; -} - -static void exynos4210_pmu_write(void *opaque, hwaddr offset, - uint64_t val, unsigned size) -{ - Exynos4210PmuState *s = (Exynos4210PmuState *)opaque; - unsigned i; - const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs; - - for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) { - if (reg_p->offset == offset) { - PRINT_DEBUG_EXTEND("%s <0x%04x> <- 0x%04x\n", reg_p->name, - (uint32_t)offset, (uint32_t)val); - s->reg[i] = val; - return; - } - reg_p++; - } - PRINT_DEBUG("QEMU PMU ERROR: bad write offset 0x%04x\n", (uint32_t)offset); -} - -static const MemoryRegionOps exynos4210_pmu_ops = { - .read = exynos4210_pmu_read, - .write = exynos4210_pmu_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - .unaligned = false - } -}; - -static void exynos4210_pmu_reset(DeviceState *dev) -{ - Exynos4210PmuState *s = EXYNOS4210_PMU(dev); - unsigned i; - - /* Set default values for registers */ - for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) { - s->reg[i] = exynos4210_pmu_regs[i].reset_value; - } -} - -static int exynos4210_pmu_init(SysBusDevice *dev) -{ - Exynos4210PmuState *s = EXYNOS4210_PMU(dev); - - /* memory mapping */ - memory_region_init_io(&s->iomem, OBJECT(dev), &exynos4210_pmu_ops, s, - "exynos4210.pmu", EXYNOS4210_PMU_REGS_MEM_SIZE); - sysbus_init_mmio(dev, &s->iomem); - return 0; -} - -static const VMStateDescription exynos4210_pmu_vmstate = { - .name = "exynos4210.pmu", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(reg, Exynos4210PmuState, PMU_NUM_OF_REGISTERS), - VMSTATE_END_OF_LIST() - } -}; - -static void exynos4210_pmu_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = exynos4210_pmu_init; - dc->reset = exynos4210_pmu_reset; - dc->vmsd = &exynos4210_pmu_vmstate; -} - -static const TypeInfo exynos4210_pmu_info = { - .name = TYPE_EXYNOS4210_PMU, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(Exynos4210PmuState), - .class_init = exynos4210_pmu_class_init, -}; - -static void exynos4210_pmu_register(void) -{ - type_register_static(&exynos4210_pmu_info); -} - -type_init(exynos4210_pmu_register) diff --git a/qemu/hw/misc/hyperv_testdev.c b/qemu/hw/misc/hyperv_testdev.c deleted file mode 100644 index 1883fd7f2..000000000 --- a/qemu/hw/misc/hyperv_testdev.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * QEMU KVM Hyper-V test device to support Hyper-V kvm-unit-tests - * - * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com> - * - * Authors: - * Andrey Smetanin <asmetanin@virtuozzo.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/qdev.h" -#include "hw/isa/isa.h" -#include "sysemu/kvm.h" -#include "linux/kvm.h" -#include "target-i386/hyperv.h" -#include "kvm_i386.h" - -#define HV_TEST_DEV_MAX_SINT_ROUTES 64 - -struct HypervTestDev { - ISADevice parent_obj; - MemoryRegion sint_control; - HvSintRoute *sint_route[HV_TEST_DEV_MAX_SINT_ROUTES]; -}; -typedef struct HypervTestDev HypervTestDev; - -#define TYPE_HYPERV_TEST_DEV "hyperv-testdev" -#define HYPERV_TEST_DEV(obj) \ - OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV) - -enum { - HV_TEST_DEV_SINT_ROUTE_CREATE = 1, - HV_TEST_DEV_SINT_ROUTE_DESTROY, - HV_TEST_DEV_SINT_ROUTE_SET_SINT -}; - -static int alloc_sint_route_index(HypervTestDev *dev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dev->sint_route); i++) { - if (dev->sint_route[i] == NULL) { - return i; - } - } - return -1; -} - -static void free_sint_route_index(HypervTestDev *dev, int i) -{ - assert(i >= 0 && i < ARRAY_SIZE(dev->sint_route)); - dev->sint_route[i] = NULL; -} - -static int find_sint_route_index(HypervTestDev *dev, uint32_t vcpu_id, - uint32_t sint) -{ - HvSintRoute *sint_route; - int i; - - for (i = 0; i < ARRAY_SIZE(dev->sint_route); i++) { - sint_route = dev->sint_route[i]; - if (sint_route && sint_route->vcpu_id == vcpu_id && - sint_route->sint == sint) { - return i; - } - } - return -1; -} - -static void hv_synic_test_dev_control(HypervTestDev *dev, uint32_t ctl, - uint32_t vcpu_id, uint32_t sint) -{ - int i; - HvSintRoute *sint_route; - - switch (ctl) { - case HV_TEST_DEV_SINT_ROUTE_CREATE: - i = alloc_sint_route_index(dev); - assert(i >= 0); - sint_route = kvm_hv_sint_route_create(vcpu_id, sint, NULL); - assert(sint_route); - dev->sint_route[i] = sint_route; - break; - case HV_TEST_DEV_SINT_ROUTE_DESTROY: - i = find_sint_route_index(dev, vcpu_id, sint); - assert(i >= 0); - sint_route = dev->sint_route[i]; - kvm_hv_sint_route_destroy(sint_route); - free_sint_route_index(dev, i); - break; - case HV_TEST_DEV_SINT_ROUTE_SET_SINT: - i = find_sint_route_index(dev, vcpu_id, sint); - assert(i >= 0); - sint_route = dev->sint_route[i]; - kvm_hv_sint_route_set_sint(sint_route); - break; - default: - break; - } -} - -static void hv_test_dev_control(void *opaque, hwaddr addr, uint64_t data, - uint32_t len) -{ - HypervTestDev *dev = HYPERV_TEST_DEV(opaque); - uint8_t ctl; - - ctl = (data >> 16ULL) & 0xFF; - switch (ctl) { - case HV_TEST_DEV_SINT_ROUTE_CREATE: - case HV_TEST_DEV_SINT_ROUTE_DESTROY: - case HV_TEST_DEV_SINT_ROUTE_SET_SINT: { - uint8_t sint = data & 0xFF; - uint8_t vcpu_id = (data >> 8ULL) & 0xFF; - hv_synic_test_dev_control(dev, ctl, vcpu_id, sint); - break; - } - default: - break; - } -} - -static const MemoryRegionOps synic_test_sint_ops = { - .write = hv_test_dev_control, - .valid.min_access_size = 4, - .valid.max_access_size = 4, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void hv_test_dev_realizefn(DeviceState *d, Error **errp) -{ - ISADevice *isa = ISA_DEVICE(d); - HypervTestDev *dev = HYPERV_TEST_DEV(d); - MemoryRegion *io = isa_address_space_io(isa); - - memset(dev->sint_route, 0, sizeof(dev->sint_route)); - memory_region_init_io(&dev->sint_control, OBJECT(dev), - &synic_test_sint_ops, dev, - "hyperv-testdev-ctl", 4); - memory_region_add_subregion(io, 0x3000, &dev->sint_control); -} - -static void hv_test_dev_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - dc->realize = hv_test_dev_realizefn; -} - -static const TypeInfo hv_test_dev_info = { - .name = TYPE_HYPERV_TEST_DEV, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(HypervTestDev), - .class_init = hv_test_dev_class_init, -}; - -static void hv_test_dev_register_types(void) -{ - type_register_static(&hv_test_dev_info); -} -type_init(hv_test_dev_register_types); diff --git a/qemu/hw/misc/imx25_ccm.c b/qemu/hw/misc/imx25_ccm.c deleted file mode 100644 index 225604d82..000000000 --- a/qemu/hw/misc/imx25_ccm.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * IMX25 Clock Control Module - * - * Copyright (C) 2012 NICTA - * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - * To get the timer frequencies right, we need to emulate at least part of - * the CCM. - */ - -#include "qemu/osdep.h" -#include "hw/misc/imx25_ccm.h" - -#ifndef DEBUG_IMX25_CCM -#define DEBUG_IMX25_CCM 0 -#endif - -#define DPRINTF(fmt, args...) \ - do { \ - if (DEBUG_IMX25_CCM) { \ - fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX25_CCM, \ - __func__, ##args); \ - } \ - } while (0) - -static char const *imx25_ccm_reg_name(uint32_t reg) -{ - static char unknown[20]; - - switch (reg) { - case IMX25_CCM_MPCTL_REG: - return "mpctl"; - case IMX25_CCM_UPCTL_REG: - return "upctl"; - case IMX25_CCM_CCTL_REG: - return "cctl"; - case IMX25_CCM_CGCR0_REG: - return "cgcr0"; - case IMX25_CCM_CGCR1_REG: - return "cgcr1"; - case IMX25_CCM_CGCR2_REG: - return "cgcr2"; - case IMX25_CCM_PCDR0_REG: - return "pcdr0"; - case IMX25_CCM_PCDR1_REG: - return "pcdr1"; - case IMX25_CCM_PCDR2_REG: - return "pcdr2"; - case IMX25_CCM_PCDR3_REG: - return "pcdr3"; - case IMX25_CCM_RCSR_REG: - return "rcsr"; - case IMX25_CCM_CRDR_REG: - return "crdr"; - case IMX25_CCM_DCVR0_REG: - return "dcvr0"; - case IMX25_CCM_DCVR1_REG: - return "dcvr1"; - case IMX25_CCM_DCVR2_REG: - return "dcvr2"; - case IMX25_CCM_DCVR3_REG: - return "dcvr3"; - case IMX25_CCM_LTR0_REG: - return "ltr0"; - case IMX25_CCM_LTR1_REG: - return "ltr1"; - case IMX25_CCM_LTR2_REG: - return "ltr2"; - case IMX25_CCM_LTR3_REG: - return "ltr3"; - case IMX25_CCM_LTBR0_REG: - return "ltbr0"; - case IMX25_CCM_LTBR1_REG: - return "ltbr1"; - case IMX25_CCM_PMCR0_REG: - return "pmcr0"; - case IMX25_CCM_PMCR1_REG: - return "pmcr1"; - case IMX25_CCM_PMCR2_REG: - return "pmcr2"; - case IMX25_CCM_MCR_REG: - return "mcr"; - case IMX25_CCM_LPIMR0_REG: - return "lpimr0"; - case IMX25_CCM_LPIMR1_REG: - return "lpimr1"; - default: - sprintf(unknown, "[%d ?]", reg); - return unknown; - } -} -#define CKIH_FREQ 24000000 /* 24MHz crystal input */ - -static const VMStateDescription vmstate_imx25_ccm = { - .name = TYPE_IMX25_CCM, - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(reg, IMX25CCMState, IMX25_CCM_MAX_REG), - VMSTATE_END_OF_LIST() - }, -}; - -static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev) -{ - uint32_t freq; - IMX25CCMState *s = IMX25_CCM(dev); - - if (EXTRACT(s->reg[IMX25_CCM_CCTL_REG], MPLL_BYPASS)) { - freq = CKIH_FREQ; - } else { - freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ); - } - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev) -{ - uint32_t freq; - IMX25CCMState *s = IMX25_CCM(dev); - - freq = imx25_ccm_get_mpll_clk(dev); - - if (EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_SRC)) { - freq = (freq * 3 / 4); - } - - freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV)); - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev) -{ - uint32_t freq; - IMX25CCMState *s = IMX25_CCM(dev); - - freq = imx25_ccm_get_mcu_clk(dev) - / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV)); - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev) -{ - uint32_t freq; - - freq = imx25_ccm_get_ahb_clk(dev) / 2; - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) -{ - uint32_t freq = 0; - DPRINTF("Clock = %d)\n", clock); - - switch (clock) { - case CLK_NONE: - break; - case CLK_IPG: - case CLK_IPG_HIGH: - freq = imx25_ccm_get_ipg_clk(dev); - break; - case CLK_32k: - freq = CKIL_FREQ; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", - TYPE_IMX25_CCM, __func__, clock); - break; - } - - DPRINTF("Clock = %d) = %d\n", clock, freq); - - return freq; -} - -static void imx25_ccm_reset(DeviceState *dev) -{ - IMX25CCMState *s = IMX25_CCM(dev); - - DPRINTF("\n"); - - memset(s->reg, 0, IMX25_CCM_MAX_REG * sizeof(uint32_t)); - s->reg[IMX25_CCM_MPCTL_REG] = 0x800b2c01; - s->reg[IMX25_CCM_UPCTL_REG] = 0x84042800; - /* - * The value below gives: - * CPU = 133 MHz, AHB = 66,5 MHz, IPG = 33 MHz. - */ - s->reg[IMX25_CCM_CCTL_REG] = 0xd0030000; - s->reg[IMX25_CCM_CGCR0_REG] = 0x028A0100; - s->reg[IMX25_CCM_CGCR1_REG] = 0x04008100; - s->reg[IMX25_CCM_CGCR2_REG] = 0x00000438; - s->reg[IMX25_CCM_PCDR0_REG] = 0x01010101; - s->reg[IMX25_CCM_PCDR1_REG] = 0x01010101; - s->reg[IMX25_CCM_PCDR2_REG] = 0x01010101; - s->reg[IMX25_CCM_PCDR3_REG] = 0x01010101; - s->reg[IMX25_CCM_PMCR0_REG] = 0x00A00000; - s->reg[IMX25_CCM_PMCR1_REG] = 0x0000A030; - s->reg[IMX25_CCM_PMCR2_REG] = 0x0000A030; - s->reg[IMX25_CCM_MCR_REG] = 0x43000000; - - /* - * default boot will change the reset values to allow: - * CPU = 399 MHz, AHB = 133 MHz, IPG = 66,5 MHz. - * For some reason, this doesn't work. With the value below, linux - * detects a 88 MHz IPG CLK instead of 66,5 MHz. - s->reg[IMX25_CCM_CCTL_REG] = 0x20032000; - */ -} - -static uint64_t imx25_ccm_read(void *opaque, hwaddr offset, unsigned size) -{ - uint32_t value = 0; - IMX25CCMState *s = (IMX25CCMState *)opaque; - - if (offset < 0x70) { - value = s->reg[offset >> 2]; - } else { - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" - HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset); - } - - DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx25_ccm_reg_name(offset >> 2), - value); - - return value; -} - -static void imx25_ccm_write(void *opaque, hwaddr offset, uint64_t value, - unsigned size) -{ - IMX25CCMState *s = (IMX25CCMState *)opaque; - - DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx25_ccm_reg_name(offset >> 2), - (uint32_t)value); - - if (offset < 0x70) { - /* - * We will do a better implementation later. In particular some bits - * cannot be written to. - */ - s->reg[offset >> 2] = value; - } else { - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" - HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset); - } -} - -static const struct MemoryRegionOps imx25_ccm_ops = { - .read = imx25_ccm_read, - .write = imx25_ccm_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - /* - * Our device would not work correctly if the guest was doing - * unaligned access. This might not be a limitation on the real - * device but in practice there is no reason for a guest to access - * this device unaligned. - */ - .min_access_size = 4, - .max_access_size = 4, - .unaligned = false, - }, -}; - -static void imx25_ccm_init(Object *obj) -{ - DeviceState *dev = DEVICE(obj); - SysBusDevice *sd = SYS_BUS_DEVICE(obj); - IMX25CCMState *s = IMX25_CCM(obj); - - memory_region_init_io(&s->iomem, OBJECT(dev), &imx25_ccm_ops, s, - TYPE_IMX25_CCM, 0x1000); - sysbus_init_mmio(sd, &s->iomem); -} - -static void imx25_ccm_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - IMXCCMClass *ccm = IMX_CCM_CLASS(klass); - - dc->reset = imx25_ccm_reset; - dc->vmsd = &vmstate_imx25_ccm; - dc->desc = "i.MX25 Clock Control Module"; - - ccm->get_clock_frequency = imx25_ccm_get_clock_frequency; -} - -static const TypeInfo imx25_ccm_info = { - .name = TYPE_IMX25_CCM, - .parent = TYPE_IMX_CCM, - .instance_size = sizeof(IMX25CCMState), - .instance_init = imx25_ccm_init, - .class_init = imx25_ccm_class_init, -}; - -static void imx25_ccm_register_types(void) -{ - type_register_static(&imx25_ccm_info); -} - -type_init(imx25_ccm_register_types) diff --git a/qemu/hw/misc/imx31_ccm.c b/qemu/hw/misc/imx31_ccm.c deleted file mode 100644 index 80c164716..000000000 --- a/qemu/hw/misc/imx31_ccm.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * IMX31 Clock Control Module - * - * Copyright (C) 2012 NICTA - * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - * To get the timer frequencies right, we need to emulate at least part of - * the i.MX31 CCM. - */ - -#include "qemu/osdep.h" -#include "hw/misc/imx31_ccm.h" - -#define CKIH_FREQ 26000000 /* 26MHz crystal input */ - -#ifndef DEBUG_IMX31_CCM -#define DEBUG_IMX31_CCM 0 -#endif - -#define DPRINTF(fmt, args...) \ - do { \ - if (DEBUG_IMX31_CCM) { \ - fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX31_CCM, \ - __func__, ##args); \ - } \ - } while (0) - -static char const *imx31_ccm_reg_name(uint32_t reg) -{ - static char unknown[20]; - - switch (reg) { - case IMX31_CCM_CCMR_REG: - return "CCMR"; - case IMX31_CCM_PDR0_REG: - return "PDR0"; - case IMX31_CCM_PDR1_REG: - return "PDR1"; - case IMX31_CCM_RCSR_REG: - return "RCSR"; - case IMX31_CCM_MPCTL_REG: - return "MPCTL"; - case IMX31_CCM_UPCTL_REG: - return "UPCTL"; - case IMX31_CCM_SPCTL_REG: - return "SPCTL"; - case IMX31_CCM_COSR_REG: - return "COSR"; - case IMX31_CCM_CGR0_REG: - return "CGR0"; - case IMX31_CCM_CGR1_REG: - return "CGR1"; - case IMX31_CCM_CGR2_REG: - return "CGR2"; - case IMX31_CCM_WIMR_REG: - return "WIMR"; - case IMX31_CCM_LDC_REG: - return "LDC"; - case IMX31_CCM_DCVR0_REG: - return "DCVR0"; - case IMX31_CCM_DCVR1_REG: - return "DCVR1"; - case IMX31_CCM_DCVR2_REG: - return "DCVR2"; - case IMX31_CCM_DCVR3_REG: - return "DCVR3"; - case IMX31_CCM_LTR0_REG: - return "LTR0"; - case IMX31_CCM_LTR1_REG: - return "LTR1"; - case IMX31_CCM_LTR2_REG: - return "LTR2"; - case IMX31_CCM_LTR3_REG: - return "LTR3"; - case IMX31_CCM_LTBR0_REG: - return "LTBR0"; - case IMX31_CCM_LTBR1_REG: - return "LTBR1"; - case IMX31_CCM_PMCR0_REG: - return "PMCR0"; - case IMX31_CCM_PMCR1_REG: - return "PMCR1"; - case IMX31_CCM_PDR2_REG: - return "PDR2"; - default: - sprintf(unknown, "[%d ?]", reg); - return unknown; - } -} - -static const VMStateDescription vmstate_imx31_ccm = { - .name = TYPE_IMX31_CCM, - .version_id = 2, - .minimum_version_id = 2, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(reg, IMX31CCMState, IMX31_CCM_MAX_REG), - VMSTATE_END_OF_LIST() - }, -}; - -static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev) -{ - uint32_t freq = 0; - IMX31CCMState *s = IMX31_CCM(dev); - - if ((s->reg[IMX31_CCM_CCMR_REG] & CCMR_PRCS) == 2) { - if (s->reg[IMX31_CCM_CCMR_REG] & CCMR_FPME) { - freq = CKIL_FREQ; - if (s->reg[IMX31_CCM_CCMR_REG] & CCMR_FPMF) { - freq *= 1024; - } - } - } else { - freq = CKIH_FREQ; - } - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev) -{ - uint32_t freq; - IMX31CCMState *s = IMX31_CCM(dev); - - freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG], - imx31_ccm_get_pll_ref_clk(dev)); - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev) -{ - uint32_t freq; - IMX31CCMState *s = IMX31_CCM(dev); - - if ((s->reg[IMX31_CCM_CCMR_REG] & CCMR_MDS) || - !(s->reg[IMX31_CCM_CCMR_REG] & CCMR_MPE)) { - freq = imx31_ccm_get_pll_ref_clk(dev); - } else { - freq = imx31_ccm_get_mpll_clk(dev); - } - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev) -{ - uint32_t freq; - IMX31CCMState *s = IMX31_CCM(dev); - - freq = imx31_ccm_get_mcu_main_clk(dev) - / (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX)); - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev) -{ - uint32_t freq; - IMX31CCMState *s = IMX31_CCM(dev); - - freq = imx31_ccm_get_hclk_clk(dev) - / (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG)); - - DPRINTF("freq = %d\n", freq); - - return freq; -} - -static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) -{ - uint32_t freq = 0; - - switch (clock) { - case CLK_NONE: - break; - case CLK_IPG: - case CLK_IPG_HIGH: - freq = imx31_ccm_get_ipg_clk(dev); - break; - case CLK_32k: - freq = CKIL_FREQ; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", - TYPE_IMX31_CCM, __func__, clock); - break; - } - - DPRINTF("Clock = %d) = %d\n", clock, freq); - - return freq; -} - -static void imx31_ccm_reset(DeviceState *dev) -{ - IMX31CCMState *s = IMX31_CCM(dev); - - DPRINTF("()\n"); - - memset(s->reg, 0, sizeof(uint32_t) * IMX31_CCM_MAX_REG); - - s->reg[IMX31_CCM_CCMR_REG] = 0x074b0b7d; - s->reg[IMX31_CCM_PDR0_REG] = 0xff870b48; - s->reg[IMX31_CCM_PDR1_REG] = 0x49fcfe7f; - s->reg[IMX31_CCM_RCSR_REG] = 0x007f0000; - s->reg[IMX31_CCM_MPCTL_REG] = 0x04001800; - s->reg[IMX31_CCM_UPCTL_REG] = 0x04051c03; - s->reg[IMX31_CCM_SPCTL_REG] = 0x04043001; - s->reg[IMX31_CCM_COSR_REG] = 0x00000280; - s->reg[IMX31_CCM_CGR0_REG] = 0xffffffff; - s->reg[IMX31_CCM_CGR1_REG] = 0xffffffff; - s->reg[IMX31_CCM_CGR2_REG] = 0xffffffff; - s->reg[IMX31_CCM_WIMR_REG] = 0xffffffff; - s->reg[IMX31_CCM_LTR1_REG] = 0x00004040; - s->reg[IMX31_CCM_PMCR0_REG] = 0x80209828; - s->reg[IMX31_CCM_PMCR1_REG] = 0x00aa0000; - s->reg[IMX31_CCM_PDR2_REG] = 0x00000285; -} - -static uint64_t imx31_ccm_read(void *opaque, hwaddr offset, unsigned size) -{ - uint32_t value = 0; - IMX31CCMState *s = (IMX31CCMState *)opaque; - - if ((offset >> 2) < IMX31_CCM_MAX_REG) { - value = s->reg[offset >> 2]; - } else { - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" - HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset); - } - - DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2), - value); - - return (uint64_t)value; -} - -static void imx31_ccm_write(void *opaque, hwaddr offset, uint64_t value, - unsigned size) -{ - IMX31CCMState *s = (IMX31CCMState *)opaque; - - DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2), - (uint32_t)value); - - switch (offset >> 2) { - case IMX31_CCM_CCMR_REG: - s->reg[IMX31_CCM_CCMR_REG] = CCMR_FPMF | (value & 0x3b6fdfff); - break; - case IMX31_CCM_PDR0_REG: - s->reg[IMX31_CCM_PDR0_REG] = value & 0xff9f3fff; - break; - case IMX31_CCM_PDR1_REG: - s->reg[IMX31_CCM_PDR1_REG] = value; - break; - case IMX31_CCM_MPCTL_REG: - s->reg[IMX31_CCM_MPCTL_REG] = value & 0xbfff3fff; - break; - case IMX31_CCM_SPCTL_REG: - s->reg[IMX31_CCM_SPCTL_REG] = value & 0xbfff3fff; - break; - case IMX31_CCM_CGR0_REG: - s->reg[IMX31_CCM_CGR0_REG] = value; - break; - case IMX31_CCM_CGR1_REG: - s->reg[IMX31_CCM_CGR1_REG] = value; - break; - case IMX31_CCM_CGR2_REG: - s->reg[IMX31_CCM_CGR2_REG] = value; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" - HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset); - break; - } -} - -static const struct MemoryRegionOps imx31_ccm_ops = { - .read = imx31_ccm_read, - .write = imx31_ccm_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - /* - * Our device would not work correctly if the guest was doing - * unaligned access. This might not be a limitation on the real - * device but in practice there is no reason for a guest to access - * this device unaligned. - */ - .min_access_size = 4, - .max_access_size = 4, - .unaligned = false, - }, - -}; - -static void imx31_ccm_init(Object *obj) -{ - DeviceState *dev = DEVICE(obj); - SysBusDevice *sd = SYS_BUS_DEVICE(obj); - IMX31CCMState *s = IMX31_CCM(obj); - - memory_region_init_io(&s->iomem, OBJECT(dev), &imx31_ccm_ops, s, - TYPE_IMX31_CCM, 0x1000); - sysbus_init_mmio(sd, &s->iomem); -} - -static void imx31_ccm_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - IMXCCMClass *ccm = IMX_CCM_CLASS(klass); - - dc->reset = imx31_ccm_reset; - dc->vmsd = &vmstate_imx31_ccm; - dc->desc = "i.MX31 Clock Control Module"; - - ccm->get_clock_frequency = imx31_ccm_get_clock_frequency; -} - -static const TypeInfo imx31_ccm_info = { - .name = TYPE_IMX31_CCM, - .parent = TYPE_IMX_CCM, - .instance_size = sizeof(IMX31CCMState), - .instance_init = imx31_ccm_init, - .class_init = imx31_ccm_class_init, -}; - -static void imx31_ccm_register_types(void) -{ - type_register_static(&imx31_ccm_info); -} - -type_init(imx31_ccm_register_types) diff --git a/qemu/hw/misc/imx6_ccm.c b/qemu/hw/misc/imx6_ccm.c deleted file mode 100644 index 4e1d49da6..000000000 --- a/qemu/hw/misc/imx6_ccm.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * IMX6 Clock Control Module - * - * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - * To get the timer frequencies right, we need to emulate at least part of - * the CCM. - */ - -#include "qemu/osdep.h" -#include "hw/misc/imx6_ccm.h" - -#ifndef DEBUG_IMX6_CCM -#define DEBUG_IMX6_CCM 0 -#endif - -#define DPRINTF(fmt, args...) \ - do { \ - if (DEBUG_IMX6_CCM) { \ - fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX6_CCM, \ - __func__, ##args); \ - } \ - } while (0) - -static char const *imx6_ccm_reg_name(uint32_t reg) -{ - static char unknown[20]; - - switch (reg) { - case CCM_CCR: - return "CCR"; - case CCM_CCDR: - return "CCDR"; - case CCM_CSR: - return "CSR"; - case CCM_CCSR: - return "CCSR"; - case CCM_CACRR: - return "CACRR"; - case CCM_CBCDR: - return "CBCDR"; - case CCM_CBCMR: - return "CBCMR"; - case CCM_CSCMR1: - return "CSCMR1"; - case CCM_CSCMR2: - return "CSCMR2"; - case CCM_CSCDR1: - return "CSCDR1"; - case CCM_CS1CDR: - return "CS1CDR"; - case CCM_CS2CDR: - return "CS2CDR"; - case CCM_CDCDR: - return "CDCDR"; - case CCM_CHSCCDR: - return "CHSCCDR"; - case CCM_CSCDR2: - return "CSCDR2"; - case CCM_CSCDR3: - return "CSCDR3"; - case CCM_CDHIPR: - return "CDHIPR"; - case CCM_CTOR: - return "CTOR"; - case CCM_CLPCR: - return "CLPCR"; - case CCM_CISR: - return "CISR"; - case CCM_CIMR: - return "CIMR"; - case CCM_CCOSR: - return "CCOSR"; - case CCM_CGPR: - return "CGPR"; - case CCM_CCGR0: - return "CCGR0"; - case CCM_CCGR1: - return "CCGR1"; - case CCM_CCGR2: - return "CCGR2"; - case CCM_CCGR3: - return "CCGR3"; - case CCM_CCGR4: - return "CCGR4"; - case CCM_CCGR5: - return "CCGR5"; - case CCM_CCGR6: - return "CCGR6"; - case CCM_CMEOR: - return "CMEOR"; - default: - sprintf(unknown, "%d ?", reg); - return unknown; - } -} - -static char const *imx6_analog_reg_name(uint32_t reg) -{ - static char unknown[20]; - - switch (reg) { - case CCM_ANALOG_PLL_ARM: - return "PLL_ARM"; - case CCM_ANALOG_PLL_ARM_SET: - return "PLL_ARM_SET"; - case CCM_ANALOG_PLL_ARM_CLR: - return "PLL_ARM_CLR"; - case CCM_ANALOG_PLL_ARM_TOG: - return "PLL_ARM_TOG"; - case CCM_ANALOG_PLL_USB1: - return "PLL_USB1"; - case CCM_ANALOG_PLL_USB1_SET: - return "PLL_USB1_SET"; - case CCM_ANALOG_PLL_USB1_CLR: - return "PLL_USB1_CLR"; - case CCM_ANALOG_PLL_USB1_TOG: - return "PLL_USB1_TOG"; - case CCM_ANALOG_PLL_USB2: - return "PLL_USB2"; - case CCM_ANALOG_PLL_USB2_SET: - return "PLL_USB2_SET"; - case CCM_ANALOG_PLL_USB2_CLR: - return "PLL_USB2_CLR"; - case CCM_ANALOG_PLL_USB2_TOG: - return "PLL_USB2_TOG"; - case CCM_ANALOG_PLL_SYS: - return "PLL_SYS"; - case CCM_ANALOG_PLL_SYS_SET: - return "PLL_SYS_SET"; - case CCM_ANALOG_PLL_SYS_CLR: - return "PLL_SYS_CLR"; - case CCM_ANALOG_PLL_SYS_TOG: - return "PLL_SYS_TOG"; - case CCM_ANALOG_PLL_SYS_SS: - return "PLL_SYS_SS"; - case CCM_ANALOG_PLL_SYS_NUM: - return "PLL_SYS_NUM"; - case CCM_ANALOG_PLL_SYS_DENOM: - return "PLL_SYS_DENOM"; - case CCM_ANALOG_PLL_AUDIO: - return "PLL_AUDIO"; - case CCM_ANALOG_PLL_AUDIO_SET: - return "PLL_AUDIO_SET"; - case CCM_ANALOG_PLL_AUDIO_CLR: - return "PLL_AUDIO_CLR"; - case CCM_ANALOG_PLL_AUDIO_TOG: - return "PLL_AUDIO_TOG"; - case CCM_ANALOG_PLL_AUDIO_NUM: - return "PLL_AUDIO_NUM"; - case CCM_ANALOG_PLL_AUDIO_DENOM: - return "PLL_AUDIO_DENOM"; - case CCM_ANALOG_PLL_VIDEO: - return "PLL_VIDEO"; - case CCM_ANALOG_PLL_VIDEO_SET: - return "PLL_VIDEO_SET"; - case CCM_ANALOG_PLL_VIDEO_CLR: - return "PLL_VIDEO_CLR"; - case CCM_ANALOG_PLL_VIDEO_TOG: - return "PLL_VIDEO_TOG"; - case CCM_ANALOG_PLL_VIDEO_NUM: - return "PLL_VIDEO_NUM"; - case CCM_ANALOG_PLL_VIDEO_DENOM: - return "PLL_VIDEO_DENOM"; - case CCM_ANALOG_PLL_MLB: - return "PLL_MLB"; - case CCM_ANALOG_PLL_MLB_SET: - return "PLL_MLB_SET"; - case CCM_ANALOG_PLL_MLB_CLR: - return "PLL_MLB_CLR"; - case CCM_ANALOG_PLL_MLB_TOG: - return "PLL_MLB_TOG"; - case CCM_ANALOG_PLL_ENET: - return "PLL_ENET"; - case CCM_ANALOG_PLL_ENET_SET: - return "PLL_ENET_SET"; - case CCM_ANALOG_PLL_ENET_CLR: - return "PLL_ENET_CLR"; - case CCM_ANALOG_PLL_ENET_TOG: - return "PLL_ENET_TOG"; - case CCM_ANALOG_PFD_480: - return "PFD_480"; - case CCM_ANALOG_PFD_480_SET: - return "PFD_480_SET"; - case CCM_ANALOG_PFD_480_CLR: - return "PFD_480_CLR"; - case CCM_ANALOG_PFD_480_TOG: - return "PFD_480_TOG"; - case CCM_ANALOG_PFD_528: - return "PFD_528"; - case CCM_ANALOG_PFD_528_SET: - return "PFD_528_SET"; - case CCM_ANALOG_PFD_528_CLR: - return "PFD_528_CLR"; - case CCM_ANALOG_PFD_528_TOG: - return "PFD_528_TOG"; - case CCM_ANALOG_MISC0: - return "MISC0"; - case CCM_ANALOG_MISC0_SET: - return "MISC0_SET"; - case CCM_ANALOG_MISC0_CLR: - return "MISC0_CLR"; - case CCM_ANALOG_MISC0_TOG: - return "MISC0_TOG"; - case CCM_ANALOG_MISC2: - return "MISC2"; - case CCM_ANALOG_MISC2_SET: - return "MISC2_SET"; - case CCM_ANALOG_MISC2_CLR: - return "MISC2_CLR"; - case CCM_ANALOG_MISC2_TOG: - return "MISC2_TOG"; - case PMU_REG_1P1: - return "PMU_REG_1P1"; - case PMU_REG_3P0: - return "PMU_REG_3P0"; - case PMU_REG_2P5: - return "PMU_REG_2P5"; - case PMU_REG_CORE: - return "PMU_REG_CORE"; - case PMU_MISC1: - return "PMU_MISC1"; - case PMU_MISC1_SET: - return "PMU_MISC1_SET"; - case PMU_MISC1_CLR: - return "PMU_MISC1_CLR"; - case PMU_MISC1_TOG: - return "PMU_MISC1_TOG"; - case USB_ANALOG_DIGPROG: - return "USB_ANALOG_DIGPROG"; - default: - sprintf(unknown, "%d ?", reg); - return unknown; - } -} - -#define CKIH_FREQ 24000000 /* 24MHz crystal input */ - -static const VMStateDescription vmstate_imx6_ccm = { - .name = TYPE_IMX6_CCM, - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(ccm, IMX6CCMState, CCM_MAX), - VMSTATE_UINT32_ARRAY(analog, IMX6CCMState, CCM_ANALOG_MAX), - VMSTATE_END_OF_LIST() - }, -}; - -static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev) -{ - uint64_t freq = 24000000; - - if (EXTRACT(dev->analog[CCM_ANALOG_PLL_SYS], DIV_SELECT)) { - freq *= 22; - } else { - freq *= 20; - } - - DPRINTF("freq = %d\n", (uint32_t)freq); - - return freq; -} - -static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev) -{ - uint64_t freq = 0; - - freq = imx6_analog_get_pll2_clk(dev) * 18 - / EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC); - - DPRINTF("freq = %d\n", (uint32_t)freq); - - return freq; -} - -static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev) -{ - uint64_t freq = 0; - - freq = imx6_analog_get_pll2_clk(dev) * 18 - / EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC); - - DPRINTF("freq = %d\n", (uint32_t)freq); - - return freq; -} - -static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev) -{ - uint64_t freq = 0; - - switch (EXTRACT(dev->ccm[CCM_CBCMR], PRE_PERIPH_CLK_SEL)) { - case 0: - freq = imx6_analog_get_pll2_clk(dev); - break; - case 1: - freq = imx6_analog_get_pll2_pfd2_clk(dev); - break; - case 2: - freq = imx6_analog_get_pll2_pfd0_clk(dev); - break; - case 3: - freq = imx6_analog_get_pll2_pfd2_clk(dev) / 2; - break; - default: - /* We should never get there */ - g_assert_not_reached(); - break; - } - - DPRINTF("freq = %d\n", (uint32_t)freq); - - return freq; -} - -static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev) -{ - uint64_t freq = 0; - - freq = imx6_analog_get_periph_clk(dev) - / (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF)); - - DPRINTF("freq = %d\n", (uint32_t)freq); - - return freq; -} - -static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev) -{ - uint64_t freq = 0; - - freq = imx6_ccm_get_ahb_clk(dev) - / (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));; - - DPRINTF("freq = %d\n", (uint32_t)freq); - - return freq; -} - -static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev) -{ - uint64_t freq = 0; - - freq = imx6_ccm_get_ipg_clk(dev) - / (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF)); - - DPRINTF("freq = %d\n", (uint32_t)freq); - - return freq; -} - -static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) -{ - uint32_t freq = 0; - IMX6CCMState *s = IMX6_CCM(dev); - - switch (clock) { - case CLK_NONE: - break; - case CLK_IPG: - freq = imx6_ccm_get_ipg_clk(s); - break; - case CLK_IPG_HIGH: - freq = imx6_ccm_get_per_clk(s); - break; - case CLK_32k: - freq = CKIL_FREQ; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", - TYPE_IMX6_CCM, __func__, clock); - break; - } - - DPRINTF("Clock = %d) = %d\n", clock, freq); - - return freq; -} - -static void imx6_ccm_reset(DeviceState *dev) -{ - IMX6CCMState *s = IMX6_CCM(dev); - - DPRINTF("\n"); - - s->ccm[CCM_CCR] = 0x040116FF; - s->ccm[CCM_CCDR] = 0x00000000; - s->ccm[CCM_CSR] = 0x00000010; - s->ccm[CCM_CCSR] = 0x00000100; - s->ccm[CCM_CACRR] = 0x00000000; - s->ccm[CCM_CBCDR] = 0x00018D40; - s->ccm[CCM_CBCMR] = 0x00022324; - s->ccm[CCM_CSCMR1] = 0x00F00000; - s->ccm[CCM_CSCMR2] = 0x02B92F06; - s->ccm[CCM_CSCDR1] = 0x00490B00; - s->ccm[CCM_CS1CDR] = 0x0EC102C1; - s->ccm[CCM_CS2CDR] = 0x000736C1; - s->ccm[CCM_CDCDR] = 0x33F71F92; - s->ccm[CCM_CHSCCDR] = 0x0002A150; - s->ccm[CCM_CSCDR2] = 0x0002A150; - s->ccm[CCM_CSCDR3] = 0x00014841; - s->ccm[CCM_CDHIPR] = 0x00000000; - s->ccm[CCM_CTOR] = 0x00000000; - s->ccm[CCM_CLPCR] = 0x00000079; - s->ccm[CCM_CISR] = 0x00000000; - s->ccm[CCM_CIMR] = 0xFFFFFFFF; - s->ccm[CCM_CCOSR] = 0x000A0001; - s->ccm[CCM_CGPR] = 0x0000FE62; - s->ccm[CCM_CCGR0] = 0xFFFFFFFF; - s->ccm[CCM_CCGR1] = 0xFFFFFFFF; - s->ccm[CCM_CCGR2] = 0xFC3FFFFF; - s->ccm[CCM_CCGR3] = 0xFFFFFFFF; - s->ccm[CCM_CCGR4] = 0xFFFFFFFF; - s->ccm[CCM_CCGR5] = 0xFFFFFFFF; - s->ccm[CCM_CCGR6] = 0xFFFFFFFF; - s->ccm[CCM_CMEOR] = 0xFFFFFFFF; - - s->analog[CCM_ANALOG_PLL_ARM] = 0x00013042; - s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000; - s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000; - s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001; - s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000; - s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000; - s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012; - s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006; - s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100; - s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C; - s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C; - s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100; - s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447; - s->analog[CCM_ANALOG_PLL_MLB] = 0x00010000; - s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001; - s->analog[CCM_ANALOG_PFD_480] = 0x1311100C; - s->analog[CCM_ANALOG_PFD_528] = 0x1018101B; - - s->analog[PMU_REG_1P1] = 0x00001073; - s->analog[PMU_REG_3P0] = 0x00000F74; - s->analog[PMU_REG_2P5] = 0x00005071; - s->analog[PMU_REG_CORE] = 0x00402010; - s->analog[PMU_MISC0] = 0x04000000; - s->analog[PMU_MISC1] = 0x00000000; - s->analog[PMU_MISC2] = 0x00272727; - - s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x00000004; - s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000; - s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000; - s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000; - s->analog[USB_ANALOG_USB1_MISC] = 0x00000002; - s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x00000004; - s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000; - s->analog[USB_ANALOG_USB2_MISC] = 0x00000002; - s->analog[USB_ANALOG_DIGPROG] = 0x00000000; - - /* all PLLs need to be locked */ - s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK; - s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK; - s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK; - s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK; - s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK; - s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK; - s->analog[CCM_ANALOG_PLL_MLB] |= CCM_ANALOG_PLL_LOCK; - s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK; -} - -static uint64_t imx6_ccm_read(void *opaque, hwaddr offset, unsigned size) -{ - uint32_t value = 0; - uint32_t index = offset >> 2; - IMX6CCMState *s = (IMX6CCMState *)opaque; - - value = s->ccm[index]; - - DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_ccm_reg_name(index), value); - - return (uint64_t)value; -} - -static void imx6_ccm_write(void *opaque, hwaddr offset, uint64_t value, - unsigned size) -{ - uint32_t index = offset >> 2; - IMX6CCMState *s = (IMX6CCMState *)opaque; - - DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_ccm_reg_name(index), - (uint32_t)value); - - /* - * We will do a better implementation later. In particular some bits - * cannot be written to. - */ - s->ccm[index] = (uint32_t)value; -} - -static uint64_t imx6_analog_read(void *opaque, hwaddr offset, unsigned size) -{ - uint32_t value; - uint32_t index = offset >> 2; - IMX6CCMState *s = (IMX6CCMState *)opaque; - - switch (index) { - case CCM_ANALOG_PLL_ARM_SET: - case CCM_ANALOG_PLL_USB1_SET: - case CCM_ANALOG_PLL_USB2_SET: - case CCM_ANALOG_PLL_SYS_SET: - case CCM_ANALOG_PLL_AUDIO_SET: - case CCM_ANALOG_PLL_VIDEO_SET: - case CCM_ANALOG_PLL_MLB_SET: - case CCM_ANALOG_PLL_ENET_SET: - case CCM_ANALOG_PFD_480_SET: - case CCM_ANALOG_PFD_528_SET: - case CCM_ANALOG_MISC0_SET: - case PMU_MISC1_SET: - case CCM_ANALOG_MISC2_SET: - case USB_ANALOG_USB1_VBUS_DETECT_SET: - case USB_ANALOG_USB1_CHRG_DETECT_SET: - case USB_ANALOG_USB1_MISC_SET: - case USB_ANALOG_USB2_VBUS_DETECT_SET: - case USB_ANALOG_USB2_CHRG_DETECT_SET: - case USB_ANALOG_USB2_MISC_SET: - /* - * All REG_NAME_SET register access are in fact targeting the - * the REG_NAME register. - */ - value = s->analog[index - 1]; - break; - case CCM_ANALOG_PLL_ARM_CLR: - case CCM_ANALOG_PLL_USB1_CLR: - case CCM_ANALOG_PLL_USB2_CLR: - case CCM_ANALOG_PLL_SYS_CLR: - case CCM_ANALOG_PLL_AUDIO_CLR: - case CCM_ANALOG_PLL_VIDEO_CLR: - case CCM_ANALOG_PLL_MLB_CLR: - case CCM_ANALOG_PLL_ENET_CLR: - case CCM_ANALOG_PFD_480_CLR: - case CCM_ANALOG_PFD_528_CLR: - case CCM_ANALOG_MISC0_CLR: - case PMU_MISC1_CLR: - case CCM_ANALOG_MISC2_CLR: - case USB_ANALOG_USB1_VBUS_DETECT_CLR: - case USB_ANALOG_USB1_CHRG_DETECT_CLR: - case USB_ANALOG_USB1_MISC_CLR: - case USB_ANALOG_USB2_VBUS_DETECT_CLR: - case USB_ANALOG_USB2_CHRG_DETECT_CLR: - case USB_ANALOG_USB2_MISC_CLR: - /* - * All REG_NAME_CLR register access are in fact targeting the - * the REG_NAME register. - */ - value = s->analog[index - 2]; - break; - case CCM_ANALOG_PLL_ARM_TOG: - case CCM_ANALOG_PLL_USB1_TOG: - case CCM_ANALOG_PLL_USB2_TOG: - case CCM_ANALOG_PLL_SYS_TOG: - case CCM_ANALOG_PLL_AUDIO_TOG: - case CCM_ANALOG_PLL_VIDEO_TOG: - case CCM_ANALOG_PLL_MLB_TOG: - case CCM_ANALOG_PLL_ENET_TOG: - case CCM_ANALOG_PFD_480_TOG: - case CCM_ANALOG_PFD_528_TOG: - case CCM_ANALOG_MISC0_TOG: - case PMU_MISC1_TOG: - case CCM_ANALOG_MISC2_TOG: - case USB_ANALOG_USB1_VBUS_DETECT_TOG: - case USB_ANALOG_USB1_CHRG_DETECT_TOG: - case USB_ANALOG_USB1_MISC_TOG: - case USB_ANALOG_USB2_VBUS_DETECT_TOG: - case USB_ANALOG_USB2_CHRG_DETECT_TOG: - case USB_ANALOG_USB2_MISC_TOG: - /* - * All REG_NAME_TOG register access are in fact targeting the - * the REG_NAME register. - */ - value = s->analog[index - 3]; - break; - default: - value = s->analog[index]; - break; - } - - DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_analog_reg_name(index), value); - - return (uint64_t)value; -} - -static void imx6_analog_write(void *opaque, hwaddr offset, uint64_t value, - unsigned size) -{ - uint32_t index = offset >> 2; - IMX6CCMState *s = (IMX6CCMState *)opaque; - - DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_analog_reg_name(index), - (uint32_t)value); - - switch (index) { - case CCM_ANALOG_PLL_ARM_SET: - case CCM_ANALOG_PLL_USB1_SET: - case CCM_ANALOG_PLL_USB2_SET: - case CCM_ANALOG_PLL_SYS_SET: - case CCM_ANALOG_PLL_AUDIO_SET: - case CCM_ANALOG_PLL_VIDEO_SET: - case CCM_ANALOG_PLL_MLB_SET: - case CCM_ANALOG_PLL_ENET_SET: - case CCM_ANALOG_PFD_480_SET: - case CCM_ANALOG_PFD_528_SET: - case CCM_ANALOG_MISC0_SET: - case PMU_MISC1_SET: - case CCM_ANALOG_MISC2_SET: - case USB_ANALOG_USB1_VBUS_DETECT_SET: - case USB_ANALOG_USB1_CHRG_DETECT_SET: - case USB_ANALOG_USB1_MISC_SET: - case USB_ANALOG_USB2_VBUS_DETECT_SET: - case USB_ANALOG_USB2_CHRG_DETECT_SET: - case USB_ANALOG_USB2_MISC_SET: - /* - * All REG_NAME_SET register access are in fact targeting the - * the REG_NAME register. So we change the value of the - * REG_NAME register, setting bits passed in the value. - */ - s->analog[index - 1] |= value; - break; - case CCM_ANALOG_PLL_ARM_CLR: - case CCM_ANALOG_PLL_USB1_CLR: - case CCM_ANALOG_PLL_USB2_CLR: - case CCM_ANALOG_PLL_SYS_CLR: - case CCM_ANALOG_PLL_AUDIO_CLR: - case CCM_ANALOG_PLL_VIDEO_CLR: - case CCM_ANALOG_PLL_MLB_CLR: - case CCM_ANALOG_PLL_ENET_CLR: - case CCM_ANALOG_PFD_480_CLR: - case CCM_ANALOG_PFD_528_CLR: - case CCM_ANALOG_MISC0_CLR: - case PMU_MISC1_CLR: - case CCM_ANALOG_MISC2_CLR: - case USB_ANALOG_USB1_VBUS_DETECT_CLR: - case USB_ANALOG_USB1_CHRG_DETECT_CLR: - case USB_ANALOG_USB1_MISC_CLR: - case USB_ANALOG_USB2_VBUS_DETECT_CLR: - case USB_ANALOG_USB2_CHRG_DETECT_CLR: - case USB_ANALOG_USB2_MISC_CLR: - /* - * All REG_NAME_CLR register access are in fact targeting the - * the REG_NAME register. So we change the value of the - * REG_NAME register, unsetting bits passed in the value. - */ - s->analog[index - 2] &= ~value; - break; - case CCM_ANALOG_PLL_ARM_TOG: - case CCM_ANALOG_PLL_USB1_TOG: - case CCM_ANALOG_PLL_USB2_TOG: - case CCM_ANALOG_PLL_SYS_TOG: - case CCM_ANALOG_PLL_AUDIO_TOG: - case CCM_ANALOG_PLL_VIDEO_TOG: - case CCM_ANALOG_PLL_MLB_TOG: - case CCM_ANALOG_PLL_ENET_TOG: - case CCM_ANALOG_PFD_480_TOG: - case CCM_ANALOG_PFD_528_TOG: - case CCM_ANALOG_MISC0_TOG: - case PMU_MISC1_TOG: - case CCM_ANALOG_MISC2_TOG: - case USB_ANALOG_USB1_VBUS_DETECT_TOG: - case USB_ANALOG_USB1_CHRG_DETECT_TOG: - case USB_ANALOG_USB1_MISC_TOG: - case USB_ANALOG_USB2_VBUS_DETECT_TOG: - case USB_ANALOG_USB2_CHRG_DETECT_TOG: - case USB_ANALOG_USB2_MISC_TOG: - /* - * All REG_NAME_TOG register access are in fact targeting the - * the REG_NAME register. So we change the value of the - * REG_NAME register, toggling bits passed in the value. - */ - s->analog[index - 3] ^= value; - break; - default: - /* - * We will do a better implementation later. In particular some bits - * cannot be written to. - */ - s->analog[index] = value; - break; - } -} - -static const struct MemoryRegionOps imx6_ccm_ops = { - .read = imx6_ccm_read, - .write = imx6_ccm_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - /* - * Our device would not work correctly if the guest was doing - * unaligned access. This might not be a limitation on the real - * device but in practice there is no reason for a guest to access - * this device unaligned. - */ - .min_access_size = 4, - .max_access_size = 4, - .unaligned = false, - }, -}; - -static const struct MemoryRegionOps imx6_analog_ops = { - .read = imx6_analog_read, - .write = imx6_analog_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - /* - * Our device would not work correctly if the guest was doing - * unaligned access. This might not be a limitation on the real - * device but in practice there is no reason for a guest to access - * this device unaligned. - */ - .min_access_size = 4, - .max_access_size = 4, - .unaligned = false, - }, -}; - -static void imx6_ccm_init(Object *obj) -{ - DeviceState *dev = DEVICE(obj); - SysBusDevice *sd = SYS_BUS_DEVICE(obj); - IMX6CCMState *s = IMX6_CCM(obj); - - /* initialize a container for the all memory range */ - memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6_CCM, 0x5000); - - /* We initialize an IO memory region for the CCM part */ - memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6_ccm_ops, s, - TYPE_IMX6_CCM ".ccm", CCM_MAX * sizeof(uint32_t)); - - /* Add the CCM as a subregion at offset 0 */ - memory_region_add_subregion(&s->container, 0, &s->ioccm); - - /* We initialize an IO memory region for the ANALOG part */ - memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6_analog_ops, s, - TYPE_IMX6_CCM ".analog", - CCM_ANALOG_MAX * sizeof(uint32_t)); - - /* Add the ANALOG as a subregion at offset 0x4000 */ - memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog); - - sysbus_init_mmio(sd, &s->container); -} - -static void imx6_ccm_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - IMXCCMClass *ccm = IMX_CCM_CLASS(klass); - - dc->reset = imx6_ccm_reset; - dc->vmsd = &vmstate_imx6_ccm; - dc->desc = "i.MX6 Clock Control Module"; - - ccm->get_clock_frequency = imx6_ccm_get_clock_frequency; -} - -static const TypeInfo imx6_ccm_info = { - .name = TYPE_IMX6_CCM, - .parent = TYPE_IMX_CCM, - .instance_size = sizeof(IMX6CCMState), - .instance_init = imx6_ccm_init, - .class_init = imx6_ccm_class_init, -}; - -static void imx6_ccm_register_types(void) -{ - type_register_static(&imx6_ccm_info); -} - -type_init(imx6_ccm_register_types) diff --git a/qemu/hw/misc/imx_ccm.c b/qemu/hw/misc/imx_ccm.c deleted file mode 100644 index 986d890ca..000000000 --- a/qemu/hw/misc/imx_ccm.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * IMX31 Clock Control Module - * - * Copyright (C) 2012 NICTA - * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - * This is an abstract base class used to get a common interface to - * retrieve the CCM frequencies from the various i.MX SOC. - */ - -#include "qemu/osdep.h" -#include "hw/misc/imx_ccm.h" - -#ifndef DEBUG_IMX_CCM -#define DEBUG_IMX_CCM 0 -#endif - -#define DPRINTF(fmt, args...) \ - do { \ - if (DEBUG_IMX_CCM) { \ - fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_CCM, \ - __func__, ##args); \ - } \ - } while (0) - - -uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) -{ - uint32_t freq = 0; - IMXCCMClass *klass = IMX_GET_CLASS(dev); - - if (klass->get_clock_frequency) { - freq = klass->get_clock_frequency(dev, clock); - } - - DPRINTF("(clock = %d) = %d\n", clock, freq); - - return freq; -} - -/* - * Calculate PLL output frequency - */ -uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq) -{ - int32_t freq; - int32_t mfn = MFN(pllreg); /* Numerator */ - uint32_t mfi = MFI(pllreg); /* Integer part */ - uint32_t mfd = 1 + MFD(pllreg); /* Denominator */ - uint32_t pd = 1 + PD(pllreg); /* Pre-divider */ - - if (mfi < 5) { - mfi = 5; - } - - /* mfn is 10-bit signed twos-complement */ - mfn <<= 32 - 10; - mfn >>= 32 - 10; - - freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) / - (mfd * pd)) << 10; - - DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq, - freq); - - return freq; -} - -static const TypeInfo imx_ccm_info = { - .name = TYPE_IMX_CCM, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(IMXCCMState), - .class_size = sizeof(IMXCCMClass), - .abstract = true, -}; - -static void imx_ccm_register_types(void) -{ - type_register_static(&imx_ccm_info); -} - -type_init(imx_ccm_register_types) diff --git a/qemu/hw/misc/ivshmem.c b/qemu/hw/misc/ivshmem.c deleted file mode 100644 index e40f23bfc..000000000 --- a/qemu/hw/misc/ivshmem.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* - * Inter-VM Shared Memory PCI device. - * - * Author: - * Cam Macdonell <cam@cs.ualberta.ca> - * - * Based On: cirrus_vga.c - * Copyright (c) 2004 Fabrice Bellard - * Copyright (c) 2004 Makoto Suzuki (suzu) - * - * and rtl8139.c - * Copyright (c) 2006 Igor Kovalenko - * - * This code is licensed under the GNU GPL v2. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu/cutils.h" -#include "hw/hw.h" -#include "hw/i386/pc.h" -#include "hw/pci/pci.h" -#include "hw/pci/msi.h" -#include "hw/pci/msix.h" -#include "sysemu/kvm.h" -#include "migration/migration.h" -#include "qemu/error-report.h" -#include "qemu/event_notifier.h" -#include "qom/object_interfaces.h" -#include "sysemu/char.h" -#include "sysemu/hostmem.h" -#include "sysemu/qtest.h" -#include "qapi/visitor.h" -#include "exec/ram_addr.h" - -#include "hw/misc/ivshmem.h" - -#include <sys/mman.h> - -#define PCI_VENDOR_ID_IVSHMEM PCI_VENDOR_ID_REDHAT_QUMRANET -#define PCI_DEVICE_ID_IVSHMEM 0x1110 - -#define IVSHMEM_MAX_PEERS UINT16_MAX -#define IVSHMEM_IOEVENTFD 0 -#define IVSHMEM_MSI 1 - -#define IVSHMEM_REG_BAR_SIZE 0x100 - -#define IVSHMEM_DEBUG 0 -#define IVSHMEM_DPRINTF(fmt, ...) \ - do { \ - if (IVSHMEM_DEBUG) { \ - printf("IVSHMEM: " fmt, ## __VA_ARGS__); \ - } \ - } while (0) - -#define TYPE_IVSHMEM_COMMON "ivshmem-common" -#define IVSHMEM_COMMON(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_COMMON) - -#define TYPE_IVSHMEM_PLAIN "ivshmem-plain" -#define IVSHMEM_PLAIN(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_PLAIN) - -#define TYPE_IVSHMEM_DOORBELL "ivshmem-doorbell" -#define IVSHMEM_DOORBELL(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_DOORBELL) - -#define TYPE_IVSHMEM "ivshmem" -#define IVSHMEM(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM) - -typedef struct Peer { - int nb_eventfds; - EventNotifier *eventfds; -} Peer; - -typedef struct MSIVector { - PCIDevice *pdev; - int virq; -} MSIVector; - -typedef struct IVShmemState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - uint32_t features; - - /* exactly one of these two may be set */ - HostMemoryBackend *hostmem; /* with interrupts */ - CharDriverState *server_chr; /* without interrupts */ - - /* registers */ - uint32_t intrmask; - uint32_t intrstatus; - int vm_id; - - /* BARs */ - MemoryRegion ivshmem_mmio; /* BAR 0 (registers) */ - MemoryRegion *ivshmem_bar2; /* BAR 2 (shared memory) */ - MemoryRegion server_bar2; /* used with server_chr */ - - /* interrupt support */ - Peer *peers; - int nb_peers; /* space in @peers[] */ - uint32_t vectors; - MSIVector *msi_vectors; - uint64_t msg_buf; /* buffer for receiving server messages */ - int msg_buffered_bytes; /* #bytes in @msg_buf */ - - /* migration stuff */ - OnOffAuto master; - Error *migration_blocker; - - /* legacy cruft */ - char *role; - char *shmobj; - char *sizearg; - size_t legacy_size; - uint32_t not_legacy_32bit; -} IVShmemState; - -/* registers for the Inter-VM shared memory device */ -enum ivshmem_registers { - INTRMASK = 0, - INTRSTATUS = 4, - IVPOSITION = 8, - DOORBELL = 12, -}; - -static inline uint32_t ivshmem_has_feature(IVShmemState *ivs, - unsigned int feature) { - return (ivs->features & (1 << feature)); -} - -static inline bool ivshmem_is_master(IVShmemState *s) -{ - assert(s->master != ON_OFF_AUTO_AUTO); - return s->master == ON_OFF_AUTO_ON; -} - -static void ivshmem_update_irq(IVShmemState *s) -{ - PCIDevice *d = PCI_DEVICE(s); - uint32_t isr = s->intrstatus & s->intrmask; - - /* - * Do nothing unless the device actually uses INTx. Here's how - * the device variants signal interrupts, what they put in PCI - * config space: - * Device variant Interrupt Interrupt Pin MSI-X cap. - * ivshmem-plain none 0 no - * ivshmem-doorbell MSI-X 1 yes(1) - * ivshmem,msi=off INTx 1 no - * ivshmem,msi=on MSI-X 1(2) yes(1) - * (1) if guest enabled MSI-X - * (2) the device lies - * Leads to the condition for doing nothing: - */ - if (ivshmem_has_feature(s, IVSHMEM_MSI) - || !d->config[PCI_INTERRUPT_PIN]) { - return; - } - - /* don't print ISR resets */ - if (isr) { - IVSHMEM_DPRINTF("Set IRQ to %d (%04x %04x)\n", - isr ? 1 : 0, s->intrstatus, s->intrmask); - } - - pci_set_irq(d, isr != 0); -} - -static void ivshmem_IntrMask_write(IVShmemState *s, uint32_t val) -{ - IVSHMEM_DPRINTF("IntrMask write(w) val = 0x%04x\n", val); - - s->intrmask = val; - ivshmem_update_irq(s); -} - -static uint32_t ivshmem_IntrMask_read(IVShmemState *s) -{ - uint32_t ret = s->intrmask; - - IVSHMEM_DPRINTF("intrmask read(w) val = 0x%04x\n", ret); - return ret; -} - -static void ivshmem_IntrStatus_write(IVShmemState *s, uint32_t val) -{ - IVSHMEM_DPRINTF("IntrStatus write(w) val = 0x%04x\n", val); - - s->intrstatus = val; - ivshmem_update_irq(s); -} - -static uint32_t ivshmem_IntrStatus_read(IVShmemState *s) -{ - uint32_t ret = s->intrstatus; - - /* reading ISR clears all interrupts */ - s->intrstatus = 0; - ivshmem_update_irq(s); - return ret; -} - -static void ivshmem_io_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - IVShmemState *s = opaque; - - uint16_t dest = val >> 16; - uint16_t vector = val & 0xff; - - addr &= 0xfc; - - IVSHMEM_DPRINTF("writing to addr " TARGET_FMT_plx "\n", addr); - switch (addr) - { - case INTRMASK: - ivshmem_IntrMask_write(s, val); - break; - - case INTRSTATUS: - ivshmem_IntrStatus_write(s, val); - break; - - case DOORBELL: - /* check that dest VM ID is reasonable */ - if (dest >= s->nb_peers) { - IVSHMEM_DPRINTF("Invalid destination VM ID (%d)\n", dest); - break; - } - - /* check doorbell range */ - if (vector < s->peers[dest].nb_eventfds) { - IVSHMEM_DPRINTF("Notifying VM %d on vector %d\n", dest, vector); - event_notifier_set(&s->peers[dest].eventfds[vector]); - } else { - IVSHMEM_DPRINTF("Invalid destination vector %d on VM %d\n", - vector, dest); - } - break; - default: - IVSHMEM_DPRINTF("Unhandled write " TARGET_FMT_plx "\n", addr); - } -} - -static uint64_t ivshmem_io_read(void *opaque, hwaddr addr, - unsigned size) -{ - - IVShmemState *s = opaque; - uint32_t ret; - - switch (addr) - { - case INTRMASK: - ret = ivshmem_IntrMask_read(s); - break; - - case INTRSTATUS: - ret = ivshmem_IntrStatus_read(s); - break; - - case IVPOSITION: - ret = s->vm_id; - break; - - default: - IVSHMEM_DPRINTF("why are we reading " TARGET_FMT_plx "\n", addr); - ret = 0; - } - - return ret; -} - -static const MemoryRegionOps ivshmem_mmio_ops = { - .read = ivshmem_io_read, - .write = ivshmem_io_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static void ivshmem_vector_notify(void *opaque) -{ - MSIVector *entry = opaque; - PCIDevice *pdev = entry->pdev; - IVShmemState *s = IVSHMEM_COMMON(pdev); - int vector = entry - s->msi_vectors; - EventNotifier *n = &s->peers[s->vm_id].eventfds[vector]; - - if (!event_notifier_test_and_clear(n)) { - return; - } - - IVSHMEM_DPRINTF("interrupt on vector %p %d\n", pdev, vector); - if (ivshmem_has_feature(s, IVSHMEM_MSI)) { - if (msix_enabled(pdev)) { - msix_notify(pdev, vector); - } - } else { - ivshmem_IntrStatus_write(s, 1); - } -} - -static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector, - MSIMessage msg) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - EventNotifier *n = &s->peers[s->vm_id].eventfds[vector]; - MSIVector *v = &s->msi_vectors[vector]; - int ret; - - IVSHMEM_DPRINTF("vector unmask %p %d\n", dev, vector); - - ret = kvm_irqchip_update_msi_route(kvm_state, v->virq, msg, dev); - if (ret < 0) { - return ret; - } - - return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq); -} - -static void ivshmem_vector_mask(PCIDevice *dev, unsigned vector) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - EventNotifier *n = &s->peers[s->vm_id].eventfds[vector]; - int ret; - - IVSHMEM_DPRINTF("vector mask %p %d\n", dev, vector); - - ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, - s->msi_vectors[vector].virq); - if (ret != 0) { - error_report("remove_irqfd_notifier_gsi failed"); - } -} - -static void ivshmem_vector_poll(PCIDevice *dev, - unsigned int vector_start, - unsigned int vector_end) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - unsigned int vector; - - IVSHMEM_DPRINTF("vector poll %p %d-%d\n", dev, vector_start, vector_end); - - vector_end = MIN(vector_end, s->vectors); - - for (vector = vector_start; vector < vector_end; vector++) { - EventNotifier *notifier = &s->peers[s->vm_id].eventfds[vector]; - - if (!msix_is_masked(dev, vector)) { - continue; - } - - if (event_notifier_test_and_clear(notifier)) { - msix_set_pending(dev, vector); - } - } -} - -static void watch_vector_notifier(IVShmemState *s, EventNotifier *n, - int vector) -{ - int eventfd = event_notifier_get_fd(n); - - assert(!s->msi_vectors[vector].pdev); - s->msi_vectors[vector].pdev = PCI_DEVICE(s); - - qemu_set_fd_handler(eventfd, ivshmem_vector_notify, - NULL, &s->msi_vectors[vector]); -} - -static void ivshmem_add_eventfd(IVShmemState *s, int posn, int i) -{ - memory_region_add_eventfd(&s->ivshmem_mmio, - DOORBELL, - 4, - true, - (posn << 16) | i, - &s->peers[posn].eventfds[i]); -} - -static void ivshmem_del_eventfd(IVShmemState *s, int posn, int i) -{ - memory_region_del_eventfd(&s->ivshmem_mmio, - DOORBELL, - 4, - true, - (posn << 16) | i, - &s->peers[posn].eventfds[i]); -} - -static void close_peer_eventfds(IVShmemState *s, int posn) -{ - int i, n; - - assert(posn >= 0 && posn < s->nb_peers); - n = s->peers[posn].nb_eventfds; - - if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { - memory_region_transaction_begin(); - for (i = 0; i < n; i++) { - ivshmem_del_eventfd(s, posn, i); - } - memory_region_transaction_commit(); - } - - for (i = 0; i < n; i++) { - event_notifier_cleanup(&s->peers[posn].eventfds[i]); - } - - g_free(s->peers[posn].eventfds); - s->peers[posn].nb_eventfds = 0; -} - -static void resize_peers(IVShmemState *s, int nb_peers) -{ - int old_nb_peers = s->nb_peers; - int i; - - assert(nb_peers > old_nb_peers); - IVSHMEM_DPRINTF("bumping storage to %d peers\n", nb_peers); - - s->peers = g_realloc(s->peers, nb_peers * sizeof(Peer)); - s->nb_peers = nb_peers; - - for (i = old_nb_peers; i < nb_peers; i++) { - s->peers[i].eventfds = g_new0(EventNotifier, s->vectors); - s->peers[i].nb_eventfds = 0; - } -} - -static void ivshmem_add_kvm_msi_virq(IVShmemState *s, int vector, - Error **errp) -{ - PCIDevice *pdev = PCI_DEVICE(s); - MSIMessage msg = msix_get_message(pdev, vector); - int ret; - - IVSHMEM_DPRINTF("ivshmem_add_kvm_msi_virq vector:%d\n", vector); - assert(!s->msi_vectors[vector].pdev); - - ret = kvm_irqchip_add_msi_route(kvm_state, msg, pdev); - if (ret < 0) { - error_setg(errp, "kvm_irqchip_add_msi_route failed"); - return; - } - - s->msi_vectors[vector].virq = ret; - s->msi_vectors[vector].pdev = pdev; -} - -static void setup_interrupt(IVShmemState *s, int vector, Error **errp) -{ - EventNotifier *n = &s->peers[s->vm_id].eventfds[vector]; - bool with_irqfd = kvm_msi_via_irqfd_enabled() && - ivshmem_has_feature(s, IVSHMEM_MSI); - PCIDevice *pdev = PCI_DEVICE(s); - Error *err = NULL; - - IVSHMEM_DPRINTF("setting up interrupt for vector: %d\n", vector); - - if (!with_irqfd) { - IVSHMEM_DPRINTF("with eventfd\n"); - watch_vector_notifier(s, n, vector); - } else if (msix_enabled(pdev)) { - IVSHMEM_DPRINTF("with irqfd\n"); - ivshmem_add_kvm_msi_virq(s, vector, &err); - if (err) { - error_propagate(errp, err); - return; - } - - if (!msix_is_masked(pdev, vector)) { - kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, - s->msi_vectors[vector].virq); - /* TODO handle error */ - } - } else { - /* it will be delayed until msix is enabled, in write_config */ - IVSHMEM_DPRINTF("with irqfd, delayed until msix enabled\n"); - } -} - -static void process_msg_shmem(IVShmemState *s, int fd, Error **errp) -{ - struct stat buf; - size_t size; - void *ptr; - - if (s->ivshmem_bar2) { - error_setg(errp, "server sent unexpected shared memory message"); - close(fd); - return; - } - - if (fstat(fd, &buf) < 0) { - error_setg_errno(errp, errno, - "can't determine size of shared memory sent by server"); - close(fd); - return; - } - - size = buf.st_size; - - /* Legacy cruft */ - if (s->legacy_size != SIZE_MAX) { - if (size < s->legacy_size) { - error_setg(errp, "server sent only %zd bytes of shared memory", - (size_t)buf.st_size); - close(fd); - return; - } - size = s->legacy_size; - } - - /* mmap the region and map into the BAR2 */ - ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) { - error_setg_errno(errp, errno, "Failed to mmap shared memory"); - close(fd); - return; - } - memory_region_init_ram_ptr(&s->server_bar2, OBJECT(s), - "ivshmem.bar2", size, ptr); - qemu_set_ram_fd(memory_region_get_ram_addr(&s->server_bar2), fd); - s->ivshmem_bar2 = &s->server_bar2; -} - -static void process_msg_disconnect(IVShmemState *s, uint16_t posn, - Error **errp) -{ - IVSHMEM_DPRINTF("posn %d has gone away\n", posn); - if (posn >= s->nb_peers || posn == s->vm_id) { - error_setg(errp, "invalid peer %d", posn); - return; - } - close_peer_eventfds(s, posn); -} - -static void process_msg_connect(IVShmemState *s, uint16_t posn, int fd, - Error **errp) -{ - Peer *peer = &s->peers[posn]; - int vector; - - /* - * The N-th connect message for this peer comes with the file - * descriptor for vector N-1. Count messages to find the vector. - */ - if (peer->nb_eventfds >= s->vectors) { - error_setg(errp, "Too many eventfd received, device has %d vectors", - s->vectors); - close(fd); - return; - } - vector = peer->nb_eventfds++; - - IVSHMEM_DPRINTF("eventfds[%d][%d] = %d\n", posn, vector, fd); - event_notifier_init_fd(&peer->eventfds[vector], fd); - fcntl_setfl(fd, O_NONBLOCK); /* msix/irqfd poll non block */ - - if (posn == s->vm_id) { - setup_interrupt(s, vector, errp); - /* TODO do we need to handle the error? */ - } - - if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { - ivshmem_add_eventfd(s, posn, vector); - } -} - -static void process_msg(IVShmemState *s, int64_t msg, int fd, Error **errp) -{ - IVSHMEM_DPRINTF("posn is %" PRId64 ", fd is %d\n", msg, fd); - - if (msg < -1 || msg > IVSHMEM_MAX_PEERS) { - error_setg(errp, "server sent invalid message %" PRId64, msg); - close(fd); - return; - } - - if (msg == -1) { - process_msg_shmem(s, fd, errp); - return; - } - - if (msg >= s->nb_peers) { - resize_peers(s, msg + 1); - } - - if (fd >= 0) { - process_msg_connect(s, msg, fd, errp); - } else { - process_msg_disconnect(s, msg, errp); - } -} - -static int ivshmem_can_receive(void *opaque) -{ - IVShmemState *s = opaque; - - assert(s->msg_buffered_bytes < sizeof(s->msg_buf)); - return sizeof(s->msg_buf) - s->msg_buffered_bytes; -} - -static void ivshmem_read(void *opaque, const uint8_t *buf, int size) -{ - IVShmemState *s = opaque; - Error *err = NULL; - int fd; - int64_t msg; - - assert(size >= 0 && s->msg_buffered_bytes + size <= sizeof(s->msg_buf)); - memcpy((unsigned char *)&s->msg_buf + s->msg_buffered_bytes, buf, size); - s->msg_buffered_bytes += size; - if (s->msg_buffered_bytes < sizeof(s->msg_buf)) { - return; - } - msg = le64_to_cpu(s->msg_buf); - s->msg_buffered_bytes = 0; - - fd = qemu_chr_fe_get_msgfd(s->server_chr); - IVSHMEM_DPRINTF("posn is %" PRId64 ", fd is %d\n", msg, fd); - - process_msg(s, msg, fd, &err); - if (err) { - error_report_err(err); - } -} - -static int64_t ivshmem_recv_msg(IVShmemState *s, int *pfd, Error **errp) -{ - int64_t msg; - int n, ret; - - n = 0; - do { - ret = qemu_chr_fe_read_all(s->server_chr, (uint8_t *)&msg + n, - sizeof(msg) - n); - if (ret < 0 && ret != -EINTR) { - error_setg_errno(errp, -ret, "read from server failed"); - return INT64_MIN; - } - n += ret; - } while (n < sizeof(msg)); - - *pfd = qemu_chr_fe_get_msgfd(s->server_chr); - return msg; -} - -static void ivshmem_recv_setup(IVShmemState *s, Error **errp) -{ - Error *err = NULL; - int64_t msg; - int fd; - - msg = ivshmem_recv_msg(s, &fd, &err); - if (err) { - error_propagate(errp, err); - return; - } - if (msg != IVSHMEM_PROTOCOL_VERSION) { - error_setg(errp, "server sent version %" PRId64 ", expecting %d", - msg, IVSHMEM_PROTOCOL_VERSION); - return; - } - if (fd != -1) { - error_setg(errp, "server sent invalid version message"); - return; - } - - /* - * ivshmem-server sends the remaining initial messages in a fixed - * order, but the device has always accepted them in any order. - * Stay as compatible as practical, just in case people use - * servers that behave differently. - */ - - /* - * ivshmem_device_spec.txt has always required the ID message - * right here, and ivshmem-server has always complied. However, - * older versions of the device accepted it out of order, but - * broke when an interrupt setup message arrived before it. - */ - msg = ivshmem_recv_msg(s, &fd, &err); - if (err) { - error_propagate(errp, err); - return; - } - if (fd != -1 || msg < 0 || msg > IVSHMEM_MAX_PEERS) { - error_setg(errp, "server sent invalid ID message"); - return; - } - s->vm_id = msg; - - /* - * Receive more messages until we got shared memory. - */ - do { - msg = ivshmem_recv_msg(s, &fd, &err); - if (err) { - error_propagate(errp, err); - return; - } - process_msg(s, msg, fd, &err); - if (err) { - error_propagate(errp, err); - return; - } - } while (msg != -1); - - /* - * This function must either map the shared memory or fail. The - * loop above ensures that: it terminates normally only after it - * successfully processed the server's shared memory message. - * Assert that actually mapped the shared memory: - */ - assert(s->ivshmem_bar2); -} - -/* Select the MSI-X vectors used by device. - * ivshmem maps events to vectors statically, so - * we just enable all vectors on init and after reset. */ -static void ivshmem_msix_vector_use(IVShmemState *s) -{ - PCIDevice *d = PCI_DEVICE(s); - int i; - - for (i = 0; i < s->vectors; i++) { - msix_vector_use(d, i); - } -} - -static void ivshmem_reset(DeviceState *d) -{ - IVShmemState *s = IVSHMEM_COMMON(d); - - s->intrstatus = 0; - s->intrmask = 0; - if (ivshmem_has_feature(s, IVSHMEM_MSI)) { - ivshmem_msix_vector_use(s); - } -} - -static int ivshmem_setup_interrupts(IVShmemState *s) -{ - /* allocate QEMU callback data for receiving interrupts */ - s->msi_vectors = g_malloc0(s->vectors * sizeof(MSIVector)); - - if (ivshmem_has_feature(s, IVSHMEM_MSI)) { - if (msix_init_exclusive_bar(PCI_DEVICE(s), s->vectors, 1)) { - return -1; - } - - IVSHMEM_DPRINTF("msix initialized (%d vectors)\n", s->vectors); - ivshmem_msix_vector_use(s); - } - - return 0; -} - -static void ivshmem_enable_irqfd(IVShmemState *s) -{ - PCIDevice *pdev = PCI_DEVICE(s); - int i; - - for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) { - Error *err = NULL; - - ivshmem_add_kvm_msi_virq(s, i, &err); - if (err) { - error_report_err(err); - /* TODO do we need to handle the error? */ - } - } - - if (msix_set_vector_notifiers(pdev, - ivshmem_vector_unmask, - ivshmem_vector_mask, - ivshmem_vector_poll)) { - error_report("ivshmem: msix_set_vector_notifiers failed"); - } -} - -static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector) -{ - IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector); - - if (s->msi_vectors[vector].pdev == NULL) { - return; - } - - /* it was cleaned when masked in the frontend. */ - kvm_irqchip_release_virq(kvm_state, s->msi_vectors[vector].virq); - - s->msi_vectors[vector].pdev = NULL; -} - -static void ivshmem_disable_irqfd(IVShmemState *s) -{ - PCIDevice *pdev = PCI_DEVICE(s); - int i; - - for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) { - ivshmem_remove_kvm_msi_virq(s, i); - } - - msix_unset_vector_notifiers(pdev); -} - -static void ivshmem_write_config(PCIDevice *pdev, uint32_t address, - uint32_t val, int len) -{ - IVShmemState *s = IVSHMEM_COMMON(pdev); - int is_enabled, was_enabled = msix_enabled(pdev); - - pci_default_write_config(pdev, address, val, len); - is_enabled = msix_enabled(pdev); - - if (kvm_msi_via_irqfd_enabled()) { - if (!was_enabled && is_enabled) { - ivshmem_enable_irqfd(s); - } else if (was_enabled && !is_enabled) { - ivshmem_disable_irqfd(s); - } - } -} - -static void ivshmem_common_realize(PCIDevice *dev, Error **errp) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - Error *err = NULL; - uint8_t *pci_conf; - uint8_t attr = PCI_BASE_ADDRESS_SPACE_MEMORY | - PCI_BASE_ADDRESS_MEM_PREFETCH; - - /* IRQFD requires MSI */ - if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD) && - !ivshmem_has_feature(s, IVSHMEM_MSI)) { - error_setg(errp, "ioeventfd/irqfd requires MSI"); - return; - } - - pci_conf = dev->config; - pci_conf[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY; - - memory_region_init_io(&s->ivshmem_mmio, OBJECT(s), &ivshmem_mmio_ops, s, - "ivshmem-mmio", IVSHMEM_REG_BAR_SIZE); - - /* region for registers*/ - pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, - &s->ivshmem_mmio); - - if (!s->not_legacy_32bit) { - attr |= PCI_BASE_ADDRESS_MEM_TYPE_64; - } - - if (s->hostmem != NULL) { - IVSHMEM_DPRINTF("using hostmem\n"); - - s->ivshmem_bar2 = host_memory_backend_get_memory(s->hostmem, - &error_abort); - } else { - assert(s->server_chr); - - IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n", - s->server_chr->filename); - - /* we allocate enough space for 16 peers and grow as needed */ - resize_peers(s, 16); - - /* - * Receive setup messages from server synchronously. - * Older versions did it asynchronously, but that creates a - * number of entertaining race conditions. - */ - ivshmem_recv_setup(s, &err); - if (err) { - error_propagate(errp, err); - return; - } - - if (s->master == ON_OFF_AUTO_ON && s->vm_id != 0) { - error_setg(errp, - "master must connect to the server before any peers"); - return; - } - - qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, - ivshmem_read, NULL, s); - - if (ivshmem_setup_interrupts(s) < 0) { - error_setg(errp, "failed to initialize interrupts"); - return; - } - } - - vmstate_register_ram(s->ivshmem_bar2, DEVICE(s)); - pci_register_bar(PCI_DEVICE(s), 2, attr, s->ivshmem_bar2); - - if (s->master == ON_OFF_AUTO_AUTO) { - s->master = s->vm_id == 0 ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; - } - - if (!ivshmem_is_master(s)) { - error_setg(&s->migration_blocker, - "Migration is disabled when using feature 'peer mode' in device 'ivshmem'"); - migrate_add_blocker(s->migration_blocker); - } -} - -static void ivshmem_exit(PCIDevice *dev) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - int i; - - if (s->migration_blocker) { - migrate_del_blocker(s->migration_blocker); - error_free(s->migration_blocker); - } - - if (memory_region_is_mapped(s->ivshmem_bar2)) { - if (!s->hostmem) { - void *addr = memory_region_get_ram_ptr(s->ivshmem_bar2); - int fd; - - if (munmap(addr, memory_region_size(s->ivshmem_bar2) == -1)) { - error_report("Failed to munmap shared memory %s", - strerror(errno)); - } - - fd = qemu_get_ram_fd(memory_region_get_ram_addr(s->ivshmem_bar2)); - close(fd); - } - - vmstate_unregister_ram(s->ivshmem_bar2, DEVICE(dev)); - } - - if (s->peers) { - for (i = 0; i < s->nb_peers; i++) { - close_peer_eventfds(s, i); - } - g_free(s->peers); - } - - if (ivshmem_has_feature(s, IVSHMEM_MSI)) { - msix_uninit_exclusive_bar(dev); - } - - g_free(s->msi_vectors); -} - -static int ivshmem_pre_load(void *opaque) -{ - IVShmemState *s = opaque; - - if (!ivshmem_is_master(s)) { - error_report("'peer' devices are not migratable"); - return -EINVAL; - } - - return 0; -} - -static int ivshmem_post_load(void *opaque, int version_id) -{ - IVShmemState *s = opaque; - - if (ivshmem_has_feature(s, IVSHMEM_MSI)) { - ivshmem_msix_vector_use(s); - } - return 0; -} - -static void ivshmem_common_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = ivshmem_common_realize; - k->exit = ivshmem_exit; - k->config_write = ivshmem_write_config; - k->vendor_id = PCI_VENDOR_ID_IVSHMEM; - k->device_id = PCI_DEVICE_ID_IVSHMEM; - k->class_id = PCI_CLASS_MEMORY_RAM; - k->revision = 1; - dc->reset = ivshmem_reset; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - dc->desc = "Inter-VM shared memory"; -} - -static const TypeInfo ivshmem_common_info = { - .name = TYPE_IVSHMEM_COMMON, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(IVShmemState), - .abstract = true, - .class_init = ivshmem_common_class_init, -}; - -static void ivshmem_check_memdev_is_busy(Object *obj, const char *name, - Object *val, Error **errp) -{ - MemoryRegion *mr; - - mr = host_memory_backend_get_memory(MEMORY_BACKEND(val), &error_abort); - if (memory_region_is_mapped(mr)) { - char *path = object_get_canonical_path_component(val); - error_setg(errp, "can't use already busy memdev: %s", path); - g_free(path); - } else { - qdev_prop_allow_set_link_before_realize(obj, name, val, errp); - } -} - -static const VMStateDescription ivshmem_plain_vmsd = { - .name = TYPE_IVSHMEM_PLAIN, - .version_id = 0, - .minimum_version_id = 0, - .pre_load = ivshmem_pre_load, - .post_load = ivshmem_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, IVShmemState), - VMSTATE_UINT32(intrstatus, IVShmemState), - VMSTATE_UINT32(intrmask, IVShmemState), - VMSTATE_END_OF_LIST() - }, -}; - -static Property ivshmem_plain_properties[] = { - DEFINE_PROP_ON_OFF_AUTO("master", IVShmemState, master, ON_OFF_AUTO_OFF), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ivshmem_plain_init(Object *obj) -{ - IVShmemState *s = IVSHMEM_PLAIN(obj); - - object_property_add_link(obj, "memdev", TYPE_MEMORY_BACKEND, - (Object **)&s->hostmem, - ivshmem_check_memdev_is_busy, - OBJ_PROP_LINK_UNREF_ON_RELEASE, - &error_abort); -} - -static void ivshmem_plain_realize(PCIDevice *dev, Error **errp) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - - if (!s->hostmem) { - error_setg(errp, "You must specify a 'memdev'"); - return; - } - - ivshmem_common_realize(dev, errp); -} - -static void ivshmem_plain_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = ivshmem_plain_realize; - dc->props = ivshmem_plain_properties; - dc->vmsd = &ivshmem_plain_vmsd; -} - -static const TypeInfo ivshmem_plain_info = { - .name = TYPE_IVSHMEM_PLAIN, - .parent = TYPE_IVSHMEM_COMMON, - .instance_size = sizeof(IVShmemState), - .instance_init = ivshmem_plain_init, - .class_init = ivshmem_plain_class_init, -}; - -static const VMStateDescription ivshmem_doorbell_vmsd = { - .name = TYPE_IVSHMEM_DOORBELL, - .version_id = 0, - .minimum_version_id = 0, - .pre_load = ivshmem_pre_load, - .post_load = ivshmem_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, IVShmemState), - VMSTATE_MSIX(parent_obj, IVShmemState), - VMSTATE_UINT32(intrstatus, IVShmemState), - VMSTATE_UINT32(intrmask, IVShmemState), - VMSTATE_END_OF_LIST() - }, -}; - -static Property ivshmem_doorbell_properties[] = { - DEFINE_PROP_CHR("chardev", IVShmemState, server_chr), - DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1), - DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD, - true), - DEFINE_PROP_ON_OFF_AUTO("master", IVShmemState, master, ON_OFF_AUTO_OFF), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ivshmem_doorbell_init(Object *obj) -{ - IVShmemState *s = IVSHMEM_DOORBELL(obj); - - s->features |= (1 << IVSHMEM_MSI); - s->legacy_size = SIZE_MAX; /* whatever the server sends */ -} - -static void ivshmem_doorbell_realize(PCIDevice *dev, Error **errp) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - - if (!s->server_chr) { - error_setg(errp, "You must specify a 'chardev'"); - return; - } - - ivshmem_common_realize(dev, errp); -} - -static void ivshmem_doorbell_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = ivshmem_doorbell_realize; - dc->props = ivshmem_doorbell_properties; - dc->vmsd = &ivshmem_doorbell_vmsd; -} - -static const TypeInfo ivshmem_doorbell_info = { - .name = TYPE_IVSHMEM_DOORBELL, - .parent = TYPE_IVSHMEM_COMMON, - .instance_size = sizeof(IVShmemState), - .instance_init = ivshmem_doorbell_init, - .class_init = ivshmem_doorbell_class_init, -}; - -static int ivshmem_load_old(QEMUFile *f, void *opaque, int version_id) -{ - IVShmemState *s = opaque; - PCIDevice *pdev = PCI_DEVICE(s); - int ret; - - IVSHMEM_DPRINTF("ivshmem_load_old\n"); - - if (version_id != 0) { - return -EINVAL; - } - - ret = ivshmem_pre_load(s); - if (ret) { - return ret; - } - - ret = pci_device_load(pdev, f); - if (ret) { - return ret; - } - - if (ivshmem_has_feature(s, IVSHMEM_MSI)) { - msix_load(pdev, f); - ivshmem_msix_vector_use(s); - } else { - s->intrstatus = qemu_get_be32(f); - s->intrmask = qemu_get_be32(f); - } - - return 0; -} - -static bool test_msix(void *opaque, int version_id) -{ - IVShmemState *s = opaque; - - return ivshmem_has_feature(s, IVSHMEM_MSI); -} - -static bool test_no_msix(void *opaque, int version_id) -{ - return !test_msix(opaque, version_id); -} - -static const VMStateDescription ivshmem_vmsd = { - .name = "ivshmem", - .version_id = 1, - .minimum_version_id = 1, - .pre_load = ivshmem_pre_load, - .post_load = ivshmem_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, IVShmemState), - - VMSTATE_MSIX_TEST(parent_obj, IVShmemState, test_msix), - VMSTATE_UINT32_TEST(intrstatus, IVShmemState, test_no_msix), - VMSTATE_UINT32_TEST(intrmask, IVShmemState, test_no_msix), - - VMSTATE_END_OF_LIST() - }, - .load_state_old = ivshmem_load_old, - .minimum_version_id_old = 0 -}; - -static Property ivshmem_properties[] = { - DEFINE_PROP_CHR("chardev", IVShmemState, server_chr), - DEFINE_PROP_STRING("size", IVShmemState, sizearg), - DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1), - DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD, - false), - DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true), - DEFINE_PROP_STRING("shm", IVShmemState, shmobj), - DEFINE_PROP_STRING("role", IVShmemState, role), - DEFINE_PROP_UINT32("use64", IVShmemState, not_legacy_32bit, 1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void desugar_shm(IVShmemState *s) -{ - Object *obj; - char *path; - - obj = object_new("memory-backend-file"); - path = g_strdup_printf("/dev/shm/%s", s->shmobj); - object_property_set_str(obj, path, "mem-path", &error_abort); - g_free(path); - object_property_set_int(obj, s->legacy_size, "size", &error_abort); - object_property_set_bool(obj, true, "share", &error_abort); - object_property_add_child(OBJECT(s), "internal-shm-backend", obj, - &error_abort); - user_creatable_complete(obj, &error_abort); - s->hostmem = MEMORY_BACKEND(obj); -} - -static void ivshmem_realize(PCIDevice *dev, Error **errp) -{ - IVShmemState *s = IVSHMEM_COMMON(dev); - - if (!qtest_enabled()) { - error_report("ivshmem is deprecated, please use ivshmem-plain" - " or ivshmem-doorbell instead"); - } - - if (!!s->server_chr + !!s->shmobj != 1) { - error_setg(errp, "You must specify either 'shm' or 'chardev'"); - return; - } - - if (s->sizearg == NULL) { - s->legacy_size = 4 << 20; /* 4 MB default */ - } else { - char *end; - int64_t size = qemu_strtosz(s->sizearg, &end); - if (size < 0 || (size_t)size != size || *end != '\0' - || !is_power_of_2(size)) { - error_setg(errp, "Invalid size %s", s->sizearg); - return; - } - s->legacy_size = size; - } - - /* check that role is reasonable */ - if (s->role) { - if (strncmp(s->role, "peer", 5) == 0) { - s->master = ON_OFF_AUTO_OFF; - } else if (strncmp(s->role, "master", 7) == 0) { - s->master = ON_OFF_AUTO_ON; - } else { - error_setg(errp, "'role' must be 'peer' or 'master'"); - return; - } - } else { - s->master = ON_OFF_AUTO_AUTO; - } - - if (s->shmobj) { - desugar_shm(s); - } - - /* - * Note: we don't use INTx with IVSHMEM_MSI at all, so this is a - * bald-faced lie then. But it's a backwards compatible lie. - */ - pci_config_set_interrupt_pin(dev->config, 1); - - ivshmem_common_realize(dev, errp); -} - -static void ivshmem_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = ivshmem_realize; - k->revision = 0; - dc->desc = "Inter-VM shared memory (legacy)"; - dc->props = ivshmem_properties; - dc->vmsd = &ivshmem_vmsd; -} - -static const TypeInfo ivshmem_info = { - .name = TYPE_IVSHMEM, - .parent = TYPE_IVSHMEM_COMMON, - .instance_size = sizeof(IVShmemState), - .class_init = ivshmem_class_init, -}; - -static void ivshmem_register_types(void) -{ - type_register_static(&ivshmem_common_info); - type_register_static(&ivshmem_plain_info); - type_register_static(&ivshmem_doorbell_info); - type_register_static(&ivshmem_info); -} - -type_init(ivshmem_register_types) diff --git a/qemu/hw/misc/macio/Makefile.objs b/qemu/hw/misc/macio/Makefile.objs deleted file mode 100644 index ef7ac249e..000000000 --- a/qemu/hw/misc/macio/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -common-obj-y += macio.o -common-obj-$(CONFIG_CUDA) += cuda.o -common-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o diff --git a/qemu/hw/misc/macio/cuda.c b/qemu/hw/misc/macio/cuda.c deleted file mode 100644 index f15f30110..000000000 --- a/qemu/hw/misc/macio/cuda.c +++ /dev/null @@ -1,964 +0,0 @@ -/* - * QEMU PowerMac CUDA device support - * - * Copyright (c) 2004-2007 Fabrice Bellard - * 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 "hw/hw.h" -#include "hw/ppc/mac.h" -#include "hw/input/adb.h" -#include "qemu/timer.h" -#include "sysemu/sysemu.h" -#include "qemu/cutils.h" - -/* XXX: implement all timer modes */ - -/* debug CUDA */ -//#define DEBUG_CUDA - -/* debug CUDA packets */ -//#define DEBUG_CUDA_PACKET - -#ifdef DEBUG_CUDA -#define CUDA_DPRINTF(fmt, ...) \ - do { printf("CUDA: " fmt , ## __VA_ARGS__); } while (0) -#else -#define CUDA_DPRINTF(fmt, ...) -#endif - -/* Bits in B data register: all active low */ -#define TREQ 0x08 /* Transfer request (input) */ -#define TACK 0x10 /* Transfer acknowledge (output) */ -#define TIP 0x20 /* Transfer in progress (output) */ - -/* Bits in ACR */ -#define SR_CTRL 0x1c /* Shift register control bits */ -#define SR_EXT 0x0c /* Shift on external clock */ -#define SR_OUT 0x10 /* Shift out if 1 */ - -/* Bits in IFR and IER */ -#define IER_SET 0x80 /* set bits in IER */ -#define IER_CLR 0 /* clear bits in IER */ -#define SR_INT 0x04 /* Shift register full/empty */ -#define SR_DATA_INT 0x08 -#define SR_CLOCK_INT 0x10 -#define T1_INT 0x40 /* Timer 1 interrupt */ -#define T2_INT 0x20 /* Timer 2 interrupt */ - -/* Bits in ACR */ -#define T1MODE 0xc0 /* Timer 1 mode */ -#define T1MODE_CONT 0x40 /* continuous interrupts */ - -/* commands (1st byte) */ -#define ADB_PACKET 0 -#define CUDA_PACKET 1 -#define ERROR_PACKET 2 -#define TIMER_PACKET 3 -#define POWER_PACKET 4 -#define MACIIC_PACKET 5 -#define PMU_PACKET 6 - - -/* CUDA commands (2nd byte) */ -#define CUDA_WARM_START 0x0 -#define CUDA_AUTOPOLL 0x1 -#define CUDA_GET_6805_ADDR 0x2 -#define CUDA_GET_TIME 0x3 -#define CUDA_GET_PRAM 0x7 -#define CUDA_SET_6805_ADDR 0x8 -#define CUDA_SET_TIME 0x9 -#define CUDA_POWERDOWN 0xa -#define CUDA_POWERUP_TIME 0xb -#define CUDA_SET_PRAM 0xc -#define CUDA_MS_RESET 0xd -#define CUDA_SEND_DFAC 0xe -#define CUDA_BATTERY_SWAP_SENSE 0x10 -#define CUDA_RESET_SYSTEM 0x11 -#define CUDA_SET_IPL 0x12 -#define CUDA_FILE_SERVER_FLAG 0x13 -#define CUDA_SET_AUTO_RATE 0x14 -#define CUDA_GET_AUTO_RATE 0x16 -#define CUDA_SET_DEVICE_LIST 0x19 -#define CUDA_GET_DEVICE_LIST 0x1a -#define CUDA_SET_ONE_SECOND_MODE 0x1b -#define CUDA_SET_POWER_MESSAGES 0x21 -#define CUDA_GET_SET_IIC 0x22 -#define CUDA_WAKEUP 0x23 -#define CUDA_TIMER_TICKLE 0x24 -#define CUDA_COMBINED_FORMAT_IIC 0x25 - -#define CUDA_TIMER_FREQ (4700000 / 6) - -/* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */ -#define RTC_OFFSET 2082844800 - -/* CUDA registers */ -#define CUDA_REG_B 0x00 -#define CUDA_REG_A 0x01 -#define CUDA_REG_DIRB 0x02 -#define CUDA_REG_DIRA 0x03 -#define CUDA_REG_T1CL 0x04 -#define CUDA_REG_T1CH 0x05 -#define CUDA_REG_T1LL 0x06 -#define CUDA_REG_T1LH 0x07 -#define CUDA_REG_T2CL 0x08 -#define CUDA_REG_T2CH 0x09 -#define CUDA_REG_SR 0x0a -#define CUDA_REG_ACR 0x0b -#define CUDA_REG_PCR 0x0c -#define CUDA_REG_IFR 0x0d -#define CUDA_REG_IER 0x0e -#define CUDA_REG_ANH 0x0f - -static void cuda_update(CUDAState *s); -static void cuda_receive_packet_from_host(CUDAState *s, - const uint8_t *data, int len); -static void cuda_timer_update(CUDAState *s, CUDATimer *ti, - int64_t current_time); - -static void cuda_update_irq(CUDAState *s) -{ - if (s->ifr & s->ier & (SR_INT | T1_INT | T2_INT)) { - qemu_irq_raise(s->irq); - } else { - qemu_irq_lower(s->irq); - } -} - -static uint64_t get_tb(uint64_t time, uint64_t freq) -{ - return muldiv64(time, freq, NANOSECONDS_PER_SECOND); -} - -static unsigned int get_counter(CUDATimer *ti) -{ - int64_t d; - unsigned int counter; - uint64_t tb_diff; - uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - - /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */ - tb_diff = get_tb(current_time, ti->frequency) - ti->load_time; - d = (tb_diff * 0xBF401675E5DULL) / (ti->frequency << 24); - - if (ti->index == 0) { - /* the timer goes down from latch to -1 (period of latch + 2) */ - if (d <= (ti->counter_value + 1)) { - counter = (ti->counter_value - d) & 0xffff; - } else { - counter = (d - (ti->counter_value + 1)) % (ti->latch + 2); - counter = (ti->latch - counter) & 0xffff; - } - } else { - counter = (ti->counter_value - d) & 0xffff; - } - return counter; -} - -static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) -{ - CUDA_DPRINTF("T%d.counter=%d\n", 1 + ti->index, val); - ti->load_time = get_tb(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - s->frequency); - ti->counter_value = val; - cuda_timer_update(s, ti, ti->load_time); -} - -static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) -{ - int64_t d, next_time; - unsigned int counter; - - /* current counter value */ - d = muldiv64(current_time - s->load_time, - CUDA_TIMER_FREQ, NANOSECONDS_PER_SECOND); - /* the timer goes down from latch to -1 (period of latch + 2) */ - if (d <= (s->counter_value + 1)) { - counter = (s->counter_value - d) & 0xffff; - } else { - counter = (d - (s->counter_value + 1)) % (s->latch + 2); - counter = (s->latch - counter) & 0xffff; - } - - /* Note: we consider the irq is raised on 0 */ - if (counter == 0xffff) { - next_time = d + s->latch + 1; - } else if (counter == 0) { - next_time = d + s->latch + 2; - } else { - next_time = d + counter; - } - CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n", - s->latch, d, next_time - d); - next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, CUDA_TIMER_FREQ) + - s->load_time; - if (next_time <= current_time) - next_time = current_time + 1; - return next_time; -} - -static void cuda_timer_update(CUDAState *s, CUDATimer *ti, - int64_t current_time) -{ - if (!ti->timer) - return; - if (ti->index == 0 && (s->acr & T1MODE) != T1MODE_CONT) { - timer_del(ti->timer); - } else { - ti->next_irq_time = get_next_irq_time(ti, current_time); - timer_mod(ti->timer, ti->next_irq_time); - } -} - -static void cuda_timer1(void *opaque) -{ - CUDAState *s = opaque; - CUDATimer *ti = &s->timers[0]; - - cuda_timer_update(s, ti, ti->next_irq_time); - s->ifr |= T1_INT; - cuda_update_irq(s); -} - -static void cuda_timer2(void *opaque) -{ - CUDAState *s = opaque; - CUDATimer *ti = &s->timers[1]; - - cuda_timer_update(s, ti, ti->next_irq_time); - s->ifr |= T2_INT; - cuda_update_irq(s); -} - -static void cuda_set_sr_int(void *opaque) -{ - CUDAState *s = opaque; - - CUDA_DPRINTF("CUDA: %s:%d\n", __func__, __LINE__); - s->ifr |= SR_INT; - cuda_update_irq(s); -} - -static void cuda_delay_set_sr_int(CUDAState *s) -{ - int64_t expire; - - if (s->dirb == 0xff) { - /* Not in Mac OS, fire the IRQ directly */ - cuda_set_sr_int(s); - return; - } - - CUDA_DPRINTF("CUDA: %s:%d\n", __func__, __LINE__); - - expire = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 300 * SCALE_US; - timer_mod(s->sr_delay_timer, expire); -} - -static uint32_t cuda_readb(void *opaque, hwaddr addr) -{ - CUDAState *s = opaque; - uint32_t val; - - addr = (addr >> 9) & 0xf; - switch(addr) { - case CUDA_REG_B: - val = s->b; - break; - case CUDA_REG_A: - val = s->a; - break; - case CUDA_REG_DIRB: - val = s->dirb; - break; - case CUDA_REG_DIRA: - val = s->dira; - break; - case CUDA_REG_T1CL: - val = get_counter(&s->timers[0]) & 0xff; - s->ifr &= ~T1_INT; - cuda_update_irq(s); - break; - case CUDA_REG_T1CH: - val = get_counter(&s->timers[0]) >> 8; - cuda_update_irq(s); - break; - case CUDA_REG_T1LL: - val = s->timers[0].latch & 0xff; - break; - case CUDA_REG_T1LH: - /* XXX: check this */ - val = (s->timers[0].latch >> 8) & 0xff; - break; - case CUDA_REG_T2CL: - val = get_counter(&s->timers[1]) & 0xff; - s->ifr &= ~T2_INT; - cuda_update_irq(s); - break; - case CUDA_REG_T2CH: - val = get_counter(&s->timers[1]) >> 8; - break; - case CUDA_REG_SR: - val = s->sr; - s->ifr &= ~(SR_INT | SR_CLOCK_INT | SR_DATA_INT); - cuda_update_irq(s); - break; - case CUDA_REG_ACR: - val = s->acr; - break; - case CUDA_REG_PCR: - val = s->pcr; - break; - case CUDA_REG_IFR: - val = s->ifr; - if (s->ifr & s->ier) { - val |= 0x80; - } - break; - case CUDA_REG_IER: - val = s->ier | 0x80; - break; - default: - case CUDA_REG_ANH: - val = s->anh; - break; - } - if (addr != CUDA_REG_IFR || val != 0) { - CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val); - } - - return val; -} - -static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val) -{ - CUDAState *s = opaque; - - addr = (addr >> 9) & 0xf; - CUDA_DPRINTF("write: reg=0x%x val=%02x\n", (int)addr, val); - - switch(addr) { - case CUDA_REG_B: - s->b = val; - cuda_update(s); - break; - case CUDA_REG_A: - s->a = val; - break; - case CUDA_REG_DIRB: - s->dirb = val; - break; - case CUDA_REG_DIRA: - s->dira = val; - break; - case CUDA_REG_T1CL: - s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; - cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); - break; - case CUDA_REG_T1CH: - s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); - s->ifr &= ~T1_INT; - set_counter(s, &s->timers[0], s->timers[0].latch); - break; - case CUDA_REG_T1LL: - s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; - cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); - break; - case CUDA_REG_T1LH: - s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); - s->ifr &= ~T1_INT; - cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); - break; - case CUDA_REG_T2CL: - s->timers[1].latch = (s->timers[1].latch & 0xff00) | val; - break; - case CUDA_REG_T2CH: - /* To ensure T2 generates an interrupt on zero crossing with the - common timer code, write the value directly from the latch to - the counter */ - s->timers[1].latch = (s->timers[1].latch & 0xff) | (val << 8); - s->ifr &= ~T2_INT; - set_counter(s, &s->timers[1], s->timers[1].latch); - break; - case CUDA_REG_SR: - s->sr = val; - break; - case CUDA_REG_ACR: - s->acr = val; - cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); - cuda_update(s); - break; - case CUDA_REG_PCR: - s->pcr = val; - break; - case CUDA_REG_IFR: - /* reset bits */ - s->ifr &= ~val; - cuda_update_irq(s); - break; - case CUDA_REG_IER: - if (val & IER_SET) { - /* set bits */ - s->ier |= val & 0x7f; - } else { - /* reset bits */ - s->ier &= ~val; - } - cuda_update_irq(s); - break; - default: - case CUDA_REG_ANH: - s->anh = val; - break; - } -} - -/* NOTE: TIP and TREQ are negated */ -static void cuda_update(CUDAState *s) -{ - int packet_received, len; - - packet_received = 0; - if (!(s->b & TIP)) { - /* transfer requested from host */ - - if (s->acr & SR_OUT) { - /* data output */ - if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { - if (s->data_out_index < sizeof(s->data_out)) { - CUDA_DPRINTF("send: %02x\n", s->sr); - s->data_out[s->data_out_index++] = s->sr; - cuda_delay_set_sr_int(s); - } - } - } else { - if (s->data_in_index < s->data_in_size) { - /* data input */ - if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { - s->sr = s->data_in[s->data_in_index++]; - CUDA_DPRINTF("recv: %02x\n", s->sr); - /* indicate end of transfer */ - if (s->data_in_index >= s->data_in_size) { - s->b = (s->b | TREQ); - } - cuda_delay_set_sr_int(s); - } - } - } - } else { - /* no transfer requested: handle sync case */ - if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) { - /* update TREQ state each time TACK change state */ - if (s->b & TACK) - s->b = (s->b | TREQ); - else - s->b = (s->b & ~TREQ); - cuda_delay_set_sr_int(s); - } else { - if (!(s->last_b & TIP)) { - /* handle end of host to cuda transfer */ - packet_received = (s->data_out_index > 0); - /* always an IRQ at the end of transfer */ - cuda_delay_set_sr_int(s); - } - /* signal if there is data to read */ - if (s->data_in_index < s->data_in_size) { - s->b = (s->b & ~TREQ); - } - } - } - - s->last_acr = s->acr; - s->last_b = s->b; - - /* NOTE: cuda_receive_packet_from_host() can call cuda_update() - recursively */ - if (packet_received) { - len = s->data_out_index; - s->data_out_index = 0; - cuda_receive_packet_from_host(s, s->data_out, len); - } -} - -static void cuda_send_packet_to_host(CUDAState *s, - const uint8_t *data, int len) -{ -#ifdef DEBUG_CUDA_PACKET - { - int i; - printf("cuda_send_packet_to_host:\n"); - for(i = 0; i < len; i++) - printf(" %02x", data[i]); - printf("\n"); - } -#endif - memcpy(s->data_in, data, len); - s->data_in_size = len; - s->data_in_index = 0; - cuda_update(s); - cuda_delay_set_sr_int(s); -} - -static void cuda_adb_poll(void *opaque) -{ - CUDAState *s = opaque; - uint8_t obuf[ADB_MAX_OUT_LEN + 2]; - int olen; - - olen = adb_poll(&s->adb_bus, obuf + 2, s->adb_poll_mask); - if (olen > 0) { - obuf[0] = ADB_PACKET; - obuf[1] = 0x40; /* polled data */ - cuda_send_packet_to_host(s, obuf, olen + 2); - } - timer_mod(s->adb_poll_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms))); -} - -/* description of commands */ -typedef struct CudaCommand { - uint8_t command; - const char *name; - bool (*handler)(CUDAState *s, - const uint8_t *in_args, int in_len, - uint8_t *out_args, int *out_len); -} CudaCommand; - -static bool cuda_cmd_autopoll(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - int autopoll; - - if (in_len != 1) { - return false; - } - - autopoll = (in_data[0] != 0); - if (autopoll != s->autopoll) { - s->autopoll = autopoll; - if (autopoll) { - timer_mod(s->adb_poll_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms))); - } else { - timer_del(s->adb_poll_timer); - } - } - return true; -} - -static bool cuda_cmd_set_autorate(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - if (in_len != 1) { - return false; - } - - /* we don't want a period of 0 ms */ - /* FIXME: check what real hardware does */ - if (in_data[0] == 0) { - return false; - } - - s->autopoll_rate_ms = in_data[0]; - if (s->autopoll) { - timer_mod(s->adb_poll_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms))); - } - return true; -} - -static bool cuda_cmd_set_device_list(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - if (in_len != 2) { - return false; - } - - s->adb_poll_mask = (((uint16_t)in_data[0]) << 8) | in_data[1]; - return true; -} - -static bool cuda_cmd_powerdown(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - if (in_len != 0) { - return false; - } - - qemu_system_shutdown_request(); - return true; -} - -static bool cuda_cmd_reset_system(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - if (in_len != 0) { - return false; - } - - qemu_system_reset_request(); - return true; -} - -static bool cuda_cmd_set_file_server_flag(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - if (in_len != 1) { - return false; - } - - qemu_log_mask(LOG_UNIMP, - "CUDA: unimplemented command FILE_SERVER_FLAG %d\n", - in_data[0]); - return true; -} - -static bool cuda_cmd_set_power_message(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - if (in_len != 1) { - return false; - } - - qemu_log_mask(LOG_UNIMP, - "CUDA: unimplemented command SET_POWER_MESSAGE %d\n", - in_data[0]); - return true; -} - -static bool cuda_cmd_get_time(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - uint32_t ti; - - if (in_len != 0) { - return false; - } - - ti = s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - / NANOSECONDS_PER_SECOND); - out_data[0] = ti >> 24; - out_data[1] = ti >> 16; - out_data[2] = ti >> 8; - out_data[3] = ti; - *out_len = 4; - return true; -} - -static bool cuda_cmd_set_time(CUDAState *s, - const uint8_t *in_data, int in_len, - uint8_t *out_data, int *out_len) -{ - uint32_t ti; - - if (in_len != 4) { - return false; - } - - ti = (((uint32_t)in_data[0]) << 24) + (((uint32_t)in_data[1]) << 16) - + (((uint32_t)in_data[2]) << 8) + in_data[3]; - s->tick_offset = ti - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - / NANOSECONDS_PER_SECOND); - return true; -} - -static const CudaCommand handlers[] = { - { CUDA_AUTOPOLL, "AUTOPOLL", cuda_cmd_autopoll }, - { CUDA_SET_AUTO_RATE, "SET_AUTO_RATE", cuda_cmd_set_autorate }, - { CUDA_SET_DEVICE_LIST, "SET_DEVICE_LIST", cuda_cmd_set_device_list }, - { CUDA_POWERDOWN, "POWERDOWN", cuda_cmd_powerdown }, - { CUDA_RESET_SYSTEM, "RESET_SYSTEM", cuda_cmd_reset_system }, - { CUDA_FILE_SERVER_FLAG, "FILE_SERVER_FLAG", - cuda_cmd_set_file_server_flag }, - { CUDA_SET_POWER_MESSAGES, "SET_POWER_MESSAGES", - cuda_cmd_set_power_message }, - { CUDA_GET_TIME, "GET_TIME", cuda_cmd_get_time }, - { CUDA_SET_TIME, "SET_TIME", cuda_cmd_set_time }, -}; - -static void cuda_receive_packet(CUDAState *s, - const uint8_t *data, int len) -{ - uint8_t obuf[16] = { CUDA_PACKET, 0, data[0] }; - int i, out_len = 0; - - for (i = 0; i < ARRAY_SIZE(handlers); i++) { - const CudaCommand *desc = &handlers[i]; - if (desc->command == data[0]) { - CUDA_DPRINTF("handling command %s\n", desc->name); - out_len = 0; - if (desc->handler(s, data + 1, len - 1, obuf + 3, &out_len)) { - cuda_send_packet_to_host(s, obuf, 3 + out_len); - } else { - qemu_log_mask(LOG_GUEST_ERROR, - "CUDA: %s: wrong parameters %d\n", - desc->name, len); - obuf[0] = ERROR_PACKET; - obuf[1] = 0x5; /* bad parameters */ - obuf[2] = CUDA_PACKET; - obuf[3] = data[0]; - cuda_send_packet_to_host(s, obuf, 4); - } - return; - } - } - - qemu_log_mask(LOG_GUEST_ERROR, "CUDA: unknown command 0x%02x\n", data[0]); - obuf[0] = ERROR_PACKET; - obuf[1] = 0x2; /* unknown command */ - obuf[2] = CUDA_PACKET; - obuf[3] = data[0]; - cuda_send_packet_to_host(s, obuf, 4); -} - -static void cuda_receive_packet_from_host(CUDAState *s, - const uint8_t *data, int len) -{ -#ifdef DEBUG_CUDA_PACKET - { - int i; - printf("cuda_receive_packet_from_host:\n"); - for(i = 0; i < len; i++) - printf(" %02x", data[i]); - printf("\n"); - } -#endif - switch(data[0]) { - case ADB_PACKET: - { - uint8_t obuf[ADB_MAX_OUT_LEN + 3]; - int olen; - olen = adb_request(&s->adb_bus, obuf + 2, data + 1, len - 1); - if (olen > 0) { - obuf[0] = ADB_PACKET; - obuf[1] = 0x00; - cuda_send_packet_to_host(s, obuf, olen + 2); - } else { - /* error */ - obuf[0] = ADB_PACKET; - obuf[1] = -olen; - obuf[2] = data[1]; - olen = 0; - cuda_send_packet_to_host(s, obuf, olen + 3); - } - } - break; - case CUDA_PACKET: - cuda_receive_packet(s, data + 1, len - 1); - break; - } -} - -static void cuda_writew (void *opaque, hwaddr addr, uint32_t value) -{ -} - -static void cuda_writel (void *opaque, hwaddr addr, uint32_t value) -{ -} - -static uint32_t cuda_readw (void *opaque, hwaddr addr) -{ - return 0; -} - -static uint32_t cuda_readl (void *opaque, hwaddr addr) -{ - return 0; -} - -static const MemoryRegionOps cuda_ops = { - .old_mmio = { - .write = { - cuda_writeb, - cuda_writew, - cuda_writel, - }, - .read = { - cuda_readb, - cuda_readw, - cuda_readl, - }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static bool cuda_timer_exist(void *opaque, int version_id) -{ - CUDATimer *s = opaque; - - return s->timer != NULL; -} - -static const VMStateDescription vmstate_cuda_timer = { - .name = "cuda_timer", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT16(latch, CUDATimer), - VMSTATE_UINT16(counter_value, CUDATimer), - VMSTATE_INT64(load_time, CUDATimer), - VMSTATE_INT64(next_irq_time, CUDATimer), - VMSTATE_TIMER_PTR_TEST(timer, CUDATimer, cuda_timer_exist), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_cuda = { - .name = "cuda", - .version_id = 4, - .minimum_version_id = 4, - .fields = (VMStateField[]) { - VMSTATE_UINT8(a, CUDAState), - VMSTATE_UINT8(b, CUDAState), - VMSTATE_UINT8(last_b, CUDAState), - VMSTATE_UINT8(dira, CUDAState), - VMSTATE_UINT8(dirb, CUDAState), - VMSTATE_UINT8(sr, CUDAState), - VMSTATE_UINT8(acr, CUDAState), - VMSTATE_UINT8(last_acr, CUDAState), - VMSTATE_UINT8(pcr, CUDAState), - VMSTATE_UINT8(ifr, CUDAState), - VMSTATE_UINT8(ier, CUDAState), - VMSTATE_UINT8(anh, CUDAState), - VMSTATE_INT32(data_in_size, CUDAState), - VMSTATE_INT32(data_in_index, CUDAState), - VMSTATE_INT32(data_out_index, CUDAState), - VMSTATE_UINT8(autopoll, CUDAState), - VMSTATE_UINT8(autopoll_rate_ms, CUDAState), - VMSTATE_UINT16(adb_poll_mask, CUDAState), - VMSTATE_BUFFER(data_in, CUDAState), - VMSTATE_BUFFER(data_out, CUDAState), - VMSTATE_UINT32(tick_offset, CUDAState), - VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1, - vmstate_cuda_timer, CUDATimer), - VMSTATE_TIMER_PTR(adb_poll_timer, CUDAState), - VMSTATE_TIMER_PTR(sr_delay_timer, CUDAState), - VMSTATE_END_OF_LIST() - } -}; - -static void cuda_reset(DeviceState *dev) -{ - CUDAState *s = CUDA(dev); - - s->b = 0; - s->a = 0; - s->dirb = 0xff; - s->dira = 0; - s->sr = 0; - s->acr = 0; - s->pcr = 0; - s->ifr = 0; - s->ier = 0; - // s->ier = T1_INT | SR_INT; - s->anh = 0; - s->data_in_size = 0; - s->data_in_index = 0; - s->data_out_index = 0; - s->autopoll = 0; - - s->timers[0].latch = 0xffff; - set_counter(s, &s->timers[0], 0xffff); - - s->timers[1].latch = 0xffff; - - s->sr_delay_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_set_sr_int, s); -} - -static void cuda_realizefn(DeviceState *dev, Error **errp) -{ - CUDAState *s = CUDA(dev); - struct tm tm; - - s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s); - s->timers[0].frequency = s->frequency; - s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer2, s); - s->timers[1].frequency = (SCALE_US * 6000) / 4700; - - qemu_get_timedate(&tm, 0); - s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; - - s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s); - s->autopoll_rate_ms = 20; - s->adb_poll_mask = 0xffff; -} - -static void cuda_initfn(Object *obj) -{ - SysBusDevice *d = SYS_BUS_DEVICE(obj); - CUDAState *s = CUDA(obj); - int i; - - memory_region_init_io(&s->mem, obj, &cuda_ops, s, "cuda", 0x2000); - sysbus_init_mmio(d, &s->mem); - sysbus_init_irq(d, &s->irq); - - for (i = 0; i < ARRAY_SIZE(s->timers); i++) { - s->timers[i].index = i; - } - - qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS, - DEVICE(obj), "adb.0"); -} - -static Property cuda_properties[] = { - DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0), - DEFINE_PROP_END_OF_LIST() -}; - -static void cuda_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - dc->realize = cuda_realizefn; - dc->reset = cuda_reset; - dc->vmsd = &vmstate_cuda; - dc->props = cuda_properties; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo cuda_type_info = { - .name = TYPE_CUDA, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(CUDAState), - .instance_init = cuda_initfn, - .class_init = cuda_class_init, -}; - -static void cuda_register_types(void) -{ - type_register_static(&cuda_type_info); -} - -type_init(cuda_register_types) diff --git a/qemu/hw/misc/macio/mac_dbdma.c b/qemu/hw/misc/macio/mac_dbdma.c deleted file mode 100644 index 6051f17db..000000000 --- a/qemu/hw/misc/macio/mac_dbdma.c +++ /dev/null @@ -1,820 +0,0 @@ -/* - * PowerMac descriptor-based DMA emulation - * - * Copyright (c) 2005-2007 Fabrice Bellard - * Copyright (c) 2007 Jocelyn Mayer - * Copyright (c) 2009 Laurent Vivier - * - * some parts from linux-2.6.28, arch/powerpc/include/asm/dbdma.h - * - * Definitions for using the Apple Descriptor-Based DMA controller - * in Power Macintosh computers. - * - * Copyright (C) 1996 Paul Mackerras. - * - * some parts from mol 0.9.71 - * - * Descriptor based DMA emulation - * - * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se) - * - * 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 "hw/hw.h" -#include "hw/isa/isa.h" -#include "hw/ppc/mac_dbdma.h" -#include "qemu/main-loop.h" - -/* debug DBDMA */ -//#define DEBUG_DBDMA - -#ifdef DEBUG_DBDMA -#define DBDMA_DPRINTF(fmt, ...) \ - do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DBDMA_DPRINTF(fmt, ...) -#endif - -/* - */ - -static DBDMAState *dbdma_from_ch(DBDMA_channel *ch) -{ - return container_of(ch, DBDMAState, channels[ch->channel]); -} - -#ifdef DEBUG_DBDMA -static void dump_dbdma_cmd(dbdma_cmd *cmd) -{ - printf("dbdma_cmd %p\n", cmd); - printf(" req_count 0x%04x\n", le16_to_cpu(cmd->req_count)); - printf(" command 0x%04x\n", le16_to_cpu(cmd->command)); - printf(" phy_addr 0x%08x\n", le32_to_cpu(cmd->phy_addr)); - printf(" cmd_dep 0x%08x\n", le32_to_cpu(cmd->cmd_dep)); - printf(" res_count 0x%04x\n", le16_to_cpu(cmd->res_count)); - printf(" xfer_status 0x%04x\n", le16_to_cpu(cmd->xfer_status)); -} -#else -static void dump_dbdma_cmd(dbdma_cmd *cmd) -{ -} -#endif -static void dbdma_cmdptr_load(DBDMA_channel *ch) -{ - DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n", - ch->regs[DBDMA_CMDPTR_LO]); - cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO], - &ch->current, sizeof(dbdma_cmd)); -} - -static void dbdma_cmdptr_save(DBDMA_channel *ch) -{ - DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n", - ch->regs[DBDMA_CMDPTR_LO]); - DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n", - le16_to_cpu(ch->current.xfer_status), - le16_to_cpu(ch->current.res_count)); - cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO], - &ch->current, sizeof(dbdma_cmd)); -} - -static void kill_channel(DBDMA_channel *ch) -{ - DBDMA_DPRINTF("kill_channel\n"); - - ch->regs[DBDMA_STATUS] |= DEAD; - ch->regs[DBDMA_STATUS] &= ~ACTIVE; - - qemu_irq_raise(ch->irq); -} - -static void conditional_interrupt(DBDMA_channel *ch) -{ - dbdma_cmd *current = &ch->current; - uint16_t intr; - uint16_t sel_mask, sel_value; - uint32_t status; - int cond; - - DBDMA_DPRINTF("%s\n", __func__); - - intr = le16_to_cpu(current->command) & INTR_MASK; - - switch(intr) { - case INTR_NEVER: /* don't interrupt */ - return; - case INTR_ALWAYS: /* always interrupt */ - qemu_irq_raise(ch->irq); - DBDMA_DPRINTF("%s: raise\n", __func__); - return; - } - - status = ch->regs[DBDMA_STATUS] & DEVSTAT; - - sel_mask = (ch->regs[DBDMA_INTR_SEL] >> 16) & 0x0f; - sel_value = ch->regs[DBDMA_INTR_SEL] & 0x0f; - - cond = (status & sel_mask) == (sel_value & sel_mask); - - switch(intr) { - case INTR_IFSET: /* intr if condition bit is 1 */ - if (cond) { - qemu_irq_raise(ch->irq); - DBDMA_DPRINTF("%s: raise\n", __func__); - } - return; - case INTR_IFCLR: /* intr if condition bit is 0 */ - if (!cond) { - qemu_irq_raise(ch->irq); - DBDMA_DPRINTF("%s: raise\n", __func__); - } - return; - } -} - -static int conditional_wait(DBDMA_channel *ch) -{ - dbdma_cmd *current = &ch->current; - uint16_t wait; - uint16_t sel_mask, sel_value; - uint32_t status; - int cond; - - DBDMA_DPRINTF("conditional_wait\n"); - - wait = le16_to_cpu(current->command) & WAIT_MASK; - - switch(wait) { - case WAIT_NEVER: /* don't wait */ - return 0; - case WAIT_ALWAYS: /* always wait */ - return 1; - } - - status = ch->regs[DBDMA_STATUS] & DEVSTAT; - - sel_mask = (ch->regs[DBDMA_WAIT_SEL] >> 16) & 0x0f; - sel_value = ch->regs[DBDMA_WAIT_SEL] & 0x0f; - - cond = (status & sel_mask) == (sel_value & sel_mask); - - switch(wait) { - case WAIT_IFSET: /* wait if condition bit is 1 */ - if (cond) - return 1; - return 0; - case WAIT_IFCLR: /* wait if condition bit is 0 */ - if (!cond) - return 1; - return 0; - } - return 0; -} - -static void next(DBDMA_channel *ch) -{ - uint32_t cp; - - ch->regs[DBDMA_STATUS] &= ~BT; - - cp = ch->regs[DBDMA_CMDPTR_LO]; - ch->regs[DBDMA_CMDPTR_LO] = cp + sizeof(dbdma_cmd); - dbdma_cmdptr_load(ch); -} - -static void branch(DBDMA_channel *ch) -{ - dbdma_cmd *current = &ch->current; - - ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep; - ch->regs[DBDMA_STATUS] |= BT; - dbdma_cmdptr_load(ch); -} - -static void conditional_branch(DBDMA_channel *ch) -{ - dbdma_cmd *current = &ch->current; - uint16_t br; - uint16_t sel_mask, sel_value; - uint32_t status; - int cond; - - DBDMA_DPRINTF("conditional_branch\n"); - - /* check if we must branch */ - - br = le16_to_cpu(current->command) & BR_MASK; - - switch(br) { - case BR_NEVER: /* don't branch */ - next(ch); - return; - case BR_ALWAYS: /* always branch */ - branch(ch); - return; - } - - status = ch->regs[DBDMA_STATUS] & DEVSTAT; - - sel_mask = (ch->regs[DBDMA_BRANCH_SEL] >> 16) & 0x0f; - sel_value = ch->regs[DBDMA_BRANCH_SEL] & 0x0f; - - cond = (status & sel_mask) == (sel_value & sel_mask); - - switch(br) { - case BR_IFSET: /* branch if condition bit is 1 */ - if (cond) - branch(ch); - else - next(ch); - return; - case BR_IFCLR: /* branch if condition bit is 0 */ - if (!cond) - branch(ch); - else - next(ch); - return; - } -} - -static void channel_run(DBDMA_channel *ch); - -static void dbdma_end(DBDMA_io *io) -{ - DBDMA_channel *ch = io->channel; - dbdma_cmd *current = &ch->current; - - DBDMA_DPRINTF("%s\n", __func__); - - if (conditional_wait(ch)) - goto wait; - - current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]); - current->res_count = cpu_to_le16(io->len); - dbdma_cmdptr_save(ch); - if (io->is_last) - ch->regs[DBDMA_STATUS] &= ~FLUSH; - - conditional_interrupt(ch); - conditional_branch(ch); - -wait: - /* Indicate that we're ready for a new DMA round */ - ch->io.processing = false; - - if ((ch->regs[DBDMA_STATUS] & RUN) && - (ch->regs[DBDMA_STATUS] & ACTIVE)) - channel_run(ch); -} - -static void start_output(DBDMA_channel *ch, int key, uint32_t addr, - uint16_t req_count, int is_last) -{ - DBDMA_DPRINTF("start_output\n"); - - /* KEY_REGS, KEY_DEVICE and KEY_STREAM - * are not implemented in the mac-io chip - */ - - DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); - if (!addr || key > KEY_STREAM3) { - kill_channel(ch); - return; - } - - ch->io.addr = addr; - ch->io.len = req_count; - ch->io.is_last = is_last; - ch->io.dma_end = dbdma_end; - ch->io.is_dma_out = 1; - ch->io.processing = true; - if (ch->rw) { - ch->rw(&ch->io); - } -} - -static void start_input(DBDMA_channel *ch, int key, uint32_t addr, - uint16_t req_count, int is_last) -{ - DBDMA_DPRINTF("start_input\n"); - - /* KEY_REGS, KEY_DEVICE and KEY_STREAM - * are not implemented in the mac-io chip - */ - - DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); - if (!addr || key > KEY_STREAM3) { - kill_channel(ch); - return; - } - - ch->io.addr = addr; - ch->io.len = req_count; - ch->io.is_last = is_last; - ch->io.dma_end = dbdma_end; - ch->io.is_dma_out = 0; - ch->io.processing = true; - if (ch->rw) { - ch->rw(&ch->io); - } -} - -static void load_word(DBDMA_channel *ch, int key, uint32_t addr, - uint16_t len) -{ - dbdma_cmd *current = &ch->current; - uint32_t val; - - DBDMA_DPRINTF("load_word\n"); - - /* only implements KEY_SYSTEM */ - - if (key != KEY_SYSTEM) { - printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key); - kill_channel(ch); - return; - } - - cpu_physical_memory_read(addr, &val, len); - - if (len == 2) - val = (val << 16) | (current->cmd_dep & 0x0000ffff); - else if (len == 1) - val = (val << 24) | (current->cmd_dep & 0x00ffffff); - - current->cmd_dep = val; - - if (conditional_wait(ch)) - goto wait; - - current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]); - dbdma_cmdptr_save(ch); - ch->regs[DBDMA_STATUS] &= ~FLUSH; - - conditional_interrupt(ch); - next(ch); - -wait: - DBDMA_kick(dbdma_from_ch(ch)); -} - -static void store_word(DBDMA_channel *ch, int key, uint32_t addr, - uint16_t len) -{ - dbdma_cmd *current = &ch->current; - uint32_t val; - - DBDMA_DPRINTF("store_word\n"); - - /* only implements KEY_SYSTEM */ - - if (key != KEY_SYSTEM) { - printf("DBDMA: STORE_WORD, unimplemented key %x\n", key); - kill_channel(ch); - return; - } - - val = current->cmd_dep; - if (len == 2) - val >>= 16; - else if (len == 1) - val >>= 24; - - cpu_physical_memory_write(addr, &val, len); - - if (conditional_wait(ch)) - goto wait; - - current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]); - dbdma_cmdptr_save(ch); - ch->regs[DBDMA_STATUS] &= ~FLUSH; - - conditional_interrupt(ch); - next(ch); - -wait: - DBDMA_kick(dbdma_from_ch(ch)); -} - -static void nop(DBDMA_channel *ch) -{ - dbdma_cmd *current = &ch->current; - - if (conditional_wait(ch)) - goto wait; - - current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]); - dbdma_cmdptr_save(ch); - - conditional_interrupt(ch); - conditional_branch(ch); - -wait: - DBDMA_kick(dbdma_from_ch(ch)); -} - -static void stop(DBDMA_channel *ch) -{ - ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH); - - /* the stop command does not increment command pointer */ -} - -static void channel_run(DBDMA_channel *ch) -{ - dbdma_cmd *current = &ch->current; - uint16_t cmd, key; - uint16_t req_count; - uint32_t phy_addr; - - DBDMA_DPRINTF("channel_run\n"); - dump_dbdma_cmd(current); - - /* clear WAKE flag at command fetch */ - - ch->regs[DBDMA_STATUS] &= ~WAKE; - - cmd = le16_to_cpu(current->command) & COMMAND_MASK; - - switch (cmd) { - case DBDMA_NOP: - nop(ch); - return; - - case DBDMA_STOP: - stop(ch); - return; - } - - key = le16_to_cpu(current->command) & 0x0700; - req_count = le16_to_cpu(current->req_count); - phy_addr = le32_to_cpu(current->phy_addr); - - if (key == KEY_STREAM4) { - printf("command %x, invalid key 4\n", cmd); - kill_channel(ch); - return; - } - - switch (cmd) { - case OUTPUT_MORE: - start_output(ch, key, phy_addr, req_count, 0); - return; - - case OUTPUT_LAST: - start_output(ch, key, phy_addr, req_count, 1); - return; - - case INPUT_MORE: - start_input(ch, key, phy_addr, req_count, 0); - return; - - case INPUT_LAST: - start_input(ch, key, phy_addr, req_count, 1); - return; - } - - if (key < KEY_REGS) { - printf("command %x, invalid key %x\n", cmd, key); - key = KEY_SYSTEM; - } - - /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits - * and BRANCH is invalid - */ - - req_count = req_count & 0x0007; - if (req_count & 0x4) { - req_count = 4; - phy_addr &= ~3; - } else if (req_count & 0x2) { - req_count = 2; - phy_addr &= ~1; - } else - req_count = 1; - - switch (cmd) { - case LOAD_WORD: - load_word(ch, key, phy_addr, req_count); - return; - - case STORE_WORD: - store_word(ch, key, phy_addr, req_count); - return; - } -} - -static void DBDMA_run(DBDMAState *s) -{ - int channel; - - for (channel = 0; channel < DBDMA_CHANNELS; channel++) { - DBDMA_channel *ch = &s->channels[channel]; - uint32_t status = ch->regs[DBDMA_STATUS]; - if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) { - channel_run(ch); - } - } -} - -static void DBDMA_run_bh(void *opaque) -{ - DBDMAState *s = opaque; - - DBDMA_DPRINTF("DBDMA_run_bh\n"); - - DBDMA_run(s); -} - -void DBDMA_kick(DBDMAState *dbdma) -{ - qemu_bh_schedule(dbdma->bh); -} - -void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, - DBDMA_rw rw, DBDMA_flush flush, - void *opaque) -{ - DBDMAState *s = dbdma; - DBDMA_channel *ch = &s->channels[nchan]; - - DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan); - - assert(rw); - assert(flush); - - ch->irq = irq; - ch->rw = rw; - ch->flush = flush; - ch->io.opaque = opaque; -} - -static void -dbdma_control_write(DBDMA_channel *ch) -{ - uint16_t mask, value; - uint32_t status; - - mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff; - value = ch->regs[DBDMA_CONTROL] & 0xffff; - - value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT); - - status = ch->regs[DBDMA_STATUS]; - - status = (value & mask) | (status & ~mask); - - if (status & WAKE) - status |= ACTIVE; - if (status & RUN) { - status |= ACTIVE; - status &= ~DEAD; - } - if (status & PAUSE) - status &= ~ACTIVE; - if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) { - /* RUN is cleared */ - status &= ~(ACTIVE|DEAD); - } - - if ((status & FLUSH) && ch->flush) { - ch->flush(&ch->io); - status &= ~FLUSH; - } - - DBDMA_DPRINTF(" status 0x%08x\n", status); - - ch->regs[DBDMA_STATUS] = status; - - if (status & ACTIVE) { - DBDMA_kick(dbdma_from_ch(ch)); - } -} - -static void dbdma_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - int channel = addr >> DBDMA_CHANNEL_SHIFT; - DBDMAState *s = opaque; - DBDMA_channel *ch = &s->channels[channel]; - int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; - - DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n", - addr, value); - DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", - (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); - - /* cmdptr cannot be modified if channel is ACTIVE */ - - if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) { - return; - } - - ch->regs[reg] = value; - - switch(reg) { - case DBDMA_CONTROL: - dbdma_control_write(ch); - break; - case DBDMA_CMDPTR_LO: - /* 16-byte aligned */ - ch->regs[DBDMA_CMDPTR_LO] &= ~0xf; - dbdma_cmdptr_load(ch); - break; - case DBDMA_STATUS: - case DBDMA_INTR_SEL: - case DBDMA_BRANCH_SEL: - case DBDMA_WAIT_SEL: - /* nothing to do */ - break; - case DBDMA_XFER_MODE: - case DBDMA_CMDPTR_HI: - case DBDMA_DATA2PTR_HI: - case DBDMA_DATA2PTR_LO: - case DBDMA_ADDRESS_HI: - case DBDMA_BRANCH_ADDR_HI: - case DBDMA_RES1: - case DBDMA_RES2: - case DBDMA_RES3: - case DBDMA_RES4: - /* unused */ - break; - } -} - -static uint64_t dbdma_read(void *opaque, hwaddr addr, - unsigned size) -{ - uint32_t value; - int channel = addr >> DBDMA_CHANNEL_SHIFT; - DBDMAState *s = opaque; - DBDMA_channel *ch = &s->channels[channel]; - int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; - - value = ch->regs[reg]; - - DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value); - DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", - (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); - - switch(reg) { - case DBDMA_CONTROL: - value = 0; - break; - case DBDMA_STATUS: - case DBDMA_CMDPTR_LO: - case DBDMA_INTR_SEL: - case DBDMA_BRANCH_SEL: - case DBDMA_WAIT_SEL: - /* nothing to do */ - break; - case DBDMA_XFER_MODE: - case DBDMA_CMDPTR_HI: - case DBDMA_DATA2PTR_HI: - case DBDMA_DATA2PTR_LO: - case DBDMA_ADDRESS_HI: - case DBDMA_BRANCH_ADDR_HI: - /* unused */ - value = 0; - break; - case DBDMA_RES1: - case DBDMA_RES2: - case DBDMA_RES3: - case DBDMA_RES4: - /* reserved */ - break; - } - - return value; -} - -static const MemoryRegionOps dbdma_ops = { - .read = dbdma_read, - .write = dbdma_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const VMStateDescription vmstate_dbdma_io = { - .name = "dbdma_io", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT64(addr, struct DBDMA_io), - VMSTATE_INT32(len, struct DBDMA_io), - VMSTATE_INT32(is_last, struct DBDMA_io), - VMSTATE_INT32(is_dma_out, struct DBDMA_io), - VMSTATE_BOOL(processing, struct DBDMA_io), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_dbdma_cmd = { - .name = "dbdma_cmd", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT16(req_count, dbdma_cmd), - VMSTATE_UINT16(command, dbdma_cmd), - VMSTATE_UINT32(phy_addr, dbdma_cmd), - VMSTATE_UINT32(cmd_dep, dbdma_cmd), - VMSTATE_UINT16(res_count, dbdma_cmd), - VMSTATE_UINT16(xfer_status, dbdma_cmd), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_dbdma_channel = { - .name = "dbdma_channel", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS), - VMSTATE_STRUCT(io, struct DBDMA_channel, 0, vmstate_dbdma_io, DBDMA_io), - VMSTATE_STRUCT(current, struct DBDMA_channel, 0, vmstate_dbdma_cmd, - dbdma_cmd), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_dbdma = { - .name = "dbdma", - .version_id = 3, - .minimum_version_id = 3, - .fields = (VMStateField[]) { - VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1, - vmstate_dbdma_channel, DBDMA_channel), - VMSTATE_END_OF_LIST() - } -}; - -static void dbdma_reset(void *opaque) -{ - DBDMAState *s = opaque; - int i; - - for (i = 0; i < DBDMA_CHANNELS; i++) - memset(s->channels[i].regs, 0, DBDMA_SIZE); -} - -static void dbdma_unassigned_rw(DBDMA_io *io) -{ - DBDMA_channel *ch = io->channel; - qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n", - __func__, ch->channel); -} - -static void dbdma_unassigned_flush(DBDMA_io *io) -{ - DBDMA_channel *ch = io->channel; - qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n", - __func__, ch->channel); -} - -void* DBDMA_init (MemoryRegion **dbdma_mem) -{ - DBDMAState *s; - int i; - - s = g_malloc0(sizeof(DBDMAState)); - - for (i = 0; i < DBDMA_CHANNELS; i++) { - DBDMA_io *io = &s->channels[i].io; - DBDMA_channel *ch = &s->channels[i]; - qemu_iovec_init(&io->iov, 1); - - ch->rw = dbdma_unassigned_rw; - ch->flush = dbdma_unassigned_flush; - ch->channel = i; - ch->io.channel = ch; - } - - memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000); - *dbdma_mem = &s->mem; - vmstate_register(NULL, -1, &vmstate_dbdma, s); - qemu_register_reset(dbdma_reset, s); - - s->bh = qemu_bh_new(DBDMA_run_bh, s); - - return s; -} diff --git a/qemu/hw/misc/macio/macio.c b/qemu/hw/misc/macio/macio.c deleted file mode 100644 index be03926b9..000000000 --- a/qemu/hw/misc/macio/macio.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * PowerMac MacIO device emulation - * - * Copyright (c) 2005-2007 Fabrice Bellard - * 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 "qapi/error.h" -#include "hw/hw.h" -#include "hw/ppc/mac.h" -#include "hw/pci/pci.h" -#include "hw/ppc/mac_dbdma.h" -#include "hw/char/escc.h" - -#define TYPE_MACIO "macio" -#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) - -typedef struct MacIOState -{ - /*< private >*/ - PCIDevice parent; - /*< public >*/ - - MemoryRegion bar; - CUDAState cuda; - void *dbdma; - MemoryRegion *pic_mem; - MemoryRegion *escc_mem; - uint64_t frequency; -} MacIOState; - -#define OLDWORLD_MACIO(obj) \ - OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO) - -typedef struct OldWorldMacIOState { - /*< private >*/ - MacIOState parent_obj; - /*< public >*/ - - qemu_irq irqs[5]; - - MacIONVRAMState nvram; - MACIOIDEState ide[2]; -} OldWorldMacIOState; - -#define NEWWORLD_MACIO(obj) \ - OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO) - -typedef struct NewWorldMacIOState { - /*< private >*/ - MacIOState parent_obj; - /*< public >*/ - qemu_irq irqs[5]; - MACIOIDEState ide[2]; -} NewWorldMacIOState; - -/* - * The mac-io has two interfaces to the ESCC. One is called "escc-legacy", - * while the other one is the normal, current ESCC interface. - * - * The magic below creates memory aliases to spawn the escc-legacy device - * purely by rerouting the respective registers to our escc region. This - * works because the only difference between the two memory regions is the - * register layout, not their semantics. - * - * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf - */ -static void macio_escc_legacy_setup(MacIOState *macio_state) -{ - MemoryRegion *escc_legacy = g_new(MemoryRegion, 1); - MemoryRegion *bar = &macio_state->bar; - int i; - static const int maps[] = { - 0x00, 0x00, - 0x02, 0x20, - 0x04, 0x10, - 0x06, 0x30, - 0x08, 0x40, - 0x0A, 0x50, - 0x60, 0x60, - 0x70, 0x70, - 0x80, 0x70, - 0x90, 0x80, - 0xA0, 0x90, - 0xB0, 0xA0, - 0xC0, 0xB0, - 0xD0, 0xC0, - 0xE0, 0xD0, - 0xF0, 0xE0, - }; - - memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256); - for (i = 0; i < ARRAY_SIZE(maps); i += 2) { - MemoryRegion *port = g_new(MemoryRegion, 1); - memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port", - macio_state->escc_mem, maps[i+1], 0x2); - memory_region_add_subregion(escc_legacy, maps[i], port); - } - - memory_region_add_subregion(bar, 0x12000, escc_legacy); -} - -static void macio_bar_setup(MacIOState *macio_state) -{ - MemoryRegion *bar = &macio_state->bar; - - if (macio_state->escc_mem) { - memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem); - macio_escc_legacy_setup(macio_state); - } -} - -static void macio_common_realize(PCIDevice *d, Error **errp) -{ - MacIOState *s = MACIO(d); - SysBusDevice *sysbus_dev; - Error *err = NULL; - MemoryRegion *dbdma_mem; - - s->dbdma = DBDMA_init(&dbdma_mem); - memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem); - - object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - sysbus_dev = SYS_BUS_DEVICE(&s->cuda); - memory_region_add_subregion(&s->bar, 0x16000, - sysbus_mmio_get_region(sysbus_dev, 0)); - - macio_bar_setup(s); - pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); -} - -static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide, - qemu_irq irq0, qemu_irq irq1, int dmaid, - Error **errp) -{ - SysBusDevice *sysbus_dev; - - sysbus_dev = SYS_BUS_DEVICE(ide); - sysbus_connect_irq(sysbus_dev, 0, irq0); - sysbus_connect_irq(sysbus_dev, 1, irq1); - macio_ide_register_dma(ide, s->dbdma, dmaid); - object_property_set_bool(OBJECT(ide), true, "realized", errp); -} - -static void macio_oldworld_realize(PCIDevice *d, Error **errp) -{ - MacIOState *s = MACIO(d); - OldWorldMacIOState *os = OLDWORLD_MACIO(d); - Error *err = NULL; - SysBusDevice *sysbus_dev; - int i; - int cur_irq = 0; - - macio_common_realize(d, &err); - if (err) { - error_propagate(errp, err); - return; - } - - sysbus_dev = SYS_BUS_DEVICE(&s->cuda); - sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); - - object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - sysbus_dev = SYS_BUS_DEVICE(&os->nvram); - memory_region_add_subregion(&s->bar, 0x60000, - sysbus_mmio_get_region(sysbus_dev, 0)); - pmac_format_nvram_partition(&os->nvram, os->nvram.size); - - if (s->pic_mem) { - /* Heathrow PIC */ - memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); - } - - /* IDE buses */ - for (i = 0; i < ARRAY_SIZE(os->ide); i++) { - qemu_irq irq0 = os->irqs[cur_irq++]; - qemu_irq irq1 = os->irqs[cur_irq++]; - - macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err); - if (err) { - error_propagate(errp, err); - return; - } - } -} - -static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size, - int index) -{ - gchar *name; - - object_initialize(ide, ide_size, TYPE_MACIO_IDE); - qdev_set_parent_bus(DEVICE(ide), sysbus_get_default()); - memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000), - &ide->mem); - name = g_strdup_printf("ide[%i]", index); - object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL); - g_free(name); -} - -static void macio_oldworld_init(Object *obj) -{ - MacIOState *s = MACIO(obj); - OldWorldMacIOState *os = OLDWORLD_MACIO(obj); - DeviceState *dev; - int i; - - qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); - - object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM); - dev = DEVICE(&os->nvram); - qdev_prop_set_uint32(dev, "size", 0x2000); - qdev_prop_set_uint32(dev, "it_shift", 4); - - for (i = 0; i < 2; i++) { - macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i); - } -} - -static void timer_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ -} - -static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) -{ - uint32_t value = 0; - uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - uint64_t kltime; - - kltime = muldiv64(systime, 4194300, NANOSECONDS_PER_SECOND * 4); - kltime = muldiv64(kltime, 18432000, 1048575); - - switch (addr) { - case 0x38: - value = kltime; - break; - case 0x3c: - value = kltime >> 32; - break; - } - - return value; -} - -static const MemoryRegionOps timer_ops = { - .read = timer_read, - .write = timer_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void macio_newworld_realize(PCIDevice *d, Error **errp) -{ - MacIOState *s = MACIO(d); - NewWorldMacIOState *ns = NEWWORLD_MACIO(d); - Error *err = NULL; - SysBusDevice *sysbus_dev; - MemoryRegion *timer_memory = NULL; - int i; - int cur_irq = 0; - - macio_common_realize(d, &err); - if (err) { - error_propagate(errp, err); - return; - } - - sysbus_dev = SYS_BUS_DEVICE(&s->cuda); - sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); - - if (s->pic_mem) { - /* OpenPIC */ - memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); - } - - /* IDE buses */ - for (i = 0; i < ARRAY_SIZE(ns->ide); i++) { - qemu_irq irq0 = ns->irqs[cur_irq++]; - qemu_irq irq1 = ns->irqs[cur_irq++]; - - macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err); - if (err) { - error_propagate(errp, err); - return; - } - } - - /* Timer */ - timer_memory = g_new(MemoryRegion, 1); - memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer", - 0x1000); - memory_region_add_subregion(&s->bar, 0x15000, timer_memory); -} - -static void macio_newworld_init(Object *obj) -{ - MacIOState *s = MACIO(obj); - NewWorldMacIOState *ns = NEWWORLD_MACIO(obj); - int i; - - qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); - - for (i = 0; i < 2; i++) { - macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i); - } -} - -static void macio_instance_init(Object *obj) -{ - MacIOState *s = MACIO(obj); - - memory_region_init(&s->bar, obj, "macio", 0x80000); - - object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA); - qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); - object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL); -} - -static const VMStateDescription vmstate_macio_oldworld = { - .name = "macio-oldworld", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState), - VMSTATE_END_OF_LIST() - } -}; - -static void macio_oldworld_class_init(ObjectClass *oc, void *data) -{ - PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); - DeviceClass *dc = DEVICE_CLASS(oc); - - pdc->realize = macio_oldworld_realize; - pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201; - dc->vmsd = &vmstate_macio_oldworld; -} - -static const VMStateDescription vmstate_macio_newworld = { - .name = "macio-newworld", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState), - VMSTATE_END_OF_LIST() - } -}; - -static void macio_newworld_class_init(ObjectClass *oc, void *data) -{ - PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); - DeviceClass *dc = DEVICE_CLASS(oc); - - pdc->realize = macio_newworld_realize; - pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL; - dc->vmsd = &vmstate_macio_newworld; -} - -static Property macio_properties[] = { - DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0), - DEFINE_PROP_END_OF_LIST() -}; - -static void macio_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->vendor_id = PCI_VENDOR_ID_APPLE; - k->class_id = PCI_CLASS_OTHERS << 8; - dc->props = macio_properties; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo macio_oldworld_type_info = { - .name = TYPE_OLDWORLD_MACIO, - .parent = TYPE_MACIO, - .instance_size = sizeof(OldWorldMacIOState), - .instance_init = macio_oldworld_init, - .class_init = macio_oldworld_class_init, -}; - -static const TypeInfo macio_newworld_type_info = { - .name = TYPE_NEWWORLD_MACIO, - .parent = TYPE_MACIO, - .instance_size = sizeof(NewWorldMacIOState), - .instance_init = macio_newworld_init, - .class_init = macio_newworld_class_init, -}; - -static const TypeInfo macio_type_info = { - .name = TYPE_MACIO, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(MacIOState), - .instance_init = macio_instance_init, - .abstract = true, - .class_init = macio_class_init, -}; - -static void macio_register_types(void) -{ - type_register_static(&macio_type_info); - type_register_static(&macio_oldworld_type_info); - type_register_static(&macio_newworld_type_info); -} - -type_init(macio_register_types) - -void macio_init(PCIDevice *d, - MemoryRegion *pic_mem, - MemoryRegion *escc_mem) -{ - MacIOState *macio_state = MACIO(d); - - macio_state->pic_mem = pic_mem; - macio_state->escc_mem = escc_mem; - /* Note: this code is strongly inspirated from the corresponding code - in PearPC */ - qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency", - macio_state->frequency); - - qdev_init_nofail(DEVICE(d)); -} diff --git a/qemu/hw/misc/max111x.c b/qemu/hw/misc/max111x.c deleted file mode 100644 index 9014f0f70..000000000 --- a/qemu/hw/misc/max111x.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Maxim MAX1110/1111 ADC chip emulation. - * - * Copyright (c) 2006 Openedhand Ltd. - * Written by Andrzej Zaborowski <balrog@zabor.org> - * - * This code is licensed under the GNU GPLv2. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "hw/ssi/ssi.h" - -typedef struct { - SSISlave parent_obj; - - qemu_irq interrupt; - uint8_t tb1, rb2, rb3; - int cycle; - - uint8_t input[8]; - int inputs, com; -} MAX111xState; - -#define TYPE_MAX_111X "max111x" - -#define MAX_111X(obj) \ - OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X) - -#define TYPE_MAX_1110 "max1110" -#define TYPE_MAX_1111 "max1111" - -/* Control-byte bitfields */ -#define CB_PD0 (1 << 0) -#define CB_PD1 (1 << 1) -#define CB_SGL (1 << 2) -#define CB_UNI (1 << 3) -#define CB_SEL0 (1 << 4) -#define CB_SEL1 (1 << 5) -#define CB_SEL2 (1 << 6) -#define CB_START (1 << 7) - -#define CHANNEL_NUM(v, b0, b1, b2) \ - ((((v) >> (2 + (b0))) & 4) | \ - (((v) >> (3 + (b1))) & 2) | \ - (((v) >> (4 + (b2))) & 1)) - -static uint32_t max111x_read(MAX111xState *s) -{ - if (!s->tb1) - return 0; - - switch (s->cycle ++) { - case 1: - return s->rb2; - case 2: - return s->rb3; - } - - return 0; -} - -/* Interpret a control-byte */ -static void max111x_write(MAX111xState *s, uint32_t value) -{ - int measure, chan; - - /* Ignore the value if START bit is zero */ - if (!(value & CB_START)) - return; - - s->cycle = 0; - - if (!(value & CB_PD1)) { - s->tb1 = 0; - return; - } - - s->tb1 = value; - - if (s->inputs == 8) - chan = CHANNEL_NUM(value, 1, 0, 2); - else - chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2); - - if (value & CB_SGL) - measure = s->input[chan] - s->com; - else - measure = s->input[chan] - s->input[chan ^ 1]; - - if (!(value & CB_UNI)) - measure ^= 0x80; - - s->rb2 = (measure >> 2) & 0x3f; - s->rb3 = (measure << 6) & 0xc0; - - /* FIXME: When should the IRQ be lowered? */ - qemu_irq_raise(s->interrupt); -} - -static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) -{ - MAX111xState *s = MAX_111X(dev); - max111x_write(s, value); - return max111x_read(s); -} - -static const VMStateDescription vmstate_max111x = { - .name = "max111x", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(parent_obj, MAX111xState), - VMSTATE_UINT8(tb1, MAX111xState), - VMSTATE_UINT8(rb2, MAX111xState), - VMSTATE_UINT8(rb3, MAX111xState), - VMSTATE_INT32_EQUAL(inputs, MAX111xState), - VMSTATE_INT32(com, MAX111xState), - VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs, - vmstate_info_uint8, uint8_t), - VMSTATE_END_OF_LIST() - } -}; - -static int max111x_init(SSISlave *d, int inputs) -{ - DeviceState *dev = DEVICE(d); - MAX111xState *s = MAX_111X(dev); - - qdev_init_gpio_out(dev, &s->interrupt, 1); - - s->inputs = inputs; - /* TODO: add a user interface for setting these */ - s->input[0] = 0xf0; - s->input[1] = 0xe0; - s->input[2] = 0xd0; - s->input[3] = 0xc0; - s->input[4] = 0xb0; - s->input[5] = 0xa0; - s->input[6] = 0x90; - s->input[7] = 0x80; - s->com = 0; - - vmstate_register(dev, -1, &vmstate_max111x, s); - return 0; -} - -static int max1110_init(SSISlave *dev) -{ - return max111x_init(dev, 8); -} - -static int max1111_init(SSISlave *dev) -{ - return max111x_init(dev, 4); -} - -void max111x_set_input(DeviceState *dev, int line, uint8_t value) -{ - MAX111xState *s = MAX_111X(dev); - assert(line >= 0 && line < s->inputs); - s->input[line] = value; -} - -static void max111x_class_init(ObjectClass *klass, void *data) -{ - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); - - k->transfer = max111x_transfer; -} - -static const TypeInfo max111x_info = { - .name = TYPE_MAX_111X, - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(MAX111xState), - .class_init = max111x_class_init, - .abstract = true, -}; - -static void max1110_class_init(ObjectClass *klass, void *data) -{ - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); - - k->init = max1110_init; -} - -static const TypeInfo max1110_info = { - .name = TYPE_MAX_1110, - .parent = TYPE_MAX_111X, - .class_init = max1110_class_init, -}; - -static void max1111_class_init(ObjectClass *klass, void *data) -{ - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); - - k->init = max1111_init; -} - -static const TypeInfo max1111_info = { - .name = TYPE_MAX_1111, - .parent = TYPE_MAX_111X, - .class_init = max1111_class_init, -}; - -static void max111x_register_types(void) -{ - type_register_static(&max111x_info); - type_register_static(&max1110_info); - type_register_static(&max1111_info); -} - -type_init(max111x_register_types) diff --git a/qemu/hw/misc/milkymist-hpdmc.c b/qemu/hw/misc/milkymist-hpdmc.c deleted file mode 100644 index b97000fc4..000000000 --- a/qemu/hw/misc/milkymist-hpdmc.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * QEMU model of the Milkymist High Performance Dynamic Memory Controller. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://www.milkymist.org/socdoc/hpdmc.pdf - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "trace.h" -#include "qemu/error-report.h" - -enum { - R_SYSTEM = 0, - R_BYPASS, - R_TIMING, - R_IODELAY, - R_MAX -}; - -enum { - IODELAY_DQSDELAY_RDY = (1<<5), - IODELAY_PLL1_LOCKED = (1<<6), - IODELAY_PLL2_LOCKED = (1<<7), -}; - -#define TYPE_MILKYMIST_HPDMC "milkymist-hpdmc" -#define MILKYMIST_HPDMC(obj) \ - OBJECT_CHECK(MilkymistHpdmcState, (obj), TYPE_MILKYMIST_HPDMC) - -struct MilkymistHpdmcState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - - uint32_t regs[R_MAX]; -}; -typedef struct MilkymistHpdmcState MilkymistHpdmcState; - -static uint64_t hpdmc_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistHpdmcState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_SYSTEM: - case R_BYPASS: - case R_TIMING: - case R_IODELAY: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_hpdmc: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_hpdmc_memory_read(addr << 2, r); - - return r; -} - -static void hpdmc_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistHpdmcState *s = opaque; - - trace_milkymist_hpdmc_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_SYSTEM: - case R_BYPASS: - case R_TIMING: - s->regs[addr] = value; - break; - case R_IODELAY: - /* ignore writes */ - break; - - default: - error_report("milkymist_hpdmc: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps hpdmc_mmio_ops = { - .read = hpdmc_read, - .write = hpdmc_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_hpdmc_reset(DeviceState *d) -{ - MilkymistHpdmcState *s = MILKYMIST_HPDMC(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - /* defaults */ - s->regs[R_IODELAY] = IODELAY_DQSDELAY_RDY | IODELAY_PLL1_LOCKED - | IODELAY_PLL2_LOCKED; -} - -static int milkymist_hpdmc_init(SysBusDevice *dev) -{ - MilkymistHpdmcState *s = MILKYMIST_HPDMC(dev); - - memory_region_init_io(&s->regs_region, OBJECT(dev), &hpdmc_mmio_ops, s, - "milkymist-hpdmc", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); - - return 0; -} - -static const VMStateDescription vmstate_milkymist_hpdmc = { - .name = "milkymist-hpdmc", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistHpdmcState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static void milkymist_hpdmc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = milkymist_hpdmc_init; - dc->reset = milkymist_hpdmc_reset; - dc->vmsd = &vmstate_milkymist_hpdmc; -} - -static const TypeInfo milkymist_hpdmc_info = { - .name = TYPE_MILKYMIST_HPDMC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistHpdmcState), - .class_init = milkymist_hpdmc_class_init, -}; - -static void milkymist_hpdmc_register_types(void) -{ - type_register_static(&milkymist_hpdmc_info); -} - -type_init(milkymist_hpdmc_register_types) diff --git a/qemu/hw/misc/milkymist-pfpu.c b/qemu/hw/misc/milkymist-pfpu.c deleted file mode 100644 index 57acd7b36..000000000 --- a/qemu/hw/misc/milkymist-pfpu.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * QEMU model of the Milkymist programmable FPU. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://www.milkymist.org/socdoc/pfpu.pdf - * - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "trace.h" -#include "qemu/log.h" -#include "qemu/error-report.h" -#include <math.h> - -/* #define TRACE_EXEC */ - -#ifdef TRACE_EXEC -# define D_EXEC(x) x -#else -# define D_EXEC(x) -#endif - -enum { - R_CTL = 0, - R_MESHBASE, - R_HMESHLAST, - R_VMESHLAST, - R_CODEPAGE, - R_VERTICES, - R_COLLISIONS, - R_STRAYWRITES, - R_LASTDMA, - R_PC, - R_DREGBASE, - R_CODEBASE, - R_MAX -}; - -enum { - CTL_START_BUSY = (1<<0), -}; - -enum { - OP_NOP = 0, - OP_FADD, - OP_FSUB, - OP_FMUL, - OP_FABS, - OP_F2I, - OP_I2F, - OP_VECTOUT, - OP_SIN, - OP_COS, - OP_ABOVE, - OP_EQUAL, - OP_COPY, - OP_IF, - OP_TSIGN, - OP_QUAKE, -}; - -enum { - GPR_X = 0, - GPR_Y = 1, - GPR_FLAGS = 2, -}; - -enum { - LATENCY_FADD = 5, - LATENCY_FSUB = 5, - LATENCY_FMUL = 7, - LATENCY_FABS = 2, - LATENCY_F2I = 2, - LATENCY_I2F = 3, - LATENCY_VECTOUT = 0, - LATENCY_SIN = 4, - LATENCY_COS = 4, - LATENCY_ABOVE = 2, - LATENCY_EQUAL = 2, - LATENCY_COPY = 2, - LATENCY_IF = 2, - LATENCY_TSIGN = 2, - LATENCY_QUAKE = 2, - MAX_LATENCY = 7 -}; - -#define GPR_BEGIN 0x100 -#define GPR_END 0x17f -#define MICROCODE_BEGIN 0x200 -#define MICROCODE_END 0x3ff -#define MICROCODE_WORDS 2048 - -#define REINTERPRET_CAST(type, val) (*((type *)&(val))) - -#ifdef TRACE_EXEC -static const char *opcode_to_str[] = { - "NOP", "FADD", "FSUB", "FMUL", "FABS", "F2I", "I2F", "VECTOUT", - "SIN", "COS", "ABOVE", "EQUAL", "COPY", "IF", "TSIGN", "QUAKE", -}; -#endif - -#define TYPE_MILKYMIST_PFPU "milkymist-pfpu" -#define MILKYMIST_PFPU(obj) \ - OBJECT_CHECK(MilkymistPFPUState, (obj), TYPE_MILKYMIST_PFPU) - -struct MilkymistPFPUState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - CharDriverState *chr; - qemu_irq irq; - - uint32_t regs[R_MAX]; - uint32_t gp_regs[128]; - uint32_t microcode[MICROCODE_WORDS]; - - int output_queue_pos; - uint32_t output_queue[MAX_LATENCY]; -}; -typedef struct MilkymistPFPUState MilkymistPFPUState; - -static inline hwaddr -get_dma_address(uint32_t base, uint32_t x, uint32_t y) -{ - return base + 8 * (128 * y + x); -} - -static inline void -output_queue_insert(MilkymistPFPUState *s, uint32_t val, int pos) -{ - s->output_queue[(s->output_queue_pos + pos) % MAX_LATENCY] = val; -} - -static inline uint32_t -output_queue_remove(MilkymistPFPUState *s) -{ - return s->output_queue[s->output_queue_pos]; -} - -static inline void -output_queue_advance(MilkymistPFPUState *s) -{ - s->output_queue[s->output_queue_pos] = 0; - s->output_queue_pos = (s->output_queue_pos + 1) % MAX_LATENCY; -} - -static int pfpu_decode_insn(MilkymistPFPUState *s) -{ - uint32_t pc = s->regs[R_PC]; - uint32_t insn = s->microcode[pc]; - uint32_t reg_a = (insn >> 18) & 0x7f; - uint32_t reg_b = (insn >> 11) & 0x7f; - uint32_t op = (insn >> 7) & 0xf; - uint32_t reg_d = insn & 0x7f; - uint32_t r = 0; - int latency = 0; - - switch (op) { - case OP_NOP: - break; - case OP_FADD: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = a + b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FADD; - D_EXEC(qemu_log("ADD a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_FSUB: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = a - b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FSUB; - D_EXEC(qemu_log("SUB a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_FMUL: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = a * b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FMUL; - D_EXEC(qemu_log("MUL a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_FABS: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float t = fabsf(a); - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FABS; - D_EXEC(qemu_log("ABS a=%f t=%f, r=%08x\n", a, t, r)); - } break; - case OP_F2I: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - int32_t t = a; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_F2I; - D_EXEC(qemu_log("F2I a=%f t=%d, r=%08x\n", a, t, r)); - } break; - case OP_I2F: - { - int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]); - float t = a; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_I2F; - D_EXEC(qemu_log("I2F a=%08x t=%f, r=%08x\n", a, t, r)); - } break; - case OP_VECTOUT: - { - uint32_t a = cpu_to_be32(s->gp_regs[reg_a]); - uint32_t b = cpu_to_be32(s->gp_regs[reg_b]); - hwaddr dma_ptr = - get_dma_address(s->regs[R_MESHBASE], - s->gp_regs[GPR_X], s->gp_regs[GPR_Y]); - cpu_physical_memory_write(dma_ptr, &a, 4); - cpu_physical_memory_write(dma_ptr + 4, &b, 4); - s->regs[R_LASTDMA] = dma_ptr + 4; - D_EXEC(qemu_log("VECTOUT a=%08x b=%08x dma=%08x\n", a, b, dma_ptr)); - trace_milkymist_pfpu_vectout(a, b, dma_ptr); - } break; - case OP_SIN: - { - int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]); - float t = sinf(a * (1.0f / (M_PI * 4096.0f))); - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_SIN; - D_EXEC(qemu_log("SIN a=%d t=%f, r=%08x\n", a, t, r)); - } break; - case OP_COS: - { - int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]); - float t = cosf(a * (1.0f / (M_PI * 4096.0f))); - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_COS; - D_EXEC(qemu_log("COS a=%d t=%f, r=%08x\n", a, t, r)); - } break; - case OP_ABOVE: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = (a > b) ? 1.0f : 0.0f; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_ABOVE; - D_EXEC(qemu_log("ABOVE a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_EQUAL: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = (a == b) ? 1.0f : 0.0f; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_EQUAL; - D_EXEC(qemu_log("EQUAL a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_COPY: - { - r = s->gp_regs[reg_a]; - latency = LATENCY_COPY; - D_EXEC(qemu_log("COPY")); - } break; - case OP_IF: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - uint32_t f = s->gp_regs[GPR_FLAGS]; - float t = (f != 0) ? a : b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_IF; - D_EXEC(qemu_log("IF f=%u a=%f b=%f t=%f, r=%08x\n", f, a, b, t, r)); - } break; - case OP_TSIGN: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = (b < 0) ? -a : a; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_TSIGN; - D_EXEC(qemu_log("TSIGN a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_QUAKE: - { - uint32_t a = s->gp_regs[reg_a]; - r = 0x5f3759df - (a >> 1); - latency = LATENCY_QUAKE; - D_EXEC(qemu_log("QUAKE a=%d r=%08x\n", a, r)); - } break; - - default: - error_report("milkymist_pfpu: unknown opcode %d", op); - break; - } - - if (!reg_d) { - D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n", - s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency, - s->regs[R_PC] + latency)); - } else { - D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n", - s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency, - s->regs[R_PC] + latency, reg_d)); - } - - if (op == OP_VECTOUT) { - return 0; - } - - /* store output for this cycle */ - if (reg_d) { - uint32_t val = output_queue_remove(s); - D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val)); - s->gp_regs[reg_d] = val; - } - - output_queue_advance(s); - - /* store op output */ - if (op != OP_NOP) { - output_queue_insert(s, r, latency-1); - } - - /* advance PC */ - s->regs[R_PC]++; - - return 1; -}; - -static void pfpu_start(MilkymistPFPUState *s) -{ - int x, y; - int i; - - for (y = 0; y <= s->regs[R_VMESHLAST]; y++) { - for (x = 0; x <= s->regs[R_HMESHLAST]; x++) { - D_EXEC(qemu_log("\nprocessing x=%d y=%d\n", x, y)); - - /* set current position */ - s->gp_regs[GPR_X] = x; - s->gp_regs[GPR_Y] = y; - - /* run microcode on this position */ - i = 0; - while (pfpu_decode_insn(s)) { - /* decode at most MICROCODE_WORDS instructions */ - if (++i >= MICROCODE_WORDS) { - error_report("milkymist_pfpu: too many instructions " - "executed in microcode. No VECTOUT?"); - break; - } - } - - /* reset pc for next run */ - s->regs[R_PC] = 0; - } - } - - s->regs[R_VERTICES] = x * y; - - trace_milkymist_pfpu_pulse_irq(); - qemu_irq_pulse(s->irq); -} - -static inline int get_microcode_address(MilkymistPFPUState *s, uint32_t addr) -{ - return (512 * s->regs[R_CODEPAGE]) + addr - MICROCODE_BEGIN; -} - -static uint64_t pfpu_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistPFPUState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CTL: - case R_MESHBASE: - case R_HMESHLAST: - case R_VMESHLAST: - case R_CODEPAGE: - case R_VERTICES: - case R_COLLISIONS: - case R_STRAYWRITES: - case R_LASTDMA: - case R_PC: - case R_DREGBASE: - case R_CODEBASE: - r = s->regs[addr]; - break; - case GPR_BEGIN ... GPR_END: - r = s->gp_regs[addr - GPR_BEGIN]; - break; - case MICROCODE_BEGIN ... MICROCODE_END: - r = s->microcode[get_microcode_address(s, addr)]; - break; - - default: - error_report("milkymist_pfpu: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_pfpu_memory_read(addr << 2, r); - - return r; -} - -static void pfpu_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistPFPUState *s = opaque; - - trace_milkymist_pfpu_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTL: - if (value & CTL_START_BUSY) { - pfpu_start(s); - } - break; - case R_MESHBASE: - case R_HMESHLAST: - case R_VMESHLAST: - case R_CODEPAGE: - case R_VERTICES: - case R_COLLISIONS: - case R_STRAYWRITES: - case R_LASTDMA: - case R_PC: - case R_DREGBASE: - case R_CODEBASE: - s->regs[addr] = value; - break; - case GPR_BEGIN ... GPR_END: - s->gp_regs[addr - GPR_BEGIN] = value; - break; - case MICROCODE_BEGIN ... MICROCODE_END: - s->microcode[get_microcode_address(s, addr)] = value; - break; - - default: - error_report("milkymist_pfpu: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps pfpu_mmio_ops = { - .read = pfpu_read, - .write = pfpu_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_pfpu_reset(DeviceState *d) -{ - MilkymistPFPUState *s = MILKYMIST_PFPU(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - for (i = 0; i < 128; i++) { - s->gp_regs[i] = 0; - } - for (i = 0; i < MICROCODE_WORDS; i++) { - s->microcode[i] = 0; - } - s->output_queue_pos = 0; - for (i = 0; i < MAX_LATENCY; i++) { - s->output_queue[i] = 0; - } -} - -static int milkymist_pfpu_init(SysBusDevice *dev) -{ - MilkymistPFPUState *s = MILKYMIST_PFPU(dev); - - sysbus_init_irq(dev, &s->irq); - - memory_region_init_io(&s->regs_region, OBJECT(dev), &pfpu_mmio_ops, s, - "milkymist-pfpu", MICROCODE_END * 4); - sysbus_init_mmio(dev, &s->regs_region); - - return 0; -} - -static const VMStateDescription vmstate_milkymist_pfpu = { - .name = "milkymist-pfpu", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistPFPUState, R_MAX), - VMSTATE_UINT32_ARRAY(gp_regs, MilkymistPFPUState, 128), - VMSTATE_UINT32_ARRAY(microcode, MilkymistPFPUState, MICROCODE_WORDS), - VMSTATE_INT32(output_queue_pos, MilkymistPFPUState), - VMSTATE_UINT32_ARRAY(output_queue, MilkymistPFPUState, MAX_LATENCY), - VMSTATE_END_OF_LIST() - } -}; - -static void milkymist_pfpu_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = milkymist_pfpu_init; - dc->reset = milkymist_pfpu_reset; - dc->vmsd = &vmstate_milkymist_pfpu; -} - -static const TypeInfo milkymist_pfpu_info = { - .name = TYPE_MILKYMIST_PFPU, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistPFPUState), - .class_init = milkymist_pfpu_class_init, -}; - -static void milkymist_pfpu_register_types(void) -{ - type_register_static(&milkymist_pfpu_info); -} - -type_init(milkymist_pfpu_register_types) diff --git a/qemu/hw/misc/mips_cmgcr.c b/qemu/hw/misc/mips_cmgcr.c deleted file mode 100644 index 37be23995..000000000 --- a/qemu/hw/misc/mips_cmgcr.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. - * Authors: Sanjay Lal <sanjayl@kymasys.com> - * - * Copyright (C) 2015 Imagination Technologies - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "sysemu/sysemu.h" -#include "hw/misc/mips_cmgcr.h" -#include "hw/misc/mips_cpc.h" - -static inline bool is_cpc_connected(MIPSGCRState *s) -{ - return s->cpc_mr != NULL; -} - -static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val) -{ - if (is_cpc_connected(gcr)) { - gcr->cpc_base = val & GCR_CPC_BASE_MSK; - memory_region_transaction_begin(); - memory_region_set_address(gcr->cpc_mr, - gcr->cpc_base & GCR_CPC_BASE_CPCBASE_MSK); - memory_region_set_enabled(gcr->cpc_mr, - gcr->cpc_base & GCR_CPC_BASE_CPCEN_MSK); - memory_region_transaction_commit(); - } -} - -/* Read GCR registers */ -static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) -{ - MIPSGCRState *gcr = (MIPSGCRState *) opaque; - - switch (addr) { - /* Global Control Block Register */ - case GCR_CONFIG_OFS: - /* Set PCORES to 0 */ - return 0; - case GCR_BASE_OFS: - return gcr->gcr_base; - case GCR_REV_OFS: - return gcr->gcr_rev; - case GCR_CPC_BASE_OFS: - return gcr->cpc_base; - case GCR_CPC_STATUS_OFS: - return is_cpc_connected(gcr); - case GCR_L2_CONFIG_OFS: - /* L2 BYPASS */ - return GCR_L2_CONFIG_BYPASS_MSK; - /* Core-Local and Core-Other Control Blocks */ - case MIPS_CLCB_OFS + GCR_CL_CONFIG_OFS: - case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS: - /* Set PVP to # of VPs - 1 */ - return gcr->num_vps - 1; - case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS: - return 0; - default: - qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx - "\n", size, addr); - return 0; - } - return 0; -} - -/* Write GCR registers */ -static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) -{ - MIPSGCRState *gcr = (MIPSGCRState *)opaque; - - switch (addr) { - case GCR_CPC_BASE_OFS: - update_cpc_base(gcr, data); - break; - default: - qemu_log_mask(LOG_UNIMP, "Write %d bytes at GCR offset 0x%" HWADDR_PRIx - " 0x%" PRIx64 "\n", size, addr, data); - break; - } -} - -static const MemoryRegionOps gcr_ops = { - .read = gcr_read, - .write = gcr_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .max_access_size = 8, - }, -}; - -static void mips_gcr_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - MIPSGCRState *s = MIPS_GCR(obj); - - object_property_add_link(obj, "cpc", TYPE_MEMORY_REGION, - (Object **)&s->cpc_mr, - qdev_prop_allow_set_link_before_realize, - OBJ_PROP_LINK_UNREF_ON_RELEASE, - &error_abort); - - memory_region_init_io(&s->iomem, OBJECT(s), &gcr_ops, s, - "mips-gcr", GCR_ADDRSPACE_SZ); - sysbus_init_mmio(sbd, &s->iomem); -} - -static void mips_gcr_reset(DeviceState *dev) -{ - MIPSGCRState *s = MIPS_GCR(dev); - - update_cpc_base(s, 0); -} - -static const VMStateDescription vmstate_mips_gcr = { - .name = "mips-gcr", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT64(cpc_base, MIPSGCRState), - VMSTATE_END_OF_LIST() - }, -}; - -static Property mips_gcr_properties[] = { - DEFINE_PROP_INT32("num-vp", MIPSGCRState, num_vps, 1), - DEFINE_PROP_INT32("gcr-rev", MIPSGCRState, gcr_rev, 0x800), - DEFINE_PROP_UINT64("gcr-base", MIPSGCRState, gcr_base, GCR_BASE_ADDR), - DEFINE_PROP_END_OF_LIST(), -}; - -static void mips_gcr_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - dc->props = mips_gcr_properties; - dc->vmsd = &vmstate_mips_gcr; - dc->reset = mips_gcr_reset; -} - -static const TypeInfo mips_gcr_info = { - .name = TYPE_MIPS_GCR, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MIPSGCRState), - .instance_init = mips_gcr_init, - .class_init = mips_gcr_class_init, -}; - -static void mips_gcr_register_types(void) -{ - type_register_static(&mips_gcr_info); -} - -type_init(mips_gcr_register_types) diff --git a/qemu/hw/misc/mips_cpc.c b/qemu/hw/misc/mips_cpc.c deleted file mode 100644 index d2b8e42da..000000000 --- a/qemu/hw/misc/mips_cpc.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Cluster Power Controller emulation - * - * Copyright (c) 2016 Imagination Technologies - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/sysbus.h" - -#include "hw/misc/mips_cpc.h" - -static inline uint64_t cpc_vp_run_mask(MIPSCPCState *cpc) -{ - return (1ULL << cpc->num_vp) - 1; -} - -static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run) -{ - CPUState *cs = first_cpu; - - CPU_FOREACH(cs) { - uint64_t i = 1ULL << cs->cpu_index; - if (i & vp_run & ~cpc->vp_running) { - cpu_interrupt(cs, CPU_INTERRUPT_WAKE); - cpc->vp_running |= i; - } - } -} - -static void cpc_stop_vp(MIPSCPCState *cpc, uint64_t vp_stop) -{ - CPUState *cs = first_cpu; - - CPU_FOREACH(cs) { - uint64_t i = 1ULL << cs->cpu_index; - if (i & vp_stop & cpc->vp_running) { - cs->halted = 1; - cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); - cpc->vp_running &= ~i; - } - } -} - -static void cpc_write(void *opaque, hwaddr offset, uint64_t data, - unsigned size) -{ - MIPSCPCState *s = opaque; - - switch (offset) { - case CPC_CL_BASE_OFS + CPC_VP_RUN_OFS: - case CPC_CO_BASE_OFS + CPC_VP_RUN_OFS: - cpc_run_vp(s, data & cpc_vp_run_mask(s)); - break; - case CPC_CL_BASE_OFS + CPC_VP_STOP_OFS: - case CPC_CO_BASE_OFS + CPC_VP_STOP_OFS: - cpc_stop_vp(s, data & cpc_vp_run_mask(s)); - break; - default: - qemu_log_mask(LOG_UNIMP, - "%s: Bad offset 0x%x\n", __func__, (int)offset); - break; - } - - return; -} - -static uint64_t cpc_read(void *opaque, hwaddr offset, unsigned size) -{ - MIPSCPCState *s = opaque; - - switch (offset) { - case CPC_CL_BASE_OFS + CPC_VP_RUNNING_OFS: - case CPC_CO_BASE_OFS + CPC_VP_RUNNING_OFS: - return s->vp_running; - default: - qemu_log_mask(LOG_UNIMP, - "%s: Bad offset 0x%x\n", __func__, (int)offset); - return 0; - } -} - -static const MemoryRegionOps cpc_ops = { - .read = cpc_read, - .write = cpc_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .max_access_size = 8, - }, -}; - -static void mips_cpc_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - MIPSCPCState *s = MIPS_CPC(obj); - - memory_region_init_io(&s->mr, OBJECT(s), &cpc_ops, s, "mips-cpc", - CPC_ADDRSPACE_SZ); - sysbus_init_mmio(sbd, &s->mr); -} - -static void mips_cpc_realize(DeviceState *dev, Error **errp) -{ - MIPSCPCState *s = MIPS_CPC(dev); - - if (s->vp_start_running > cpc_vp_run_mask(s)) { - error_setg(errp, - "incorrect vp_start_running 0x%" PRIx64 " for num_vp = %d", - s->vp_running, s->num_vp); - return; - } -} - -static void mips_cpc_reset(DeviceState *dev) -{ - MIPSCPCState *s = MIPS_CPC(dev); - - /* Reflect the fact that all VPs are halted on reset */ - s->vp_running = 0; - - /* Put selected VPs into run state */ - cpc_run_vp(s, s->vp_start_running); -} - -static const VMStateDescription vmstate_mips_cpc = { - .name = "mips-cpc", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT64(vp_running, MIPSCPCState), - VMSTATE_END_OF_LIST() - }, -}; - -static Property mips_cpc_properties[] = { - DEFINE_PROP_UINT32("num-vp", MIPSCPCState, num_vp, 0x1), - DEFINE_PROP_UINT64("vp-start-running", MIPSCPCState, vp_start_running, 0x1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void mips_cpc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = mips_cpc_realize; - dc->reset = mips_cpc_reset; - dc->vmsd = &vmstate_mips_cpc; - dc->props = mips_cpc_properties; -} - -static const TypeInfo mips_cpc_info = { - .name = TYPE_MIPS_CPC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MIPSCPCState), - .instance_init = mips_cpc_init, - .class_init = mips_cpc_class_init, -}; - -static void mips_cpc_register_types(void) -{ - type_register_static(&mips_cpc_info); -} - -type_init(mips_cpc_register_types) diff --git a/qemu/hw/misc/mips_itu.c b/qemu/hw/misc/mips_itu.c deleted file mode 100644 index da5455062..000000000 --- a/qemu/hw/misc/mips_itu.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Inter-Thread Communication Unit emulation. - * - * Copyright (c) 2016 Imagination Technologies - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "sysemu/sysemu.h" -#include "hw/misc/mips_itu.h" - -#define ITC_TAG_ADDRSPACE_SZ (ITC_ADDRESSMAP_NUM * 8) -/* Initialize as 4kB area to fit all 32 cells with default 128B grain. - Storage may be resized by the software. */ -#define ITC_STORAGE_ADDRSPACE_SZ 0x1000 - -#define ITC_FIFO_NUM_MAX 16 -#define ITC_SEMAPH_NUM_MAX 16 -#define ITC_AM1_NUMENTRIES_OFS 20 - -#define ITC_CELL_PV_MAX_VAL 0xFFFF - -#define ITC_CELL_TAG_FIFO_DEPTH 28 -#define ITC_CELL_TAG_FIFO_PTR 18 -#define ITC_CELL_TAG_FIFO 17 -#define ITC_CELL_TAG_T 16 -#define ITC_CELL_TAG_F 1 -#define ITC_CELL_TAG_E 0 - -#define ITC_AM0_BASE_ADDRESS_MASK 0xFFFFFC00ULL -#define ITC_AM0_EN_MASK 0x1 - -#define ITC_AM1_ADDR_MASK_MASK 0x1FC00 -#define ITC_AM1_ENTRY_GRAIN_MASK 0x7 - -typedef enum ITCView { - ITCVIEW_BYPASS = 0, - ITCVIEW_CONTROL = 1, - ITCVIEW_EF_SYNC = 2, - ITCVIEW_EF_TRY = 3, - ITCVIEW_PV_SYNC = 4, - ITCVIEW_PV_TRY = 5 -} ITCView; - -MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu) -{ - return &itu->tag_io; -} - -static uint64_t itc_tag_read(void *opaque, hwaddr addr, unsigned size) -{ - MIPSITUState *tag = (MIPSITUState *)opaque; - uint64_t index = addr >> 3; - - if (index >= ITC_ADDRESSMAP_NUM) { - qemu_log_mask(LOG_GUEST_ERROR, "Read 0x%" PRIx64 "\n", addr); - return 0; - } - - return tag->ITCAddressMap[index]; -} - -static void itc_reconfigure(MIPSITUState *tag) -{ - uint64_t *am = &tag->ITCAddressMap[0]; - MemoryRegion *mr = &tag->storage_io; - hwaddr address = am[0] & ITC_AM0_BASE_ADDRESS_MASK; - uint64_t size = (1 << 10) + (am[1] & ITC_AM1_ADDR_MASK_MASK); - bool is_enabled = (am[0] & ITC_AM0_EN_MASK) != 0; - - memory_region_transaction_begin(); - if (!(size & (size - 1))) { - memory_region_set_size(mr, size); - } - memory_region_set_address(mr, address); - memory_region_set_enabled(mr, is_enabled); - memory_region_transaction_commit(); -} - -static void itc_tag_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - MIPSITUState *tag = (MIPSITUState *)opaque; - uint64_t *am = &tag->ITCAddressMap[0]; - uint64_t am_old, mask; - uint64_t index = addr >> 3; - - switch (index) { - case 0: - mask = ITC_AM0_BASE_ADDRESS_MASK | ITC_AM0_EN_MASK; - break; - case 1: - mask = ITC_AM1_ADDR_MASK_MASK | ITC_AM1_ENTRY_GRAIN_MASK; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "Bad write 0x%" PRIx64 "\n", addr); - return; - } - - am_old = am[index]; - am[index] = (data & mask) | (am_old & ~mask); - if (am_old != am[index]) { - itc_reconfigure(tag); - } -} - -static const MemoryRegionOps itc_tag_ops = { - .read = itc_tag_read, - .write = itc_tag_write, - .impl = { - .max_access_size = 8, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static inline uint32_t get_num_cells(MIPSITUState *s) -{ - return s->num_fifo + s->num_semaphores; -} - -static inline ITCView get_itc_view(hwaddr addr) -{ - return (addr >> 3) & 0xf; -} - -static inline int get_cell_stride_shift(const MIPSITUState *s) -{ - /* Minimum interval (for EntryGain = 0) is 128 B */ - return 7 + (s->ITCAddressMap[1] & ITC_AM1_ENTRY_GRAIN_MASK); -} - -static inline ITCStorageCell *get_cell(MIPSITUState *s, - hwaddr addr) -{ - uint32_t cell_idx = addr >> get_cell_stride_shift(s); - uint32_t num_cells = get_num_cells(s); - - if (cell_idx >= num_cells) { - cell_idx = num_cells - 1; - } - - return &s->cell[cell_idx]; -} - -static void wake_blocked_threads(ITCStorageCell *c) -{ - CPUState *cs; - CPU_FOREACH(cs) { - if (cs->halted && (c->blocked_threads & (1ULL << cs->cpu_index))) { - cpu_interrupt(cs, CPU_INTERRUPT_WAKE); - } - } - c->blocked_threads = 0; -} - -static void QEMU_NORETURN block_thread_and_exit(ITCStorageCell *c) -{ - c->blocked_threads |= 1ULL << current_cpu->cpu_index; - cpu_restore_state(current_cpu, current_cpu->mem_io_pc); - current_cpu->halted = 1; - current_cpu->exception_index = EXCP_HLT; - cpu_loop_exit(current_cpu); -} - -/* ITC Bypass View */ - -static inline uint64_t view_bypass_read(ITCStorageCell *c) -{ - if (c->tag.FIFO) { - return c->data[c->fifo_out]; - } else { - return c->data[0]; - } -} - -static inline void view_bypass_write(ITCStorageCell *c, uint64_t val) -{ - if (c->tag.FIFO && (c->tag.FIFOPtr > 0)) { - int idx = (c->fifo_out + c->tag.FIFOPtr - 1) % ITC_CELL_DEPTH; - c->data[idx] = val; - } - - /* ignore a write to the semaphore cell */ -} - -/* ITC Control View */ - -static inline uint64_t view_control_read(ITCStorageCell *c) -{ - return ((uint64_t)c->tag.FIFODepth << ITC_CELL_TAG_FIFO_DEPTH) | - (c->tag.FIFOPtr << ITC_CELL_TAG_FIFO_PTR) | - (c->tag.FIFO << ITC_CELL_TAG_FIFO) | - (c->tag.T << ITC_CELL_TAG_T) | - (c->tag.E << ITC_CELL_TAG_E) | - (c->tag.F << ITC_CELL_TAG_F); -} - -static inline void view_control_write(ITCStorageCell *c, uint64_t val) -{ - c->tag.T = (val >> ITC_CELL_TAG_T) & 1; - c->tag.E = (val >> ITC_CELL_TAG_E) & 1; - c->tag.F = (val >> ITC_CELL_TAG_F) & 1; - - if (c->tag.E) { - c->tag.FIFOPtr = 0; - } -} - -/* ITC Empty/Full View */ - -static uint64_t view_ef_common_read(ITCStorageCell *c, bool blocking) -{ - uint64_t ret = 0; - - if (!c->tag.FIFO) { - return 0; - } - - c->tag.F = 0; - - if (blocking && c->tag.E) { - block_thread_and_exit(c); - } - - if (c->blocked_threads) { - wake_blocked_threads(c); - } - - if (c->tag.FIFOPtr > 0) { - ret = c->data[c->fifo_out]; - c->fifo_out = (c->fifo_out + 1) % ITC_CELL_DEPTH; - c->tag.FIFOPtr--; - } - - if (c->tag.FIFOPtr == 0) { - c->tag.E = 1; - } - - return ret; -} - -static uint64_t view_ef_sync_read(ITCStorageCell *c) -{ - return view_ef_common_read(c, true); -} - -static uint64_t view_ef_try_read(ITCStorageCell *c) -{ - return view_ef_common_read(c, false); -} - -static inline void view_ef_common_write(ITCStorageCell *c, uint64_t val, - bool blocking) -{ - if (!c->tag.FIFO) { - return; - } - - c->tag.E = 0; - - if (blocking && c->tag.F) { - block_thread_and_exit(c); - } - - if (c->blocked_threads) { - wake_blocked_threads(c); - } - - if (c->tag.FIFOPtr < ITC_CELL_DEPTH) { - int idx = (c->fifo_out + c->tag.FIFOPtr) % ITC_CELL_DEPTH; - c->data[idx] = val; - c->tag.FIFOPtr++; - } - - if (c->tag.FIFOPtr == ITC_CELL_DEPTH) { - c->tag.F = 1; - } -} - -static void view_ef_sync_write(ITCStorageCell *c, uint64_t val) -{ - view_ef_common_write(c, val, true); -} - -static void view_ef_try_write(ITCStorageCell *c, uint64_t val) -{ - view_ef_common_write(c, val, false); -} - -/* ITC P/V View */ - -static uint64_t view_pv_common_read(ITCStorageCell *c, bool blocking) -{ - uint64_t ret = c->data[0]; - - if (c->tag.FIFO) { - return 0; - } - - if (c->data[0] > 0) { - c->data[0]--; - } else if (blocking) { - block_thread_and_exit(c); - } - - return ret; -} - -static uint64_t view_pv_sync_read(ITCStorageCell *c) -{ - return view_pv_common_read(c, true); -} - -static uint64_t view_pv_try_read(ITCStorageCell *c) -{ - return view_pv_common_read(c, false); -} - -static inline void view_pv_common_write(ITCStorageCell *c) -{ - if (c->tag.FIFO) { - return; - } - - if (c->data[0] < ITC_CELL_PV_MAX_VAL) { - c->data[0]++; - } - - if (c->blocked_threads) { - wake_blocked_threads(c); - } -} - -static void view_pv_sync_write(ITCStorageCell *c) -{ - view_pv_common_write(c); -} - -static void view_pv_try_write(ITCStorageCell *c) -{ - view_pv_common_write(c); -} - -static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size) -{ - MIPSITUState *s = (MIPSITUState *)opaque; - ITCStorageCell *cell = get_cell(s, addr); - ITCView view = get_itc_view(addr); - uint64_t ret = -1; - - switch (view) { - case ITCVIEW_BYPASS: - ret = view_bypass_read(cell); - break; - case ITCVIEW_CONTROL: - ret = view_control_read(cell); - break; - case ITCVIEW_EF_SYNC: - ret = view_ef_sync_read(cell); - break; - case ITCVIEW_EF_TRY: - ret = view_ef_try_read(cell); - break; - case ITCVIEW_PV_SYNC: - ret = view_pv_sync_read(cell); - break; - case ITCVIEW_PV_TRY: - ret = view_pv_try_read(cell); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "itc_storage_read: Bad ITC View %d\n", (int)view); - break; - } - - return ret; -} - -static void itc_storage_write(void *opaque, hwaddr addr, uint64_t data, - unsigned size) -{ - MIPSITUState *s = (MIPSITUState *)opaque; - ITCStorageCell *cell = get_cell(s, addr); - ITCView view = get_itc_view(addr); - - switch (view) { - case ITCVIEW_BYPASS: - view_bypass_write(cell, data); - break; - case ITCVIEW_CONTROL: - view_control_write(cell, data); - break; - case ITCVIEW_EF_SYNC: - view_ef_sync_write(cell, data); - break; - case ITCVIEW_EF_TRY: - view_ef_try_write(cell, data); - break; - case ITCVIEW_PV_SYNC: - view_pv_sync_write(cell); - break; - case ITCVIEW_PV_TRY: - view_pv_try_write(cell); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "itc_storage_write: Bad ITC View %d\n", (int)view); - break; - } - -} - -static const MemoryRegionOps itc_storage_ops = { - .read = itc_storage_read, - .write = itc_storage_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void itc_reset_cells(MIPSITUState *s) -{ - int i; - - memset(s->cell, 0, get_num_cells(s) * sizeof(s->cell[0])); - - for (i = 0; i < s->num_fifo; i++) { - s->cell[i].tag.E = 1; - s->cell[i].tag.FIFO = 1; - s->cell[i].tag.FIFODepth = ITC_CELL_DEPTH_SHIFT; - } -} - -static void mips_itu_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - MIPSITUState *s = MIPS_ITU(obj); - - memory_region_init_io(&s->storage_io, OBJECT(s), &itc_storage_ops, s, - "mips-itc-storage", ITC_STORAGE_ADDRSPACE_SZ); - sysbus_init_mmio(sbd, &s->storage_io); - - memory_region_init_io(&s->tag_io, OBJECT(s), &itc_tag_ops, s, - "mips-itc-tag", ITC_TAG_ADDRSPACE_SZ); -} - -static void mips_itu_realize(DeviceState *dev, Error **errp) -{ - MIPSITUState *s = MIPS_ITU(dev); - - if (s->num_fifo > ITC_FIFO_NUM_MAX) { - error_setg(errp, "Exceed maximum number of FIFO cells: %d", - s->num_fifo); - return; - } - if (s->num_semaphores > ITC_SEMAPH_NUM_MAX) { - error_setg(errp, "Exceed maximum number of Semaphore cells: %d", - s->num_semaphores); - return; - } - - s->cell = g_new(ITCStorageCell, get_num_cells(s)); -} - -static void mips_itu_reset(DeviceState *dev) -{ - MIPSITUState *s = MIPS_ITU(dev); - - s->ITCAddressMap[0] = 0; - s->ITCAddressMap[1] = - ((ITC_STORAGE_ADDRSPACE_SZ - 1) & ITC_AM1_ADDR_MASK_MASK) | - (get_num_cells(s) << ITC_AM1_NUMENTRIES_OFS); - itc_reconfigure(s); - - itc_reset_cells(s); -} - -static Property mips_itu_properties[] = { - DEFINE_PROP_INT32("num-fifo", MIPSITUState, num_fifo, - ITC_FIFO_NUM_MAX), - DEFINE_PROP_INT32("num-semaphores", MIPSITUState, num_semaphores, - ITC_SEMAPH_NUM_MAX), - DEFINE_PROP_END_OF_LIST(), -}; - -static void mips_itu_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->props = mips_itu_properties; - dc->realize = mips_itu_realize; - dc->reset = mips_itu_reset; -} - -static const TypeInfo mips_itu_info = { - .name = TYPE_MIPS_ITU, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MIPSITUState), - .instance_init = mips_itu_init, - .class_init = mips_itu_class_init, -}; - -static void mips_itu_register_types(void) -{ - type_register_static(&mips_itu_info); -} - -type_init(mips_itu_register_types) diff --git a/qemu/hw/misc/mst_fpga.c b/qemu/hw/misc/mst_fpga.c deleted file mode 100644 index 48d7dfb2d..000000000 --- a/qemu/hw/misc/mst_fpga.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * PXA270-based Intel Mainstone platforms. - * FPGA driver - * - * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or - * <akuster@mvista.com> - * - * This code is licensed under the GNU GPL v2. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" - -/* Mainstone FPGA for extern irqs */ -#define FPGA_GPIO_PIN 0 -#define MST_NUM_IRQS 16 -#define MST_LEDDAT1 0x10 -#define MST_LEDDAT2 0x14 -#define MST_LEDCTRL 0x40 -#define MST_GPSWR 0x60 -#define MST_MSCWR1 0x80 -#define MST_MSCWR2 0x84 -#define MST_MSCWR3 0x88 -#define MST_MSCRD 0x90 -#define MST_INTMSKENA 0xc0 -#define MST_INTSETCLR 0xd0 -#define MST_PCMCIA0 0xe0 -#define MST_PCMCIA1 0xe4 - -#define MST_PCMCIAx_READY (1 << 10) -#define MST_PCMCIAx_nCD (1 << 5) - -#define MST_PCMCIA_CD0_IRQ 9 -#define MST_PCMCIA_CD1_IRQ 13 - -#define TYPE_MAINSTONE_FPGA "mainstone-fpga" -#define MAINSTONE_FPGA(obj) \ - OBJECT_CHECK(mst_irq_state, (obj), TYPE_MAINSTONE_FPGA) - -typedef struct mst_irq_state{ - SysBusDevice parent_obj; - - MemoryRegion iomem; - - qemu_irq parent; - - uint32_t prev_level; - uint32_t leddat1; - uint32_t leddat2; - uint32_t ledctrl; - uint32_t gpswr; - uint32_t mscwr1; - uint32_t mscwr2; - uint32_t mscwr3; - uint32_t mscrd; - uint32_t intmskena; - uint32_t intsetclr; - uint32_t pcmcia0; - uint32_t pcmcia1; -}mst_irq_state; - -static void -mst_fpga_set_irq(void *opaque, int irq, int level) -{ - mst_irq_state *s = (mst_irq_state *)opaque; - uint32_t oldint = s->intsetclr & s->intmskena; - - if (level) - s->prev_level |= 1u << irq; - else - s->prev_level &= ~(1u << irq); - - switch(irq) { - case MST_PCMCIA_CD0_IRQ: - if (level) - s->pcmcia0 &= ~MST_PCMCIAx_nCD; - else - s->pcmcia0 |= MST_PCMCIAx_nCD; - break; - case MST_PCMCIA_CD1_IRQ: - if (level) - s->pcmcia1 &= ~MST_PCMCIAx_nCD; - else - s->pcmcia1 |= MST_PCMCIAx_nCD; - break; - } - - if ((s->intmskena & (1u << irq)) && level) - s->intsetclr |= 1u << irq; - - if (oldint != (s->intsetclr & s->intmskena)) - qemu_set_irq(s->parent, s->intsetclr & s->intmskena); -} - - -static uint64_t -mst_fpga_readb(void *opaque, hwaddr addr, unsigned size) -{ - mst_irq_state *s = (mst_irq_state *) opaque; - - switch (addr) { - case MST_LEDDAT1: - return s->leddat1; - case MST_LEDDAT2: - return s->leddat2; - case MST_LEDCTRL: - return s->ledctrl; - case MST_GPSWR: - return s->gpswr; - case MST_MSCWR1: - return s->mscwr1; - case MST_MSCWR2: - return s->mscwr2; - case MST_MSCWR3: - return s->mscwr3; - case MST_MSCRD: - return s->mscrd; - case MST_INTMSKENA: - return s->intmskena; - case MST_INTSETCLR: - return s->intsetclr; - case MST_PCMCIA0: - return s->pcmcia0; - case MST_PCMCIA1: - return s->pcmcia1; - default: - printf("Mainstone - mst_fpga_readb: Bad register offset " - "0x" TARGET_FMT_plx "\n", addr); - } - return 0; -} - -static void -mst_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - mst_irq_state *s = (mst_irq_state *) opaque; - value &= 0xffffffff; - - switch (addr) { - case MST_LEDDAT1: - s->leddat1 = value; - break; - case MST_LEDDAT2: - s->leddat2 = value; - break; - case MST_LEDCTRL: - s->ledctrl = value; - break; - case MST_GPSWR: - s->gpswr = value; - break; - case MST_MSCWR1: - s->mscwr1 = value; - break; - case MST_MSCWR2: - s->mscwr2 = value; - break; - case MST_MSCWR3: - s->mscwr3 = value; - break; - case MST_MSCRD: - s->mscrd = value; - break; - case MST_INTMSKENA: /* Mask interrupt */ - s->intmskena = (value & 0xFEEFF); - qemu_set_irq(s->parent, s->intsetclr & s->intmskena); - break; - case MST_INTSETCLR: /* clear or set interrupt */ - s->intsetclr = (value & 0xFEEFF); - qemu_set_irq(s->parent, s->intsetclr & s->intmskena); - break; - /* For PCMCIAx allow the to change only power and reset */ - case MST_PCMCIA0: - s->pcmcia0 = (value & 0x1f) | (s->pcmcia0 & ~0x1f); - break; - case MST_PCMCIA1: - s->pcmcia1 = (value & 0x1f) | (s->pcmcia1 & ~0x1f); - break; - default: - printf("Mainstone - mst_fpga_writeb: Bad register offset " - "0x" TARGET_FMT_plx "\n", addr); - } -} - -static const MemoryRegionOps mst_fpga_ops = { - .read = mst_fpga_readb, - .write = mst_fpga_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int mst_fpga_post_load(void *opaque, int version_id) -{ - mst_irq_state *s = (mst_irq_state *) opaque; - - qemu_set_irq(s->parent, s->intsetclr & s->intmskena); - return 0; -} - -static int mst_fpga_init(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - mst_irq_state *s = MAINSTONE_FPGA(dev); - - s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD; - s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD; - - sysbus_init_irq(sbd, &s->parent); - - /* alloc the external 16 irqs */ - qdev_init_gpio_in(dev, mst_fpga_set_irq, MST_NUM_IRQS); - - memory_region_init_io(&s->iomem, OBJECT(s), &mst_fpga_ops, s, - "fpga", 0x00100000); - sysbus_init_mmio(sbd, &s->iomem); - return 0; -} - -static VMStateDescription vmstate_mst_fpga_regs = { - .name = "mainstone_fpga", - .version_id = 0, - .minimum_version_id = 0, - .post_load = mst_fpga_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32(prev_level, mst_irq_state), - VMSTATE_UINT32(leddat1, mst_irq_state), - VMSTATE_UINT32(leddat2, mst_irq_state), - VMSTATE_UINT32(ledctrl, mst_irq_state), - VMSTATE_UINT32(gpswr, mst_irq_state), - VMSTATE_UINT32(mscwr1, mst_irq_state), - VMSTATE_UINT32(mscwr2, mst_irq_state), - VMSTATE_UINT32(mscwr3, mst_irq_state), - VMSTATE_UINT32(mscrd, mst_irq_state), - VMSTATE_UINT32(intmskena, mst_irq_state), - VMSTATE_UINT32(intsetclr, mst_irq_state), - VMSTATE_UINT32(pcmcia0, mst_irq_state), - VMSTATE_UINT32(pcmcia1, mst_irq_state), - VMSTATE_END_OF_LIST(), - }, -}; - -static void mst_fpga_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = mst_fpga_init; - dc->desc = "Mainstone II FPGA"; - dc->vmsd = &vmstate_mst_fpga_regs; -} - -static const TypeInfo mst_fpga_info = { - .name = TYPE_MAINSTONE_FPGA, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(mst_irq_state), - .class_init = mst_fpga_class_init, -}; - -static void mst_fpga_register_types(void) -{ - type_register_static(&mst_fpga_info); -} - -type_init(mst_fpga_register_types) diff --git a/qemu/hw/misc/omap_clk.c b/qemu/hw/misc/omap_clk.c deleted file mode 100644 index 19151d07d..000000000 --- a/qemu/hw/misc/omap_clk.c +++ /dev/null @@ -1,1265 +0,0 @@ -/* - * OMAP clocks. - * - * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org> - * - * Clocks data comes in part from arch/arm/mach-omap1/clock.h in Linux. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/arm/omap.h" - -struct clk { - const char *name; - const char *alias; - struct clk *parent; - struct clk *child1; - struct clk *sibling; -#define ALWAYS_ENABLED (1 << 0) -#define CLOCK_IN_OMAP310 (1 << 10) -#define CLOCK_IN_OMAP730 (1 << 11) -#define CLOCK_IN_OMAP1510 (1 << 12) -#define CLOCK_IN_OMAP16XX (1 << 13) -#define CLOCK_IN_OMAP242X (1 << 14) -#define CLOCK_IN_OMAP243X (1 << 15) -#define CLOCK_IN_OMAP343X (1 << 16) - uint32_t flags; - int id; - - int running; /* Is currently ticking */ - int enabled; /* Is enabled, regardless of its input clk */ - unsigned long rate; /* Current rate (if .running) */ - unsigned int divisor; /* Rate relative to input (if .enabled) */ - unsigned int multiplier; /* Rate relative to input (if .enabled) */ - qemu_irq users[16]; /* Who to notify on change */ - int usecount; /* Automatically idle when unused */ -}; - -static struct clk xtal_osc12m = { - .name = "xtal_osc_12m", - .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk xtal_osc32k = { - .name = "xtal_osc_32k", - .rate = 32768, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -}; - -static struct clk ck_ref = { - .name = "ck_ref", - .alias = "clkin", - .parent = &xtal_osc12m, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -/* If a dpll is disabled it becomes a bypass, child clocks don't stop */ -static struct clk dpll1 = { - .name = "dpll1", - .parent = &ck_ref, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk dpll2 = { - .name = "dpll2", - .parent = &ck_ref, - .flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED, -}; - -static struct clk dpll3 = { - .name = "dpll3", - .parent = &ck_ref, - .flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED, -}; - -static struct clk dpll4 = { - .name = "dpll4", - .parent = &ck_ref, - .multiplier = 4, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk apll = { - .name = "apll", - .parent = &ck_ref, - .multiplier = 48, - .divisor = 12, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk ck_48m = { - .name = "ck_48m", - .parent = &dpll4, /* either dpll4 or apll */ - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk ck_dpll1out = { - .name = "ck_dpll1out", - .parent = &dpll1, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk sossi_ck = { - .name = "ck_sossi", - .parent = &ck_dpll1out, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk clkm1 = { - .name = "clkm1", - .alias = "ck_gen1", - .parent = &dpll1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk clkm2 = { - .name = "clkm2", - .alias = "ck_gen2", - .parent = &dpll1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk clkm3 = { - .name = "clkm3", - .alias = "ck_gen3", - .parent = &dpll1, /* either dpll1 or ck_ref */ - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk arm_ck = { - .name = "arm_ck", - .alias = "mpu_ck", - .parent = &clkm1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk armper_ck = { - .name = "armper_ck", - .alias = "mpuper_ck", - .parent = &clkm1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk arm_gpio_ck = { - .name = "arm_gpio_ck", - .alias = "mpu_gpio_ck", - .parent = &clkm1, - .divisor = 1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, -}; - -static struct clk armxor_ck = { - .name = "armxor_ck", - .alias = "mpuxor_ck", - .parent = &ck_ref, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk armtim_ck = { - .name = "armtim_ck", - .alias = "mputim_ck", - .parent = &ck_ref, /* either CLKIN or DPLL1 */ - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk armwdt_ck = { - .name = "armwdt_ck", - .alias = "mpuwd_ck", - .parent = &clkm1, - .divisor = 14, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk arminth_ck16xx = { - .name = "arminth_ck", - .parent = &arm_ck, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, - /* Note: On 16xx the frequency can be divided by 2 by programming - * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 - * - * 1510 version is in TC clocks. - */ -}; - -static struct clk dsp_ck = { - .name = "dsp_ck", - .parent = &clkm2, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, -}; - -static struct clk dspmmu_ck = { - .name = "dspmmu_ck", - .parent = &clkm2, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - ALWAYS_ENABLED, -}; - -static struct clk dspper_ck = { - .name = "dspper_ck", - .parent = &clkm2, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, -}; - -static struct clk dspxor_ck = { - .name = "dspxor_ck", - .parent = &ck_ref, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, -}; - -static struct clk dsptim_ck = { - .name = "dsptim_ck", - .parent = &ck_ref, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, -}; - -static struct clk tc_ck = { - .name = "tc_ck", - .parent = &clkm3, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk arminth_ck15xx = { - .name = "arminth_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, - /* Note: On 1510 the frequency follows TC_CK - * - * 16xx version is in MPU clocks. - */ -}; - -static struct clk tipb_ck = { - /* No-idle controlled by "tc_ck" */ - .name = "tipb_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, -}; - -static struct clk l3_ocpi_ck = { - /* No-idle controlled by "tc_ck" */ - .name = "l3_ocpi_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk tc1_ck = { - .name = "tc1_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk tc2_ck = { - .name = "tc2_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk dma_ck = { - /* No-idle controlled by "tc_ck" */ - .name = "dma_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk dma_lcdfree_ck = { - .name = "dma_lcdfree_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, -}; - -static struct clk api_ck = { - .name = "api_ck", - .alias = "mpui_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk lb_ck = { - .name = "lb_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, -}; - -static struct clk lbfree_ck = { - .name = "lbfree_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, -}; - -static struct clk hsab_ck = { - .name = "hsab_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, -}; - -static struct clk rhea1_ck = { - .name = "rhea1_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, -}; - -static struct clk rhea2_ck = { - .name = "rhea2_ck", - .parent = &tc_ck, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, -}; - -static struct clk lcd_ck_16xx = { - .name = "lcd_ck", - .parent = &clkm3, - .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730, -}; - -static struct clk lcd_ck_1510 = { - .name = "lcd_ck", - .parent = &clkm3, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, -}; - -static struct clk uart1_1510 = { - .name = "uart1_ck", - /* Direct from ULPD, no real parent */ - .parent = &armper_ck, /* either armper_ck or dpll4 */ - .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, -}; - -static struct clk uart1_16xx = { - .name = "uart1_ck", - /* Direct from ULPD, no real parent */ - .parent = &armper_ck, - .rate = 48000000, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk uart2_ck = { - .name = "uart2_ck", - /* Direct from ULPD, no real parent */ - .parent = &armper_ck, /* either armper_ck or dpll4 */ - .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, -}; - -static struct clk uart3_1510 = { - .name = "uart3_ck", - /* Direct from ULPD, no real parent */ - .parent = &armper_ck, /* either armper_ck or dpll4 */ - .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, -}; - -static struct clk uart3_16xx = { - .name = "uart3_ck", - /* Direct from ULPD, no real parent */ - .parent = &armper_ck, - .rate = 48000000, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk usb_clk0 = { /* 6 MHz output on W4_USB_CLK0 */ - .name = "usb_clk0", - .alias = "usb.clko", - /* Direct from ULPD, no parent */ - .rate = 6000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk usb_hhc_ck1510 = { - .name = "usb_hhc_ck", - /* Direct from ULPD, no parent */ - .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, -}; - -static struct clk usb_hhc_ck16xx = { - .name = "usb_hhc_ck", - /* Direct from ULPD, no parent */ - .rate = 48000000, - /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk usb_w2fc_mclk = { - .name = "usb_w2fc_mclk", - .alias = "usb_w2fc_ck", - .parent = &ck_48m, - .rate = 48000000, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, -}; - -static struct clk mclk_1510 = { - .name = "mclk", - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .rate = 12000000, - .flags = CLOCK_IN_OMAP1510, -}; - -static struct clk bclk_310 = { - .name = "bt_mclk_out", /* Alias midi_mclk_out? */ - .parent = &armper_ck, - .flags = CLOCK_IN_OMAP310, -}; - -static struct clk mclk_310 = { - .name = "com_mclk_out", - .parent = &armper_ck, - .flags = CLOCK_IN_OMAP310, -}; - -static struct clk mclk_16xx = { - .name = "mclk", - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk bclk_1510 = { - .name = "bclk", - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .rate = 12000000, - .flags = CLOCK_IN_OMAP1510, -}; - -static struct clk bclk_16xx = { - .name = "bclk", - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk mmc1_ck = { - .name = "mmc_ck", - .id = 1, - /* Functional clock is direct from ULPD, interface clock is ARMPER */ - .parent = &armper_ck, /* either armper_ck or dpll4 */ - .rate = 48000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -}; - -static struct clk mmc2_ck = { - .name = "mmc_ck", - .id = 2, - /* Functional clock is direct from ULPD, interface clock is ARMPER */ - .parent = &armper_ck, - .rate = 48000000, - .flags = CLOCK_IN_OMAP16XX, -}; - -static struct clk cam_mclk = { - .name = "cam.mclk", - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, - .rate = 12000000, -}; - -static struct clk cam_exclk = { - .name = "cam.exclk", - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, - /* Either 12M from cam.mclk or 48M from dpll4 */ - .parent = &cam_mclk, -}; - -static struct clk cam_lclk = { - .name = "cam.lclk", - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, -}; - -static struct clk i2c_fck = { - .name = "i2c_fck", - .id = 1, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - ALWAYS_ENABLED, - .parent = &armxor_ck, -}; - -static struct clk i2c_ick = { - .name = "i2c_ick", - .id = 1, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, - .parent = &armper_ck, -}; - -static struct clk clk32k = { - .name = "clk32-kHz", - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .parent = &xtal_osc32k, -}; - -static struct clk ref_clk = { - .name = "ref_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .rate = 12000000, /* 12 MHz or 13 MHz or 19.2 MHz */ - /*.parent = sys.xtalin */ -}; - -static struct clk apll_96m = { - .name = "apll_96m", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .rate = 96000000, - /*.parent = ref_clk */ -}; - -static struct clk apll_54m = { - .name = "apll_54m", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .rate = 54000000, - /*.parent = ref_clk */ -}; - -static struct clk sys_clk = { - .name = "sys_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .rate = 32768, - /*.parent = sys.xtalin */ -}; - -static struct clk sleep_clk = { - .name = "sleep_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .rate = 32768, - /*.parent = sys.xtalin */ -}; - -static struct clk dpll_ck = { - .name = "dpll", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .parent = &ref_clk, -}; - -static struct clk dpll_x2_ck = { - .name = "dpll_x2", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .parent = &ref_clk, -}; - -static struct clk wdt1_sys_clk = { - .name = "wdt1_sys_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, - .rate = 32768, - /*.parent = sys.xtalin */ -}; - -static struct clk func_96m_clk = { - .name = "func_96m_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .divisor = 1, - .parent = &apll_96m, -}; - -static struct clk func_48m_clk = { - .name = "func_48m_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .divisor = 2, - .parent = &apll_96m, -}; - -static struct clk func_12m_clk = { - .name = "func_12m_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .divisor = 8, - .parent = &apll_96m, -}; - -static struct clk func_54m_clk = { - .name = "func_54m_clk", - .flags = CLOCK_IN_OMAP242X, - .divisor = 1, - .parent = &apll_54m, -}; - -static struct clk sys_clkout = { - .name = "clkout", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk sys_clkout2 = { - .name = "clkout2", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_clk = { - .name = "core_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &dpll_x2_ck, /* Switchable between dpll_ck and clk32k */ -}; - -static struct clk l3_clk = { - .name = "l3_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_clk, -}; - -static struct clk core_l4_iclk = { - .name = "core_l4_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &l3_clk, -}; - -static struct clk wu_l4_iclk = { - .name = "wu_l4_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &l3_clk, -}; - -static struct clk core_l3_iclk = { - .name = "core_l3_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_clk, -}; - -static struct clk core_l4_usb_clk = { - .name = "core_l4_usb_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &l3_clk, -}; - -static struct clk wu_gpt1_clk = { - .name = "wu_gpt1_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk wu_32k_clk = { - .name = "wu_32k_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk uart1_fclk = { - .name = "uart1_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_48m_clk, -}; - -static struct clk uart1_iclk = { - .name = "uart1_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, -}; - -static struct clk uart2_fclk = { - .name = "uart2_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_48m_clk, -}; - -static struct clk uart2_iclk = { - .name = "uart2_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, -}; - -static struct clk uart3_fclk = { - .name = "uart3_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_48m_clk, -}; - -static struct clk uart3_iclk = { - .name = "uart3_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, -}; - -static struct clk mpu_fclk = { - .name = "mpu_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_clk, -}; - -static struct clk mpu_iclk = { - .name = "mpu_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_clk, -}; - -static struct clk int_m_fclk = { - .name = "int_m_fclk", - .alias = "mpu_intc_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_clk, -}; - -static struct clk int_m_iclk = { - .name = "int_m_iclk", - .alias = "mpu_intc_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_clk, -}; - -static struct clk core_gpt2_clk = { - .name = "core_gpt2_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt3_clk = { - .name = "core_gpt3_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt4_clk = { - .name = "core_gpt4_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt5_clk = { - .name = "core_gpt5_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt6_clk = { - .name = "core_gpt6_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt7_clk = { - .name = "core_gpt7_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt8_clk = { - .name = "core_gpt8_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt9_clk = { - .name = "core_gpt9_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt10_clk = { - .name = "core_gpt10_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt11_clk = { - .name = "core_gpt11_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk core_gpt12_clk = { - .name = "core_gpt12_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, -}; - -static struct clk mcbsp1_clk = { - .name = "mcbsp1_cg", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .divisor = 2, - .parent = &func_96m_clk, -}; - -static struct clk mcbsp2_clk = { - .name = "mcbsp2_cg", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .divisor = 2, - .parent = &func_96m_clk, -}; - -static struct clk emul_clk = { - .name = "emul_ck", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_54m_clk, -}; - -static struct clk sdma_fclk = { - .name = "sdma_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &l3_clk, -}; - -static struct clk sdma_iclk = { - .name = "sdma_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l3_iclk, /* core_l4_iclk for the configuration port */ -}; - -static struct clk i2c1_fclk = { - .name = "i2c1.fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_12m_clk, - .divisor = 1, -}; - -static struct clk i2c1_iclk = { - .name = "i2c1.iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, -}; - -static struct clk i2c2_fclk = { - .name = "i2c2.fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_12m_clk, - .divisor = 1, -}; - -static struct clk i2c2_iclk = { - .name = "i2c2.iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, -}; - -static struct clk gpio_dbclk[5] = { - { - .name = "gpio1_dbclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &wu_32k_clk, - }, { - .name = "gpio2_dbclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &wu_32k_clk, - }, { - .name = "gpio3_dbclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &wu_32k_clk, - }, { - .name = "gpio4_dbclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &wu_32k_clk, - }, { - .name = "gpio5_dbclk", - .flags = CLOCK_IN_OMAP243X, - .parent = &wu_32k_clk, - }, -}; - -static struct clk gpio_iclk = { - .name = "gpio_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &wu_l4_iclk, -}; - -static struct clk mmc_fck = { - .name = "mmc_fclk", - .flags = CLOCK_IN_OMAP242X, - .parent = &func_96m_clk, -}; - -static struct clk mmc_ick = { - .name = "mmc_iclk", - .flags = CLOCK_IN_OMAP242X, - .parent = &core_l4_iclk, -}; - -static struct clk spi_fclk[3] = { - { - .name = "spi1_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_48m_clk, - }, { - .name = "spi2_fclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_48m_clk, - }, { - .name = "spi3_fclk", - .flags = CLOCK_IN_OMAP243X, - .parent = &func_48m_clk, - }, -}; - -static struct clk dss_clk[2] = { - { - .name = "dss_clk1", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_clk, - }, { - .name = "dss_clk2", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &sys_clk, - }, -}; - -static struct clk dss_54m_clk = { - .name = "dss_54m_clk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &func_54m_clk, -}; - -static struct clk dss_l3_iclk = { - .name = "dss_l3_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l3_iclk, -}; - -static struct clk dss_l4_iclk = { - .name = "dss_l4_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, -}; - -static struct clk spi_iclk[3] = { - { - .name = "spi1_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, - }, { - .name = "spi2_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, - }, { - .name = "spi3_iclk", - .flags = CLOCK_IN_OMAP243X, - .parent = &core_l4_iclk, - }, -}; - -static struct clk omapctrl_clk = { - .name = "omapctrl_iclk", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - /* XXX Should be in WKUP domain */ - .parent = &core_l4_iclk, -}; - -static struct clk *onchip_clks[] = { - /* OMAP 1 */ - - /* non-ULPD clocks */ - &xtal_osc12m, - &xtal_osc32k, - &ck_ref, - &dpll1, - &dpll2, - &dpll3, - &dpll4, - &apll, - &ck_48m, - /* CK_GEN1 clocks */ - &clkm1, - &ck_dpll1out, - &sossi_ck, - &arm_ck, - &armper_ck, - &arm_gpio_ck, - &armxor_ck, - &armtim_ck, - &armwdt_ck, - &arminth_ck15xx, &arminth_ck16xx, - /* CK_GEN2 clocks */ - &clkm2, - &dsp_ck, - &dspmmu_ck, - &dspper_ck, - &dspxor_ck, - &dsptim_ck, - /* CK_GEN3 clocks */ - &clkm3, - &tc_ck, - &tipb_ck, - &l3_ocpi_ck, - &tc1_ck, - &tc2_ck, - &dma_ck, - &dma_lcdfree_ck, - &api_ck, - &lb_ck, - &lbfree_ck, - &hsab_ck, - &rhea1_ck, - &rhea2_ck, - &lcd_ck_16xx, - &lcd_ck_1510, - /* ULPD clocks */ - &uart1_1510, - &uart1_16xx, - &uart2_ck, - &uart3_1510, - &uart3_16xx, - &usb_clk0, - &usb_hhc_ck1510, &usb_hhc_ck16xx, - &mclk_1510, &mclk_16xx, &mclk_310, - &bclk_1510, &bclk_16xx, &bclk_310, - &mmc1_ck, - &mmc2_ck, - &cam_mclk, - &cam_exclk, - &cam_lclk, - &clk32k, - &usb_w2fc_mclk, - /* Virtual clocks */ - &i2c_fck, - &i2c_ick, - - /* OMAP 2 */ - - &ref_clk, - &apll_96m, - &apll_54m, - &sys_clk, - &sleep_clk, - &dpll_ck, - &dpll_x2_ck, - &wdt1_sys_clk, - &func_96m_clk, - &func_48m_clk, - &func_12m_clk, - &func_54m_clk, - &sys_clkout, - &sys_clkout2, - &core_clk, - &l3_clk, - &core_l4_iclk, - &wu_l4_iclk, - &core_l3_iclk, - &core_l4_usb_clk, - &wu_gpt1_clk, - &wu_32k_clk, - &uart1_fclk, - &uart1_iclk, - &uart2_fclk, - &uart2_iclk, - &uart3_fclk, - &uart3_iclk, - &mpu_fclk, - &mpu_iclk, - &int_m_fclk, - &int_m_iclk, - &core_gpt2_clk, - &core_gpt3_clk, - &core_gpt4_clk, - &core_gpt5_clk, - &core_gpt6_clk, - &core_gpt7_clk, - &core_gpt8_clk, - &core_gpt9_clk, - &core_gpt10_clk, - &core_gpt11_clk, - &core_gpt12_clk, - &mcbsp1_clk, - &mcbsp2_clk, - &emul_clk, - &sdma_fclk, - &sdma_iclk, - &i2c1_fclk, - &i2c1_iclk, - &i2c2_fclk, - &i2c2_iclk, - &gpio_dbclk[0], - &gpio_dbclk[1], - &gpio_dbclk[2], - &gpio_dbclk[3], - &gpio_iclk, - &mmc_fck, - &mmc_ick, - &spi_fclk[0], - &spi_iclk[0], - &spi_fclk[1], - &spi_iclk[1], - &spi_fclk[2], - &spi_iclk[2], - &dss_clk[0], - &dss_clk[1], - &dss_54m_clk, - &dss_l3_iclk, - &dss_l4_iclk, - &omapctrl_clk, - - NULL -}; - -void omap_clk_adduser(struct clk *clk, qemu_irq user) -{ - qemu_irq *i; - - for (i = clk->users; *i; i ++); - *i = user; -} - -struct clk *omap_findclk(struct omap_mpu_state_s *mpu, const char *name) -{ - struct clk *i; - - for (i = mpu->clks; i->name; i ++) - if (!strcmp(i->name, name) || (i->alias && !strcmp(i->alias, name))) - return i; - hw_error("%s: %s not found\n", __FUNCTION__, name); -} - -void omap_clk_get(struct clk *clk) -{ - clk->usecount ++; -} - -void omap_clk_put(struct clk *clk) -{ - if (!(clk->usecount --)) - hw_error("%s: %s is not in use\n", __FUNCTION__, clk->name); -} - -static void omap_clk_update(struct clk *clk) -{ - int parent, running; - qemu_irq *user; - struct clk *i; - - if (clk->parent) - parent = clk->parent->running; - else - parent = 1; - - running = parent && (clk->enabled || - ((clk->flags & ALWAYS_ENABLED) && clk->usecount)); - if (clk->running != running) { - clk->running = running; - for (user = clk->users; *user; user ++) - qemu_set_irq(*user, running); - for (i = clk->child1; i; i = i->sibling) - omap_clk_update(i); - } -} - -static void omap_clk_rate_update_full(struct clk *clk, unsigned long int rate, - unsigned long int div, unsigned long int mult) -{ - struct clk *i; - qemu_irq *user; - - clk->rate = muldiv64(rate, mult, div); - if (clk->running) - for (user = clk->users; *user; user ++) - qemu_irq_raise(*user); - for (i = clk->child1; i; i = i->sibling) - omap_clk_rate_update_full(i, rate, - div * i->divisor, mult * i->multiplier); -} - -static void omap_clk_rate_update(struct clk *clk) -{ - struct clk *i; - unsigned long int div, mult = div = 1; - - for (i = clk; i->parent; i = i->parent) { - div *= i->divisor; - mult *= i->multiplier; - } - - omap_clk_rate_update_full(clk, i->rate, div, mult); -} - -void omap_clk_reparent(struct clk *clk, struct clk *parent) -{ - struct clk **p; - - if (clk->parent) { - for (p = &clk->parent->child1; *p != clk; p = &(*p)->sibling); - *p = clk->sibling; - } - - clk->parent = parent; - if (parent) { - clk->sibling = parent->child1; - parent->child1 = clk; - omap_clk_update(clk); - omap_clk_rate_update(clk); - } else - clk->sibling = NULL; -} - -void omap_clk_onoff(struct clk *clk, int on) -{ - clk->enabled = on; - omap_clk_update(clk); -} - -void omap_clk_canidle(struct clk *clk, int can) -{ - if (can) - omap_clk_put(clk); - else - omap_clk_get(clk); -} - -void omap_clk_setrate(struct clk *clk, int divide, int multiply) -{ - clk->divisor = divide; - clk->multiplier = multiply; - omap_clk_rate_update(clk); -} - -int64_t omap_clk_getrate(omap_clk clk) -{ - return clk->rate; -} - -void omap_clk_init(struct omap_mpu_state_s *mpu) -{ - struct clk **i, *j, *k; - int count; - int flag; - - if (cpu_is_omap310(mpu)) - flag = CLOCK_IN_OMAP310; - else if (cpu_is_omap1510(mpu)) - flag = CLOCK_IN_OMAP1510; - else if (cpu_is_omap2410(mpu) || cpu_is_omap2420(mpu)) - flag = CLOCK_IN_OMAP242X; - else if (cpu_is_omap2430(mpu)) - flag = CLOCK_IN_OMAP243X; - else if (cpu_is_omap3430(mpu)) - flag = CLOCK_IN_OMAP243X; - else - return; - - for (i = onchip_clks, count = 0; *i; i ++) - if ((*i)->flags & flag) - count ++; - mpu->clks = g_new0(struct clk, count + 1); - for (i = onchip_clks, j = mpu->clks; *i; i ++) - if ((*i)->flags & flag) { - memcpy(j, *i, sizeof(struct clk)); - for (k = mpu->clks; k < j; k ++) - if (j->parent && !strcmp(j->parent->name, k->name)) { - j->parent = k; - j->sibling = k->child1; - k->child1 = j; - } else if (k->parent && !strcmp(k->parent->name, j->name)) { - k->parent = j; - k->sibling = j->child1; - j->child1 = k; - } - j->divisor = j->divisor ?: 1; - j->multiplier = j->multiplier ?: 1; - j ++; - } - for (j = mpu->clks; count --; j ++) { - omap_clk_update(j); - omap_clk_rate_update(j); - } -} diff --git a/qemu/hw/misc/omap_gpmc.c b/qemu/hw/misc/omap_gpmc.c deleted file mode 100644 index 67d8e2f02..000000000 --- a/qemu/hw/misc/omap_gpmc.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - * TI OMAP general purpose memory controller emulation. - * - * Copyright (C) 2007-2009 Nokia Corporation - * Original code written by Andrzej Zaborowski <andrew@openedhand.com> - * Enhancements for OMAP3 and NAND support written by Juha Riihimäki - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) any later version of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/block/flash.h" -#include "hw/arm/omap.h" -#include "exec/memory.h" -#include "exec/address-spaces.h" - -/* General-Purpose Memory Controller */ -struct omap_gpmc_s { - qemu_irq irq; - qemu_irq drq; - MemoryRegion iomem; - int accept_256; - - uint8_t revision; - uint8_t sysconfig; - uint16_t irqst; - uint16_t irqen; - uint16_t lastirq; - uint16_t timeout; - uint16_t config; - struct omap_gpmc_cs_file_s { - uint32_t config[7]; - MemoryRegion *iomem; - MemoryRegion container; - MemoryRegion nandiomem; - DeviceState *dev; - } cs_file[8]; - int ecc_cs; - int ecc_ptr; - uint32_t ecc_cfg; - ECCState ecc[9]; - struct prefetch { - uint32_t config1; /* GPMC_PREFETCH_CONFIG1 */ - uint32_t transfercount; /* GPMC_PREFETCH_CONFIG2:TRANSFERCOUNT */ - int startengine; /* GPMC_PREFETCH_CONTROL:STARTENGINE */ - int fifopointer; /* GPMC_PREFETCH_STATUS:FIFOPOINTER */ - int count; /* GPMC_PREFETCH_STATUS:COUNTVALUE */ - MemoryRegion iomem; - uint8_t fifo[64]; - } prefetch; -}; - -#define OMAP_GPMC_8BIT 0 -#define OMAP_GPMC_16BIT 1 -#define OMAP_GPMC_NOR 0 -#define OMAP_GPMC_NAND 2 - -static int omap_gpmc_devtype(struct omap_gpmc_cs_file_s *f) -{ - return (f->config[0] >> 10) & 3; -} - -static int omap_gpmc_devsize(struct omap_gpmc_cs_file_s *f) -{ - /* devsize field is really 2 bits but we ignore the high - * bit to ensure consistent behaviour if the guest sets - * it (values 2 and 3 are reserved in the TRM) - */ - return (f->config[0] >> 12) & 1; -} - -/* Extract the chip-select value from the prefetch config1 register */ -static int prefetch_cs(uint32_t config1) -{ - return (config1 >> 24) & 7; -} - -static int prefetch_threshold(uint32_t config1) -{ - return (config1 >> 8) & 0x7f; -} - -static void omap_gpmc_int_update(struct omap_gpmc_s *s) -{ - /* The TRM is a bit unclear, but it seems to say that - * the TERMINALCOUNTSTATUS bit is set only on the - * transition when the prefetch engine goes from - * active to inactive, whereas the FIFOEVENTSTATUS - * bit is held high as long as the fifo has at - * least THRESHOLD bytes available. - * So we do the latter here, but TERMINALCOUNTSTATUS - * is set elsewhere. - */ - if (s->prefetch.fifopointer >= prefetch_threshold(s->prefetch.config1)) { - s->irqst |= 1; - } - if ((s->irqen & s->irqst) != s->lastirq) { - s->lastirq = s->irqen & s->irqst; - qemu_set_irq(s->irq, s->lastirq); - } -} - -static void omap_gpmc_dma_update(struct omap_gpmc_s *s, int value) -{ - if (s->prefetch.config1 & 4) { - qemu_set_irq(s->drq, value); - } -} - -/* Access functions for when a NAND-like device is mapped into memory: - * all addresses in the region behave like accesses to the relevant - * GPMC_NAND_DATA_i register (which is actually implemented to call these) - */ -static uint64_t omap_nand_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque; - uint64_t v; - nand_setpins(f->dev, 0, 0, 0, 1, 0); - switch (omap_gpmc_devsize(f)) { - case OMAP_GPMC_8BIT: - v = nand_getio(f->dev); - if (size == 1) { - return v; - } - v |= (nand_getio(f->dev) << 8); - if (size == 2) { - return v; - } - v |= (nand_getio(f->dev) << 16); - v |= (nand_getio(f->dev) << 24); - return v; - case OMAP_GPMC_16BIT: - v = nand_getio(f->dev); - if (size == 1) { - /* 8 bit read from 16 bit device : probably a guest bug */ - return v & 0xff; - } - if (size == 2) { - return v; - } - v |= (nand_getio(f->dev) << 16); - return v; - default: - abort(); - } -} - -static void omap_nand_setio(DeviceState *dev, uint64_t value, - int nandsize, int size) -{ - /* Write the specified value to the NAND device, respecting - * both size of the NAND device and size of the write access. - */ - switch (nandsize) { - case OMAP_GPMC_8BIT: - switch (size) { - case 1: - nand_setio(dev, value & 0xff); - break; - case 2: - nand_setio(dev, value & 0xff); - nand_setio(dev, (value >> 8) & 0xff); - break; - case 4: - default: - nand_setio(dev, value & 0xff); - nand_setio(dev, (value >> 8) & 0xff); - nand_setio(dev, (value >> 16) & 0xff); - nand_setio(dev, (value >> 24) & 0xff); - break; - } - break; - case OMAP_GPMC_16BIT: - switch (size) { - case 1: - /* writing to a 16bit device with 8bit access is probably a guest - * bug; pass the value through anyway. - */ - case 2: - nand_setio(dev, value & 0xffff); - break; - case 4: - default: - nand_setio(dev, value & 0xffff); - nand_setio(dev, (value >> 16) & 0xffff); - break; - } - break; - } -} - -static void omap_nand_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque; - nand_setpins(f->dev, 0, 0, 0, 1, 0); - omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size); -} - -static const MemoryRegionOps omap_nand_ops = { - .read = omap_nand_read, - .write = omap_nand_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void fill_prefetch_fifo(struct omap_gpmc_s *s) -{ - /* Fill the prefetch FIFO by reading data from NAND. - * We do this synchronously, unlike the hardware which - * will do this asynchronously. We refill when the - * FIFO has THRESHOLD bytes free, and we always refill - * as much data as possible starting at the top end - * of the FIFO. - * (We have to refill at THRESHOLD rather than waiting - * for the FIFO to empty to allow for the case where - * the FIFO size isn't an exact multiple of THRESHOLD - * and we're doing DMA transfers.) - * This means we never need to handle wrap-around in - * the fifo-reading code, and the next byte of data - * to read is always fifo[63 - fifopointer]. - */ - int fptr; - int cs = prefetch_cs(s->prefetch.config1); - int is16bit = (((s->cs_file[cs].config[0] >> 12) & 3) != 0); - int bytes; - /* Don't believe the bit of the OMAP TRM that says that COUNTVALUE - * and TRANSFERCOUNT are in units of 16 bit words for 16 bit NAND. - * Instead believe the bit that says it is always a byte count. - */ - bytes = 64 - s->prefetch.fifopointer; - if (bytes > s->prefetch.count) { - bytes = s->prefetch.count; - } - if (is16bit) { - bytes &= ~1; - } - - s->prefetch.count -= bytes; - s->prefetch.fifopointer += bytes; - fptr = 64 - s->prefetch.fifopointer; - /* Move the existing data in the FIFO so it sits just - * before what we're about to read in - */ - while (fptr < (64 - bytes)) { - s->prefetch.fifo[fptr] = s->prefetch.fifo[fptr + bytes]; - fptr++; - } - while (fptr < 64) { - if (is16bit) { - uint32_t v = omap_nand_read(&s->cs_file[cs], 0, 2); - s->prefetch.fifo[fptr++] = v & 0xff; - s->prefetch.fifo[fptr++] = (v >> 8) & 0xff; - } else { - s->prefetch.fifo[fptr++] = omap_nand_read(&s->cs_file[cs], 0, 1); - } - } - if (s->prefetch.startengine && (s->prefetch.count == 0)) { - /* This was the final transfer: raise TERMINALCOUNTSTATUS */ - s->irqst |= 2; - s->prefetch.startengine = 0; - } - /* If there are any bytes in the FIFO at this point then - * we must raise a DMA request (either this is a final part - * transfer, or we filled the FIFO in which case we certainly - * have THRESHOLD bytes available) - */ - if (s->prefetch.fifopointer != 0) { - omap_gpmc_dma_update(s, 1); - } - omap_gpmc_int_update(s); -} - -/* Access functions for a NAND-like device when the prefetch/postwrite - * engine is enabled -- all addresses in the region behave alike: - * data is read or written to the FIFO. - */ -static uint64_t omap_gpmc_prefetch_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; - uint32_t data; - if (s->prefetch.config1 & 1) { - /* The TRM doesn't define the behaviour if you read from the - * FIFO when the prefetch engine is in write mode. We choose - * to always return zero. - */ - return 0; - } - /* Note that trying to read an empty fifo repeats the last byte */ - if (s->prefetch.fifopointer) { - s->prefetch.fifopointer--; - } - data = s->prefetch.fifo[63 - s->prefetch.fifopointer]; - if (s->prefetch.fifopointer == - (64 - prefetch_threshold(s->prefetch.config1))) { - /* We've drained THRESHOLD bytes now. So deassert the - * DMA request, then refill the FIFO (which will probably - * assert it again.) - */ - omap_gpmc_dma_update(s, 0); - fill_prefetch_fifo(s); - } - omap_gpmc_int_update(s); - return data; -} - -static void omap_gpmc_prefetch_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; - int cs = prefetch_cs(s->prefetch.config1); - if ((s->prefetch.config1 & 1) == 0) { - /* The TRM doesn't define the behaviour of writing to the - * FIFO when the prefetch engine is in read mode. We - * choose to ignore the write. - */ - return; - } - if (s->prefetch.count == 0) { - /* The TRM doesn't define the behaviour of writing to the - * FIFO if the transfer is complete. We choose to ignore. - */ - return; - } - /* The only reason we do any data buffering in postwrite - * mode is if we are talking to a 16 bit NAND device, in - * which case we need to buffer the first byte of the - * 16 bit word until the other byte arrives. - */ - int is16bit = (((s->cs_file[cs].config[0] >> 12) & 3) != 0); - if (is16bit) { - /* fifopointer alternates between 64 (waiting for first - * byte of word) and 63 (waiting for second byte) - */ - if (s->prefetch.fifopointer == 64) { - s->prefetch.fifo[0] = value; - s->prefetch.fifopointer--; - } else { - value = (value << 8) | s->prefetch.fifo[0]; - omap_nand_write(&s->cs_file[cs], 0, value, 2); - s->prefetch.count--; - s->prefetch.fifopointer = 64; - } - } else { - /* Just write the byte : fifopointer remains 64 at all times */ - omap_nand_write(&s->cs_file[cs], 0, value, 1); - s->prefetch.count--; - } - if (s->prefetch.count == 0) { - /* Final transfer: raise TERMINALCOUNTSTATUS */ - s->irqst |= 2; - s->prefetch.startengine = 0; - } - omap_gpmc_int_update(s); -} - -static const MemoryRegionOps omap_prefetch_ops = { - .read = omap_gpmc_prefetch_read, - .write = omap_gpmc_prefetch_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl.min_access_size = 1, - .impl.max_access_size = 1, -}; - -static MemoryRegion *omap_gpmc_cs_memregion(struct omap_gpmc_s *s, int cs) -{ - /* Return the MemoryRegion* to map/unmap for this chipselect */ - struct omap_gpmc_cs_file_s *f = &s->cs_file[cs]; - if (omap_gpmc_devtype(f) == OMAP_GPMC_NOR) { - return f->iomem; - } - if ((s->prefetch.config1 & 0x80) && - (prefetch_cs(s->prefetch.config1) == cs)) { - /* The prefetch engine is enabled for this CS: map the FIFO */ - return &s->prefetch.iomem; - } - return &f->nandiomem; -} - -static void omap_gpmc_cs_map(struct omap_gpmc_s *s, int cs) -{ - struct omap_gpmc_cs_file_s *f = &s->cs_file[cs]; - uint32_t mask = (f->config[6] >> 8) & 0xf; - uint32_t base = f->config[6] & 0x3f; - uint32_t size; - - if (!f->iomem && !f->dev) { - return; - } - - if (!(f->config[6] & (1 << 6))) { - /* Do nothing unless CSVALID */ - return; - } - - /* TODO: check for overlapping regions and report access errors */ - if (mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf - && !(s->accept_256 && !mask)) { - fprintf(stderr, "%s: invalid chip-select mask address (0x%x)\n", - __func__, mask); - } - - base <<= 24; - size = (0x0fffffff & ~(mask << 24)) + 1; - /* TODO: rather than setting the size of the mapping (which should be - * constant), the mask should cause wrapping of the address space, so - * that the same memory becomes accessible at every <i>size</i> bytes - * starting from <i>base</i>. */ - memory_region_init(&f->container, NULL, "omap-gpmc-file", size); - memory_region_add_subregion(&f->container, 0, - omap_gpmc_cs_memregion(s, cs)); - memory_region_add_subregion(get_system_memory(), base, - &f->container); -} - -static void omap_gpmc_cs_unmap(struct omap_gpmc_s *s, int cs) -{ - struct omap_gpmc_cs_file_s *f = &s->cs_file[cs]; - if (!(f->config[6] & (1 << 6))) { - /* Do nothing unless CSVALID */ - return; - } - if (!f->iomem && !f->dev) { - return; - } - memory_region_del_subregion(get_system_memory(), &f->container); - memory_region_del_subregion(&f->container, omap_gpmc_cs_memregion(s, cs)); - object_unparent(OBJECT(&f->container)); -} - -void omap_gpmc_reset(struct omap_gpmc_s *s) -{ - int i; - - s->sysconfig = 0; - s->irqst = 0; - s->irqen = 0; - omap_gpmc_int_update(s); - for (i = 0; i < 8; i++) { - /* This has to happen before we change any of the config - * used to determine which memory regions are mapped or unmapped. - */ - omap_gpmc_cs_unmap(s, i); - } - s->timeout = 0; - s->config = 0xa00; - s->prefetch.config1 = 0x00004000; - s->prefetch.transfercount = 0x00000000; - s->prefetch.startengine = 0; - s->prefetch.fifopointer = 0; - s->prefetch.count = 0; - for (i = 0; i < 8; i ++) { - s->cs_file[i].config[1] = 0x101001; - s->cs_file[i].config[2] = 0x020201; - s->cs_file[i].config[3] = 0x10031003; - s->cs_file[i].config[4] = 0x10f1111; - s->cs_file[i].config[5] = 0; - s->cs_file[i].config[6] = 0xf00; - /* In theory we could probe attached devices for some CFG1 - * bits here, but we just retain them across resets as they - * were set initially by omap_gpmc_attach(). - */ - if (i == 0) { - s->cs_file[i].config[0] &= 0x00433e00; - s->cs_file[i].config[6] |= 1 << 6; /* CSVALID */ - omap_gpmc_cs_map(s, i); - } else { - s->cs_file[i].config[0] &= 0x00403c00; - } - } - s->ecc_cs = 0; - s->ecc_ptr = 0; - s->ecc_cfg = 0x3fcff000; - for (i = 0; i < 9; i ++) - ecc_reset(&s->ecc[i]); -} - -static int gpmc_wordaccess_only(hwaddr addr) -{ - /* Return true if the register offset is to a register that - * only permits word width accesses. - * Non-word accesses are only OK for GPMC_NAND_DATA/ADDRESS/COMMAND - * for any chipselect. - */ - if (addr >= 0x60 && addr <= 0x1d4) { - int cs = (addr - 0x60) / 0x30; - addr -= cs * 0x30; - if (addr >= 0x7c && addr < 0x88) { - /* GPMC_NAND_COMMAND, GPMC_NAND_ADDRESS, GPMC_NAND_DATA */ - return 0; - } - } - return 1; -} - -static uint64_t omap_gpmc_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; - int cs; - struct omap_gpmc_cs_file_s *f; - - if (size != 4 && gpmc_wordaccess_only(addr)) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x000: /* GPMC_REVISION */ - return s->revision; - - case 0x010: /* GPMC_SYSCONFIG */ - return s->sysconfig; - - case 0x014: /* GPMC_SYSSTATUS */ - return 1; /* RESETDONE */ - - case 0x018: /* GPMC_IRQSTATUS */ - return s->irqst; - - case 0x01c: /* GPMC_IRQENABLE */ - return s->irqen; - - case 0x040: /* GPMC_TIMEOUT_CONTROL */ - return s->timeout; - - case 0x044: /* GPMC_ERR_ADDRESS */ - case 0x048: /* GPMC_ERR_TYPE */ - return 0; - - case 0x050: /* GPMC_CONFIG */ - return s->config; - - case 0x054: /* GPMC_STATUS */ - return 0x001; - - case 0x060 ... 0x1d4: - cs = (addr - 0x060) / 0x30; - addr -= cs * 0x30; - f = s->cs_file + cs; - switch (addr) { - case 0x60: /* GPMC_CONFIG1 */ - return f->config[0]; - case 0x64: /* GPMC_CONFIG2 */ - return f->config[1]; - case 0x68: /* GPMC_CONFIG3 */ - return f->config[2]; - case 0x6c: /* GPMC_CONFIG4 */ - return f->config[3]; - case 0x70: /* GPMC_CONFIG5 */ - return f->config[4]; - case 0x74: /* GPMC_CONFIG6 */ - return f->config[5]; - case 0x78: /* GPMC_CONFIG7 */ - return f->config[6]; - case 0x84 ... 0x87: /* GPMC_NAND_DATA */ - if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { - return omap_nand_read(f, 0, size); - } - return 0; - } - break; - - case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ - return s->prefetch.config1; - case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ - return s->prefetch.transfercount; - case 0x1ec: /* GPMC_PREFETCH_CONTROL */ - return s->prefetch.startengine; - case 0x1f0: /* GPMC_PREFETCH_STATUS */ - /* NB: The OMAP3 TRM is inconsistent about whether the GPMC - * FIFOTHRESHOLDSTATUS bit should be set when - * FIFOPOINTER > FIFOTHRESHOLD or when it is >= FIFOTHRESHOLD. - * Apparently the underlying functional spec from which the TRM was - * created states that the behaviour is ">=", and this also - * makes more conceptual sense. - */ - return (s->prefetch.fifopointer << 24) | - ((s->prefetch.fifopointer >= - ((s->prefetch.config1 >> 8) & 0x7f) ? 1 : 0) << 16) | - s->prefetch.count; - - case 0x1f4: /* GPMC_ECC_CONFIG */ - return s->ecc_cs; - case 0x1f8: /* GPMC_ECC_CONTROL */ - return s->ecc_ptr; - case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */ - return s->ecc_cfg; - case 0x200 ... 0x220: /* GPMC_ECC_RESULT */ - cs = (addr & 0x1f) >> 2; - /* TODO: check correctness */ - return - ((s->ecc[cs].cp & 0x07) << 0) | - ((s->ecc[cs].cp & 0x38) << 13) | - ((s->ecc[cs].lp[0] & 0x1ff) << 3) | - ((s->ecc[cs].lp[1] & 0x1ff) << 19); - - case 0x230: /* GPMC_TESTMODE_CTRL */ - return 0; - case 0x234: /* GPMC_PSA_LSB */ - case 0x238: /* GPMC_PSA_MSB */ - return 0x00000000; - } - - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_gpmc_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; - int cs; - struct omap_gpmc_cs_file_s *f; - - if (size != 4 && gpmc_wordaccess_only(addr)) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - switch (addr) { - case 0x000: /* GPMC_REVISION */ - case 0x014: /* GPMC_SYSSTATUS */ - case 0x054: /* GPMC_STATUS */ - case 0x1f0: /* GPMC_PREFETCH_STATUS */ - case 0x200 ... 0x220: /* GPMC_ECC_RESULT */ - case 0x234: /* GPMC_PSA_LSB */ - case 0x238: /* GPMC_PSA_MSB */ - OMAP_RO_REG(addr); - break; - - case 0x010: /* GPMC_SYSCONFIG */ - if ((value >> 3) == 0x3) - fprintf(stderr, "%s: bad SDRAM idle mode %"PRIi64"\n", - __FUNCTION__, value >> 3); - if (value & 2) - omap_gpmc_reset(s); - s->sysconfig = value & 0x19; - break; - - case 0x018: /* GPMC_IRQSTATUS */ - s->irqst &= ~value; - omap_gpmc_int_update(s); - break; - - case 0x01c: /* GPMC_IRQENABLE */ - s->irqen = value & 0xf03; - omap_gpmc_int_update(s); - break; - - case 0x040: /* GPMC_TIMEOUT_CONTROL */ - s->timeout = value & 0x1ff1; - break; - - case 0x044: /* GPMC_ERR_ADDRESS */ - case 0x048: /* GPMC_ERR_TYPE */ - break; - - case 0x050: /* GPMC_CONFIG */ - s->config = value & 0xf13; - break; - - case 0x060 ... 0x1d4: - cs = (addr - 0x060) / 0x30; - addr -= cs * 0x30; - f = s->cs_file + cs; - switch (addr) { - case 0x60: /* GPMC_CONFIG1 */ - f->config[0] = value & 0xffef3e13; - break; - case 0x64: /* GPMC_CONFIG2 */ - f->config[1] = value & 0x001f1f8f; - break; - case 0x68: /* GPMC_CONFIG3 */ - f->config[2] = value & 0x001f1f8f; - break; - case 0x6c: /* GPMC_CONFIG4 */ - f->config[3] = value & 0x1f8f1f8f; - break; - case 0x70: /* GPMC_CONFIG5 */ - f->config[4] = value & 0x0f1f1f1f; - break; - case 0x74: /* GPMC_CONFIG6 */ - f->config[5] = value & 0x00000fcf; - break; - case 0x78: /* GPMC_CONFIG7 */ - if ((f->config[6] ^ value) & 0xf7f) { - omap_gpmc_cs_unmap(s, cs); - f->config[6] = value & 0x00000f7f; - omap_gpmc_cs_map(s, cs); - } - break; - case 0x7c ... 0x7f: /* GPMC_NAND_COMMAND */ - if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { - nand_setpins(f->dev, 1, 0, 0, 1, 0); /* CLE */ - omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size); - } - break; - case 0x80 ... 0x83: /* GPMC_NAND_ADDRESS */ - if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { - nand_setpins(f->dev, 0, 1, 0, 1, 0); /* ALE */ - omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size); - } - break; - case 0x84 ... 0x87: /* GPMC_NAND_DATA */ - if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { - omap_nand_write(f, 0, value, size); - } - break; - default: - goto bad_reg; - } - break; - - case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ - if (!s->prefetch.startengine) { - uint32_t newconfig1 = value & 0x7f8f7fbf; - uint32_t changed; - changed = newconfig1 ^ s->prefetch.config1; - if (changed & (0x80 | 0x7000000)) { - /* Turning the engine on or off, or mapping it somewhere else. - * cs_map() and cs_unmap() check the prefetch config and - * overall CSVALID bits, so it is sufficient to unmap-and-map - * both the old cs and the new one. Note that we adhere to - * the "unmap/change config/map" order (and not unmap twice - * if newcs == oldcs), otherwise we'll try to delete the wrong - * memory region. - */ - int oldcs = prefetch_cs(s->prefetch.config1); - int newcs = prefetch_cs(newconfig1); - omap_gpmc_cs_unmap(s, oldcs); - if (oldcs != newcs) { - omap_gpmc_cs_unmap(s, newcs); - } - s->prefetch.config1 = newconfig1; - omap_gpmc_cs_map(s, oldcs); - if (oldcs != newcs) { - omap_gpmc_cs_map(s, newcs); - } - } else { - s->prefetch.config1 = newconfig1; - } - } - break; - - case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ - if (!s->prefetch.startengine) { - s->prefetch.transfercount = value & 0x3fff; - } - break; - - case 0x1ec: /* GPMC_PREFETCH_CONTROL */ - if (s->prefetch.startengine != (value & 1)) { - s->prefetch.startengine = value & 1; - if (s->prefetch.startengine) { - /* Prefetch engine start */ - s->prefetch.count = s->prefetch.transfercount; - if (s->prefetch.config1 & 1) { - /* Write */ - s->prefetch.fifopointer = 64; - } else { - /* Read */ - s->prefetch.fifopointer = 0; - fill_prefetch_fifo(s); - } - } else { - /* Prefetch engine forcibly stopped. The TRM - * doesn't define the behaviour if you do this. - * We clear the prefetch count, which means that - * we permit no more writes, and don't read any - * more data from NAND. The CPU can still drain - * the FIFO of unread data. - */ - s->prefetch.count = 0; - } - omap_gpmc_int_update(s); - } - break; - - case 0x1f4: /* GPMC_ECC_CONFIG */ - s->ecc_cs = 0x8f; - break; - case 0x1f8: /* GPMC_ECC_CONTROL */ - if (value & (1 << 8)) - for (cs = 0; cs < 9; cs ++) - ecc_reset(&s->ecc[cs]); - s->ecc_ptr = value & 0xf; - if (s->ecc_ptr == 0 || s->ecc_ptr > 9) { - s->ecc_ptr = 0; - s->ecc_cs &= ~1; - } - break; - case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */ - s->ecc_cfg = value & 0x3fcff1ff; - break; - case 0x230: /* GPMC_TESTMODE_CTRL */ - if (value & 7) - fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__); - break; - - default: - bad_reg: - OMAP_BAD_REG(addr); - return; - } -} - -static const MemoryRegionOps omap_gpmc_ops = { - .read = omap_gpmc_read, - .write = omap_gpmc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, - hwaddr base, - qemu_irq irq, qemu_irq drq) -{ - int cs; - struct omap_gpmc_s *s = g_new0(struct omap_gpmc_s, 1); - - memory_region_init_io(&s->iomem, NULL, &omap_gpmc_ops, s, "omap-gpmc", 0x1000); - memory_region_add_subregion(get_system_memory(), base, &s->iomem); - - s->irq = irq; - s->drq = drq; - s->accept_256 = cpu_is_omap3630(mpu); - s->revision = cpu_class_omap3(mpu) ? 0x50 : 0x20; - s->lastirq = 0; - omap_gpmc_reset(s); - - /* We have to register a different IO memory handler for each - * chip select region in case a NAND device is mapped there. We - * make the region the worst-case size of 256MB and rely on the - * container memory region in cs_map to chop it down to the actual - * guest-requested size. - */ - for (cs = 0; cs < 8; cs++) { - memory_region_init_io(&s->cs_file[cs].nandiomem, NULL, - &omap_nand_ops, - &s->cs_file[cs], - "omap-nand", - 256 * 1024 * 1024); - } - - memory_region_init_io(&s->prefetch.iomem, NULL, &omap_prefetch_ops, s, - "omap-gpmc-prefetch", 256 * 1024 * 1024); - return s; -} - -void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem) -{ - struct omap_gpmc_cs_file_s *f; - assert(iomem); - - if (cs < 0 || cs >= 8) { - fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs); - exit(-1); - } - f = &s->cs_file[cs]; - - omap_gpmc_cs_unmap(s, cs); - f->config[0] &= ~(0xf << 10); - f->iomem = iomem; - omap_gpmc_cs_map(s, cs); -} - -void omap_gpmc_attach_nand(struct omap_gpmc_s *s, int cs, DeviceState *nand) -{ - struct omap_gpmc_cs_file_s *f; - assert(nand); - - if (cs < 0 || cs >= 8) { - fprintf(stderr, "%s: bad chip-select %i\n", __func__, cs); - exit(-1); - } - f = &s->cs_file[cs]; - - omap_gpmc_cs_unmap(s, cs); - f->config[0] &= ~(0xf << 10); - f->config[0] |= (OMAP_GPMC_NAND << 10); - f->dev = nand; - if (nand_getbuswidth(f->dev) == 16) { - f->config[0] |= OMAP_GPMC_16BIT << 12; - } - omap_gpmc_cs_map(s, cs); -} diff --git a/qemu/hw/misc/omap_l4.c b/qemu/hw/misc/omap_l4.c deleted file mode 100644 index 88c533a0f..000000000 --- a/qemu/hw/misc/omap_l4.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * TI OMAP L4 interconnect emulation. - * - * Copyright (C) 2007-2009 Nokia Corporation - * Written by Andrzej Zaborowski <andrew@openedhand.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) any later version of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/arm/omap.h" - -struct omap_l4_s { - MemoryRegion *address_space; - hwaddr base; - int ta_num; - struct omap_target_agent_s ta[0]; -}; - -struct omap_l4_s *omap_l4_init(MemoryRegion *address_space, - hwaddr base, int ta_num) -{ - struct omap_l4_s *bus = g_malloc0( - sizeof(*bus) + ta_num * sizeof(*bus->ta)); - - bus->address_space = address_space; - bus->ta_num = ta_num; - bus->base = base; - - return bus; -} - -hwaddr omap_l4_region_base(struct omap_target_agent_s *ta, - int region) -{ - return ta->bus->base + ta->start[region].offset; -} - -hwaddr omap_l4_region_size(struct omap_target_agent_s *ta, - int region) -{ - return ta->start[region].size; -} - -static uint64_t omap_l4ta_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; - - if (size != 2) { - return omap_badwidth_read16(opaque, addr); - } - - switch (addr) { - case 0x00: /* COMPONENT */ - return s->component; - - case 0x20: /* AGENT_CONTROL */ - return s->control; - - case 0x28: /* AGENT_STATUS */ - return s->status; - } - - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_l4ta_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; - - if (size != 4) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - switch (addr) { - case 0x00: /* COMPONENT */ - case 0x28: /* AGENT_STATUS */ - OMAP_RO_REG(addr); - break; - - case 0x20: /* AGENT_CONTROL */ - s->control = value & 0x01000700; - if (value & 1) /* OCP_RESET */ - s->status &= ~1; /* REQ_TIMEOUT */ - break; - - default: - OMAP_BAD_REG(addr); - } -} - -static const MemoryRegionOps omap_l4ta_ops = { - .read = omap_l4ta_read, - .write = omap_l4ta_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, - const struct omap_l4_region_s *regions, - const struct omap_l4_agent_info_s *agents, - int cs) -{ - int i; - struct omap_target_agent_s *ta = NULL; - const struct omap_l4_agent_info_s *info = NULL; - - for (i = 0; i < bus->ta_num; i ++) - if (agents[i].ta == cs) { - ta = &bus->ta[i]; - info = &agents[i]; - break; - } - if (!ta) { - fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs); - exit(-1); - } - - ta->bus = bus; - ta->start = ®ions[info->region]; - ta->regions = info->regions; - - ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); - ta->status = 0x00000000; - ta->control = 0x00000200; /* XXX 01000200 for L4TAO */ - - memory_region_init_io(&ta->iomem, NULL, &omap_l4ta_ops, ta, "omap.l4ta", - omap_l4_region_size(ta, info->ta_region)); - omap_l4_attach(ta, info->ta_region, &ta->iomem); - - return ta; -} - -hwaddr omap_l4_attach(struct omap_target_agent_s *ta, - int region, MemoryRegion *mr) -{ - hwaddr base; - - if (region < 0 || region >= ta->regions) { - fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region); - exit(-1); - } - - base = ta->bus->base + ta->start[region].offset; - if (mr) { - memory_region_add_subregion(ta->bus->address_space, base, mr); - } - - return base; -} diff --git a/qemu/hw/misc/omap_sdrc.c b/qemu/hw/misc/omap_sdrc.c deleted file mode 100644 index dff37ecaf..000000000 --- a/qemu/hw/misc/omap_sdrc.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * TI OMAP SDRAM controller emulation. - * - * Copyright (C) 2007-2008 Nokia Corporation - * Written by Andrzej Zaborowski <andrew@openedhand.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) any later version of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/arm/omap.h" - -/* SDRAM Controller Subsystem */ -struct omap_sdrc_s { - MemoryRegion iomem; - uint8_t config; -}; - -void omap_sdrc_reset(struct omap_sdrc_s *s) -{ - s->config = 0x10; -} - -static uint64_t omap_sdrc_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; - - if (size != 4) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x00: /* SDRC_REVISION */ - return 0x20; - - case 0x10: /* SDRC_SYSCONFIG */ - return s->config; - - case 0x14: /* SDRC_SYSSTATUS */ - return 1; /* RESETDONE */ - - case 0x40: /* SDRC_CS_CFG */ - case 0x44: /* SDRC_SHARING */ - case 0x48: /* SDRC_ERR_ADDR */ - case 0x4c: /* SDRC_ERR_TYPE */ - case 0x60: /* SDRC_DLLA_SCTRL */ - case 0x64: /* SDRC_DLLA_STATUS */ - case 0x68: /* SDRC_DLLB_CTRL */ - case 0x6c: /* SDRC_DLLB_STATUS */ - case 0x70: /* SDRC_POWER */ - case 0x80: /* SDRC_MCFG_0 */ - case 0x84: /* SDRC_MR_0 */ - case 0x88: /* SDRC_EMR1_0 */ - case 0x8c: /* SDRC_EMR2_0 */ - case 0x90: /* SDRC_EMR3_0 */ - case 0x94: /* SDRC_DCDL1_CTRL */ - case 0x98: /* SDRC_DCDL2_CTRL */ - case 0x9c: /* SDRC_ACTIM_CTRLA_0 */ - case 0xa0: /* SDRC_ACTIM_CTRLB_0 */ - case 0xa4: /* SDRC_RFR_CTRL_0 */ - case 0xa8: /* SDRC_MANUAL_0 */ - case 0xb0: /* SDRC_MCFG_1 */ - case 0xb4: /* SDRC_MR_1 */ - case 0xb8: /* SDRC_EMR1_1 */ - case 0xbc: /* SDRC_EMR2_1 */ - case 0xc0: /* SDRC_EMR3_1 */ - case 0xc4: /* SDRC_ACTIM_CTRLA_1 */ - case 0xc8: /* SDRC_ACTIM_CTRLB_1 */ - case 0xd4: /* SDRC_RFR_CTRL_1 */ - case 0xd8: /* SDRC_MANUAL_1 */ - return 0x00; - } - - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_sdrc_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; - - if (size != 4) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - switch (addr) { - case 0x00: /* SDRC_REVISION */ - case 0x14: /* SDRC_SYSSTATUS */ - case 0x48: /* SDRC_ERR_ADDR */ - case 0x64: /* SDRC_DLLA_STATUS */ - case 0x6c: /* SDRC_DLLB_STATUS */ - OMAP_RO_REG(addr); - return; - - case 0x10: /* SDRC_SYSCONFIG */ - if ((value >> 3) != 0x2) - fprintf(stderr, "%s: bad SDRAM idle mode %i\n", - __FUNCTION__, (unsigned)value >> 3); - if (value & 2) - omap_sdrc_reset(s); - s->config = value & 0x18; - break; - - case 0x40: /* SDRC_CS_CFG */ - case 0x44: /* SDRC_SHARING */ - case 0x4c: /* SDRC_ERR_TYPE */ - case 0x60: /* SDRC_DLLA_SCTRL */ - case 0x68: /* SDRC_DLLB_CTRL */ - case 0x70: /* SDRC_POWER */ - case 0x80: /* SDRC_MCFG_0 */ - case 0x84: /* SDRC_MR_0 */ - case 0x88: /* SDRC_EMR1_0 */ - case 0x8c: /* SDRC_EMR2_0 */ - case 0x90: /* SDRC_EMR3_0 */ - case 0x94: /* SDRC_DCDL1_CTRL */ - case 0x98: /* SDRC_DCDL2_CTRL */ - case 0x9c: /* SDRC_ACTIM_CTRLA_0 */ - case 0xa0: /* SDRC_ACTIM_CTRLB_0 */ - case 0xa4: /* SDRC_RFR_CTRL_0 */ - case 0xa8: /* SDRC_MANUAL_0 */ - case 0xb0: /* SDRC_MCFG_1 */ - case 0xb4: /* SDRC_MR_1 */ - case 0xb8: /* SDRC_EMR1_1 */ - case 0xbc: /* SDRC_EMR2_1 */ - case 0xc0: /* SDRC_EMR3_1 */ - case 0xc4: /* SDRC_ACTIM_CTRLA_1 */ - case 0xc8: /* SDRC_ACTIM_CTRLB_1 */ - case 0xd4: /* SDRC_RFR_CTRL_1 */ - case 0xd8: /* SDRC_MANUAL_1 */ - break; - - default: - OMAP_BAD_REG(addr); - return; - } -} - -static const MemoryRegionOps omap_sdrc_ops = { - .read = omap_sdrc_read, - .write = omap_sdrc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem, - hwaddr base) -{ - struct omap_sdrc_s *s = g_new0(struct omap_sdrc_s, 1); - - omap_sdrc_reset(s); - - memory_region_init_io(&s->iomem, NULL, &omap_sdrc_ops, s, "omap.sdrc", 0x1000); - memory_region_add_subregion(sysmem, base, &s->iomem); - - return s; -} diff --git a/qemu/hw/misc/omap_tap.c b/qemu/hw/misc/omap_tap.c deleted file mode 100644 index e6ea8ee23..000000000 --- a/qemu/hw/misc/omap_tap.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * TI OMAP TEST-Chip-level TAP emulation. - * - * Copyright (C) 2007-2008 Nokia Corporation - * Written by Andrzej Zaborowski <andrew@openedhand.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) any later version of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/arm/omap.h" - -/* TEST-Chip-level TAP */ -static uint64_t omap_tap_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; - - if (size != 4) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x204: /* IDCODE_reg */ - switch (s->mpu_model) { - case omap2420: - case omap2422: - case omap2423: - return 0x5b5d902f; /* ES 2.2 */ - case omap2430: - return 0x5b68a02f; /* ES 2.2 */ - case omap3430: - return 0x1b7ae02f; /* ES 2 */ - default: - hw_error("%s: Bad mpu model\n", __FUNCTION__); - } - - case 0x208: /* PRODUCTION_ID_reg for OMAP2 */ - case 0x210: /* PRODUCTION_ID_reg for OMAP3 */ - switch (s->mpu_model) { - case omap2420: - return 0x000254f0; /* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */ - case omap2422: - return 0x000400f0; - case omap2423: - return 0x000800f0; - case omap2430: - return 0x000000f0; - case omap3430: - return 0x000000f0; - default: - hw_error("%s: Bad mpu model\n", __FUNCTION__); - } - - case 0x20c: - switch (s->mpu_model) { - case omap2420: - case omap2422: - case omap2423: - return 0xcafeb5d9; /* ES 2.2 */ - case omap2430: - return 0xcafeb68a; /* ES 2.2 */ - case omap3430: - return 0xcafeb7ae; /* ES 2 */ - default: - hw_error("%s: Bad mpu model\n", __FUNCTION__); - } - - case 0x218: /* DIE_ID_reg */ - return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); - case 0x21c: /* DIE_ID_reg */ - return 0x54 << 24; - case 0x220: /* DIE_ID_reg */ - return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); - case 0x224: /* DIE_ID_reg */ - return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); - } - - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_tap_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - if (size != 4) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - OMAP_BAD_REG(addr); -} - -static const MemoryRegionOps omap_tap_ops = { - .read = omap_tap_read, - .write = omap_tap_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -void omap_tap_init(struct omap_target_agent_s *ta, - struct omap_mpu_state_s *mpu) -{ - memory_region_init_io(&mpu->tap_iomem, NULL, &omap_tap_ops, mpu, "omap.tap", - omap_l4_region_size(ta, 0)); - omap_l4_attach(ta, 0, &mpu->tap_iomem); -} diff --git a/qemu/hw/misc/pc-testdev.c b/qemu/hw/misc/pc-testdev.c deleted file mode 100644 index 086893dcc..000000000 --- a/qemu/hw/misc/pc-testdev.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * QEMU x86 ISA testdev - * - * Copyright (c) 2012 Avi Kivity, Gerd Hoffmann, Marcelo Tosatti - * - * 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. - */ - -/* - * This device is used to test KVM features specific to the x86 port, such - * as emulation, power management, interrupt routing, among others. It's meant - * to be used like: - * - * qemu-system-x86_64 -device pc-testdev -serial stdio \ - * -device isa-debug-exit,iobase=0xf4,iosize=0x4 \ - * -kernel /home/lmr/Code/virt-test.git/kvm/unittests/msr.flat - * - * Where msr.flat is one of the KVM unittests, present on a separate repo, - * git://git.kernel.org/pub/scm/virt/kvm/kvm-unit-tests.git -*/ - -#include "qemu/osdep.h" -#if defined(CONFIG_POSIX) -#include <sys/mman.h> -#endif -#include "hw/hw.h" -#include "hw/qdev.h" -#include "hw/isa/isa.h" - -#define IOMEM_LEN 0x10000 - -typedef struct PCTestdev { - ISADevice parent_obj; - - MemoryRegion ioport; - MemoryRegion ioport_byte; - MemoryRegion flush; - MemoryRegion irq; - MemoryRegion iomem; - uint32_t ioport_data; - char iomem_buf[IOMEM_LEN]; -} PCTestdev; - -#define TYPE_TESTDEV "pc-testdev" -#define TESTDEV(obj) \ - OBJECT_CHECK(PCTestdev, (obj), TYPE_TESTDEV) - -static void test_irq_line(void *opaque, hwaddr addr, uint64_t data, - unsigned len) -{ - PCTestdev *dev = opaque; - ISADevice *isa = ISA_DEVICE(dev); - - qemu_set_irq(isa_get_irq(isa, addr), !!data); -} - -static const MemoryRegionOps test_irq_ops = { - .write = test_irq_line, - .valid.min_access_size = 1, - .valid.max_access_size = 1, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void test_ioport_write(void *opaque, hwaddr addr, uint64_t data, - unsigned len) -{ - PCTestdev *dev = opaque; - int bits = len * 8; - int start_bit = (addr & 3) * 8; - uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit; - dev->ioport_data &= ~mask; - dev->ioport_data |= data << start_bit; -} - -static uint64_t test_ioport_read(void *opaque, hwaddr addr, unsigned len) -{ - PCTestdev *dev = opaque; - int bits = len * 8; - int start_bit = (addr & 3) * 8; - uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit; - return (dev->ioport_data & mask) >> start_bit; -} - -static const MemoryRegionOps test_ioport_ops = { - .read = test_ioport_read, - .write = test_ioport_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static const MemoryRegionOps test_ioport_byte_ops = { - .read = test_ioport_read, - .write = test_ioport_write, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .impl.min_access_size = 1, - .impl.max_access_size = 1, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void test_flush_page(void *opaque, hwaddr addr, uint64_t data, - unsigned len) -{ - hwaddr page = 4096; - void *a = cpu_physical_memory_map(data & ~0xffful, &page, 0); - - /* We might not be able to get the full page, only mprotect what we actually - have mapped */ -#if defined(CONFIG_POSIX) - mprotect(a, page, PROT_NONE); - mprotect(a, page, PROT_READ|PROT_WRITE); -#endif - cpu_physical_memory_unmap(a, page, 0, 0); -} - -static const MemoryRegionOps test_flush_ops = { - .write = test_flush_page, - .valid.min_access_size = 4, - .valid.max_access_size = 4, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static uint64_t test_iomem_read(void *opaque, hwaddr addr, unsigned len) -{ - PCTestdev *dev = opaque; - uint64_t ret = 0; - memcpy(&ret, &dev->iomem_buf[addr], len); - - return ret; -} - -static void test_iomem_write(void *opaque, hwaddr addr, uint64_t val, - unsigned len) -{ - PCTestdev *dev = opaque; - memcpy(&dev->iomem_buf[addr], &val, len); - dev->iomem_buf[addr] = val; -} - -static const MemoryRegionOps test_iomem_ops = { - .read = test_iomem_read, - .write = test_iomem_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void testdev_realizefn(DeviceState *d, Error **errp) -{ - ISADevice *isa = ISA_DEVICE(d); - PCTestdev *dev = TESTDEV(d); - MemoryRegion *mem = isa_address_space(isa); - MemoryRegion *io = isa_address_space_io(isa); - - memory_region_init_io(&dev->ioport, OBJECT(dev), &test_ioport_ops, dev, - "pc-testdev-ioport", 4); - memory_region_init_io(&dev->ioport_byte, OBJECT(dev), - &test_ioport_byte_ops, dev, - "pc-testdev-ioport-byte", 4); - memory_region_init_io(&dev->flush, OBJECT(dev), &test_flush_ops, dev, - "pc-testdev-flush-page", 4); - memory_region_init_io(&dev->irq, OBJECT(dev), &test_irq_ops, dev, - "pc-testdev-irq-line", 24); - memory_region_init_io(&dev->iomem, OBJECT(dev), &test_iomem_ops, dev, - "pc-testdev-iomem", IOMEM_LEN); - - memory_region_add_subregion(io, 0xe0, &dev->ioport); - memory_region_add_subregion(io, 0xe4, &dev->flush); - memory_region_add_subregion(io, 0xe8, &dev->ioport_byte); - memory_region_add_subregion(io, 0x2000, &dev->irq); - memory_region_add_subregion(mem, 0xff000000, &dev->iomem); -} - -static void testdev_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - dc->realize = testdev_realizefn; -} - -static const TypeInfo testdev_info = { - .name = TYPE_TESTDEV, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(PCTestdev), - .class_init = testdev_class_init, -}; - -static void testdev_register_types(void) -{ - type_register_static(&testdev_info); -} - -type_init(testdev_register_types) diff --git a/qemu/hw/misc/pci-testdev.c b/qemu/hw/misc/pci-testdev.c deleted file mode 100644 index 2f2e98977..000000000 --- a/qemu/hw/misc/pci-testdev.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * QEMU PCI test device - * - * Copyright (c) 2012 Red Hat Inc. - * Author: Michael S. Tsirkin <mst@redhat.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/pci/pci.h" -#include "qemu/event_notifier.h" - -typedef struct PCITestDevHdr { - uint8_t test; - uint8_t width; - uint8_t pad0[2]; - uint32_t offset; - uint8_t data; - uint8_t pad1[3]; - uint32_t count; - uint8_t name[]; -} PCITestDevHdr; - -typedef struct IOTest { - MemoryRegion *mr; - EventNotifier notifier; - bool hasnotifier; - unsigned size; - bool match_data; - PCITestDevHdr *hdr; - unsigned bufsize; -} IOTest; - -#define IOTEST_DATAMATCH 0xFA -#define IOTEST_NOMATCH 0xCE - -#define IOTEST_IOSIZE 128 -#define IOTEST_MEMSIZE 2048 - -static const char *iotest_test[] = { - "no-eventfd", - "wildcard-eventfd", - "datamatch-eventfd" -}; - -static const char *iotest_type[] = { - "mmio", - "portio" -}; - -#define IOTEST_TEST(i) (iotest_test[((i) % ARRAY_SIZE(iotest_test))]) -#define IOTEST_TYPE(i) (iotest_type[((i) / ARRAY_SIZE(iotest_test))]) -#define IOTEST_MAX_TEST (ARRAY_SIZE(iotest_test)) -#define IOTEST_MAX_TYPE (ARRAY_SIZE(iotest_type)) -#define IOTEST_MAX (IOTEST_MAX_TEST * IOTEST_MAX_TYPE) - -enum { - IOTEST_ACCESS_NAME, - IOTEST_ACCESS_DATA, - IOTEST_ACCESS_MAX, -}; - -#define IOTEST_ACCESS_TYPE uint8_t -#define IOTEST_ACCESS_WIDTH (sizeof(uint8_t)) - -typedef struct PCITestDevState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - MemoryRegion mmio; - MemoryRegion portio; - IOTest *tests; - int current; -} PCITestDevState; - -#define TYPE_PCI_TEST_DEV "pci-testdev" - -#define PCI_TEST_DEV(obj) \ - OBJECT_CHECK(PCITestDevState, (obj), TYPE_PCI_TEST_DEV) - -#define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio")) -#define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ? &(d)->mmio : &(d)->portio) -#define IOTEST_SIZE(i) (IOTEST_IS_MEM(i) ? IOTEST_MEMSIZE : IOTEST_IOSIZE) -#define IOTEST_PCI_BAR(i) (IOTEST_IS_MEM(i) ? PCI_BASE_ADDRESS_SPACE_MEMORY : \ - PCI_BASE_ADDRESS_SPACE_IO) - -static int pci_testdev_start(IOTest *test) -{ - test->hdr->count = 0; - if (!test->hasnotifier) { - return 0; - } - event_notifier_test_and_clear(&test->notifier); - memory_region_add_eventfd(test->mr, - le32_to_cpu(test->hdr->offset), - test->size, - test->match_data, - test->hdr->data, - &test->notifier); - return 0; -} - -static void pci_testdev_stop(IOTest *test) -{ - if (!test->hasnotifier) { - return; - } - memory_region_del_eventfd(test->mr, - le32_to_cpu(test->hdr->offset), - test->size, - test->match_data, - test->hdr->data, - &test->notifier); -} - -static void -pci_testdev_reset(PCITestDevState *d) -{ - if (d->current == -1) { - return; - } - pci_testdev_stop(&d->tests[d->current]); - d->current = -1; -} - -static void pci_testdev_inc(IOTest *test, unsigned inc) -{ - uint32_t c = le32_to_cpu(test->hdr->count); - test->hdr->count = cpu_to_le32(c + inc); -} - -static void -pci_testdev_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size, int type) -{ - PCITestDevState *d = opaque; - IOTest *test; - int t, r; - - if (addr == offsetof(PCITestDevHdr, test)) { - pci_testdev_reset(d); - if (val >= IOTEST_MAX_TEST) { - return; - } - t = type * IOTEST_MAX_TEST + val; - r = pci_testdev_start(&d->tests[t]); - if (r < 0) { - return; - } - d->current = t; - return; - } - if (d->current < 0) { - return; - } - test = &d->tests[d->current]; - if (addr != le32_to_cpu(test->hdr->offset)) { - return; - } - if (test->match_data && test->size != size) { - return; - } - if (test->match_data && val != test->hdr->data) { - return; - } - pci_testdev_inc(test, 1); -} - -static uint64_t -pci_testdev_read(void *opaque, hwaddr addr, unsigned size) -{ - PCITestDevState *d = opaque; - const char *buf; - IOTest *test; - if (d->current < 0) { - return 0; - } - test = &d->tests[d->current]; - buf = (const char *)test->hdr; - if (addr + size >= test->bufsize) { - return 0; - } - if (test->hasnotifier) { - event_notifier_test_and_clear(&test->notifier); - } - return buf[addr]; -} - -static void -pci_testdev_mmio_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - pci_testdev_write(opaque, addr, val, size, 0); -} - -static void -pci_testdev_pio_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - pci_testdev_write(opaque, addr, val, size, 1); -} - -static const MemoryRegionOps pci_testdev_mmio_ops = { - .read = pci_testdev_read, - .write = pci_testdev_mmio_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static const MemoryRegionOps pci_testdev_pio_ops = { - .read = pci_testdev_read, - .write = pci_testdev_pio_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void pci_testdev_realize(PCIDevice *pci_dev, Error **errp) -{ - PCITestDevState *d = PCI_TEST_DEV(pci_dev); - uint8_t *pci_conf; - char *name; - int r, i; - bool fastmmio = kvm_ioeventfd_any_length_enabled(); - - pci_conf = pci_dev->config; - - pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */ - - memory_region_init_io(&d->mmio, OBJECT(d), &pci_testdev_mmio_ops, d, - "pci-testdev-mmio", IOTEST_MEMSIZE * 2); - memory_region_init_io(&d->portio, OBJECT(d), &pci_testdev_pio_ops, d, - "pci-testdev-portio", IOTEST_IOSIZE * 2); - pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); - pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio); - - d->current = -1; - d->tests = g_malloc0(IOTEST_MAX * sizeof *d->tests); - for (i = 0; i < IOTEST_MAX; ++i) { - IOTest *test = &d->tests[i]; - name = g_strdup_printf("%s-%s", IOTEST_TYPE(i), IOTEST_TEST(i)); - test->bufsize = sizeof(PCITestDevHdr) + strlen(name) + 1; - test->hdr = g_malloc0(test->bufsize); - memcpy(test->hdr->name, name, strlen(name) + 1); - g_free(name); - test->hdr->offset = cpu_to_le32(IOTEST_SIZE(i) + i * IOTEST_ACCESS_WIDTH); - test->match_data = strcmp(IOTEST_TEST(i), "wildcard-eventfd"); - if (fastmmio && IOTEST_IS_MEM(i) && !test->match_data) { - test->size = 0; - } else { - test->size = IOTEST_ACCESS_WIDTH; - } - test->hdr->test = i; - test->hdr->data = test->match_data ? IOTEST_DATAMATCH : IOTEST_NOMATCH; - test->hdr->width = IOTEST_ACCESS_WIDTH; - test->mr = IOTEST_REGION(d, i); - if (!strcmp(IOTEST_TEST(i), "no-eventfd")) { - test->hasnotifier = false; - continue; - } - r = event_notifier_init(&test->notifier, 0); - assert(r >= 0); - test->hasnotifier = true; - } -} - -static void -pci_testdev_uninit(PCIDevice *dev) -{ - PCITestDevState *d = PCI_TEST_DEV(dev); - int i; - - pci_testdev_reset(d); - for (i = 0; i < IOTEST_MAX; ++i) { - if (d->tests[i].hasnotifier) { - event_notifier_cleanup(&d->tests[i].notifier); - } - g_free(d->tests[i].hdr); - } - g_free(d->tests); -} - -static void qdev_pci_testdev_reset(DeviceState *dev) -{ - PCITestDevState *d = PCI_TEST_DEV(dev); - pci_testdev_reset(d); -} - -static void pci_testdev_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = pci_testdev_realize; - k->exit = pci_testdev_uninit; - k->vendor_id = PCI_VENDOR_ID_REDHAT; - k->device_id = PCI_DEVICE_ID_REDHAT_TEST; - k->revision = 0x00; - k->class_id = PCI_CLASS_OTHERS; - dc->desc = "PCI Test Device"; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - dc->reset = qdev_pci_testdev_reset; -} - -static const TypeInfo pci_testdev_info = { - .name = TYPE_PCI_TEST_DEV, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCITestDevState), - .class_init = pci_testdev_class_init, -}; - -static void pci_testdev_register_types(void) -{ - type_register_static(&pci_testdev_info); -} - -type_init(pci_testdev_register_types) diff --git a/qemu/hw/misc/puv3_pm.c b/qemu/hw/misc/puv3_pm.c deleted file mode 100644 index 577cebaac..000000000 --- a/qemu/hw/misc/puv3_pm.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Power Management device simulation in PKUnity SoC - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation, or any later version. - * See the COPYING file in the top-level directory. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" - -#undef DEBUG_PUV3 -#include "hw/unicore32/puv3.h" - -#define TYPE_PUV3_PM "puv3_pm" -#define PUV3_PM(obj) OBJECT_CHECK(PUV3PMState, (obj), TYPE_PUV3_PM) - -typedef struct PUV3PMState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - - uint32_t reg_PMCR; - uint32_t reg_PCGR; - uint32_t reg_PLL_SYS_CFG; - uint32_t reg_PLL_DDR_CFG; - uint32_t reg_PLL_VGA_CFG; - uint32_t reg_DIVCFG; -} PUV3PMState; - -static uint64_t puv3_pm_read(void *opaque, hwaddr offset, - unsigned size) -{ - PUV3PMState *s = opaque; - uint32_t ret = 0; - - switch (offset) { - case 0x14: - ret = s->reg_PCGR; - break; - case 0x18: - ret = s->reg_PLL_SYS_CFG; - break; - case 0x1c: - ret = s->reg_PLL_DDR_CFG; - break; - case 0x20: - ret = s->reg_PLL_VGA_CFG; - break; - case 0x24: - ret = s->reg_DIVCFG; - break; - case 0x28: /* PLL SYS STATUS */ - ret = 0x00002401; - break; - case 0x2c: /* PLL DDR STATUS */ - ret = 0x00100c00; - break; - case 0x30: /* PLL VGA STATUS */ - ret = 0x00003801; - break; - case 0x34: /* DIV STATUS */ - ret = 0x22f52015; - break; - case 0x38: /* SW RESET */ - ret = 0x0; - break; - case 0x44: /* PLL DFC DONE */ - ret = 0x7; - break; - default: - DPRINTF("Bad offset 0x%x\n", offset); - } - DPRINTF("offset 0x%x, value 0x%x\n", offset, ret); - - return ret; -} - -static void puv3_pm_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PUV3PMState *s = opaque; - - switch (offset) { - case 0x0: - s->reg_PMCR = value; - break; - case 0x14: - s->reg_PCGR = value; - break; - case 0x18: - s->reg_PLL_SYS_CFG = value; - break; - case 0x1c: - s->reg_PLL_DDR_CFG = value; - break; - case 0x20: - s->reg_PLL_VGA_CFG = value; - break; - case 0x24: - case 0x38: - break; - default: - DPRINTF("Bad offset 0x%x\n", offset); - } - DPRINTF("offset 0x%x, value 0x%x\n", offset, value); -} - -static const MemoryRegionOps puv3_pm_ops = { - .read = puv3_pm_read, - .write = puv3_pm_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int puv3_pm_init(SysBusDevice *dev) -{ - PUV3PMState *s = PUV3_PM(dev); - - s->reg_PCGR = 0x0; - - memory_region_init_io(&s->iomem, OBJECT(s), &puv3_pm_ops, s, "puv3_pm", - PUV3_REGS_OFFSET); - sysbus_init_mmio(dev, &s->iomem); - - return 0; -} - -static void puv3_pm_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - - sdc->init = puv3_pm_init; -} - -static const TypeInfo puv3_pm_info = { - .name = TYPE_PUV3_PM, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PUV3PMState), - .class_init = puv3_pm_class_init, -}; - -static void puv3_pm_register_type(void) -{ - type_register_static(&puv3_pm_info); -} - -type_init(puv3_pm_register_type) diff --git a/qemu/hw/misc/pvpanic.c b/qemu/hw/misc/pvpanic.c deleted file mode 100644 index 0ac1e6ac9..000000000 --- a/qemu/hw/misc/pvpanic.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * QEMU simulated pvpanic device. - * - * Copyright Fujitsu, Corp. 2013 - * - * Authors: - * Wen Congyang <wency@cn.fujitsu.com> - * Hu Tao <hutao@cn.fujitsu.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include "qemu/osdep.h" -#include "qapi/qmp/qobject.h" -#include "qapi/qmp/qjson.h" -#include "sysemu/sysemu.h" -#include "qemu/log.h" - -#include "hw/nvram/fw_cfg.h" -#include "hw/i386/pc.h" -#include "qapi-event.h" - -/* The bit of supported pv event */ -#define PVPANIC_F_PANICKED 0 - -/* The pv event value */ -#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED) - -#define TYPE_ISA_PVPANIC_DEVICE "pvpanic" -#define ISA_PVPANIC_DEVICE(obj) \ - OBJECT_CHECK(PVPanicState, (obj), TYPE_ISA_PVPANIC_DEVICE) - -static void handle_event(int event) -{ - static bool logged; - - if (event & ~PVPANIC_PANICKED && !logged) { - qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event); - logged = true; - } - - if (event & PVPANIC_PANICKED) { - qemu_system_guest_panicked(); - return; - } -} - -#include "hw/isa/isa.h" - -typedef struct PVPanicState { - ISADevice parent_obj; - - MemoryRegion io; - uint16_t ioport; -} PVPanicState; - -/* return supported events on read */ -static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size) -{ - return PVPANIC_PANICKED; -} - -static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - handle_event(val); -} - -static const MemoryRegionOps pvpanic_ops = { - .read = pvpanic_ioport_read, - .write = pvpanic_ioport_write, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void pvpanic_isa_initfn(Object *obj) -{ - PVPanicState *s = ISA_PVPANIC_DEVICE(obj); - - memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1); -} - -static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) -{ - ISADevice *d = ISA_DEVICE(dev); - PVPanicState *s = ISA_PVPANIC_DEVICE(dev); - FWCfgState *fw_cfg = fw_cfg_find(); - uint16_t *pvpanic_port; - - if (!fw_cfg) { - return; - } - - pvpanic_port = g_malloc(sizeof(*pvpanic_port)); - *pvpanic_port = cpu_to_le16(s->ioport); - fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port, - sizeof(*pvpanic_port)); - - isa_register_ioport(d, &s->io, s->ioport); -} - -#define PVPANIC_IOPORT_PROP "ioport" - -uint16_t pvpanic_port(void) -{ - Object *o = object_resolve_path_type("", TYPE_ISA_PVPANIC_DEVICE, NULL); - if (!o) { - return 0; - } - return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL); -} - -static Property pvpanic_isa_properties[] = { - DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505), - DEFINE_PROP_END_OF_LIST(), -}; - -static void pvpanic_isa_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = pvpanic_isa_realizefn; - dc->props = pvpanic_isa_properties; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); -} - -static TypeInfo pvpanic_isa_info = { - .name = TYPE_ISA_PVPANIC_DEVICE, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(PVPanicState), - .instance_init = pvpanic_isa_initfn, - .class_init = pvpanic_isa_class_init, -}; - -static void pvpanic_register_types(void) -{ - type_register_static(&pvpanic_isa_info); -} - -type_init(pvpanic_register_types) diff --git a/qemu/hw/misc/sga.c b/qemu/hw/misc/sga.c deleted file mode 100644 index 03b006d6f..000000000 --- a/qemu/hw/misc/sga.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * QEMU dummy ISA device for loading sgabios option rom. - * - * Copyright (c) 2011 Glauber Costa, Red Hat Inc. - * - * 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. - * - * sgabios code originally available at code.google.com/p/sgabios - * - */ -#include "qemu/osdep.h" -#include "hw/pci/pci.h" -#include "hw/i386/pc.h" -#include "hw/loader.h" -#include "sysemu/sysemu.h" - -#define SGABIOS_FILENAME "sgabios.bin" - -#define TYPE_SGA "sga" -#define SGA(obj) OBJECT_CHECK(ISASGAState, (obj), TYPE_SGA) - -typedef struct ISASGAState { - ISADevice parent_obj; -} ISASGAState; - -static void sga_realizefn(DeviceState *dev, Error **errp) -{ - rom_add_vga(SGABIOS_FILENAME); -} - -static void sga_class_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->realize = sga_realizefn; - dc->desc = "Serial Graphics Adapter"; -} - -static const TypeInfo sga_info = { - .name = TYPE_SGA, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(ISASGAState), - .class_init = sga_class_initfn, -}; - -static void sga_register_types(void) -{ - type_register_static(&sga_info); -} - -type_init(sga_register_types) diff --git a/qemu/hw/misc/slavio_misc.c b/qemu/hw/misc/slavio_misc.c deleted file mode 100644 index edd5de070..000000000 --- a/qemu/hw/misc/slavio_misc.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * QEMU Sparc SLAVIO aux io port emulation - * - * Copyright (c) 2005 Fabrice Bellard - * - * 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 "sysemu/sysemu.h" -#include "hw/sysbus.h" -#include "trace.h" - -/* - * This is the auxio port, chip control and system control part of - * chip STP2001 (Slave I/O), also produced as NCR89C105. See - * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt - * - * This also includes the PMC CPU idle controller. - */ - -#define TYPE_SLAVIO_MISC "slavio_misc" -#define SLAVIO_MISC(obj) OBJECT_CHECK(MiscState, (obj), TYPE_SLAVIO_MISC) - -typedef struct MiscState { - SysBusDevice parent_obj; - - MemoryRegion cfg_iomem; - MemoryRegion diag_iomem; - MemoryRegion mdm_iomem; - MemoryRegion led_iomem; - MemoryRegion sysctrl_iomem; - MemoryRegion aux1_iomem; - MemoryRegion aux2_iomem; - qemu_irq irq; - qemu_irq fdc_tc; - uint32_t dummy; - uint8_t config; - uint8_t aux1, aux2; - uint8_t diag, mctrl; - uint8_t sysctrl; - uint16_t leds; -} MiscState; - -#define TYPE_APC "apc" -#define APC(obj) OBJECT_CHECK(APCState, (obj), TYPE_APC) - -typedef struct APCState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - qemu_irq cpu_halt; -} APCState; - -#define MISC_SIZE 1 -#define LED_SIZE 2 -#define SYSCTRL_SIZE 4 - -#define AUX1_TC 0x02 - -#define AUX2_PWROFF 0x01 -#define AUX2_PWRINTCLR 0x02 -#define AUX2_PWRFAIL 0x20 - -#define CFG_PWRINTEN 0x08 - -#define SYS_RESET 0x01 -#define SYS_RESETSTAT 0x02 - -static void slavio_misc_update_irq(void *opaque) -{ - MiscState *s = opaque; - - if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) { - trace_slavio_misc_update_irq_raise(); - qemu_irq_raise(s->irq); - } else { - trace_slavio_misc_update_irq_lower(); - qemu_irq_lower(s->irq); - } -} - -static void slavio_misc_reset(DeviceState *d) -{ - MiscState *s = SLAVIO_MISC(d); - - // Diagnostic and system control registers not cleared in reset - s->config = s->aux1 = s->aux2 = s->mctrl = 0; -} - -static void slavio_set_power_fail(void *opaque, int irq, int power_failing) -{ - MiscState *s = opaque; - - trace_slavio_set_power_fail(power_failing, s->config); - if (power_failing && (s->config & CFG_PWRINTEN)) { - s->aux2 |= AUX2_PWRFAIL; - } else { - s->aux2 &= ~AUX2_PWRFAIL; - } - slavio_misc_update_irq(s); -} - -static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - MiscState *s = opaque; - - trace_slavio_cfg_mem_writeb(val & 0xff); - s->config = val & 0xff; - slavio_misc_update_irq(s); -} - -static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr, - unsigned size) -{ - MiscState *s = opaque; - uint32_t ret = 0; - - ret = s->config; - trace_slavio_cfg_mem_readb(ret); - return ret; -} - -static const MemoryRegionOps slavio_cfg_mem_ops = { - .read = slavio_cfg_mem_readb, - .write = slavio_cfg_mem_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void slavio_diag_mem_writeb(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - MiscState *s = opaque; - - trace_slavio_diag_mem_writeb(val & 0xff); - s->diag = val & 0xff; -} - -static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr, - unsigned size) -{ - MiscState *s = opaque; - uint32_t ret = 0; - - ret = s->diag; - trace_slavio_diag_mem_readb(ret); - return ret; -} - -static const MemoryRegionOps slavio_diag_mem_ops = { - .read = slavio_diag_mem_readb, - .write = slavio_diag_mem_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - MiscState *s = opaque; - - trace_slavio_mdm_mem_writeb(val & 0xff); - s->mctrl = val & 0xff; -} - -static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr, - unsigned size) -{ - MiscState *s = opaque; - uint32_t ret = 0; - - ret = s->mctrl; - trace_slavio_mdm_mem_readb(ret); - return ret; -} - -static const MemoryRegionOps slavio_mdm_mem_ops = { - .read = slavio_mdm_mem_readb, - .write = slavio_mdm_mem_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - MiscState *s = opaque; - - trace_slavio_aux1_mem_writeb(val & 0xff); - if (val & AUX1_TC) { - // Send a pulse to floppy terminal count line - if (s->fdc_tc) { - qemu_irq_raise(s->fdc_tc); - qemu_irq_lower(s->fdc_tc); - } - val &= ~AUX1_TC; - } - s->aux1 = val & 0xff; -} - -static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr, - unsigned size) -{ - MiscState *s = opaque; - uint32_t ret = 0; - - ret = s->aux1; - trace_slavio_aux1_mem_readb(ret); - return ret; -} - -static const MemoryRegionOps slavio_aux1_mem_ops = { - .read = slavio_aux1_mem_readb, - .write = slavio_aux1_mem_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - MiscState *s = opaque; - - val &= AUX2_PWRINTCLR | AUX2_PWROFF; - trace_slavio_aux2_mem_writeb(val & 0xff); - val |= s->aux2 & AUX2_PWRFAIL; - if (val & AUX2_PWRINTCLR) // Clear Power Fail int - val &= AUX2_PWROFF; - s->aux2 = val; - if (val & AUX2_PWROFF) - qemu_system_shutdown_request(); - slavio_misc_update_irq(s); -} - -static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr, - unsigned size) -{ - MiscState *s = opaque; - uint32_t ret = 0; - - ret = s->aux2; - trace_slavio_aux2_mem_readb(ret); - return ret; -} - -static const MemoryRegionOps slavio_aux2_mem_ops = { - .read = slavio_aux2_mem_readb, - .write = slavio_aux2_mem_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void apc_mem_writeb(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - APCState *s = opaque; - - trace_apc_mem_writeb(val & 0xff); - qemu_irq_raise(s->cpu_halt); -} - -static uint64_t apc_mem_readb(void *opaque, hwaddr addr, - unsigned size) -{ - uint32_t ret = 0; - - trace_apc_mem_readb(ret); - return ret; -} - -static const MemoryRegionOps apc_mem_ops = { - .read = apc_mem_readb, - .write = apc_mem_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - } -}; - -static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr, - unsigned size) -{ - MiscState *s = opaque; - uint32_t ret = 0; - - switch (addr) { - case 0: - ret = s->sysctrl; - break; - default: - break; - } - trace_slavio_sysctrl_mem_readl(ret); - return ret; -} - -static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - MiscState *s = opaque; - - trace_slavio_sysctrl_mem_writel(val); - switch (addr) { - case 0: - if (val & SYS_RESET) { - s->sysctrl = SYS_RESETSTAT; - qemu_system_reset_request(); - } - break; - default: - break; - } -} - -static const MemoryRegionOps slavio_sysctrl_mem_ops = { - .read = slavio_sysctrl_mem_readl, - .write = slavio_sysctrl_mem_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr, - unsigned size) -{ - MiscState *s = opaque; - uint32_t ret = 0; - - switch (addr) { - case 0: - ret = s->leds; - break; - default: - break; - } - trace_slavio_led_mem_readw(ret); - return ret; -} - -static void slavio_led_mem_writew(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - MiscState *s = opaque; - - trace_slavio_led_mem_writew(val & 0xffff); - switch (addr) { - case 0: - s->leds = val; - break; - default: - break; - } -} - -static const MemoryRegionOps slavio_led_mem_ops = { - .read = slavio_led_mem_readw, - .write = slavio_led_mem_writew, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 2, - .max_access_size = 2, - }, -}; - -static const VMStateDescription vmstate_misc = { - .name ="slavio_misc", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(dummy, MiscState), - VMSTATE_UINT8(config, MiscState), - VMSTATE_UINT8(aux1, MiscState), - VMSTATE_UINT8(aux2, MiscState), - VMSTATE_UINT8(diag, MiscState), - VMSTATE_UINT8(mctrl, MiscState), - VMSTATE_UINT8(sysctrl, MiscState), - VMSTATE_END_OF_LIST() - } -}; - -static int apc_init1(SysBusDevice *dev) -{ - APCState *s = APC(dev); - - sysbus_init_irq(dev, &s->cpu_halt); - - /* Power management (APC) XXX: not a Slavio device */ - memory_region_init_io(&s->iomem, OBJECT(s), &apc_mem_ops, s, - "apc", MISC_SIZE); - sysbus_init_mmio(dev, &s->iomem); - return 0; -} - -static int slavio_misc_init1(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - MiscState *s = SLAVIO_MISC(dev); - - sysbus_init_irq(sbd, &s->irq); - sysbus_init_irq(sbd, &s->fdc_tc); - - /* 8 bit registers */ - /* Slavio control */ - memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s, - "configuration", MISC_SIZE); - sysbus_init_mmio(sbd, &s->cfg_iomem); - - /* Diagnostics */ - memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s, - "diagnostic", MISC_SIZE); - sysbus_init_mmio(sbd, &s->diag_iomem); - - /* Modem control */ - memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s, - "modem", MISC_SIZE); - sysbus_init_mmio(sbd, &s->mdm_iomem); - - /* 16 bit registers */ - /* ss600mp diag LEDs */ - memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s, - "leds", LED_SIZE); - sysbus_init_mmio(sbd, &s->led_iomem); - - /* 32 bit registers */ - /* System control */ - memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s, - "system-control", SYSCTRL_SIZE); - sysbus_init_mmio(sbd, &s->sysctrl_iomem); - - /* AUX 1 (Misc System Functions) */ - memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s, - "misc-system-functions", MISC_SIZE); - sysbus_init_mmio(sbd, &s->aux1_iomem); - - /* AUX 2 (Software Powerdown Control) */ - memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s, - "software-powerdown-control", MISC_SIZE); - sysbus_init_mmio(sbd, &s->aux2_iomem); - - qdev_init_gpio_in(dev, slavio_set_power_fail, 1); - - return 0; -} - -static void slavio_misc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = slavio_misc_init1; - dc->reset = slavio_misc_reset; - dc->vmsd = &vmstate_misc; -} - -static const TypeInfo slavio_misc_info = { - .name = TYPE_SLAVIO_MISC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MiscState), - .class_init = slavio_misc_class_init, -}; - -static void apc_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = apc_init1; -} - -static const TypeInfo apc_info = { - .name = TYPE_APC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MiscState), - .class_init = apc_class_init, -}; - -static void slavio_misc_register_types(void) -{ - type_register_static(&slavio_misc_info); - type_register_static(&apc_info); -} - -type_init(slavio_misc_register_types) diff --git a/qemu/hw/misc/stm32f2xx_syscfg.c b/qemu/hw/misc/stm32f2xx_syscfg.c deleted file mode 100644 index d0d7076ef..000000000 --- a/qemu/hw/misc/stm32f2xx_syscfg.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * STM32F2XX SYSCFG - * - * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> - * - * 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 "hw/misc/stm32f2xx_syscfg.h" - -#ifndef STM_SYSCFG_ERR_DEBUG -#define STM_SYSCFG_ERR_DEBUG 0 -#endif - -#define DB_PRINT_L(lvl, fmt, args...) do { \ - if (STM_SYSCFG_ERR_DEBUG >= lvl) { \ - qemu_log("%s: " fmt, __func__, ## args); \ - } \ -} while (0); - -#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) - -static void stm32f2xx_syscfg_reset(DeviceState *dev) -{ - STM32F2XXSyscfgState *s = STM32F2XX_SYSCFG(dev); - - s->syscfg_memrmp = 0x00000000; - s->syscfg_pmc = 0x00000000; - s->syscfg_exticr1 = 0x00000000; - s->syscfg_exticr2 = 0x00000000; - s->syscfg_exticr3 = 0x00000000; - s->syscfg_exticr4 = 0x00000000; - s->syscfg_cmpcr = 0x00000000; -} - -static uint64_t stm32f2xx_syscfg_read(void *opaque, hwaddr addr, - unsigned int size) -{ - STM32F2XXSyscfgState *s = opaque; - - DB_PRINT("0x%"HWADDR_PRIx"\n", addr); - - switch (addr) { - case SYSCFG_MEMRMP: - return s->syscfg_memrmp; - case SYSCFG_PMC: - return s->syscfg_pmc; - case SYSCFG_EXTICR1: - return s->syscfg_exticr1; - case SYSCFG_EXTICR2: - return s->syscfg_exticr2; - case SYSCFG_EXTICR3: - return s->syscfg_exticr3; - case SYSCFG_EXTICR4: - return s->syscfg_exticr4; - case SYSCFG_CMPCR: - return s->syscfg_cmpcr; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); - return 0; - } - - return 0; -} - -static void stm32f2xx_syscfg_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned int size) -{ - STM32F2XXSyscfgState *s = opaque; - uint32_t value = val64; - - DB_PRINT("0x%x, 0x%"HWADDR_PRIx"\n", value, addr); - - switch (addr) { - case SYSCFG_MEMRMP: - qemu_log_mask(LOG_UNIMP, - "%s: Changeing the memory mapping isn't supported " \ - "in QEMU\n", __func__); - return; - case SYSCFG_PMC: - qemu_log_mask(LOG_UNIMP, - "%s: Changeing the memory mapping isn't supported " \ - "in QEMU\n", __func__); - return; - case SYSCFG_EXTICR1: - s->syscfg_exticr1 = (value & 0xFFFF); - return; - case SYSCFG_EXTICR2: - s->syscfg_exticr2 = (value & 0xFFFF); - return; - case SYSCFG_EXTICR3: - s->syscfg_exticr3 = (value & 0xFFFF); - return; - case SYSCFG_EXTICR4: - s->syscfg_exticr4 = (value & 0xFFFF); - return; - case SYSCFG_CMPCR: - s->syscfg_cmpcr = value; - return; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); - } -} - -static const MemoryRegionOps stm32f2xx_syscfg_ops = { - .read = stm32f2xx_syscfg_read, - .write = stm32f2xx_syscfg_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void stm32f2xx_syscfg_init(Object *obj) -{ - STM32F2XXSyscfgState *s = STM32F2XX_SYSCFG(obj); - - sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); - - memory_region_init_io(&s->mmio, obj, &stm32f2xx_syscfg_ops, s, - TYPE_STM32F2XX_SYSCFG, 0x400); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); -} - -static void stm32f2xx_syscfg_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->reset = stm32f2xx_syscfg_reset; -} - -static const TypeInfo stm32f2xx_syscfg_info = { - .name = TYPE_STM32F2XX_SYSCFG, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(STM32F2XXSyscfgState), - .instance_init = stm32f2xx_syscfg_init, - .class_init = stm32f2xx_syscfg_class_init, -}; - -static void stm32f2xx_syscfg_register_types(void) -{ - type_register_static(&stm32f2xx_syscfg_info); -} - -type_init(stm32f2xx_syscfg_register_types) diff --git a/qemu/hw/misc/tmp105.c b/qemu/hw/misc/tmp105.c deleted file mode 100644 index f5c2472b5..000000000 --- a/qemu/hw/misc/tmp105.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Texas Instruments TMP105 temperature sensor. - * - * Copyright (C) 2008 Nokia Corporation - * Written by Andrzej Zaborowski <andrew@openedhand.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/i2c/i2c.h" -#include "tmp105.h" -#include "qapi/error.h" -#include "qapi/visitor.h" - -static void tmp105_interrupt_update(TMP105State *s) -{ - qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1)); /* POL */ -} - -static void tmp105_alarm_update(TMP105State *s) -{ - if ((s->config >> 0) & 1) { /* SD */ - if ((s->config >> 7) & 1) /* OS */ - s->config &= ~(1 << 7); /* OS */ - else - return; - } - - if ((s->config >> 1) & 1) { /* TM */ - if (s->temperature >= s->limit[1]) - s->alarm = 1; - else if (s->temperature < s->limit[0]) - s->alarm = 1; - } else { - if (s->temperature >= s->limit[1]) - s->alarm = 1; - else if (s->temperature < s->limit[0]) - s->alarm = 0; - } - - tmp105_interrupt_update(s); -} - -static void tmp105_get_temperature(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - TMP105State *s = TMP105(obj); - int64_t value = s->temperature * 1000 / 256; - - visit_type_int(v, name, &value, errp); -} - -/* Units are 0.001 centigrades relative to 0 C. s->temperature is 8.8 - * fixed point, so units are 1/256 centigrades. A simple ratio will do. - */ -static void tmp105_set_temperature(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - TMP105State *s = TMP105(obj); - Error *local_err = NULL; - int64_t temp; - - visit_type_int(v, name, &temp, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - if (temp >= 128000 || temp < -128000) { - error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range", - temp / 1000, temp % 1000); - return; - } - - s->temperature = (int16_t) (temp * 256 / 1000); - - tmp105_alarm_update(s); -} - -static const int tmp105_faultq[4] = { 1, 2, 4, 6 }; - -static void tmp105_read(TMP105State *s) -{ - s->len = 0; - - if ((s->config >> 1) & 1) { /* TM */ - s->alarm = 0; - tmp105_interrupt_update(s); - } - - switch (s->pointer & 3) { - case TMP105_REG_TEMPERATURE: - s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8); - s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) & - (0xf0 << ((~s->config >> 5) & 3)); /* R */ - break; - - case TMP105_REG_CONFIG: - s->buf[s->len ++] = s->config; - break; - - case TMP105_REG_T_LOW: - s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8; - s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0; - break; - - case TMP105_REG_T_HIGH: - s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8; - s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0; - break; - } -} - -static void tmp105_write(TMP105State *s) -{ - switch (s->pointer & 3) { - case TMP105_REG_TEMPERATURE: - break; - - case TMP105_REG_CONFIG: - if (s->buf[0] & ~s->config & (1 << 0)) /* SD */ - printf("%s: TMP105 shutdown\n", __FUNCTION__); - s->config = s->buf[0]; - s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */ - tmp105_alarm_update(s); - break; - - case TMP105_REG_T_LOW: - case TMP105_REG_T_HIGH: - if (s->len >= 3) - s->limit[s->pointer & 1] = (int16_t) - ((((uint16_t) s->buf[0]) << 8) | s->buf[1]); - tmp105_alarm_update(s); - break; - } -} - -static int tmp105_rx(I2CSlave *i2c) -{ - TMP105State *s = TMP105(i2c); - - if (s->len < 2) { - return s->buf[s->len ++]; - } else { - return 0xff; - } -} - -static int tmp105_tx(I2CSlave *i2c, uint8_t data) -{ - TMP105State *s = TMP105(i2c); - - if (s->len == 0) { - s->pointer = data; - s->len++; - } else { - if (s->len <= 2) { - s->buf[s->len - 1] = data; - } - s->len++; - tmp105_write(s); - } - - return 0; -} - -static void tmp105_event(I2CSlave *i2c, enum i2c_event event) -{ - TMP105State *s = TMP105(i2c); - - if (event == I2C_START_RECV) { - tmp105_read(s); - } - - s->len = 0; -} - -static int tmp105_post_load(void *opaque, int version_id) -{ - TMP105State *s = opaque; - - s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */ - - tmp105_interrupt_update(s); - return 0; -} - -static const VMStateDescription vmstate_tmp105 = { - .name = "TMP105", - .version_id = 0, - .minimum_version_id = 0, - .post_load = tmp105_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT8(len, TMP105State), - VMSTATE_UINT8_ARRAY(buf, TMP105State, 2), - VMSTATE_UINT8(pointer, TMP105State), - VMSTATE_UINT8(config, TMP105State), - VMSTATE_INT16(temperature, TMP105State), - VMSTATE_INT16_ARRAY(limit, TMP105State, 2), - VMSTATE_UINT8(alarm, TMP105State), - VMSTATE_I2C_SLAVE(i2c, TMP105State), - VMSTATE_END_OF_LIST() - } -}; - -static void tmp105_reset(I2CSlave *i2c) -{ - TMP105State *s = TMP105(i2c); - - s->temperature = 0; - s->pointer = 0; - s->config = 0; - s->faults = tmp105_faultq[(s->config >> 3) & 3]; - s->alarm = 0; - - tmp105_interrupt_update(s); -} - -static int tmp105_init(I2CSlave *i2c) -{ - TMP105State *s = TMP105(i2c); - - qdev_init_gpio_out(&i2c->qdev, &s->pin, 1); - - tmp105_reset(&s->i2c); - - return 0; -} - -static void tmp105_initfn(Object *obj) -{ - object_property_add(obj, "temperature", "int", - tmp105_get_temperature, - tmp105_set_temperature, NULL, NULL, NULL); -} - -static void tmp105_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); - - k->init = tmp105_init; - k->event = tmp105_event; - k->recv = tmp105_rx; - k->send = tmp105_tx; - dc->vmsd = &vmstate_tmp105; -} - -static const TypeInfo tmp105_info = { - .name = TYPE_TMP105, - .parent = TYPE_I2C_SLAVE, - .instance_size = sizeof(TMP105State), - .instance_init = tmp105_initfn, - .class_init = tmp105_class_init, -}; - -static void tmp105_register_types(void) -{ - type_register_static(&tmp105_info); -} - -type_init(tmp105_register_types) diff --git a/qemu/hw/misc/tmp105.h b/qemu/hw/misc/tmp105.h deleted file mode 100644 index 9ba05ecc9..000000000 --- a/qemu/hw/misc/tmp105.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Texas Instruments TMP105 Temperature Sensor - * - * Browse the data sheet: - * - * http://www.ti.com/lit/gpn/tmp105 - * - * Copyright (C) 2012 Alex Horn <alex.horn@cs.ox.ac.uk> - * Copyright (C) 2008-2012 Andrzej Zaborowski <balrogg@gmail.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or - * later. See the COPYING file in the top-level directory. - */ -#ifndef QEMU_TMP105_H -#define QEMU_TMP105_H - -#include "hw/i2c/i2c.h" -#include "hw/misc/tmp105_regs.h" - -#define TYPE_TMP105 "tmp105" -#define TMP105(obj) OBJECT_CHECK(TMP105State, (obj), TYPE_TMP105) - -/** - * TMP105State: - * @config: Bits 5 and 6 (value 32 and 64) determine the precision of the - * temperature. See Table 8 in the data sheet. - * - * @see_also: http://www.ti.com/lit/gpn/tmp105 - */ -typedef struct TMP105State { - /*< private >*/ - I2CSlave i2c; - /*< public >*/ - - uint8_t len; - uint8_t buf[2]; - qemu_irq pin; - - uint8_t pointer; - uint8_t config; - int16_t temperature; - int16_t limit[2]; - int faults; - uint8_t alarm; -} TMP105State; - -#endif diff --git a/qemu/hw/misc/vmport.c b/qemu/hw/misc/vmport.c deleted file mode 100644 index 689678980..000000000 --- a/qemu/hw/misc/vmport.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * QEMU VMPort emulation - * - * Copyright (C) 2007 Hervé Poussineau - * - * 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 "hw/hw.h" -#include "hw/isa/isa.h" -#include "hw/i386/pc.h" -#include "sysemu/kvm.h" -#include "hw/qdev.h" - -//#define VMPORT_DEBUG - -#define VMPORT_CMD_GETVERSION 0x0a -#define VMPORT_CMD_GETRAMSIZE 0x14 - -#define VMPORT_ENTRIES 0x2c -#define VMPORT_MAGIC 0x564D5868 - -#define TYPE_VMPORT "vmport" -#define VMPORT(obj) OBJECT_CHECK(VMPortState, (obj), TYPE_VMPORT) - -typedef struct VMPortState -{ - ISADevice parent_obj; - - MemoryRegion io; - VMPortReadFunc *func[VMPORT_ENTRIES]; - void *opaque[VMPORT_ENTRIES]; -} VMPortState; - -static VMPortState *port_state; - -void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque) -{ - if (command >= VMPORT_ENTRIES) - return; - - port_state->func[command] = func; - port_state->opaque[command] = opaque; -} - -static uint64_t vmport_ioport_read(void *opaque, hwaddr addr, - unsigned size) -{ - VMPortState *s = opaque; - CPUState *cs = current_cpu; - X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; - unsigned char command; - uint32_t eax; - - cpu_synchronize_state(cs); - - eax = env->regs[R_EAX]; - if (eax != VMPORT_MAGIC) - return eax; - - command = env->regs[R_ECX]; - if (command >= VMPORT_ENTRIES) - return eax; - if (!s->func[command]) - { -#ifdef VMPORT_DEBUG - fprintf(stderr, "vmport: unknown command %x\n", command); -#endif - return eax; - } - - return s->func[command](s->opaque[command], addr); -} - -static void vmport_ioport_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - X86CPU *cpu = X86_CPU(current_cpu); - - cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4); -} - -static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr) -{ - X86CPU *cpu = X86_CPU(current_cpu); - - cpu->env.regs[R_EBX] = VMPORT_MAGIC; - return 6; -} - -static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) -{ - X86CPU *cpu = X86_CPU(current_cpu); - - cpu->env.regs[R_EBX] = 0x1177; - return ram_size; -} - -/* vmmouse helpers */ -void vmmouse_get_data(uint32_t *data) -{ - X86CPU *cpu = X86_CPU(current_cpu); - CPUX86State *env = &cpu->env; - - data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX]; - data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX]; - data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI]; -} - -void vmmouse_set_data(const uint32_t *data) -{ - X86CPU *cpu = X86_CPU(current_cpu); - CPUX86State *env = &cpu->env; - - env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1]; - env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3]; - env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5]; -} - -static const MemoryRegionOps vmport_ops = { - .read = vmport_ioport_read, - .write = vmport_ioport_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void vmport_realizefn(DeviceState *dev, Error **errp) -{ - ISADevice *isadev = ISA_DEVICE(dev); - VMPortState *s = VMPORT(dev); - - memory_region_init_io(&s->io, OBJECT(s), &vmport_ops, s, "vmport", 1); - isa_register_ioport(isadev, &s->io, 0x5658); - - port_state = s; - /* Register some generic port commands */ - vmport_register(VMPORT_CMD_GETVERSION, vmport_cmd_get_version, NULL); - vmport_register(VMPORT_CMD_GETRAMSIZE, vmport_cmd_ram_size, NULL); -} - -static void vmport_class_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = vmport_realizefn; - /* Reason: realize sets global port_state */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo vmport_info = { - .name = TYPE_VMPORT, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(VMPortState), - .class_init = vmport_class_initfn, -}; - -static void vmport_register_types(void) -{ - type_register_static(&vmport_info); -} - -type_init(vmport_register_types) diff --git a/qemu/hw/misc/zynq-xadc.c b/qemu/hw/misc/zynq-xadc.c deleted file mode 100644 index 71fbccd79..000000000 --- a/qemu/hw/misc/zynq-xadc.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * ADC registers for Xilinx Zynq Platform - * - * Copyright (c) 2015 Guenter Roeck - * Based on hw/misc/zynq_slcr.c, written by Michal Simek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/misc/zynq-xadc.h" -#include "qemu/timer.h" -#include "sysemu/sysemu.h" - -enum { - CFG = 0x000 / 4, - INT_STS, - INT_MASK, - MSTS, - CMDFIFO, - RDFIFO, - MCTL, -}; - -#define CFG_ENABLE BIT(31) -#define CFG_CFIFOTH_SHIFT 20 -#define CFG_CFIFOTH_LENGTH 4 -#define CFG_DFIFOTH_SHIFT 16 -#define CFG_DFIFOTH_LENGTH 4 -#define CFG_WEDGE BIT(13) -#define CFG_REDGE BIT(12) -#define CFG_TCKRATE_SHIFT 8 -#define CFG_TCKRATE_LENGTH 2 - -#define CFG_TCKRATE_DIV(x) (0x1 << (x - 1)) - -#define CFG_IGAP_SHIFT 0 -#define CFG_IGAP_LENGTH 5 - -#define INT_CFIFO_LTH BIT(9) -#define INT_DFIFO_GTH BIT(8) -#define INT_OT BIT(7) -#define INT_ALM_SHIFT 0 -#define INT_ALM_LENGTH 7 -#define INT_ALM_MASK (((1 << INT_ALM_LENGTH) - 1) << INT_ALM_SHIFT) - -#define INT_ALL (INT_CFIFO_LTH | INT_DFIFO_GTH | INT_OT | INT_ALM_MASK) - -#define MSTS_CFIFO_LVL_SHIFT 16 -#define MSTS_CFIFO_LVL_LENGTH 4 -#define MSTS_DFIFO_LVL_SHIFT 12 -#define MSTS_DFIFO_LVL_LENGTH 4 -#define MSTS_CFIFOF BIT(11) -#define MSTS_CFIFOE BIT(10) -#define MSTS_DFIFOF BIT(9) -#define MSTS_DFIFOE BIT(8) -#define MSTS_OT BIT(7) -#define MSTS_ALM_SHIFT 0 -#define MSTS_ALM_LENGTH 7 - -#define MCTL_RESET BIT(4) - -#define CMD_NOP 0x00 -#define CMD_READ 0x01 -#define CMD_WRITE 0x02 - -static void zynq_xadc_update_ints(ZynqXADCState *s) -{ - - /* We are fast, commands are actioned instantly so the CFIFO is always - * empty (and below threshold). - */ - s->regs[INT_STS] |= INT_CFIFO_LTH; - - if (s->xadc_dfifo_entries > - extract32(s->regs[CFG], CFG_DFIFOTH_SHIFT, CFG_DFIFOTH_LENGTH)) { - s->regs[INT_STS] |= INT_DFIFO_GTH; - } - - qemu_set_irq(s->qemu_irq, !!(s->regs[INT_STS] & ~s->regs[INT_MASK])); -} - -static void zynq_xadc_reset(DeviceState *d) -{ - ZynqXADCState *s = ZYNQ_XADC(d); - - s->regs[CFG] = 0x14 << CFG_IGAP_SHIFT | - CFG_TCKRATE_DIV(4) << CFG_TCKRATE_SHIFT | CFG_REDGE; - s->regs[INT_STS] = INT_CFIFO_LTH; - s->regs[INT_MASK] = 0xffffffff; - s->regs[CMDFIFO] = 0; - s->regs[RDFIFO] = 0; - s->regs[MCTL] = MCTL_RESET; - - memset(s->xadc_regs, 0, sizeof(s->xadc_regs)); - memset(s->xadc_dfifo, 0, sizeof(s->xadc_dfifo)); - s->xadc_dfifo_entries = 0; - - zynq_xadc_update_ints(s); -} - -static uint16_t xadc_pop_dfifo(ZynqXADCState *s) -{ - uint16_t rv = s->xadc_dfifo[0]; - int i; - - if (s->xadc_dfifo_entries > 0) { - s->xadc_dfifo_entries--; - } - for (i = 0; i < s->xadc_dfifo_entries; i++) { - s->xadc_dfifo[i] = s->xadc_dfifo[i + 1]; - } - s->xadc_dfifo[s->xadc_dfifo_entries] = 0; - zynq_xadc_update_ints(s); - return rv; -} - -static void xadc_push_dfifo(ZynqXADCState *s, uint16_t regval) -{ - if (s->xadc_dfifo_entries < ZYNQ_XADC_FIFO_DEPTH) { - s->xadc_dfifo[s->xadc_dfifo_entries++] = s->xadc_read_reg_previous; - } - s->xadc_read_reg_previous = regval; - zynq_xadc_update_ints(s); -} - -static bool zynq_xadc_check_offset(hwaddr offset, bool rnw) -{ - switch (offset) { - case CFG: - case INT_MASK: - case INT_STS: - case MCTL: - return true; - case RDFIFO: - case MSTS: - return rnw; /* read only */ - case CMDFIFO: - return !rnw; /* write only */ - default: - return false; - } -} - -static uint64_t zynq_xadc_read(void *opaque, hwaddr offset, unsigned size) -{ - ZynqXADCState *s = opaque; - int reg = offset / 4; - uint32_t rv = 0; - - if (!zynq_xadc_check_offset(reg, true)) { - qemu_log_mask(LOG_GUEST_ERROR, "zynq_xadc: Invalid read access to " - "addr %" HWADDR_PRIx "\n", offset); - return 0; - } - - switch (reg) { - case CFG: - case INT_MASK: - case INT_STS: - case MCTL: - rv = s->regs[reg]; - break; - case MSTS: - rv = MSTS_CFIFOE; - rv |= s->xadc_dfifo_entries << MSTS_DFIFO_LVL_SHIFT; - if (!s->xadc_dfifo_entries) { - rv |= MSTS_DFIFOE; - } else if (s->xadc_dfifo_entries == ZYNQ_XADC_FIFO_DEPTH) { - rv |= MSTS_DFIFOF; - } - break; - case RDFIFO: - rv = xadc_pop_dfifo(s); - break; - } - return rv; -} - -static void zynq_xadc_write(void *opaque, hwaddr offset, uint64_t val, - unsigned size) -{ - ZynqXADCState *s = (ZynqXADCState *)opaque; - int reg = offset / 4; - int xadc_reg; - int xadc_cmd; - int xadc_data; - - if (!zynq_xadc_check_offset(reg, false)) { - qemu_log_mask(LOG_GUEST_ERROR, "zynq_xadc: Invalid write access " - "to addr %" HWADDR_PRIx "\n", offset); - return; - } - - switch (reg) { - case CFG: - s->regs[CFG] = val; - break; - case INT_STS: - s->regs[INT_STS] &= ~val; - break; - case INT_MASK: - s->regs[INT_MASK] = val & INT_ALL; - break; - case CMDFIFO: - xadc_cmd = extract32(val, 26, 4); - xadc_reg = extract32(val, 16, 10); - xadc_data = extract32(val, 0, 16); - - if (s->regs[MCTL] & MCTL_RESET) { - qemu_log_mask(LOG_GUEST_ERROR, "zynq_xadc: Sending command " - "while comm channel held in reset: %" PRIx32 "\n", - (uint32_t) val); - break; - } - - if (xadc_reg >= ZYNQ_XADC_NUM_ADC_REGS && xadc_cmd != CMD_NOP) { - qemu_log_mask(LOG_GUEST_ERROR, "read/write op to invalid xadc " - "reg 0x%x\n", xadc_reg); - break; - } - - switch (xadc_cmd) { - case CMD_READ: - xadc_push_dfifo(s, s->xadc_regs[xadc_reg]); - break; - case CMD_WRITE: - s->xadc_regs[xadc_reg] = xadc_data; - /* fallthrough */ - case CMD_NOP: - xadc_push_dfifo(s, 0); - break; - } - break; - case MCTL: - s->regs[MCTL] = val & 0x00fffeff; - break; - } - zynq_xadc_update_ints(s); -} - -static const MemoryRegionOps xadc_ops = { - .read = zynq_xadc_read, - .write = zynq_xadc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void zynq_xadc_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - ZynqXADCState *s = ZYNQ_XADC(obj); - - memory_region_init_io(&s->iomem, obj, &xadc_ops, s, "zynq-xadc", - ZYNQ_XADC_MMIO_SIZE); - sysbus_init_mmio(sbd, &s->iomem); - sysbus_init_irq(sbd, &s->qemu_irq); -} - -static const VMStateDescription vmstate_zynq_xadc = { - .name = "zynq-xadc", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, ZynqXADCState, ZYNQ_XADC_NUM_IO_REGS), - VMSTATE_UINT16_ARRAY(xadc_regs, ZynqXADCState, - ZYNQ_XADC_NUM_ADC_REGS), - VMSTATE_UINT16_ARRAY(xadc_dfifo, ZynqXADCState, - ZYNQ_XADC_FIFO_DEPTH), - VMSTATE_UINT16(xadc_read_reg_previous, ZynqXADCState), - VMSTATE_UINT16(xadc_dfifo_entries, ZynqXADCState), - VMSTATE_END_OF_LIST() - } -}; - -static void zynq_xadc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->vmsd = &vmstate_zynq_xadc; - dc->reset = zynq_xadc_reset; -} - -static const TypeInfo zynq_xadc_info = { - .class_init = zynq_xadc_class_init, - .name = TYPE_ZYNQ_XADC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(ZynqXADCState), - .instance_init = zynq_xadc_init, -}; - -static void zynq_xadc_register_types(void) -{ - type_register_static(&zynq_xadc_info); -} - -type_init(zynq_xadc_register_types) diff --git a/qemu/hw/misc/zynq_slcr.c b/qemu/hw/misc/zynq_slcr.c deleted file mode 100644 index b1b7591ef..000000000 --- a/qemu/hw/misc/zynq_slcr.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Status and system control registers for Xilinx Zynq Platform - * - * Copyright (c) 2011 Michal Simek <monstr@monstr.eu> - * Copyright (c) 2012 PetaLogix Pty Ltd. - * Based on hw/arm_sysctl.c, written by Paul Brook - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "qemu/timer.h" -#include "hw/sysbus.h" -#include "sysemu/sysemu.h" - -#ifndef ZYNQ_SLCR_ERR_DEBUG -#define ZYNQ_SLCR_ERR_DEBUG 0 -#endif - -#define DB_PRINT(...) do { \ - if (ZYNQ_SLCR_ERR_DEBUG) { \ - fprintf(stderr, ": %s: ", __func__); \ - fprintf(stderr, ## __VA_ARGS__); \ - } \ - } while (0); - -#define XILINX_LOCK_KEY 0x767b -#define XILINX_UNLOCK_KEY 0xdf0d - -#define R_PSS_RST_CTRL_SOFT_RST 0x1 - -enum { - SCL = 0x000 / 4, - LOCK, - UNLOCK, - LOCKSTA, - - ARM_PLL_CTRL = 0x100 / 4, - DDR_PLL_CTRL, - IO_PLL_CTRL, - PLL_STATUS, - ARM_PLL_CFG, - DDR_PLL_CFG, - IO_PLL_CFG, - - ARM_CLK_CTRL = 0x120 / 4, - DDR_CLK_CTRL, - DCI_CLK_CTRL, - APER_CLK_CTRL, - USB0_CLK_CTRL, - USB1_CLK_CTRL, - GEM0_RCLK_CTRL, - GEM1_RCLK_CTRL, - GEM0_CLK_CTRL, - GEM1_CLK_CTRL, - SMC_CLK_CTRL, - LQSPI_CLK_CTRL, - SDIO_CLK_CTRL, - UART_CLK_CTRL, - SPI_CLK_CTRL, - CAN_CLK_CTRL, - CAN_MIOCLK_CTRL, - DBG_CLK_CTRL, - PCAP_CLK_CTRL, - TOPSW_CLK_CTRL, - -#define FPGA_CTRL_REGS(n, start) \ - FPGA ## n ## _CLK_CTRL = (start) / 4, \ - FPGA ## n ## _THR_CTRL, \ - FPGA ## n ## _THR_CNT, \ - FPGA ## n ## _THR_STA, - FPGA_CTRL_REGS(0, 0x170) - FPGA_CTRL_REGS(1, 0x180) - FPGA_CTRL_REGS(2, 0x190) - FPGA_CTRL_REGS(3, 0x1a0) - - BANDGAP_TRIP = 0x1b8 / 4, - PLL_PREDIVISOR = 0x1c0 / 4, - CLK_621_TRUE, - - PSS_RST_CTRL = 0x200 / 4, - DDR_RST_CTRL, - TOPSW_RESET_CTRL, - DMAC_RST_CTRL, - USB_RST_CTRL, - GEM_RST_CTRL, - SDIO_RST_CTRL, - SPI_RST_CTRL, - CAN_RST_CTRL, - I2C_RST_CTRL, - UART_RST_CTRL, - GPIO_RST_CTRL, - LQSPI_RST_CTRL, - SMC_RST_CTRL, - OCM_RST_CTRL, - FPGA_RST_CTRL = 0x240 / 4, - A9_CPU_RST_CTRL, - - RS_AWDT_CTRL = 0x24c / 4, - RST_REASON, - - REBOOT_STATUS = 0x258 / 4, - BOOT_MODE, - - APU_CTRL = 0x300 / 4, - WDT_CLK_SEL, - - TZ_DMA_NS = 0x440 / 4, - TZ_DMA_IRQ_NS, - TZ_DMA_PERIPH_NS, - - PSS_IDCODE = 0x530 / 4, - - DDR_URGENT = 0x600 / 4, - DDR_CAL_START = 0x60c / 4, - DDR_REF_START = 0x614 / 4, - DDR_CMD_STA, - DDR_URGENT_SEL, - DDR_DFI_STATUS, - - MIO = 0x700 / 4, -#define MIO_LENGTH 54 - - MIO_LOOPBACK = 0x804 / 4, - MIO_MST_TRI0, - MIO_MST_TRI1, - - SD0_WP_CD_SEL = 0x830 / 4, - SD1_WP_CD_SEL, - - LVL_SHFTR_EN = 0x900 / 4, - OCM_CFG = 0x910 / 4, - - CPU_RAM = 0xa00 / 4, - - IOU = 0xa30 / 4, - - DMAC_RAM = 0xa50 / 4, - - AFI0 = 0xa60 / 4, - AFI1 = AFI0 + 3, - AFI2 = AFI1 + 3, - AFI3 = AFI2 + 3, -#define AFI_LENGTH 3 - - OCM = 0xa90 / 4, - - DEVCI_RAM = 0xaa0 / 4, - - CSG_RAM = 0xab0 / 4, - - GPIOB_CTRL = 0xb00 / 4, - GPIOB_CFG_CMOS18, - GPIOB_CFG_CMOS25, - GPIOB_CFG_CMOS33, - GPIOB_CFG_HSTL = 0xb14 / 4, - GPIOB_DRVR_BIAS_CTRL, - - DDRIOB = 0xb40 / 4, -#define DDRIOB_LENGTH 14 -}; - -#define ZYNQ_SLCR_MMIO_SIZE 0x1000 -#define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4) - -#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr" -#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR) - -typedef struct ZynqSLCRState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - - uint32_t regs[ZYNQ_SLCR_NUM_REGS]; -} ZynqSLCRState; - -static void zynq_slcr_reset(DeviceState *d) -{ - ZynqSLCRState *s = ZYNQ_SLCR(d); - int i; - - DB_PRINT("RESET\n"); - - s->regs[LOCKSTA] = 1; - /* 0x100 - 0x11C */ - s->regs[ARM_PLL_CTRL] = 0x0001A008; - s->regs[DDR_PLL_CTRL] = 0x0001A008; - s->regs[IO_PLL_CTRL] = 0x0001A008; - s->regs[PLL_STATUS] = 0x0000003F; - s->regs[ARM_PLL_CFG] = 0x00014000; - s->regs[DDR_PLL_CFG] = 0x00014000; - s->regs[IO_PLL_CFG] = 0x00014000; - - /* 0x120 - 0x16C */ - s->regs[ARM_CLK_CTRL] = 0x1F000400; - s->regs[DDR_CLK_CTRL] = 0x18400003; - s->regs[DCI_CLK_CTRL] = 0x01E03201; - s->regs[APER_CLK_CTRL] = 0x01FFCCCD; - s->regs[USB0_CLK_CTRL] = s->regs[USB1_CLK_CTRL] = 0x00101941; - s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL] = 0x00000001; - s->regs[GEM0_CLK_CTRL] = s->regs[GEM1_CLK_CTRL] = 0x00003C01; - s->regs[SMC_CLK_CTRL] = 0x00003C01; - s->regs[LQSPI_CLK_CTRL] = 0x00002821; - s->regs[SDIO_CLK_CTRL] = 0x00001E03; - s->regs[UART_CLK_CTRL] = 0x00003F03; - s->regs[SPI_CLK_CTRL] = 0x00003F03; - s->regs[CAN_CLK_CTRL] = 0x00501903; - s->regs[DBG_CLK_CTRL] = 0x00000F03; - s->regs[PCAP_CLK_CTRL] = 0x00000F01; - - /* 0x170 - 0x1AC */ - s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL] - = s->regs[FPGA3_CLK_CTRL] = 0x00101800; - s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA] - = s->regs[FPGA3_THR_STA] = 0x00010000; - - /* 0x1B0 - 0x1D8 */ - s->regs[BANDGAP_TRIP] = 0x0000001F; - s->regs[PLL_PREDIVISOR] = 0x00000001; - s->regs[CLK_621_TRUE] = 0x00000001; - - /* 0x200 - 0x25C */ - s->regs[FPGA_RST_CTRL] = 0x01F33F0F; - s->regs[RST_REASON] = 0x00000040; - - s->regs[BOOT_MODE] = 0x00000001; - - /* 0x700 - 0x7D4 */ - for (i = 0; i < 54; i++) { - s->regs[MIO + i] = 0x00001601; - } - for (i = 2; i <= 8; i++) { - s->regs[MIO + i] = 0x00000601; - } - - s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF; - - s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3] - = s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7] - = 0x00010101; - s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101; - s->regs[CPU_RAM + 6] = 0x00000001; - - s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3] - = 0x09090909; - s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909; - s->regs[IOU + 6] = 0x00000909; - - s->regs[DMAC_RAM] = 0x00000009; - - s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909; - s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909; - s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909; - s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909; - s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2] - = s->regs[AFI3 + 2] = 0x00000909; - - s->regs[OCM + 0] = 0x01010101; - s->regs[OCM + 1] = s->regs[OCM + 2] = 0x09090909; - - s->regs[DEVCI_RAM] = 0x00000909; - s->regs[CSG_RAM] = 0x00000001; - - s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2] - = s->regs[DDRIOB + 3] = 0x00000e00; - s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6] - = 0x00000e00; - s->regs[DDRIOB + 12] = 0x00000021; -} - - -static bool zynq_slcr_check_offset(hwaddr offset, bool rnw) -{ - switch (offset) { - case LOCK: - case UNLOCK: - case DDR_CAL_START: - case DDR_REF_START: - return !rnw; /* Write only */ - case LOCKSTA: - case FPGA0_THR_STA: - case FPGA1_THR_STA: - case FPGA2_THR_STA: - case FPGA3_THR_STA: - case BOOT_MODE: - case PSS_IDCODE: - case DDR_CMD_STA: - case DDR_DFI_STATUS: - case PLL_STATUS: - return rnw;/* read only */ - case SCL: - case ARM_PLL_CTRL ... IO_PLL_CTRL: - case ARM_PLL_CFG ... IO_PLL_CFG: - case ARM_CLK_CTRL ... TOPSW_CLK_CTRL: - case FPGA0_CLK_CTRL ... FPGA0_THR_CNT: - case FPGA1_CLK_CTRL ... FPGA1_THR_CNT: - case FPGA2_CLK_CTRL ... FPGA2_THR_CNT: - case FPGA3_CLK_CTRL ... FPGA3_THR_CNT: - case BANDGAP_TRIP: - case PLL_PREDIVISOR: - case CLK_621_TRUE: - case PSS_RST_CTRL ... A9_CPU_RST_CTRL: - case RS_AWDT_CTRL: - case RST_REASON: - case REBOOT_STATUS: - case APU_CTRL: - case WDT_CLK_SEL: - case TZ_DMA_NS ... TZ_DMA_PERIPH_NS: - case DDR_URGENT: - case DDR_URGENT_SEL: - case MIO ... MIO + MIO_LENGTH - 1: - case MIO_LOOPBACK ... MIO_MST_TRI1: - case SD0_WP_CD_SEL: - case SD1_WP_CD_SEL: - case LVL_SHFTR_EN: - case OCM_CFG: - case CPU_RAM: - case IOU: - case DMAC_RAM: - case AFI0 ... AFI3 + AFI_LENGTH - 1: - case OCM: - case DEVCI_RAM: - case CSG_RAM: - case GPIOB_CTRL ... GPIOB_CFG_CMOS33: - case GPIOB_CFG_HSTL: - case GPIOB_DRVR_BIAS_CTRL: - case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1: - return true; - default: - return false; - } -} - -static uint64_t zynq_slcr_read(void *opaque, hwaddr offset, - unsigned size) -{ - ZynqSLCRState *s = opaque; - offset /= 4; - uint32_t ret = s->regs[offset]; - - if (!zynq_slcr_check_offset(offset, true)) { - qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to " - " addr %" HWADDR_PRIx "\n", offset * 4); - } - - DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset * 4, ret); - return ret; -} - -static void zynq_slcr_write(void *opaque, hwaddr offset, - uint64_t val, unsigned size) -{ - ZynqSLCRState *s = (ZynqSLCRState *)opaque; - offset /= 4; - - DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n", offset * 4, val); - - if (!zynq_slcr_check_offset(offset, false)) { - qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid write access to " - "addr %" HWADDR_PRIx "\n", offset * 4); - return; - } - - switch (offset) { - case SCL: - s->regs[SCL] = val & 0x1; - return; - case LOCK: - if ((val & 0xFFFF) == XILINX_LOCK_KEY) { - DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset, - (unsigned)val & 0xFFFF); - s->regs[LOCKSTA] = 1; - } else { - DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n", - (int)offset, (unsigned)val & 0xFFFF); - } - return; - case UNLOCK: - if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) { - DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset, - (unsigned)val & 0xFFFF); - s->regs[LOCKSTA] = 0; - } else { - DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n", - (int)offset, (unsigned)val & 0xFFFF); - } - return; - } - - if (s->regs[LOCKSTA]) { - qemu_log_mask(LOG_GUEST_ERROR, - "SCLR registers are locked. Unlock them first\n"); - return; - } - s->regs[offset] = val; - - switch (offset) { - case PSS_RST_CTRL: - if (val & R_PSS_RST_CTRL_SOFT_RST) { - qemu_system_reset_request(); - } - break; - } -} - -static const MemoryRegionOps slcr_ops = { - .read = zynq_slcr_read, - .write = zynq_slcr_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void zynq_slcr_init(Object *obj) -{ - ZynqSLCRState *s = ZYNQ_SLCR(obj); - - memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr", - ZYNQ_SLCR_MMIO_SIZE); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); -} - -static const VMStateDescription vmstate_zynq_slcr = { - .name = "zynq_slcr", - .version_id = 2, - .minimum_version_id = 2, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS), - VMSTATE_END_OF_LIST() - } -}; - -static void zynq_slcr_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->vmsd = &vmstate_zynq_slcr; - dc->reset = zynq_slcr_reset; -} - -static const TypeInfo zynq_slcr_info = { - .class_init = zynq_slcr_class_init, - .name = TYPE_ZYNQ_SLCR, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(ZynqSLCRState), - .instance_init = zynq_slcr_init, -}; - -static void zynq_slcr_register_types(void) -{ - type_register_static(&zynq_slcr_info); -} - -type_init(zynq_slcr_register_types) |