Started working on iPod Touch 2G

This commit is contained in:
Martijn de Vos committed 2023-12-31 14:35:48 +01:00
1 parent 1600b9f46b
commit 96da27fe3b
11 files changed
+579

No files matched your search

+1
View File
@@ -44,3 +44,4 @@ CONFIG_ARM_VIRT=y
# CONFIG_FSL_IMX7=n
# CONFIG_FSL_IMX6UL=n
# CONFIG_ALLWINNER_H3=n
CONFIG_IPOD_TOUCH_2G=y
+4
View File
@@ -679,3 +679,7 @@ config ARMSSE
select UNIMP
select SSE_COUNTER
select SSE_TIMER
config IPOD_TOUCH_2G
bool
select IPOD_TOUCH_2G
+162
View File
@@ -0,0 +1,162 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/arm/boot.h"
#include "exec/address-spaces.h"
#include "hw/misc/unimp.h"
#include "hw/irq.h"
#include "sysemu/sysemu.h"
#include "sysemu/reset.h"
#include "hw/platform-bus.h"
#include "hw/block/flash.h"
#include "hw/qdev-clock.h"
#include "hw/arm/ipod_touch_2g.h"
#include "target/arm/cpregs.h"
#define VMSTATE_IT2G_CPREG(name) \
VMSTATE_UINT64(IT2G_CPREG_VAR_NAME(name), IPodTouchMachineState)
#define IT2G_CPREG_DEF(p_name, p_op0, p_op1, p_crn, p_crm, p_op2, p_access, p_reset) \
{ \
.cp = 15, \
.name = #p_name, .opc0 = p_op0, .crn = p_crn, .crm = p_crm, \
.opc1 = p_op1, .opc2 = p_op2, .access = p_access, .resetvalue = p_reset, \
.state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE, \
.fieldoffset = offsetof(IPodTouchMachineState, IT2G_CPREG_VAR_NAME(p_name)) \
- offsetof(ARMCPU, env) \
}
static void allocate_ram(MemoryRegion *top, const char *name, uint32_t addr, uint32_t size)
{
MemoryRegion *sec = g_new(MemoryRegion, 1);
memory_region_init_ram(sec, NULL, name, size, &error_fatal);
memory_region_add_subregion(top, addr, sec);
}
static const ARMCPRegInfo it2g_cp_reginfo_tcg[] = {
IT2G_CPREG_DEF(REG0, 0, 0, 7, 6, 0, PL1_RW, 0),
IT2G_CPREG_DEF(REG1, 0, 0, 15, 2, 4, PL1_RW, 0),
};
static void ipod_touch_cpu_setup(MachineState *machine, MemoryRegion **sysmem, ARMCPU **cpu, AddressSpace **nsas)
{
Object *cpuobj = object_new(machine->cpu_type);
*cpu = ARM_CPU(cpuobj);
CPUState *cs = CPU(*cpu);
*sysmem = get_system_memory();
object_property_set_link(cpuobj, "memory", OBJECT(*sysmem), &error_abort);
object_property_set_bool(cpuobj, "has_el3", false, NULL);
object_property_set_bool(cpuobj, "has_el2", false, NULL);
object_property_set_bool(cpuobj, "realized", true, &error_fatal);
*nsas = cpu_get_address_space(cs, ARMASIdx_NS);
define_arm_cp_regs(*cpu, it2g_cp_reginfo_tcg);
object_unref(cpuobj);
}
static void ipod_touch_cpu_reset(void *opaque)
{
IPodTouchMachineState *nms = IPOD_TOUCH_MACHINE((MachineState *)opaque);
ARMCPU *cpu = nms->cpu;
CPUState *cs = CPU(cpu);
cpu_reset(cs);
//env->regs[0] = nms->kbootargs_pa;
//cpu_set_pc(CPU(cpu), 0xc00607ec);
cpu_set_pc(CPU(cpu), VROM_MEM_BASE);
//env->regs[0] = 0x9000000;
//cpu_set_pc(CPU(cpu), LLB_BASE + 0x100);
//cpu_set_pc(CPU(cpu), VROM_MEM_BASE);
}
static void ipod_touch_memory_setup(MachineState *machine, MemoryRegion *sysmem, AddressSpace *nsas)
{
IPodTouchMachineState *nms = IPOD_TOUCH_MACHINE(machine);
allocate_ram(sysmem, "sram1", SRAM1_MEM_BASE, 0x100000);
// load the bootrom (vrom)
uint8_t *file_data = NULL;
unsigned long fsize;
if (g_file_get_contents("/Users/martijndevos/Documents/ipod_touch_2g_emulation/bootrom_240_4", (char **)&file_data, &fsize, NULL)) {
allocate_ram(sysmem, "vrom", 0x0, 0x20000);
address_space_rw(nsas, VROM_MEM_BASE, MEMTXATTRS_UNSPECIFIED, (uint8_t *)file_data, fsize, 1);
}
}
static void ipod_touch_instance_init(Object *obj)
{
}
static void ipod_touch_machine_init(MachineState *machine)
{
IPodTouchMachineState *nms = IPOD_TOUCH_MACHINE(machine);
MemoryRegion *sysmem;
AddressSpace *nsas;
ARMCPU *cpu;
ipod_touch_cpu_setup(machine, &sysmem, &cpu, &nsas);
nms->cpu = cpu;
// init clock 0
DeviceState *dev = qdev_new("ipodtouch.clock");
IPodTouchClockState *clock0_state = IPOD_TOUCH_CLOCK(dev);
nms->clock0 = clock0_state;
memory_region_add_subregion(sysmem, CLOCK0_MEM_BASE, &clock0_state->iomem);
// init clock 1
dev = qdev_new("ipodtouch.clock");
IPodTouchClockState *clock1_state = IPOD_TOUCH_CLOCK(dev);
nms->clock1 = clock1_state;
memory_region_add_subregion(sysmem, CLOCK1_MEM_BASE, &clock1_state->iomem);
// init GPIO
dev = qdev_new("ipodtouch.gpio");
IPodTouchGPIOState *gpio_state = IPOD_TOUCH_GPIO(dev);
nms->gpio_state = gpio_state;
memory_region_add_subregion(sysmem, GPIO_MEM_BASE, &gpio_state->iomem);
// init the chip ID module
dev = qdev_new("ipodtouch.chipid");
IPodTouchChipIDState *chipid_state = IPOD_TOUCH_CHIPID(dev);
nms->chipid_state = chipid_state;
memory_region_add_subregion(sysmem, CHIPID_MEM_BASE, &chipid_state->iomem);
ipod_touch_memory_setup(machine, sysmem, nsas);
qemu_register_reset(ipod_touch_cpu_reset, nms);
}
static void ipod_touch_machine_class_init(ObjectClass *klass, void *data)
{
MachineClass *mc = MACHINE_CLASS(klass);
mc->desc = "iPod Touch";
mc->init = ipod_touch_machine_init;
mc->max_cpus = 1;
mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm1176");
}
static const TypeInfo ipod_touch_machine_info = {
.name = TYPE_IPOD_TOUCH_MACHINE,
.parent = TYPE_MACHINE,
.instance_size = sizeof(IPodTouchMachineState),
.class_size = sizeof(IPodTouchMachineClass),
.class_init = ipod_touch_machine_class_init,
.instance_init = ipod_touch_instance_init,
};
static void ipod_touch_machine_types(void)
{
type_register_static(&ipod_touch_machine_info);
}
type_init(ipod_touch_machine_types)
+51
View File
@@ -0,0 +1,51 @@
#include "hw/arm/ipod_touch_chipid.h"
static uint64_t ipod_touch_chipid_read(void *opaque, hwaddr addr, unsigned size)
{
//fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
switch (addr) {
case CHIPID_UNKNOWN1:
return 0;
case CHIPID_INFO:
return (0x8720 << 16) | 0x1;
default:
hw_error("%s: reading from unknown chip ID register 0x%08x\n", __func__, addr);
}
return 0;
}
static const MemoryRegionOps ipod_touch_chipid_ops = {
.read = ipod_touch_chipid_read,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void ipod_touch_chipid_init(Object *obj)
{
IPodTouchChipIDState *s = IPOD_TOUCH_CHIPID(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->iomem, obj, &ipod_touch_chipid_ops, s, TYPE_IPOD_TOUCH_CHIPID, 0x10);
sysbus_init_mmio(sbd, &s->iomem);
}
static void ipod_touch_chipid_class_init(ObjectClass *klass, void *data)
{
}
static const TypeInfo ipod_touch_chipid_type_info = {
.name = TYPE_IPOD_TOUCH_CHIPID,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IPodTouchChipIDState),
.instance_init = ipod_touch_chipid_init,
.class_init = ipod_touch_chipid_class_init,
};
static void ipod_touch_chipid_register_types(void)
{
type_register_static(&ipod_touch_chipid_type_info);
}
type_init(ipod_touch_chipid_register_types)
+139
View File
@@ -0,0 +1,139 @@
#include "hw/arm/ipod_touch_clock.h"
static void s5l8900_clock_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
IPodTouchClockState *s = (struct IPodTouchClockState *) opaque;
switch (addr) {
case CLOCK_CONFIG0:
s->config0 = val;
break;
case CLOCK_CONFIG1:
s->config1 = val;
break;
case CLOCK_CONFIG2:
s->config2 = val;
break;
case CLOCK_CONFIG3:
s->config3 = val;
break;
case CLOCK_CONFIG4:
s->config4 = val;
break;
case CLOCK_CONFIG5:
s->config5 = val;
break;
case CLOCK_PLL0CON:
s->pll0con = val;
break;
case CLOCK_PLL1CON:
s->pll1con = val;
break;
case CLOCK_PLL2CON:
s->pll2con = val;
break;
case CLOCK_PLL3CON:
s->pll3con = val;
break;
case CLOCK_PLL0LCNT:
s->pll0lcnt = val;
break;
case CLOCK_PLL1LCNT:
s->pll1lcnt = val;
break;
case CLOCK_PLL2LCNT:
s->pll2lcnt = val;
break;
case CLOCK_PLL3LCNT:
s->pll3lcnt = val;
break;
case CLOCK_PLLLOCK:
hw_error("%s: Forbidden write to PLLLOCK register 0x%08x\n", __func__, addr);
break;
case CLOCK_PLLMODE:
s->pllmode = val;
break;
case CLOCK_PWRCON0:
s->pwrcon0 = val;
break;
case CLOCK_PWRCON1:
s->pwrcon1 = val;
break;
case CLOCK_PWRCON2:
s->pwrcon2 = val;
break;
case CLOCK_PWRCON3:
s->pwrcon3 = val;
break;
case CLOCK_PWRCON4:
s->pwrcon4 = val;
break;
default:
hw_error("%s: writing value 0x%08x to unknown clock register 0x%08x\n", __func__, val, addr);
}
}
static uint64_t s5l8900_clock_read(void *opaque, hwaddr addr, unsigned size)
{
IPodTouchClockState *s = (struct IPodTouchClockState *) opaque;
switch (addr) {
case CLOCK_CONFIG0:
return s->config0;
case CLOCK_CONFIG1:
return s->config1;
case CLOCK_CONFIG2:
return s->config2;
case CLOCK_PLL0CON:
return s->pll0con;
case CLOCK_PLL1CON:
return s->pll1con;
case CLOCK_PLL2CON:
return s->pll2con;
case CLOCK_PLL3CON:
return s->pll3con;
case CLOCK_PLLLOCK:
return (1 | 2 | 4 | 8); // all PLLs are locked
case CLOCK_PLLMODE:
return s->pllmode;
default:
hw_error("%s: reading from unknown clock register 0x%08x\n", __func__, addr);
}
return 0;
}
static const MemoryRegionOps clock_ops = {
.read = s5l8900_clock_read,
.write = s5l8900_clock_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void s5l8900_clock_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
DeviceState *dev = DEVICE(sbd);
IPodTouchClockState *s = IPOD_TOUCH_CLOCK(dev);
memory_region_init_io(&s->iomem, obj, &clock_ops, s, "clock", 0x80);
}
static void s5l8900_clock_class_init(ObjectClass *klass, void *data)
{
}
static const TypeInfo ipod_touch_clock_info = {
.name = TYPE_IPOD_TOUCH_CLOCK,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IPodTouchClockState),
.instance_init = s5l8900_clock_init,
.class_init = s5l8900_clock_class_init,
};
static void ipod_touch_machine_types(void)
{
type_register_static(&ipod_touch_clock_info);
}
type_init(ipod_touch_machine_types)
+62
View File
@@ -0,0 +1,62 @@
#include "hw/arm/ipod_touch_gpio.h"
static void s5l8900_gpio_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
{
//fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
IPodTouchGPIOState *s = (struct IPodTouchGPIOState *) opaque;
switch(addr) {
default:
break;
}
}
static uint64_t s5l8900_gpio_read(void *opaque, hwaddr addr, unsigned size)
{
//fprintf(stderr, "%s: read from location 0x%08x\n", __func__, addr);
IPodTouchGPIOState *s = (struct IPodTouchGPIOState *) opaque;
switch(addr) {
case 0x2c4:
return s->gpio_state;
default:
break;
}
return 0;
}
static const MemoryRegionOps gpio_ops = {
.read = s5l8900_gpio_read,
.write = s5l8900_gpio_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void s5l8900_gpio_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
DeviceState *dev = DEVICE(sbd);
IPodTouchGPIOState *s = IPOD_TOUCH_GPIO(dev);
memory_region_init_io(&s->iomem, obj, &gpio_ops, s, "gpio", 0x10000);
}
static void s5l8900_gpio_class_init(ObjectClass *klass, void *data)
{
}
static const TypeInfo ipod_touch_gpio_info = {
.name = TYPE_IPOD_TOUCH_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IPodTouchGPIOState),
.instance_init = s5l8900_gpio_init,
.class_init = s5l8900_gpio_class_init,
};
static void ipod_touch_machine_types(void)
{
type_register_static(&ipod_touch_gpio_info);
}
type_init(ipod_touch_machine_types)
+1
View File
@@ -65,6 +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_IPOD_TOUCH_2G', if_true: files('ipod_touch_2g.c', 'ipod_touch_clock.c', 'ipod_touch_chipid.c', 'ipod_touch_gpio.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'))
+44
View File
@@ -0,0 +1,44 @@
#ifndef HW_ARM_IPOD_TOUCH_H
#define HW_ARM_IPOD_TOUCH_H
#include "exec/hwaddr.h"
#include "hw/boards.h"
#include "hw/arm/boot.h"
#include "cpu.h"
#include "hw/arm/ipod_touch_clock.h"
#include "hw/arm/ipod_touch_chipid.h"
#include "hw/arm/ipod_touch_gpio.h"
#define TYPE_IPOD_TOUCH "iPod-Touch"
#define IT2G_CPREG_VAR_NAME(name) cpreg_##name
#define IT2G_CPREG_VAR_DEF(name) uint64_t IT2G_CPREG_VAR_NAME(name)
#define TYPE_IPOD_TOUCH_MACHINE MACHINE_TYPE_NAME(TYPE_IPOD_TOUCH)
#define IPOD_TOUCH_MACHINE(obj) \
OBJECT_CHECK(IPodTouchMachineState, (obj), TYPE_IPOD_TOUCH_MACHINE)
// memory addresses
#define VROM_MEM_BASE 0x0
#define SRAM1_MEM_BASE 0x22020000
#define CLOCK0_MEM_BASE 0x3C500000
#define GPIO_MEM_BASE 0x3CF00000
#define CHIPID_MEM_BASE 0x3D100000
#define CLOCK1_MEM_BASE 0x3E000000
typedef struct {
MachineClass parent;
} IPodTouchMachineClass;
typedef struct {
MachineState parent;
ARMCPU *cpu;
IPodTouchClockState *clock0;
IPodTouchClockState *clock1;
IPodTouchChipIDState *chipid_state;
IPodTouchGPIOState *gpio_state;
IT2G_CPREG_VAR_DEF(REG0);
IT2G_CPREG_VAR_DEF(REG1);
} IPodTouchMachineState;
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef HW_ARM_IPOD_TOUCH_CHIPID_H
#define HW_ARM_IPOD_TOUCH_CHIPID_H
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#define TYPE_IPOD_TOUCH_CHIPID "ipodtouch.chipid"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchChipIDState, IPOD_TOUCH_CHIPID)
#define CHIPID_UNKNOWN1 0x4
#define CHIPID_INFO 0x8
typedef struct IPodTouchChipIDState {
SysBusDevice busdev;
MemoryRegion iomem;
} IPodTouchChipIDState;
#endif
+68
View File
@@ -0,0 +1,68 @@
#ifndef IPOD_TOUCH_CLOCK_H
#define IPOD_TOUCH_CLOCK_H
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/clock.h"
#define TYPE_IPOD_TOUCH_CLOCK "ipodtouch.clock"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchClockState, IPOD_TOUCH_CLOCK)
#define CLOCK_CONFIG0 0x0
#define CLOCK_CONFIG1 0x4
#define CLOCK_CONFIG2 0x8
#define CLOCK_CONFIG3 0xC
#define CLOCK_CONFIG4 0x10
#define CLOCK_CONFIG5 0x14
#define CLOCK_PLL0CON 0x20
#define CLOCK_PLL1CON 0x24
#define CLOCK_PLL2CON 0x28
#define CLOCK_PLL3CON 0x2C
#define CLOCK_PLL0LCNT 0x30
#define CLOCK_PLL1LCNT 0x34
#define CLOCK_PLL2LCNT 0x38
#define CLOCK_PLL3LCNT 0x3C
#define CLOCK_PLLLOCK 0x40
#define CLOCK_PLLMODE 0x44
#define CLOCK_PWRCON0 0x48
#define CLOCK_PWRCON1 0x4C
#define CLOCK_PWRCON2 0x58
#define CLOCK_PWRCON3 0x68
#define CLOCK_PWRCON4 0x6C
typedef struct IPodTouchClockState
{
SysBusDevice busdev;
MemoryRegion iomem;
uint32_t config0;
uint32_t config1;
uint32_t config2;
uint32_t config3;
uint32_t config4;
uint32_t config5;
uint32_t pll0con;
uint32_t pll1con;
uint32_t pll2con;
uint32_t pll3con;
uint32_t pll0lcnt;
uint32_t pll1lcnt;
uint32_t pll2lcnt;
uint32_t pll3lcnt;
uint32_t pllmode;
uint32_t pwrcon0;
uint32_t pwrcon1;
uint32_t pwrcon2;
uint32_t pwrcon3;
uint32_t pwrcon4;
} IPodTouchClockState;
#endif
+28
View File
@@ -0,0 +1,28 @@
#ifndef IPOD_TOUCH_GPIO_H
#define IPOD_TOUCH_GPIO_H
#include <math.h>
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "hw/sysbus.h"
#define TYPE_IPOD_TOUCH_GPIO "ipodtouch.gpio"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchGPIOState, IPOD_TOUCH_GPIO)
#define GPIO_BUTTON_POWER 0x1605
#define GPIO_BUTTON_HOME 0x1606
#define GPIO_BUTTON_POWER_IRQ 0x2D
#define GPIO_BUTTON_HOME_IRQ 0x2E
#define NUM_GPIO_PINS 0x20
typedef struct IPodTouchGPIOState
{
SysBusDevice parent_obj;
MemoryRegion iomem;
uint32_t gpio_state;
} IPodTouchGPIOState;
#endif