mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
target-arm queue:
* code cleanup to use symbolic constants for register bank numbers * fix direct booting of modern Linux kernels on xilinx_zynq by setting SCLR values to what the kernel expects firmware to have done * implement SYSRESETREQ for ARMv7M CPU (stellaris boards) * update MAINTAINERS to mention new qemu-arm mailing list * clean up display of PSTATE in AArch64 debug logs * report Secure/Nonsecure status in CPU debug logs * fix a missing _CCA attribute in ACPI tables * add support for GICv3 to ACPI tables -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWOL2WAAoJEDwlJe0UNgzeJhEQAIZeC9hfomlu1QGVS7HmlzQ6 Vao9PyW9oxNIc91oweCWzVjQConhZW15dZsGwPiRyCa+vrgn2fss/NCBa5w2Rr72 xOSKRl12iXBGDay3GJsvBV/ZHwJTxxvowvEmSRl58IBdRG1Fn823FbHi/b7E8m4k GXWisdJ1C6r0FCS2TodSXAqkwL3fgScbEt5xAM0Zt9tkR+Z6HPMKJ2ZtZY9Kzd6S 47LLcF8Sawffs625TKcIoUxoXhc+SPloqNAWwH7u/ey9vsrpJjUmNxeSkcR1xb8v FTxWXm51D5dZRUFfMio22aYAY9ct7u2l07MAuIQ37rzr3LDMlBMDdZ5sV92Y1EG5 /1SbqWkaWJv4gs2+w6YjuIo3XavMuYnqukZsSvhma891L8KazPISFjwJbLFnh92Y xvcGOCiHAxHFY705laiOMOWCdvsRJBzBDjV7mTqjCM4VSAgQHTyW85vD+41YA7i8 bTUEXLEvL5REODEC1cH31avstW/B+IJr6ReSRV8ZSQTH10JjLlACSvjCwRtlxemV SUbPosOl23g1I78skc/gab2Y/Zs/zniVtMLBUBPN1eTk30kj6ZmkBHF0m4adpHhw 6AtMRlYEnOoTektrkMVk3IQth6FOQIGIyKMX4P27COjMUwFgG9Kiyn/+r6yH+pMZ CjSxuIcPi76HKLv+HWB2 =5aa4 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20151103' into staging target-arm queue: * code cleanup to use symbolic constants for register bank numbers * fix direct booting of modern Linux kernels on xilinx_zynq by setting SCLR values to what the kernel expects firmware to have done * implement SYSRESETREQ for ARMv7M CPU (stellaris boards) * update MAINTAINERS to mention new qemu-arm mailing list * clean up display of PSTATE in AArch64 debug logs * report Secure/Nonsecure status in CPU debug logs * fix a missing _CCA attribute in ACPI tables * add support for GICv3 to ACPI tables # gpg: Signature made Tue 03 Nov 2015 13:58:46 GMT using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" * remotes/pmaydell/tags/pull-target-arm-20151103: ARM: ACPI: Fix MPIDR value in ACPI table hw/arm/virt-acpi-build: Add GICC ACPI subtable for GICv3 hw/arm/virt-acpi-build: _CCA attribute is compulsory target-arm: Report S/NS status in the CPU debug logs target-arm: Bring AArch64 debug CPU display of PSTATE into line with AArch32 MAINTAINERS: Add new qemu-arm mailing list to ARM related entries arm: stellaris: exit on external reset request armv7-m: Implement SYSRESETREQ armv7-m: Return DeviceState* from armv7m_init() arm: xilinx_zynq: Add linux pre-boot arm: boot: Add board specific setup code API arm: boot: Adjust indentation of FIXUP comments target-arm: Add and use symbolic names for register banks Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
79cf9fad34
15 changed files with 251 additions and 93 deletions
|
@ -166,17 +166,15 @@ static void armv7m_reset(void *opaque)
|
|||
mem_size is in bytes.
|
||||
Returns the NVIC array. */
|
||||
|
||||
qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
|
||||
DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
|
||||
const char *kernel_filename, const char *cpu_model)
|
||||
{
|
||||
ARMCPU *cpu;
|
||||
CPUARMState *env;
|
||||
DeviceState *nvic;
|
||||
qemu_irq *pic = g_new(qemu_irq, num_irq);
|
||||
int image_size;
|
||||
uint64_t entry;
|
||||
uint64_t lowaddr;
|
||||
int i;
|
||||
int big_endian;
|
||||
MemoryRegion *hack = g_new(MemoryRegion, 1);
|
||||
|
||||
|
@ -198,9 +196,6 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
|
|||
qdev_init_nofail(nvic);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
|
||||
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
|
||||
for (i = 0; i < num_irq; i++) {
|
||||
pic[i] = qdev_get_gpio_in(nvic, i);
|
||||
}
|
||||
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
big_endian = 1;
|
||||
|
@ -234,7 +229,7 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
|
|||
memory_region_add_subregion(system_memory, 0xfffff000, hack);
|
||||
|
||||
qemu_register_reset(armv7m_reset, cpu);
|
||||
return pic;
|
||||
return nvic;
|
||||
}
|
||||
|
||||
static Property bitband_properties[] = {
|
||||
|
|
|
@ -28,14 +28,15 @@
|
|||
#define KERNEL64_LOAD_ADDR 0x00080000
|
||||
|
||||
typedef enum {
|
||||
FIXUP_NONE = 0, /* do nothing */
|
||||
FIXUP_TERMINATOR, /* end of insns */
|
||||
FIXUP_BOARDID, /* overwrite with board ID number */
|
||||
FIXUP_ARGPTR, /* overwrite with pointer to kernel args */
|
||||
FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */
|
||||
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
|
||||
FIXUP_BOOTREG, /* overwrite with boot register address */
|
||||
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
|
||||
FIXUP_NONE = 0, /* do nothing */
|
||||
FIXUP_TERMINATOR, /* end of insns */
|
||||
FIXUP_BOARDID, /* overwrite with board ID number */
|
||||
FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
|
||||
FIXUP_ARGPTR, /* overwrite with pointer to kernel args */
|
||||
FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */
|
||||
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
|
||||
FIXUP_BOOTREG, /* overwrite with boot register address */
|
||||
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
|
||||
FIXUP_MAX,
|
||||
} FixupType;
|
||||
|
||||
|
@ -58,8 +59,17 @@ static const ARMInsnFixup bootloader_aarch64[] = {
|
|||
{ 0, FIXUP_TERMINATOR }
|
||||
};
|
||||
|
||||
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
|
||||
/* A very small bootloader: call the board-setup code (if needed),
|
||||
* set r0-r2, then jump to the kernel.
|
||||
* If we're not calling boot setup code then we don't copy across
|
||||
* the first BOOTLOADER_NO_BOARD_SETUP_OFFSET insns in this array.
|
||||
*/
|
||||
|
||||
static const ARMInsnFixup bootloader[] = {
|
||||
{ 0xe28fe008 }, /* add lr, pc, #8 */
|
||||
{ 0xe51ff004 }, /* ldr pc, [pc, #-4] */
|
||||
{ 0, FIXUP_BOARD_SETUP },
|
||||
#define BOOTLOADER_NO_BOARD_SETUP_OFFSET 3
|
||||
{ 0xe3a00000 }, /* mov r0, #0 */
|
||||
{ 0xe59f1004 }, /* ldr r1, [pc, #4] */
|
||||
{ 0xe59f2004 }, /* ldr r2, [pc, #4] */
|
||||
|
@ -131,6 +141,7 @@ static void write_bootloader(const char *name, hwaddr addr,
|
|||
case FIXUP_NONE:
|
||||
break;
|
||||
case FIXUP_BOARDID:
|
||||
case FIXUP_BOARD_SETUP:
|
||||
case FIXUP_ARGPTR:
|
||||
case FIXUP_ENTRYPOINT:
|
||||
case FIXUP_GIC_CPU_IF:
|
||||
|
@ -640,6 +651,9 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
|
|||
elf_machine = EM_AARCH64;
|
||||
} else {
|
||||
primary_loader = bootloader;
|
||||
if (!info->write_board_setup) {
|
||||
primary_loader += BOOTLOADER_NO_BOARD_SETUP_OFFSET;
|
||||
}
|
||||
kernel_load_offset = KERNEL_LOAD_ADDR;
|
||||
elf_machine = EM_ARM;
|
||||
}
|
||||
|
@ -745,6 +759,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
|
|||
info->initrd_size = initrd_size;
|
||||
|
||||
fixupcontext[FIXUP_BOARDID] = info->board_id;
|
||||
fixupcontext[FIXUP_BOARD_SETUP] = info->board_setup_addr;
|
||||
|
||||
/* for device tree boot, we pass the DTB directly in r2. Otherwise
|
||||
* we point to the kernel args.
|
||||
|
@ -793,6 +808,9 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
|
|||
if (info->nb_cpus > 1) {
|
||||
info->write_secondary_boot(cpu, info);
|
||||
}
|
||||
if (info->write_board_setup) {
|
||||
info->write_board_setup(cpu, info);
|
||||
}
|
||||
|
||||
/* Notify devices which need to fake up firmware initialization
|
||||
* that we're doing a direct kernel boot.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "net/net.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#define GPIO_A 0
|
||||
#define GPIO_B 1
|
||||
|
@ -1176,6 +1177,14 @@ static int stellaris_adc_init(SysBusDevice *sbd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void do_sys_reset(void *opaque, int n, int level)
|
||||
{
|
||||
if (level) {
|
||||
qemu_system_reset_request();
|
||||
}
|
||||
}
|
||||
|
||||
/* Board init. */
|
||||
static stellaris_board_info stellaris_boards[] = {
|
||||
{ "LM3S811EVB",
|
||||
|
@ -1210,8 +1219,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||
0x40024000, 0x40025000, 0x40026000};
|
||||
static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
|
||||
|
||||
qemu_irq *pic;
|
||||
DeviceState *gpio_dev[7];
|
||||
DeviceState *gpio_dev[7], *nvic;
|
||||
qemu_irq gpio_in[7][8];
|
||||
qemu_irq gpio_out[7][8];
|
||||
qemu_irq adc;
|
||||
|
@ -1241,12 +1249,19 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||
vmstate_register_ram_global(sram);
|
||||
memory_region_add_subregion(system_memory, 0x20000000, sram);
|
||||
|
||||
pic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES,
|
||||
nvic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES,
|
||||
kernel_filename, cpu_model);
|
||||
|
||||
qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0,
|
||||
qemu_allocate_irq(&do_sys_reset, NULL, 0));
|
||||
|
||||
if (board->dc1 & (1 << 16)) {
|
||||
dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000,
|
||||
pic[14], pic[15], pic[16], pic[17], NULL);
|
||||
qdev_get_gpio_in(nvic, 14),
|
||||
qdev_get_gpio_in(nvic, 15),
|
||||
qdev_get_gpio_in(nvic, 16),
|
||||
qdev_get_gpio_in(nvic, 17),
|
||||
NULL);
|
||||
adc = qdev_get_gpio_in(dev, 0);
|
||||
} else {
|
||||
adc = NULL;
|
||||
|
@ -1255,19 +1270,21 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||
if (board->dc2 & (0x10000 << i)) {
|
||||
dev = sysbus_create_simple(TYPE_STELLARIS_GPTM,
|
||||
0x40030000 + i * 0x1000,
|
||||
pic[timer_irq[i]]);
|
||||
qdev_get_gpio_in(nvic, timer_irq[i]));
|
||||
/* TODO: This is incorrect, but we get away with it because
|
||||
the ADC output is only ever pulsed. */
|
||||
qdev_connect_gpio_out(dev, 0, adc);
|
||||
}
|
||||
}
|
||||
|
||||
stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a);
|
||||
stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
|
||||
board, nd_table[0].macaddr.a);
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (board->dc4 & (1 << i)) {
|
||||
gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i],
|
||||
pic[gpio_irq[i]]);
|
||||
qdev_get_gpio_in(nvic,
|
||||
gpio_irq[i]));
|
||||
for (j = 0; j < 8; j++) {
|
||||
gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j);
|
||||
gpio_out[i][j] = NULL;
|
||||
|
@ -1276,7 +1293,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||
}
|
||||
|
||||
if (board->dc2 & (1 << 12)) {
|
||||
dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000, pic[8]);
|
||||
dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000,
|
||||
qdev_get_gpio_in(nvic, 8));
|
||||
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
|
||||
if (board->peripherals & BP_OLED_I2C) {
|
||||
i2c_create_slave(i2c, "ssd0303", 0x3d);
|
||||
|
@ -1286,11 +1304,12 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||
for (i = 0; i < 4; i++) {
|
||||
if (board->dc2 & (1 << i)) {
|
||||
sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
|
||||
pic[uart_irq[i]]);
|
||||
qdev_get_gpio_in(nvic, uart_irq[i]));
|
||||
}
|
||||
}
|
||||
if (board->dc2 & (1 << 4)) {
|
||||
dev = sysbus_create_simple("pl022", 0x40008000, pic[7]);
|
||||
dev = sysbus_create_simple("pl022", 0x40008000,
|
||||
qdev_get_gpio_in(nvic, 7));
|
||||
if (board->peripherals & BP_OLED_SSI) {
|
||||
void *bus;
|
||||
DeviceState *sddev;
|
||||
|
@ -1326,7 +1345,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||
qdev_set_nic_properties(enet, &nd_table[0]);
|
||||
qdev_init_nofail(enet);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, qdev_get_gpio_in(nvic, 42));
|
||||
}
|
||||
if (board->peripherals & BP_GAMEPAD) {
|
||||
qemu_irq gpad_irq[5];
|
||||
|
|
|
@ -59,9 +59,8 @@ static void stm32f205_soc_initfn(Object *obj)
|
|||
static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
{
|
||||
STM32F205State *s = STM32F205_SOC(dev_soc);
|
||||
DeviceState *syscfgdev, *usartdev, *timerdev;
|
||||
DeviceState *syscfgdev, *usartdev, *timerdev, *nvic;
|
||||
SysBusDevice *syscfgbusdev, *usartbusdev, *timerbusdev;
|
||||
qemu_irq *pic;
|
||||
Error *err = NULL;
|
||||
int i;
|
||||
|
||||
|
@ -88,8 +87,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||
vmstate_register_ram_global(sram);
|
||||
memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
|
||||
|
||||
pic = armv7m_init(get_system_memory(), FLASH_SIZE, 96,
|
||||
s->kernel_filename, s->cpu_model);
|
||||
nvic = armv7m_init(get_system_memory(), FLASH_SIZE, 96,
|
||||
s->kernel_filename, s->cpu_model);
|
||||
|
||||
/* System configuration controller */
|
||||
syscfgdev = DEVICE(&s->syscfg);
|
||||
|
@ -100,7 +99,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||
}
|
||||
syscfgbusdev = SYS_BUS_DEVICE(syscfgdev);
|
||||
sysbus_mmio_map(syscfgbusdev, 0, 0x40013800);
|
||||
sysbus_connect_irq(syscfgbusdev, 0, pic[71]);
|
||||
sysbus_connect_irq(syscfgbusdev, 0, qdev_get_gpio_in(nvic, 71));
|
||||
|
||||
/* Attach UART (uses USART registers) and USART controllers */
|
||||
for (i = 0; i < STM_NUM_USARTS; i++) {
|
||||
|
@ -112,7 +111,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||
}
|
||||
usartbusdev = SYS_BUS_DEVICE(usartdev);
|
||||
sysbus_mmio_map(usartbusdev, 0, usart_addr[i]);
|
||||
sysbus_connect_irq(usartbusdev, 0, pic[usart_irq[i]]);
|
||||
sysbus_connect_irq(usartbusdev, 0,
|
||||
qdev_get_gpio_in(nvic, usart_irq[i]));
|
||||
}
|
||||
|
||||
/* Timer 2 to 5 */
|
||||
|
@ -126,7 +126,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||
}
|
||||
timerbusdev = SYS_BUS_DEVICE(timerdev);
|
||||
sysbus_mmio_map(timerbusdev, 0, timer_addr[i]);
|
||||
sysbus_connect_irq(timerbusdev, 0, pic[timer_irq[i]]);
|
||||
sysbus_connect_irq(timerbusdev, 0,
|
||||
qdev_get_gpio_in(nvic, timer_irq[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
|
|||
aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
|
||||
aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
|
||||
aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
|
||||
aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
|
||||
|
||||
/* Declare the PCI Routing Table. */
|
||||
Aml *rt_pkg = aml_package(nr_pcie_buses * PCI_NUM_PINS);
|
||||
|
@ -448,6 +449,24 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info,
|
|||
gicd->length = sizeof(*gicd);
|
||||
gicd->base_address = memmap[VIRT_GIC_DIST].base;
|
||||
|
||||
for (i = 0; i < guest_info->smp_cpus; i++) {
|
||||
AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data,
|
||||
sizeof *gicc);
|
||||
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
|
||||
|
||||
gicc->type = ACPI_APIC_GENERIC_INTERRUPT;
|
||||
gicc->length = sizeof(*gicc);
|
||||
if (guest_info->gic_version == 2) {
|
||||
gicc->base_address = memmap[VIRT_GIC_CPU].base;
|
||||
}
|
||||
gicc->cpu_interface_number = i;
|
||||
gicc->arm_mpidr = armcpu->mp_affinity;
|
||||
gicc->uid = i;
|
||||
if (test_bit(i, cpuinfo->found_cpus)) {
|
||||
gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
if (guest_info->gic_version == 3) {
|
||||
AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
|
||||
sizeof *gicr);
|
||||
|
@ -457,20 +476,6 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info,
|
|||
gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
|
||||
gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
|
||||
} else {
|
||||
for (i = 0; i < guest_info->smp_cpus; i++) {
|
||||
AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data,
|
||||
sizeof *gicc);
|
||||
gicc->type = ACPI_APIC_GENERIC_INTERRUPT;
|
||||
gicc->length = sizeof(*gicc);
|
||||
gicc->base_address = memmap[VIRT_GIC_CPU].base;
|
||||
gicc->cpu_interface_number = i;
|
||||
gicc->arm_mpidr = i;
|
||||
gicc->uid = i;
|
||||
if (test_bit(i, cpuinfo->found_cpus)) {
|
||||
gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
|
||||
gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
|
||||
gic_msi->length = sizeof(*gic_msi);
|
||||
|
|
|
@ -43,6 +43,45 @@ static const int dma_irqs[8] = {
|
|||
46, 47, 48, 49, 72, 73, 74, 75
|
||||
};
|
||||
|
||||
#define BOARD_SETUP_ADDR 0x100
|
||||
|
||||
#define SLCR_LOCK_OFFSET 0x004
|
||||
#define SLCR_UNLOCK_OFFSET 0x008
|
||||
#define SLCR_ARM_PLL_OFFSET 0x100
|
||||
|
||||
#define SLCR_XILINX_UNLOCK_KEY 0xdf0d
|
||||
#define SLCR_XILINX_LOCK_KEY 0x767b
|
||||
|
||||
#define ARMV7_IMM16(x) (extract32((x), 0, 12) | \
|
||||
extract32((x), 12, 4) << 16)
|
||||
|
||||
/* Write immediate val to address r0 + addr. r0 should contain base offset
|
||||
* of the SLCR block. Clobbers r1.
|
||||
*/
|
||||
|
||||
#define SLCR_WRITE(addr, val) \
|
||||
0xe3001000 + ARMV7_IMM16(extract32((val), 0, 16)), /* movw r1 ... */ \
|
||||
0xe3401000 + ARMV7_IMM16(extract32((val), 16, 16)), /* movt r1 ... */ \
|
||||
0xe5801000 + (addr)
|
||||
|
||||
static void zynq_write_board_setup(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info)
|
||||
{
|
||||
int n;
|
||||
uint32_t board_setup_blob[] = {
|
||||
0xe3a004f8, /* mov r0, #0xf8000000 */
|
||||
SLCR_WRITE(SLCR_UNLOCK_OFFSET, SLCR_XILINX_UNLOCK_KEY),
|
||||
SLCR_WRITE(SLCR_ARM_PLL_OFFSET, 0x00014008),
|
||||
SLCR_WRITE(SLCR_LOCK_OFFSET, SLCR_XILINX_LOCK_KEY),
|
||||
0xe12fff1e, /* bx lr */
|
||||
};
|
||||
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
|
||||
board_setup_blob[n] = tswap32(board_setup_blob[n]);
|
||||
}
|
||||
rom_add_blob_fixed("board-setup", board_setup_blob,
|
||||
sizeof(board_setup_blob), BOARD_SETUP_ADDR);
|
||||
}
|
||||
|
||||
static struct arm_boot_info zynq_binfo = {};
|
||||
|
||||
static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
|
||||
|
@ -252,6 +291,9 @@ static void zynq_init(MachineState *machine)
|
|||
zynq_binfo.nb_cpus = 1;
|
||||
zynq_binfo.board_id = 0xd32;
|
||||
zynq_binfo.loader_start = 0;
|
||||
zynq_binfo.board_setup_addr = BOARD_SETUP_ADDR;
|
||||
zynq_binfo.write_board_setup = zynq_write_board_setup;
|
||||
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef struct {
|
|||
MemoryRegion gic_iomem_alias;
|
||||
MemoryRegion container;
|
||||
uint32_t num_irq;
|
||||
qemu_irq sysresetreq;
|
||||
} nvic_state;
|
||||
|
||||
#define TYPE_NVIC "armv7m_nvic"
|
||||
|
@ -348,10 +349,13 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
|
|||
break;
|
||||
case 0xd0c: /* Application Interrupt/Reset Control. */
|
||||
if ((value >> 16) == 0x05fa) {
|
||||
if (value & 4) {
|
||||
qemu_irq_pulse(s->sysresetreq);
|
||||
}
|
||||
if (value & 2) {
|
||||
qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
|
||||
}
|
||||
if (value & 5) {
|
||||
if (value & 1) {
|
||||
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
|
||||
}
|
||||
if (value & 0x700) {
|
||||
|
@ -535,11 +539,14 @@ static void armv7m_nvic_instance_init(Object *obj)
|
|||
* value in the GICState struct.
|
||||
*/
|
||||
GICState *s = ARM_GIC_COMMON(obj);
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
nvic_state *nvic = NVIC(obj);
|
||||
/* The ARM v7m may have anything from 0 to 496 external interrupt
|
||||
* IRQ lines. We default to 64. Other boards may differ and should
|
||||
* set the num-irq property appropriately.
|
||||
*/
|
||||
s->num_irq = 64;
|
||||
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
|
||||
}
|
||||
|
||||
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue