Added various peripherals
This commit is contained in:
1 parent
2161b1d851
commit
29e927ab33
14 files changed
+946
-23
No files matched your search
@@ -68,6 +68,7 @@ static void atv4_memory_setup(MachineState *machine, MemoryRegion *sysmem, Addre
|
||||
// ATV4MachineState *nms = ATV4_MACHINE(machine);
|
||||
allocate_ram(sysmem, "unknown1", UNKNOWN1_MEM_BASE, 0x200000);
|
||||
allocate_ram(sysmem, "unknown2", UNKNOWN2_MEM_BASE, 0x1000);
|
||||
allocate_ram(sysmem, "unknown3", UNKNOWN3_MEM_BASE, 0x20);
|
||||
|
||||
// load the bootrom (vrom)
|
||||
uint8_t *file_data = NULL;
|
||||
@@ -92,6 +93,15 @@ static void atv4_machine_init(MachineState *machine)
|
||||
|
||||
atv4_memory_setup(machine, sysmem, nsas);
|
||||
|
||||
// init the interrupt controller
|
||||
AppleAICState *aic_state = apple_aic_create();
|
||||
nms->aic_state = aic_state;
|
||||
SysBusDevice *busdev = SYS_BUS_DEVICE(nms->aic_state);
|
||||
sysbus_realize(busdev, &error_fatal);
|
||||
for(int i = 0; i < nms->aic_state->numCPU; i++) {
|
||||
memory_region_add_subregion(sysmem, AIC_MEM_BASE + i * 0x1000, &aic_state->cpus[i].iomem);
|
||||
}
|
||||
|
||||
// init the chip ID module
|
||||
DeviceState *dev = qdev_new("atv4.chipid");
|
||||
ATV4ChipIDState *chipid_state = ATV4_CHIPID(dev);
|
||||
@@ -110,6 +120,20 @@ static void atv4_machine_init(MachineState *machine)
|
||||
memory_region_add_subregion(sysmem, PMGR_CLK_MEM_BASE, &pmgr_state->clk_iomem);
|
||||
memory_region_add_subregion(sysmem, PMGR_CLKCFG_MEM_BASE, &pmgr_state->clkcfg_iomem);
|
||||
memory_region_add_subregion(sysmem, PMGR_SOC_MEM_BASE, &pmgr_state->soc_iomem);
|
||||
memory_region_add_subregion(sysmem, PMGR_SCRATCH_MEM_BASE, &pmgr_state->scratch_iomem);
|
||||
memory_region_add_subregion(sysmem, PMGR_PWRGATE_MEM_BASE, &pmgr_state->pwrgate_iomem);
|
||||
|
||||
// init GPIO
|
||||
dev = qdev_new("atv4.gpio");
|
||||
ATV4GPIOState *gpio_state = ATV4_GPIO(dev);
|
||||
nms->gpio_state = gpio_state;
|
||||
memory_region_add_subregion(sysmem, GPIO_MEM_BASE, &gpio_state->iomem);
|
||||
|
||||
// init the Apple USB
|
||||
dev = qdev_new("atv4.ausb");
|
||||
ATV4AUSBState *ausb_state = ATV4_AUSB(dev);
|
||||
nms->ausb_state = ausb_state;
|
||||
memory_region_add_subregion(sysmem, AUSB_MEM_BASE, &ausb_state->iomem);
|
||||
|
||||
qemu_register_reset(atv4_cpu_reset, nms);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "hw/arm/atv4_ausb.h"
|
||||
|
||||
static uint64_t atv4_ausb_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
ATV4AUSBState *s = (ATV4AUSBState *) opaque;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
default:
|
||||
return 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
static void atv4_ausb_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
ATV4AUSBState *s = (ATV4AUSBState *) opaque;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps atv4_ausb_ops = {
|
||||
.read = atv4_ausb_read,
|
||||
.write = atv4_ausb_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void atv4_ausb_init(Object *obj)
|
||||
{
|
||||
ATV4AUSBState *s = ATV4_AUSB(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, obj, &atv4_ausb_ops, s, TYPE_ATV4_AUSB, 0x100);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void atv4_ausb_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static const TypeInfo atv4_ausb_type_info = {
|
||||
.name = TYPE_ATV4_AUSB,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ATV4AUSBState),
|
||||
.instance_init = atv4_ausb_init,
|
||||
.class_init = atv4_ausb_class_init,
|
||||
};
|
||||
|
||||
static void atv4_ausb_register_types(void)
|
||||
{
|
||||
type_register_static(&atv4_ausb_type_info);
|
||||
}
|
||||
|
||||
type_init(atv4_ausb_register_types)
|
||||
@@ -5,6 +5,8 @@ static uint64_t atv4_chipid_read(void *opaque, hwaddr addr, unsigned size)
|
||||
//fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
|
||||
|
||||
switch (addr) {
|
||||
case rCFG_FUSE0:
|
||||
return 0;
|
||||
case CHIPID_REVISION:
|
||||
return 1;
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "hw/arm/atv4_gpio.h"
|
||||
|
||||
static void atv4_gpio_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
ATV4GPIOState *s = (struct ATV4GPIOState *) opaque;
|
||||
|
||||
switch(addr) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t atv4_gpio_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//printf("%s: read from location 0x%08x\n", __func__, addr);
|
||||
ATV4GPIOState *s = (struct ATV4GPIOState *) opaque;
|
||||
|
||||
switch(addr) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gpio_ops = {
|
||||
.read = atv4_gpio_read,
|
||||
.write = atv4_gpio_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void atv4_gpio_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
DeviceState *dev = DEVICE(sbd);
|
||||
ATV4GPIOState *s = ATV4_GPIO(dev);
|
||||
|
||||
memory_region_init_io(&s->iomem, obj, &gpio_ops, s, "gpio", 0x1000);
|
||||
}
|
||||
|
||||
static void atv4_gpio_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static const TypeInfo atv4_gpio_info = {
|
||||
.name = TYPE_ATV4_GPIO,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ATV4GPIOState),
|
||||
.instance_init = atv4_gpio_init,
|
||||
.class_init = atv4_gpio_class_init,
|
||||
};
|
||||
|
||||
static void atv4_gpio_register_types(void)
|
||||
{
|
||||
type_register_static(&atv4_gpio_info);
|
||||
}
|
||||
|
||||
type_init(atv4_gpio_register_types)
|
||||
@@ -221,6 +221,58 @@ static void atv4_pmgr_soc_write(void *opaque, hwaddr addr, uint64_t value, unsig
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t atv4_pmgr_scratch_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
|
||||
|
||||
switch (addr) {
|
||||
case 0x0 ... 0x60:
|
||||
// TODO return the right scratch configuration
|
||||
break;
|
||||
default:
|
||||
hw_error("%s: reading from unknown PMGR SCRATCH register 0x%08x\n", __func__, addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atv4_pmgr_scratch_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
ATV4PMGRState *s = (struct ATV4PMGRState *) opaque;
|
||||
|
||||
switch(addr) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t atv4_pmgr_pwrgate_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
|
||||
|
||||
switch (addr) {
|
||||
case 0x0 ... 0x300:
|
||||
// TODO return the right scratch configuration
|
||||
break;
|
||||
default:
|
||||
hw_error("%s: reading from unknown PMGR PWRGATE register 0x%08x\n", __func__, addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atv4_pmgr_pwrgate_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
ATV4PMGRState *s = (struct ATV4PMGRState *) opaque;
|
||||
|
||||
switch(addr) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps atv4_pmgr_pll_ops = {
|
||||
.read = atv4_pmgr_pll_read,
|
||||
.write = atv4_pmgr_pll_write,
|
||||
@@ -269,6 +321,18 @@ static const MemoryRegionOps atv4_pmgr_soc_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps atv4_pmgr_scratch_ops = {
|
||||
.read = atv4_pmgr_scratch_read,
|
||||
.write = atv4_pmgr_scratch_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps atv4_pmgr_pwrgate_ops = {
|
||||
.read = atv4_pmgr_pwrgate_read,
|
||||
.write = atv4_pmgr_pwrgate_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void atv4_pmgr_init(Object *obj)
|
||||
{
|
||||
ATV4PMGRState *s = ATV4_PMGR(obj);
|
||||
@@ -305,6 +369,14 @@ static void atv4_pmgr_init(Object *obj)
|
||||
// SOC performance
|
||||
memory_region_init_io(&s->soc_iomem, obj, &atv4_pmgr_soc_ops, s, TYPE_ATV4_PMGR_SOC, 0xFF);
|
||||
sysbus_init_mmio(sbd, &s->soc_iomem);
|
||||
|
||||
// scratch
|
||||
memory_region_init_io(&s->scratch_iomem, obj, &atv4_pmgr_scratch_ops, s, TYPE_ATV4_PMGR_SCRATCH, 0x60);
|
||||
sysbus_init_mmio(sbd, &s->scratch_iomem);
|
||||
|
||||
// power gate
|
||||
memory_region_init_io(&s->pwrgate_iomem, obj, &atv4_pmgr_pwrgate_ops, s, TYPE_ATV4_PMGR_PWRGATE, 0x300);
|
||||
sysbus_init_mmio(sbd, &s->pwrgate_iomem);
|
||||
}
|
||||
|
||||
static void atv4_pmgr_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
|
||||
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
|
||||
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
|
||||
arm_ss.add(when: 'CONFIG_ATV4', if_true: files('atv4.c', 'atv4_chipid.c', 'atv4_pmgr.c'))
|
||||
arm_ss.add(when: 'CONFIG_ATV4', if_true: files('atv4.c', 'atv4_chipid.c', 'atv4_pmgr.c', 'atv4_gpio.c', 'atv4_ausb.c'))
|
||||
|
||||
system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
|
||||
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
|
||||
|
||||
@@ -0,0 +1,607 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/intc/apple_aic.h"
|
||||
#include "trace.h"
|
||||
#include "hw/irq.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/lockable.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/pci/msi.h"
|
||||
|
||||
/*
|
||||
* AIC splits IRQs into domains (ipid)
|
||||
* In T8030 device tree, we have aic->ipid_length = 72
|
||||
* => IRQ(extInts) max nr = ((len(ipid_mask)>>2)<<5) = 0x240 (interrupts)
|
||||
* -> num domains = (0x240 + 31)>>5 = 18 (domains)
|
||||
* 0x240/18 = 32 (bits) of an uint32_t
|
||||
*
|
||||
* Commands such as rAIC_EIR_MASK_SET/CLR assign each domain to a 32bit register.
|
||||
* When masking/unmasking-ing IRQ n,
|
||||
* write to (aic_base + command_reg_base + (n / 32) * 4)
|
||||
* a uint32_t which has (n % 32)-th bit set,
|
||||
* command_reg_base is 0x4100 for rAIC_EIR_MASK_SET, 0x4180 for rAIC_EIR_MASK_CLR.
|
||||
*
|
||||
* T8030 uses both fast IPI, and AIC IPIs.
|
||||
* AIC IPIs' vectors are right after IRQs' vectors.
|
||||
* num IRQ + (X * 2) -> self_ipi (cpuX->cpuX)
|
||||
* num IRQ + (Y * 2) + 1 -> other_ipi (cpuX->cpuY)
|
||||
*/
|
||||
|
||||
//TODO: this is hardcoded for T8030
|
||||
#define AIC_INT_COUNT (256)
|
||||
#define AIC_CPU_COUNT (2)
|
||||
#define AIC_VERSION (2)
|
||||
|
||||
#define rAIC_REV (0x0000)
|
||||
#define rAIC_CAP0 (0x0004)
|
||||
#define rAIC_CAP1 (0x0008)
|
||||
#define rAIC_RST (0x000C)
|
||||
|
||||
#define rAIC_GLB_CFG (0x0010)
|
||||
#define AIC_GLBCFG_IEN (1 << 0)
|
||||
#define AIC_GLBCFG_AEWT(_t) ((_t) << 4)
|
||||
#define AIC_GLBCFG_SEWT(_t) ((_t) << 8)
|
||||
#define AIC_GLBCFG_AIWT(_t) ((_t) << 12)
|
||||
#define AIC_GLBCFG_SIWT(_t) ((_t) << 16)
|
||||
#define AIC_GLBCFG_SYNC_ACG (1 << 29)
|
||||
#define AIC_GLBCFG_EIR_ACG (1 << 30)
|
||||
#define AIC_GLBCFG_REG_ACG (1 << 31)
|
||||
#define AIC_GLBCFG_WT_MASK (15)
|
||||
#define AIC_GLBCFG_WT_64MICRO (7)
|
||||
|
||||
#define rAIC_WHOAMI (0x2000)
|
||||
#define rAIC_IACK (0x2004)
|
||||
#define rAIC_IPI_SET (0x2008)
|
||||
#define rAIC_IPI_CLR (0x200C)
|
||||
#define AIC_IPI_NORMAL (1 << 0)
|
||||
#define AIC_IPI_SELF (1 << 31)
|
||||
#define rAIC_IPI_MASK_SET (0x2024)
|
||||
#define rAIC_IPI_MASK_CLR (0x2028)
|
||||
#define rAIC_IPI_DEFER_SET (0x202C)
|
||||
#define rAIC_IPI_DEFER_CLR (0x2030)
|
||||
|
||||
#define rAIC_EIR_DEST(_n) (0x3000 + ((_n) * 4))
|
||||
#define rAIC_EIR_SW_SET(_n) (0x4000 + ((_n) * 4))
|
||||
#define rAIC_EIR_SW_CLR(_n) (0x4080 + ((_n) * 4))
|
||||
#define rAIC_EIR_MASK_SET(_n) (0x4100 + ((_n) * 4))
|
||||
#define rAIC_EIR_MASK_CLR(_n) (0x4180 + ((_n) * 4))
|
||||
#define rAIC_EIR_INT_RO(_n) (0x4200 + ((_n) * 4))
|
||||
|
||||
#define rAIC_WHOAMI_Pn(_n) (0x5000 + ((_n) * 0x80))
|
||||
#define rAIC_IACK_Pn(_n) (0x5004 + ((_n) * 0x80))
|
||||
#define rAIC_IPI_SET_Pn(_n) (0x5008 + ((_n) * 0x80))
|
||||
#define rAIC_IPI_CLR_Pn(_n) (0x500C + ((_n) * 0x80))
|
||||
#define rAIC_IPI_MASK_SET_Pn(_n) (0x5024 + ((_n) * 0x80))
|
||||
#define rAIC_IPI_MASK_CLR_Pn(_n) (0x5028 + ((_n) * 0x80))
|
||||
#define rAIC_IPI_DEFER_SET_Pn(_n) (0x502C + ((_n) * 0x80))
|
||||
#define rAIC_IPI_DEFER_CLR_Pn(_n) (0x5030 + ((_n) * 0x80))
|
||||
|
||||
#define kAIC_INT_SPURIOUS (0x00000)
|
||||
#define kAIC_INT_EXT (0x10000)
|
||||
#define kAIC_INT_IPI (0x40000)
|
||||
#define kAIC_INT_IPI_NORM (0x40001)
|
||||
#define kAIC_INT_IPI_SELF (0x40002)
|
||||
|
||||
#define AIC_INT_EXT(_v) (((_v) & 0x70000) == kAIC_INT_EXT)
|
||||
#define AIC_INT_IPI(_v) (((_v) & 0x70000) == kAIC_INT_IPI)
|
||||
|
||||
#define AIC_INT_EXTID(_v) ((_v) & 0x3FF)
|
||||
|
||||
#define AIC_SRC_TO_EIR(_s) ((_s) >> 5)
|
||||
#define AIC_SRC_TO_MASK(_s) (1 << ((_s) & 0x1F))
|
||||
#define AIC_EIR_TO_SRC(_s, _v) (((_s) << 5) + ((_v) & 0x1F))
|
||||
|
||||
#define kAIC_MAX_EXTID (AIC_INT_COUNT)
|
||||
#define kAIC_VEC_IPI (kAIC_MAX_EXTID)
|
||||
#define kAIC_NUM_INTS (kAIC_VEC_IPI + 1)
|
||||
|
||||
#define kAIC_NUM_EIRS AIC_SRC_TO_EIR(kAIC_MAX_EXTID)
|
||||
|
||||
#define kAICWT 64000
|
||||
|
||||
#define kCNTFRQ (24000000)
|
||||
|
||||
static inline uint64_t apple_aic_emulate_timer(void)
|
||||
{
|
||||
int period_ns = NANOSECONDS_PER_SECOND > kCNTFRQ ?
|
||||
NANOSECONDS_PER_SECOND / kCNTFRQ : 1;
|
||||
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / period_ns;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check state and interrupt cpus, call with mutex locked
|
||||
*/
|
||||
static void apple_aic_update(AppleAICState *s)
|
||||
{
|
||||
uint32_t intr = 0;
|
||||
uint32_t potential = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
s->cpus[i].pendingIPI |= s->cpus[i].deferredIPI;
|
||||
s->cpus[i].deferredIPI = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
if ((s->cpus[i].pendingIPI & AIC_IPI_SELF) & (~s->cpus[i].ipi_mask)) {
|
||||
intr |= (1 << i);
|
||||
}
|
||||
if ((~s->cpus[i].ipi_mask & AIC_IPI_NORMAL)
|
||||
&& (s->cpus[i].pendingIPI & ((1 << s->numCPU) - 1))) {
|
||||
intr |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
i = -1;
|
||||
while ((i = find_next_bit((unsigned long *)s->eir_state, s->numIRQ, i+1))
|
||||
< s->numIRQ) {
|
||||
int dest;
|
||||
if ((test_bit(i, (unsigned long *)s->eir_mask) == 0)
|
||||
&& (dest = s->eir_dest[i])) {
|
||||
if (((intr & dest) == 0)) {
|
||||
/* The interrupt doesn't have a cpu that can process it yet */
|
||||
uint32_t cpu = find_first_bit((unsigned long *)&s->eir_dest[i],
|
||||
s->numCPU);
|
||||
intr |= (1 << cpu);
|
||||
potential |= dest;
|
||||
} else {
|
||||
int k;
|
||||
for (k = 0; k < s->numCPU; k++) {
|
||||
if (((intr & (1 << k)) == 0) && (potential & (1 << k))) {
|
||||
/*
|
||||
* cpu K isn't in the interrupt list
|
||||
* and can handle some of the previous interrupts
|
||||
*/
|
||||
intr |= (1 << k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
if (intr & (1 << i)) {
|
||||
qemu_irq_raise(s->cpus[i].irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_aic_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
AppleAICState *s = APPLE_AIC(opaque);
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&s->mutex) {
|
||||
if (level) {
|
||||
set_bit(irq, (unsigned long *)s->eir_state);
|
||||
} else {
|
||||
clear_bit(irq, (unsigned long *)s->eir_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_aic_tick(void *opaque)
|
||||
{
|
||||
AppleAICState *s = APPLE_AIC(opaque);
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&s->mutex) {
|
||||
apple_aic_update(s);
|
||||
}
|
||||
|
||||
timer_mod_ns(s->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + kAICWT);
|
||||
}
|
||||
|
||||
static void apple_aic_reset(DeviceState *dev)
|
||||
{
|
||||
int i;
|
||||
AppleAICState *s = APPLE_AIC(dev);
|
||||
|
||||
/* mask all IRQs */
|
||||
memset(s->eir_mask, 0xffff, sizeof(uint32_t) * s->numEIR);
|
||||
|
||||
#ifdef AIC_DEBUG_NEW_IRQ
|
||||
memset(s->eir_mask_once, 0xffff, sizeof(uint32_t) * s->numEIR);
|
||||
#endif
|
||||
|
||||
/* dest default to 0 */
|
||||
memset(s->eir_dest, 0, sizeof(uint32_t) * s->numIRQ);
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
/* mask all IPI */
|
||||
s->cpus[i].ipi_mask = AIC_IPI_NORMAL | AIC_IPI_SELF;
|
||||
s->cpus[i].pendingIPI = 0;
|
||||
s->cpus[i].deferredIPI = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_aic_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned size)
|
||||
{
|
||||
AppleAICCPU *o = (AppleAICCPU *)opaque;
|
||||
AppleAICState *s = APPLE_AIC(o->aic);
|
||||
uint32_t val = (uint32_t)data;
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&s->mutex) {
|
||||
switch (addr) {
|
||||
case rAIC_RST:
|
||||
apple_aic_reset(DEVICE(s));
|
||||
break;
|
||||
|
||||
case rAIC_GLB_CFG:
|
||||
s->global_cfg = data;
|
||||
break;
|
||||
|
||||
case rAIC_IPI_SET:
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
if (val & (1 << i)) {
|
||||
set_bit(o->cpu_id, (unsigned long *)&s->cpus[i].pendingIPI);
|
||||
if (~s->cpus[i].ipi_mask & AIC_IPI_NORMAL) {
|
||||
qemu_irq_raise(s->cpus[i].irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (val & AIC_IPI_SELF) {
|
||||
o->pendingIPI |= AIC_IPI_SELF;
|
||||
if (~o->ipi_mask & AIC_IPI_SELF) {
|
||||
qemu_irq_raise(o->irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_IPI_CLR:
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
if (val & (1 << i)) {
|
||||
clear_bit(o->cpu_id, (unsigned long *)&s->cpus[i].pendingIPI);
|
||||
}
|
||||
}
|
||||
|
||||
if (val & AIC_IPI_SELF) {
|
||||
o->pendingIPI &= ~AIC_IPI_SELF;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_IPI_MASK_SET:
|
||||
o->ipi_mask |= (val & (AIC_IPI_NORMAL | AIC_IPI_SELF));
|
||||
break;
|
||||
|
||||
case rAIC_IPI_MASK_CLR:
|
||||
o->ipi_mask &= ~(val & (AIC_IPI_NORMAL | AIC_IPI_SELF));
|
||||
break;
|
||||
|
||||
case rAIC_IPI_DEFER_SET:
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
if (val & (1 << i)) {
|
||||
set_bit(o->cpu_id, (unsigned long *)&s->cpus[i].deferredIPI);
|
||||
}
|
||||
}
|
||||
|
||||
if (val & AIC_IPI_SELF) {
|
||||
o->deferredIPI |= AIC_IPI_SELF;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_IPI_DEFER_CLR:
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
if (val & (1 << i)) {
|
||||
clear_bit(o->cpu_id, (unsigned long *)&s->cpus[i].deferredIPI);
|
||||
}
|
||||
}
|
||||
|
||||
if (val & AIC_IPI_SELF) {
|
||||
o->deferredIPI &= ~AIC_IPI_SELF;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_EIR_DEST(0) ... rAIC_EIR_DEST(AIC_INT_COUNT):
|
||||
{
|
||||
uint32_t vector = (addr - rAIC_EIR_DEST(0)) / 4;
|
||||
if (unlikely(vector >= s->numIRQ)) {
|
||||
break;
|
||||
}
|
||||
s->eir_dest[vector] = val;
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_EIR_SW_SET(0) ... rAIC_EIR_SW_SET(kAIC_NUM_EIRS):
|
||||
{
|
||||
uint32_t eir = (addr - rAIC_EIR_SW_SET(0)) / 4;
|
||||
if (unlikely(eir >= s->numEIR)) {
|
||||
break;
|
||||
}
|
||||
s->eir_state[eir] |= val;
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_EIR_SW_CLR(0) ... rAIC_EIR_SW_CLR(kAIC_NUM_EIRS):
|
||||
{
|
||||
uint32_t eir = (addr - rAIC_EIR_SW_CLR(0)) / 4;
|
||||
if (unlikely(eir >= s->numEIR)) {
|
||||
break;
|
||||
}
|
||||
s->eir_state[eir] &= ~val;
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_EIR_MASK_SET(0) ... rAIC_EIR_MASK_SET(kAIC_NUM_EIRS):
|
||||
{
|
||||
uint32_t eir = (addr - rAIC_EIR_MASK_SET(0)) / 4;
|
||||
if (unlikely(eir >= s->numEIR)) {
|
||||
break;
|
||||
}
|
||||
s->eir_mask[eir] |= val;
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_EIR_MASK_CLR(0) ... rAIC_EIR_MASK_CLR(kAIC_NUM_EIRS):
|
||||
{
|
||||
uint32_t eir = (addr - rAIC_EIR_MASK_CLR(0)) / 4;
|
||||
|
||||
if (unlikely(eir >= s->numEIR)) {
|
||||
break;
|
||||
}
|
||||
|
||||
s->eir_mask[eir] &= ~val;
|
||||
|
||||
#ifdef AIC_DEBUG_NEW_IRQ
|
||||
if ((s->eir_mask[eir] | s->eir_mask_once[eir]) != s->eir_mask[eir]) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if ((s->eir_mask[eir] & (1 << i)) == 0 && (s->eir_mask_once[eir] & (1 << i)) != 0) {
|
||||
//trace_aic_new_irq(AIC_EIR_TO_SRC(eir, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
s->eir_mask_once[eir] &= s->eir_mask[eir];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case rAIC_WHOAMI_Pn(0) ... rAIC_WHOAMI_Pn(AIC_CPU_COUNT) - 4:
|
||||
{
|
||||
uint32_t cpu = ((addr - 0x5000) / 0x80);
|
||||
if (unlikely(cpu >= s->numCPU)) {
|
||||
break;
|
||||
}
|
||||
addr = addr - 0x5000 + 0x2000 - 0x80 * cpu;
|
||||
qemu_mutex_unlock(&s->mutex);
|
||||
apple_aic_write(&s->cpus[cpu], addr, data, size);
|
||||
qemu_mutex_lock(&s->mutex);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
hw_error("AIC: Write to unspported reg 0x%08x cpu %u: 0x%x\n", addr, o->cpu_id, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t apple_aic_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
AppleAICCPU *o = (AppleAICCPU *)opaque;
|
||||
AppleAICState *s = APPLE_AIC(o->aic);
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&s->mutex) {
|
||||
switch (addr) {
|
||||
case rAIC_REV:
|
||||
return 2;
|
||||
|
||||
case rAIC_CAP0:
|
||||
return (((uint64_t)s->numCPU - 1) << 16) | (s->numIRQ);
|
||||
|
||||
case rAIC_GLB_CFG:
|
||||
return s->global_cfg;
|
||||
|
||||
case rAIC_WHOAMI:
|
||||
return o->cpu_id;
|
||||
|
||||
case rAIC_IACK:
|
||||
{
|
||||
int i;
|
||||
|
||||
qemu_irq_lower(o->irq);
|
||||
if (o->pendingIPI & AIC_IPI_SELF & ~o->ipi_mask) {
|
||||
o->ipi_mask |= AIC_IPI_SELF;
|
||||
return kAIC_INT_IPI | kAIC_INT_IPI_SELF;
|
||||
}
|
||||
|
||||
if (~o->ipi_mask & AIC_IPI_NORMAL) {
|
||||
if (o->pendingIPI & ((1 << s->numCPU) - 1)) {
|
||||
o->ipi_mask |= AIC_IPI_NORMAL;
|
||||
return kAIC_INT_IPI | kAIC_INT_IPI_NORM;
|
||||
}
|
||||
}
|
||||
|
||||
i = -1;
|
||||
while ((i = find_next_bit((unsigned long *)s->eir_state,
|
||||
s->numIRQ, i+1)) < s->numIRQ) {
|
||||
if (test_bit(i, (unsigned long *)s->eir_mask) == 0) {
|
||||
if (s->eir_dest[i] & (1 << o->cpu_id)) {
|
||||
set_bit(i, (unsigned long *)s->eir_mask);
|
||||
return kAIC_INT_EXT | AIC_INT_EXTID(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return kAIC_INT_SPURIOUS;
|
||||
}
|
||||
|
||||
case rAIC_EIR_DEST(0) ... rAIC_EIR_DEST(AIC_INT_COUNT):
|
||||
{
|
||||
uint32_t vector = (addr - rAIC_EIR_DEST(0)) / 4;
|
||||
|
||||
if (unlikely(vector >= s->numIRQ)) {
|
||||
break;
|
||||
}
|
||||
|
||||
return s->eir_dest[vector];
|
||||
}
|
||||
|
||||
case rAIC_EIR_MASK_SET(0) ... rAIC_EIR_MASK_SET(kAIC_NUM_EIRS):
|
||||
{
|
||||
uint32_t eir = (addr - rAIC_EIR_MASK_SET(0)) / 4;
|
||||
|
||||
if (unlikely(eir >= s->numEIR)) {
|
||||
break;
|
||||
}
|
||||
|
||||
return s->eir_mask[eir];
|
||||
}
|
||||
|
||||
case rAIC_EIR_MASK_CLR(0) ... rAIC_EIR_MASK_CLR(kAIC_NUM_EIRS):
|
||||
{
|
||||
uint32_t eir = (addr - rAIC_EIR_MASK_CLR(0)) / 4;
|
||||
|
||||
if (unlikely(eir >= s->numEIR)) {
|
||||
break;
|
||||
}
|
||||
|
||||
return s->eir_mask[eir];
|
||||
}
|
||||
|
||||
case rAIC_EIR_INT_RO(0) ... rAIC_EIR_INT_RO(kAIC_NUM_EIRS):
|
||||
{
|
||||
uint32_t eir = (addr - rAIC_EIR_INT_RO(0)) / 4;
|
||||
|
||||
if (unlikely(eir >= s->numEIR)) {
|
||||
break;
|
||||
}
|
||||
return s->eir_state[eir];
|
||||
}
|
||||
|
||||
case rAIC_WHOAMI_Pn(0) ... rAIC_WHOAMI_Pn(AIC_CPU_COUNT) - 4:
|
||||
{
|
||||
uint32_t cpu = ((addr - 0x5000) / 0x80);
|
||||
uint64_t val;
|
||||
|
||||
if (unlikely(cpu >= s->numCPU)) {
|
||||
break;
|
||||
}
|
||||
|
||||
addr = addr - 0x5000 + 0x2000 - 0x80 * cpu;
|
||||
qemu_mutex_unlock(&s->mutex);
|
||||
|
||||
val = apple_aic_read(&s->cpus[cpu], addr, size);
|
||||
qemu_mutex_lock(&s->mutex);
|
||||
return val;
|
||||
}
|
||||
default: {
|
||||
if (addr == 0x20) {
|
||||
return apple_aic_emulate_timer() & 0xFFFFFFFF;
|
||||
} else if (addr == 0x28) {
|
||||
return (apple_aic_emulate_timer() >> 32) & 0xFFFFFFFF;
|
||||
} else {
|
||||
hw_error("AIC: Read from unspported reg 0x%08x cpu: %u\n", addr, o->cpu_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps apple_aic_ops = {
|
||||
.read = apple_aic_read,
|
||||
.write = apple_aic_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.impl.min_access_size = 4,
|
||||
.impl.max_access_size = 4,
|
||||
.valid.min_access_size = 4,
|
||||
.valid.max_access_size = 4,
|
||||
.valid.unaligned = false,
|
||||
};
|
||||
|
||||
static void apple_aic_realize(DeviceState *dev, struct Error **errp)
|
||||
{
|
||||
AppleAICState *s = APPLE_AIC(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
int i;
|
||||
|
||||
qemu_mutex_init(&s->mutex);
|
||||
s->cpus = g_new0(AppleAICCPU, s->numCPU);
|
||||
|
||||
for (i = 0; i < s->numCPU; i++) {
|
||||
AppleAICCPU *cpu = &s->cpus[i];
|
||||
|
||||
cpu->aic = s;
|
||||
cpu->cpu_id = i;
|
||||
memory_region_init_io(&cpu->iomem, OBJECT(dev), &apple_aic_ops, cpu, TYPE_APPLE_AIC, 0x6000);
|
||||
sysbus_init_mmio(sbd, &cpu->iomem);
|
||||
sysbus_init_irq(sbd, &cpu->irq);
|
||||
}
|
||||
|
||||
qdev_init_gpio_in(dev, apple_aic_set_irq, s->numIRQ);
|
||||
|
||||
assert(s->numCPU > 0);
|
||||
|
||||
s->eir_mask = g_new0(uint32_t, s->numEIR);
|
||||
s->eir_dest = g_new0(uint32_t, s->numIRQ);
|
||||
s->eir_state = g_new0(uint32_t, s->numEIR);
|
||||
|
||||
#ifdef AIC_DEBUG_NEW_IRQ
|
||||
s->eir_mask_once = g_new0(uint32_t, s->numEIR);
|
||||
#endif
|
||||
|
||||
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apple_aic_tick, dev);
|
||||
timer_mod_ns(s->timer, kAICWT);
|
||||
msi_nonbroken = true;
|
||||
}
|
||||
|
||||
static void apple_aic_unrealize(DeviceState *dev)
|
||||
{
|
||||
AppleAICState *s = APPLE_AIC(dev);
|
||||
timer_free(s->timer);
|
||||
}
|
||||
|
||||
AppleAICState *apple_aic_create()
|
||||
{
|
||||
DeviceState *dev;
|
||||
AppleAICState *s;
|
||||
|
||||
dev = qdev_new(TYPE_APPLE_AIC);
|
||||
s = APPLE_AIC(dev);
|
||||
s->numEIR = 8;
|
||||
s->numIRQ = s->numEIR * 32;
|
||||
s->numCPU = 1;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void apple_aic_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = apple_aic_realize;
|
||||
dc->unrealize = apple_aic_unrealize;
|
||||
dc->reset = apple_aic_reset;
|
||||
dc->desc = "Apple Interrupt Controller";
|
||||
}
|
||||
|
||||
static const TypeInfo apple_aic_info = {
|
||||
.name = TYPE_APPLE_AIC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AppleAICState),
|
||||
.class_init = apple_aic_class_init,
|
||||
};
|
||||
|
||||
static void apple_aic_register_types(void)
|
||||
{
|
||||
type_register_static(&apple_aic_info);
|
||||
}
|
||||
|
||||
type_init(apple_aic_register_types);
|
||||
@@ -12,6 +12,7 @@ system_ss.add(when: 'CONFIG_ARM_GICV3_TCG', if_true: files(
|
||||
'arm_gicv3_its.c',
|
||||
'arm_gicv3_redist.c',
|
||||
))
|
||||
system_ss.add(when: 'CONFIG_ATV4', if_true: files('apple_aic.c'))
|
||||
system_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
|
||||
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c'))
|
||||
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
|
||||
|
||||
+25
-13
@@ -4,9 +4,12 @@
|
||||
#include "exec/hwaddr.h"
|
||||
#include "hw/boards.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/intc/apple_aic.h"
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/arm/atv4_chipid.h"
|
||||
#include "hw/arm/atv4_pmgr.h"
|
||||
#include "hw/arm/atv4_gpio.h"
|
||||
#include "hw/arm/atv4_ausb.h"
|
||||
|
||||
#define TYPE_ATV4 "ATV4"
|
||||
|
||||
@@ -18,19 +21,25 @@
|
||||
OBJECT_CHECK(ATV4MachineState, (obj), TYPE_ATV4_MACHINE)
|
||||
|
||||
// memory addresses
|
||||
#define VROM_MEM_BASE 0x100000000
|
||||
#define UNKNOWN1_MEM_BASE 0x180000000
|
||||
#define UNKNOWN2_MEM_BASE 0x202220000
|
||||
#define PMGR_MEM_BASE 0x20e000000
|
||||
#define PMGR_PLL_MEM_BASE (PMGR_MEM_BASE)
|
||||
#define PMGR_CLKCFG_MEM_BASE (PMGR_MEM_BASE + 0x10000)
|
||||
#define PMGR_CLK_MEM_BASE (PMGR_MEM_BASE + 0x10308)
|
||||
#define PMGR_SOC_MEM_BASE (PMGR_MEM_BASE + 0x1a000)
|
||||
#define PMGR_GFX_MEM_BASE (PMGR_MEM_BASE + 0x1c200)
|
||||
#define PMGR_PS_MEM_BASE (PMGR_MEM_BASE + 0x20000)
|
||||
#define PMGR_VOLMAN_MEM_BASE (PMGR_MEM_BASE + 0x23000)
|
||||
#define PMGR_ACG_MEM_BASE (PMGR_MEM_BASE + 0x32000)
|
||||
#define CHIPID_MEM_BASE 0x20e02a000
|
||||
#define VROM_MEM_BASE 0x100000000
|
||||
#define UNKNOWN1_MEM_BASE 0x180000000
|
||||
#define UNKNOWN2_MEM_BASE 0x202220000
|
||||
#define UNKNOWN3_MEM_BASE 0x202240000
|
||||
#define AUSB_MEM_BASE 0x20c900000
|
||||
#define PMGR_MEM_BASE 0x20e000000
|
||||
#define AIC_MEM_BASE 0x20e100000
|
||||
#define GPIO_MEM_BASE 0x20e300000
|
||||
#define PMGR_PLL_MEM_BASE (PMGR_MEM_BASE)
|
||||
#define PMGR_CLKCFG_MEM_BASE (PMGR_MEM_BASE + 0x10000)
|
||||
#define PMGR_CLK_MEM_BASE (PMGR_MEM_BASE + 0x10308)
|
||||
#define PMGR_SOC_MEM_BASE (PMGR_MEM_BASE + 0x1a000)
|
||||
#define PMGR_GFX_MEM_BASE (PMGR_MEM_BASE + 0x1c200)
|
||||
#define PMGR_PS_MEM_BASE (PMGR_MEM_BASE + 0x20000)
|
||||
#define PMGR_PWRGATE_MEM_BASE (PMGR_MEM_BASE + 0x22000)
|
||||
#define PMGR_VOLMAN_MEM_BASE (PMGR_MEM_BASE + 0x23000)
|
||||
#define PMGR_SCRATCH_MEM_BASE (PMGR_MEM_BASE + 0x29000)
|
||||
#define PMGR_ACG_MEM_BASE (PMGR_MEM_BASE + 0x32000)
|
||||
#define CHIPID_MEM_BASE 0x20e02a000
|
||||
|
||||
typedef struct {
|
||||
MachineClass parent;
|
||||
@@ -41,8 +50,11 @@ typedef struct {
|
||||
AddressSpace *nsas;
|
||||
qemu_irq **irq;
|
||||
ARMCPU *cpu;
|
||||
AppleAICState *aic_state;
|
||||
ATV4ChipIDState *chipid_state;
|
||||
ATV4PMGRState *pmgr_state;
|
||||
ATV4GPIOState *gpio_state;
|
||||
ATV4AUSBState *ausb_state;
|
||||
ATV4_CPREG_VAR_DEF(REG0);
|
||||
ATV4_CPREG_VAR_DEF(REG1);
|
||||
ATV4_CPREG_VAR_DEF(REG2);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef HW_ARM_ATV4_AUSB_H
|
||||
#define HW_ARM_ATV4_AUSB_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ATV4_AUSB "atv4.ausb"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ATV4AUSBState, ATV4_AUSB)
|
||||
|
||||
typedef struct ATV4AUSBState {
|
||||
SysBusDevice busdev;
|
||||
MemoryRegion iomem;
|
||||
} ATV4AUSBState;
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#define TYPE_ATV4_CHIPID "atv4.chipid"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ATV4ChipIDState, ATV4_CHIPID)
|
||||
|
||||
#define rCFG_FUSE0 0x0
|
||||
#define CHIPID_REVISION 0x10
|
||||
|
||||
typedef struct ATV4ChipIDState {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef ATV4_GPIO_H
|
||||
#define ATV4_GPIO_H
|
||||
|
||||
#include <math.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ATV4_GPIO "atv4.gpio"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ATV4GPIOState, ATV4_GPIO)
|
||||
|
||||
#define GPIO_FORCE_DFU 0xD04
|
||||
|
||||
typedef struct ATV4GPIOState
|
||||
{
|
||||
SysBusDevice parent_obj;
|
||||
MemoryRegion iomem;
|
||||
} ATV4GPIOState;
|
||||
|
||||
#endif
|
||||
@@ -5,15 +5,17 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ATV4_PMGR "atv4.pmgr"
|
||||
#define TYPE_ATV4_PMGR_VOLMAN "atv4.pmgr.volman"
|
||||
#define TYPE_ATV4_PMGR_PS "atv4.pmgr.ps"
|
||||
#define TYPE_ATV4_PMGR_GFX "atv4.pmgr.gfx"
|
||||
#define TYPE_ATV4_PMGR_ACG "atv4.pmgr.acg"
|
||||
#define TYPE_ATV4_PMGR_CLK "atv4.pmgr.clk"
|
||||
#define TYPE_ATV4_PMGR_CLKCFG "atv4.pmgr.clkcfg"
|
||||
#define TYPE_ATV4_PMGR_SOC "atv4.pmgr.soc"
|
||||
#define TYPE_ATV4_PMGR_PLL "atv4.pmgr.pll"
|
||||
#define TYPE_ATV4_PMGR "atv4.pmgr"
|
||||
#define TYPE_ATV4_PMGR_VOLMAN "atv4.pmgr.volman"
|
||||
#define TYPE_ATV4_PMGR_PS "atv4.pmgr.ps"
|
||||
#define TYPE_ATV4_PMGR_GFX "atv4.pmgr.gfx"
|
||||
#define TYPE_ATV4_PMGR_ACG "atv4.pmgr.acg"
|
||||
#define TYPE_ATV4_PMGR_CLK "atv4.pmgr.clk"
|
||||
#define TYPE_ATV4_PMGR_CLKCFG "atv4.pmgr.clkcfg"
|
||||
#define TYPE_ATV4_PMGR_SOC "atv4.pmgr.soc"
|
||||
#define TYPE_ATV4_PMGR_PLL "atv4.pmgr.pll"
|
||||
#define TYPE_ATV4_PMGR_SCRATCH "atv4.pmgr.scratch"
|
||||
#define TYPE_ATV4_PMGR_PWRGATE "atv4.pmgr.pwrgate"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ATV4PMGRState, ATV4_PMGR)
|
||||
|
||||
#define NUM_PLLS 0x6
|
||||
@@ -168,6 +170,8 @@ typedef struct ATV4PMGRState {
|
||||
MemoryRegion clk_iomem;
|
||||
MemoryRegion clkcfg_iomem;
|
||||
MemoryRegion soc_iomem;
|
||||
MemoryRegion scratch_iomem;
|
||||
MemoryRegion pwrgate_iomem;
|
||||
uint64_t pll_bypass_cfg[6];
|
||||
} ATV4PMGRState;
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef APPLE_AIC_H
|
||||
#define APPLE_AIC_H
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_APPLE_AIC "apple.aic"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(AppleAICState, APPLE_AIC)
|
||||
|
||||
#define AIC_DEBUG_NEW_IRQ
|
||||
|
||||
typedef struct AppleAICState AppleAICState;
|
||||
|
||||
typedef struct {
|
||||
AppleAICState *aic;
|
||||
qemu_irq irq;
|
||||
MemoryRegion iomem;
|
||||
uint32_t cpu_id;
|
||||
uint32_t pendingIPI;
|
||||
uint32_t deferredIPI;
|
||||
uint32_t ipi_mask;
|
||||
} AppleAICCPU;
|
||||
|
||||
struct AppleAICState {
|
||||
SysBusDevice parent_obj;
|
||||
QEMUTimer *timer;
|
||||
QemuMutex mutex;
|
||||
uint32_t numEIR;
|
||||
uint32_t numIRQ;
|
||||
uint32_t numCPU;
|
||||
uint32_t global_cfg;
|
||||
uint32_t *eir_mask;
|
||||
uint32_t *eir_dest;
|
||||
AppleAICCPU *cpus;
|
||||
uint32_t *eir_state;
|
||||
#ifdef AIC_DEBUG_NEW_IRQ
|
||||
uint32_t *eir_mask_once;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
AppleAICState *apple_aic_create();
|
||||
|
||||
#endif /* APPLE_AIC_H */
|
||||
Reference in new issue
Block a user