target-arm queue:
* fsl-imx6: Fix incorrect Ethernet interrupt defines * dump: Update correct kdump phys_base field for AArch64 * char: i.MX: Add support for "TX complete" interrupt * bcm2836/raspi: Fix various bugs resulting in panics trying to boot a Debian Linux kernel on raspi3 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJasAHJAAoJEDwlJe0UNgzew+AP+gK+v7Dmoql+8uOipAfZYPSA C6MjjvB+pJ8mj8GC9o8Kz8AOotw+GTC3sBW0Iktxx3GsGg7uCSN2fpUevzBkgUps ZMv74HDgPHc2Q5HO07+0ihNcEZvVmnq4XnozYmEm4BkiCCpyzFyMUhow9qF3xBLB QVFBdgz5lGljVw+b6o4szyxCePMST9K4Q1ZNHe70Yy2eKzEKgYXPJqt7M+Q4tEM8 fBPlphqttANxFnSXxzZzleWwNHkUDsEtGUu6Qcamh+6AHkMcyzrpiOFEy5a+Lz3t YDhUE5uzkPpHqXgzYFwQrPafaZQNb/aID1buTr2dHepOcGdgu0J0IqxuPrSehsw5 DlmIVMGN1rXvdHnQUpfR2apWJrKYA65mQVGKyAVGDBJrWAN4l7cDSvv7hdEs4Q7h a5zmxsWq5hoiVCI4gYnw1OWnzsBw1t8DDWAzdx8GdmtOyG47eMc6zG/NFz4IPu4I NPitFU6jxZ5/MEGtGaVYuvWLVokAbLBZH1Py7wdMkDiYDftzVzc6pU8FVh8BnpJi x271ZszalM+IhZNBRVnyrFHv+jXcAo/uoApdQBn4D8RHII0U+TJnf9EJHeDataJP QUuXTjsP8LeDvcrHpTANp36ljLu424wXWhMzE+zVNTauFJxpoyNnjv6rCSOShjv6 n5zR7rzfpDJ2cMbs86cz =eWl1 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180319' into staging target-arm queue: * fsl-imx6: Fix incorrect Ethernet interrupt defines * dump: Update correct kdump phys_base field for AArch64 * char: i.MX: Add support for "TX complete" interrupt * bcm2836/raspi: Fix various bugs resulting in panics trying to boot a Debian Linux kernel on raspi3 # gpg: Signature made Mon 19 Mar 2018 18:30:33 GMT # gpg: using RSA key 3C2525ED14360CDE # 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>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180319: hw/arm/raspi: Provide spin-loop code for AArch64 CPUs hw/arm/bcm2836: Hardcode correct CPU type hw/arm/bcm2836: Use correct affinity values for BCM2837 hw/arm/bcm2836: Create proper bcm2837 device hw/arm/bcm2836: Rename bcm2836 type/struct to bcm283x hw/arm/bcm2386: Fix parent type of bcm2386 hw/arm/boot: If booting a kernel in EL2, set SCR_EL3.HCE hw/arm/boot: assert that secure_boot and secure_board_setup are false for AArch64 hw/arm/raspi: Don't do board-setup or secure-boot for raspi3 char: i.MX: Add support for "TX complete" interrupt char: i.MX: Simplify imx_update() dump: Update correct kdump phys_base field for AArch64 fsl-imx6: Swap Ethernet interrupt defines Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c26ef39204
14
dump.c
14
dump.c
@ -1609,10 +1609,18 @@ static void vmcoreinfo_update_phys_base(DumpState *s)
|
||||
|
||||
lines = g_strsplit((char *)vmci, "\n", -1);
|
||||
for (i = 0; lines[i]; i++) {
|
||||
if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) {
|
||||
if (qemu_strtou64(lines[i] + 18, NULL, 16,
|
||||
const char *prefix = NULL;
|
||||
|
||||
if (s->dump_info.d_machine == EM_X86_64) {
|
||||
prefix = "NUMBER(phys_base)=";
|
||||
} else if (s->dump_info.d_machine == EM_AARCH64) {
|
||||
prefix = "NUMBER(PHYS_OFFSET)=";
|
||||
}
|
||||
|
||||
if (prefix && g_str_has_prefix(lines[i], prefix)) {
|
||||
if (qemu_strtou64(lines[i] + strlen(prefix), NULL, 16,
|
||||
&phys_base) < 0) {
|
||||
warn_report("Failed to read NUMBER(phys_base)=");
|
||||
warn_report("Failed to read %s", prefix);
|
||||
} else {
|
||||
s->dump_info.phys_base = phys_base;
|
||||
}
|
||||
|
@ -23,9 +23,40 @@
|
||||
/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
|
||||
#define BCM2836_CONTROL_BASE 0x40000000
|
||||
|
||||
struct BCM283XInfo {
|
||||
const char *name;
|
||||
const char *cpu_type;
|
||||
int clusterid;
|
||||
};
|
||||
|
||||
static const BCM283XInfo bcm283x_socs[] = {
|
||||
{
|
||||
.name = TYPE_BCM2836,
|
||||
.cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"),
|
||||
.clusterid = 0xf,
|
||||
},
|
||||
#ifdef TARGET_AARCH64
|
||||
{
|
||||
.name = TYPE_BCM2837,
|
||||
.cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
|
||||
.clusterid = 0x0,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static void bcm2836_init(Object *obj)
|
||||
{
|
||||
BCM2836State *s = BCM2836(obj);
|
||||
BCM283XState *s = BCM283X(obj);
|
||||
BCM283XClass *bc = BCM283X_GET_CLASS(obj);
|
||||
const BCM283XInfo *info = bc->info;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < BCM283X_NCPUS; n++) {
|
||||
object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
|
||||
info->cpu_type);
|
||||
object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
|
||||
object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
|
||||
@ -44,21 +75,15 @@ static void bcm2836_init(Object *obj)
|
||||
|
||||
static void bcm2836_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
BCM2836State *s = BCM2836(dev);
|
||||
BCM283XState *s = BCM283X(dev);
|
||||
BCM283XClass *bc = BCM283X_GET_CLASS(dev);
|
||||
const BCM283XInfo *info = bc->info;
|
||||
Object *obj;
|
||||
Error *err = NULL;
|
||||
int n;
|
||||
|
||||
/* common peripherals from bcm2835 */
|
||||
|
||||
obj = OBJECT(dev);
|
||||
for (n = 0; n < BCM2836_NCPUS; n++) {
|
||||
object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
|
||||
s->cpu_type);
|
||||
object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
obj = object_property_get_link(OBJECT(dev), "ram", &err);
|
||||
if (obj == NULL) {
|
||||
error_setg(errp, "%s: required ram link not found: %s",
|
||||
@ -102,11 +127,9 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
|
||||
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
|
||||
|
||||
for (n = 0; n < BCM2836_NCPUS; n++) {
|
||||
/* Mirror bcm2836, which has clusterid set to 0xf
|
||||
* TODO: this should be converted to a property of ARM_CPU
|
||||
*/
|
||||
s->cpus[n].mp_affinity = 0xF00 | n;
|
||||
for (n = 0; n < BCM283X_NCPUS; n++) {
|
||||
/* TODO: this should be converted to a property of ARM_CPU */
|
||||
s->cpus[n].mp_affinity = (info->clusterid << 8) | n;
|
||||
|
||||
/* set periphbase/CBAR value for CPU-local registers */
|
||||
object_property_set_int(OBJECT(&s->cpus[n]),
|
||||
@ -150,30 +173,44 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
static Property bcm2836_props[] = {
|
||||
DEFINE_PROP_STRING("cpu-type", BCM2836State, cpu_type),
|
||||
DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, BCM2836_NCPUS),
|
||||
DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
|
||||
BCM283X_NCPUS),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void bcm2836_class_init(ObjectClass *oc, void *data)
|
||||
static void bcm283x_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
BCM283XClass *bc = BCM283X_CLASS(oc);
|
||||
|
||||
dc->props = bcm2836_props;
|
||||
bc->info = data;
|
||||
dc->realize = bcm2836_realize;
|
||||
dc->props = bcm2836_props;
|
||||
}
|
||||
|
||||
static const TypeInfo bcm2836_type_info = {
|
||||
.name = TYPE_BCM2836,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(BCM2836State),
|
||||
static const TypeInfo bcm283x_type_info = {
|
||||
.name = TYPE_BCM283X,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(BCM283XState),
|
||||
.instance_init = bcm2836_init,
|
||||
.class_init = bcm2836_class_init,
|
||||
.class_size = sizeof(BCM283XClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void bcm2836_register_types(void)
|
||||
{
|
||||
type_register_static(&bcm2836_type_info);
|
||||
int i;
|
||||
|
||||
type_register_static(&bcm283x_type_info);
|
||||
for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) {
|
||||
TypeInfo ti = {
|
||||
.name = bcm283x_socs[i].name,
|
||||
.parent = TYPE_BCM283X,
|
||||
.class_init = bcm283x_class_init,
|
||||
.class_data = (void *) &bcm283x_socs[i],
|
||||
};
|
||||
type_register(&ti);
|
||||
}
|
||||
}
|
||||
|
||||
type_init(bcm2836_register_types)
|
||||
|
@ -720,6 +720,18 @@ static void do_cpu_reset(void *opaque)
|
||||
} else {
|
||||
env->pstate = PSTATE_MODE_EL1h;
|
||||
}
|
||||
/* AArch64 kernels never boot in secure mode */
|
||||
assert(!info->secure_boot);
|
||||
/* This hook is only supported for AArch32 currently:
|
||||
* bootloader_aarch64[] will not call the hook, and
|
||||
* the code above has already dropped us into EL2 or EL1.
|
||||
*/
|
||||
assert(!info->secure_board_setup);
|
||||
}
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_EL2)) {
|
||||
/* If we have EL2 then Linux expects the HVC insn to work */
|
||||
env->cp15.scr_el3 |= SCR_HCE;
|
||||
}
|
||||
|
||||
/* Set to non-secure if not a secure boot */
|
||||
|
@ -27,12 +27,13 @@
|
||||
#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
|
||||
#define FIRMWARE_ADDR_2 0x8000 /* Pi 2 loads kernel.img here by default */
|
||||
#define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */
|
||||
#define SPINTABLE_ADDR 0xd8 /* Pi 3 bootloader spintable */
|
||||
|
||||
/* Table of Linux board IDs for different Pi versions */
|
||||
static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
|
||||
|
||||
typedef struct RasPiState {
|
||||
BCM2836State soc;
|
||||
BCM283XState soc;
|
||||
MemoryRegion ram;
|
||||
} RasPiState;
|
||||
|
||||
@ -63,6 +64,40 @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
info->smp_loader_start);
|
||||
}
|
||||
|
||||
static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
{
|
||||
/* Unlike the AArch32 version we don't need to call the board setup hook.
|
||||
* The mechanism for doing the spin-table is also entirely different.
|
||||
* We must have four 64-bit fields at absolute addresses
|
||||
* 0xd8, 0xe0, 0xe8, 0xf0 in RAM, which are the flag variables for
|
||||
* our CPUs, and which we must ensure are zero initialized before
|
||||
* the primary CPU goes into the kernel. We put these variables inside
|
||||
* a rom blob, so that the reset for ROM contents zeroes them for us.
|
||||
*/
|
||||
static const uint32_t smpboot[] = {
|
||||
0xd2801b05, /* mov x5, 0xd8 */
|
||||
0xd53800a6, /* mrs x6, mpidr_el1 */
|
||||
0x924004c6, /* and x6, x6, #0x3 */
|
||||
0xd503205f, /* spin: wfe */
|
||||
0xf86678a4, /* ldr x4, [x5,x6,lsl #3] */
|
||||
0xb4ffffc4, /* cbz x4, spin */
|
||||
0xd2800000, /* mov x0, #0x0 */
|
||||
0xd2800001, /* mov x1, #0x0 */
|
||||
0xd2800002, /* mov x2, #0x0 */
|
||||
0xd2800003, /* mov x3, #0x0 */
|
||||
0xd61f0080, /* br x4 */
|
||||
};
|
||||
|
||||
static const uint64_t spintables[] = {
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
|
||||
info->smp_loader_start);
|
||||
rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables),
|
||||
SPINTABLE_ADDR);
|
||||
}
|
||||
|
||||
static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
{
|
||||
arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
|
||||
@ -82,15 +117,28 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
|
||||
binfo.board_id = raspi_boardid[version];
|
||||
binfo.ram_size = ram_size;
|
||||
binfo.nb_cpus = smp_cpus;
|
||||
binfo.board_setup_addr = BOARDSETUP_ADDR;
|
||||
binfo.write_board_setup = write_board_setup;
|
||||
binfo.secure_board_setup = true;
|
||||
binfo.secure_boot = true;
|
||||
|
||||
if (version <= 2) {
|
||||
/* The rpi1 and 2 require some custom setup code to run in Secure
|
||||
* mode before booting a kernel (to set up the SMC vectors so
|
||||
* that we get a no-op SMC; this is used by Linux to call the
|
||||
* firmware for some cache maintenance operations.
|
||||
* The rpi3 doesn't need this.
|
||||
*/
|
||||
binfo.board_setup_addr = BOARDSETUP_ADDR;
|
||||
binfo.write_board_setup = write_board_setup;
|
||||
binfo.secure_board_setup = true;
|
||||
binfo.secure_boot = true;
|
||||
}
|
||||
|
||||
/* Pi2 and Pi3 requires SMP setup */
|
||||
if (version >= 2) {
|
||||
binfo.smp_loader_start = SMPBOOT_ADDR;
|
||||
binfo.write_secondary_boot = write_smpboot;
|
||||
if (version == 2) {
|
||||
binfo.write_secondary_boot = write_smpboot;
|
||||
} else {
|
||||
binfo.write_secondary_boot = write_smpboot64;
|
||||
}
|
||||
binfo.secondary_cpu_reset_hook = reset_secondary;
|
||||
}
|
||||
|
||||
@ -127,7 +175,8 @@ static void raspi_init(MachineState *machine, int version)
|
||||
BusState *bus;
|
||||
DeviceState *carddev;
|
||||
|
||||
object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM2836);
|
||||
object_initialize(&s->soc, sizeof(s->soc),
|
||||
version == 3 ? TYPE_BCM2837 : TYPE_BCM2836);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
|
||||
&error_abort);
|
||||
|
||||
@ -140,8 +189,6 @@ static void raspi_init(MachineState *machine, int version)
|
||||
/* Setup the SOC */
|
||||
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
|
||||
&error_abort);
|
||||
object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
|
||||
&error_abort);
|
||||
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
|
||||
@ -180,9 +227,9 @@ static void raspi2_machine_init(MachineClass *mc)
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
|
||||
mc->max_cpus = BCM2836_NCPUS;
|
||||
mc->min_cpus = BCM2836_NCPUS;
|
||||
mc->default_cpus = BCM2836_NCPUS;
|
||||
mc->max_cpus = BCM283X_NCPUS;
|
||||
mc->min_cpus = BCM283X_NCPUS;
|
||||
mc->default_cpus = BCM283X_NCPUS;
|
||||
mc->default_ram_size = 1024 * 1024 * 1024;
|
||||
mc->ignore_memory_transaction_failures = true;
|
||||
};
|
||||
@ -203,9 +250,9 @@ static void raspi3_machine_init(MachineClass *mc)
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
|
||||
mc->max_cpus = BCM2836_NCPUS;
|
||||
mc->min_cpus = BCM2836_NCPUS;
|
||||
mc->default_cpus = BCM2836_NCPUS;
|
||||
mc->max_cpus = BCM283X_NCPUS;
|
||||
mc->min_cpus = BCM283X_NCPUS;
|
||||
mc->default_cpus = BCM283X_NCPUS;
|
||||
mc->default_ram_size = 1024 * 1024 * 1024;
|
||||
}
|
||||
DEFINE_MACHINE("raspi3", raspi3_machine_init)
|
||||
|
@ -37,8 +37,8 @@
|
||||
|
||||
static const VMStateDescription vmstate_imx_serial = {
|
||||
.name = TYPE_IMX_SERIAL,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32(readbuff, IMXSerialState),
|
||||
VMSTATE_UINT32(usr1, IMXSerialState),
|
||||
@ -50,22 +50,36 @@ static const VMStateDescription vmstate_imx_serial = {
|
||||
VMSTATE_UINT32(ubmr, IMXSerialState),
|
||||
VMSTATE_UINT32(ubrc, IMXSerialState),
|
||||
VMSTATE_UINT32(ucr3, IMXSerialState),
|
||||
VMSTATE_UINT32(ucr4, IMXSerialState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
static void imx_update(IMXSerialState *s)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t usr1;
|
||||
uint32_t usr2;
|
||||
uint32_t mask;
|
||||
|
||||
flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
|
||||
if (s->ucr1 & UCR1_TXMPTYEN) {
|
||||
flags |= (s->uts1 & UTS1_TXEMPTY);
|
||||
} else {
|
||||
flags &= ~USR1_TRDY;
|
||||
}
|
||||
/*
|
||||
* Lucky for us TRDY and RRDY has the same offset in both USR1 and
|
||||
* UCR1, so we can get away with something as simple as the
|
||||
* following:
|
||||
*/
|
||||
usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY);
|
||||
/*
|
||||
* Bits that we want in USR2 are not as conveniently laid out,
|
||||
* unfortunately.
|
||||
*/
|
||||
mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
|
||||
/*
|
||||
* TCEN and TXDC are both bit 3
|
||||
*/
|
||||
mask |= s->ucr4 & UCR4_TCEN;
|
||||
|
||||
qemu_set_irq(s->irq, !!flags);
|
||||
usr2 = s->usr2 & mask;
|
||||
|
||||
qemu_set_irq(s->irq, usr1 || usr2);
|
||||
}
|
||||
|
||||
static void imx_serial_reset(IMXSerialState *s)
|
||||
@ -155,6 +169,8 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
|
||||
return s->ucr3;
|
||||
|
||||
case 0x23: /* UCR4 */
|
||||
return s->ucr4;
|
||||
|
||||
case 0x29: /* BRM Incremental */
|
||||
return 0x0; /* TODO */
|
||||
|
||||
@ -183,8 +199,10 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->usr1 &= ~USR1_TRDY;
|
||||
s->usr2 &= ~USR2_TXDC;
|
||||
imx_update(s);
|
||||
s->usr1 |= USR1_TRDY;
|
||||
s->usr2 |= USR2_TXDC;
|
||||
imx_update(s);
|
||||
}
|
||||
break;
|
||||
@ -257,8 +275,12 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
s->ucr3 = value & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x2d: /* UTS1 */
|
||||
case 0x23: /* UCR4 */
|
||||
s->ucr4 = value & 0xffff;
|
||||
imx_update(s);
|
||||
break;
|
||||
|
||||
case 0x2d: /* UTS1 */
|
||||
qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
|
||||
HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
|
||||
/* TODO */
|
||||
|
@ -417,7 +417,33 @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
|
||||
|
||||
static void imx_eth_update(IMXFECState *s)
|
||||
{
|
||||
if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_TS_TIMER) {
|
||||
/*
|
||||
* Previous versions of qemu had the ENET_INT_MAC and ENET_INT_TS_TIMER
|
||||
* interrupts swapped. This worked with older versions of Linux (4.14
|
||||
* and older) since Linux associated both interrupt lines with Ethernet
|
||||
* MAC interrupts. Specifically,
|
||||
* - Linux 4.15 and later have separate interrupt handlers for the MAC and
|
||||
* timer interrupts. Those versions of Linux fail with versions of QEMU
|
||||
* with swapped interrupt assignments.
|
||||
* - In linux 4.14, both interrupt lines were registered with the Ethernet
|
||||
* MAC interrupt handler. As a result, all versions of qemu happen to
|
||||
* work, though that is accidental.
|
||||
* - In Linux 4.9 and older, the timer interrupt was registered directly
|
||||
* with the Ethernet MAC interrupt handler. The MAC interrupt was
|
||||
* redirected to a GPIO interrupt to work around erratum ERR006687.
|
||||
* This was implemented using the SOC's IOMUX block. In qemu, this GPIO
|
||||
* interrupt never fired since IOMUX is currently not supported in qemu.
|
||||
* Linux instead received MAC interrupts on the timer interrupt.
|
||||
* As a result, qemu versions with the swapped interrupt assignment work,
|
||||
* albeit accidentally, but qemu versions with the correct interrupt
|
||||
* assignment fail.
|
||||
*
|
||||
* To ensure that all versions of Linux work, generate ENET_INT_MAC
|
||||
* interrrupts on both interrupt lines. This should be changed if and when
|
||||
* qemu supports IOMUX.
|
||||
*/
|
||||
if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] &
|
||||
(ENET_INT_MAC | ENET_INT_TS_TIMER)) {
|
||||
qemu_set_irq(s->irq[1], 1);
|
||||
} else {
|
||||
qemu_set_irq(s->irq[1], 0);
|
||||
|
@ -15,12 +15,19 @@
|
||||
#include "hw/arm/bcm2835_peripherals.h"
|
||||
#include "hw/intc/bcm2836_control.h"
|
||||
|
||||
#define TYPE_BCM283X "bcm283x"
|
||||
#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X)
|
||||
|
||||
#define BCM283X_NCPUS 4
|
||||
|
||||
/* These type names are for specific SoCs; other than instantiating
|
||||
* them, code using these devices should always handle them via the
|
||||
* BCM283x base class, so they have no BCM2836(obj) etc macros.
|
||||
*/
|
||||
#define TYPE_BCM2836 "bcm2836"
|
||||
#define BCM2836(obj) OBJECT_CHECK(BCM2836State, (obj), TYPE_BCM2836)
|
||||
#define TYPE_BCM2837 "bcm2837"
|
||||
|
||||
#define BCM2836_NCPUS 4
|
||||
|
||||
typedef struct BCM2836State {
|
||||
typedef struct BCM283XState {
|
||||
/*< private >*/
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
@ -28,9 +35,21 @@ typedef struct BCM2836State {
|
||||
char *cpu_type;
|
||||
uint32_t enabled_cpus;
|
||||
|
||||
ARMCPU cpus[BCM2836_NCPUS];
|
||||
ARMCPU cpus[BCM283X_NCPUS];
|
||||
BCM2836ControlState control;
|
||||
BCM2835PeripheralState peripherals;
|
||||
} BCM2836State;
|
||||
} BCM283XState;
|
||||
|
||||
typedef struct BCM283XInfo BCM283XInfo;
|
||||
|
||||
typedef struct BCM283XClass {
|
||||
DeviceClass parent_class;
|
||||
const BCM283XInfo *info;
|
||||
} BCM283XClass;
|
||||
|
||||
#define BCM283X_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
|
||||
#define BCM283X_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
|
||||
|
||||
#endif /* BCM2836_H */
|
||||
|
@ -438,8 +438,8 @@ typedef struct FslIMX6State {
|
||||
#define FSL_IMX6_HDMI_MASTER_IRQ 115
|
||||
#define FSL_IMX6_HDMI_CEC_IRQ 116
|
||||
#define FSL_IMX6_MLB150_LOW_IRQ 117
|
||||
#define FSL_IMX6_ENET_MAC_1588_IRQ 118
|
||||
#define FSL_IMX6_ENET_MAC_IRQ 119
|
||||
#define FSL_IMX6_ENET_MAC_IRQ 118
|
||||
#define FSL_IMX6_ENET_MAC_1588_IRQ 119
|
||||
#define FSL_IMX6_PCIE1_IRQ 120
|
||||
#define FSL_IMX6_PCIE2_IRQ 121
|
||||
#define FSL_IMX6_PCIE3_IRQ 122
|
||||
|
@ -67,6 +67,8 @@
|
||||
#define UCR2_RXEN (1<<1) /* Receiver enable */
|
||||
#define UCR2_SRST (1<<0) /* Reset complete */
|
||||
|
||||
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
|
||||
|
||||
#define UTS1_TXEMPTY (1<<6)
|
||||
#define UTS1_RXEMPTY (1<<5)
|
||||
#define UTS1_TXFULL (1<<4)
|
||||
@ -95,6 +97,7 @@ typedef struct IMXSerialState {
|
||||
uint32_t ubmr;
|
||||
uint32_t ubrc;
|
||||
uint32_t ucr3;
|
||||
uint32_t ucr4;
|
||||
|
||||
qemu_irq irq;
|
||||
CharBackend chr;
|
||||
|
Loading…
Reference in New Issue
Block a user