target-arm queue:

* cleanup to use g_new() and friends
  * support semihosting in A64
  * add SMBIOS support to mach-virt
  * remove hw_error() usages
  * fix bug in the AArch32:AArch64 register mapping
  * add a second PCI memory window in highmem on virt board
  * fix bug in arm_excp_unmasked()
  * add i.MX31 SoC
  * remove restriction on handling affinity values in virt board
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJV7VugAAoJEDwlJe0UNgzeRDEP+weGwHL5bZcHESw9eecJVfmc
 Fv8i+dhXz9aMoOYncvWvyHliou611705nnVo5Mcj/iBimr2ELlH/joBLa4DvkDAM
 AFPZvTgFsAC0bhFSy6gDVI9Q3kIbZ7b4a2TQTbewE61HeE7AERjWphwB6zYp/dDb
 4POeOEPx8C53I4nM61+RdQgwW1zvGMuyb04R1PUyfiAQ33CoAfM/DfH4q6JzZGnq
 kDEfModgo0zT4jfXJ2Pp+a5BIyan3YyuiILOrVCNvEQOcnc2Nl9jN1/IuJNYHOPG
 i5HXrYQya/DyCxmK3SX2JqYZdILcEqYF9q4cjpf92pmwmh3wwzIyfBAfmJ+lmi0A
 tjQ+Q3OVjHZ1ztVvRWofbhUpiYuqKO8y2m1pn4cR1VwR3ZHp2zRzfgfux4h3eSZF
 F33zfnGyPi23lHOnj0l3hvo3piWONYUQ22GJcCE7YC/Ammx4j5yG+5rsikofR3nD
 mqjHsxaZyqdpm/MXWv8o97tBWEMARvRg6GkJeFAxrkhaha/QMCvmNrlWLr+mnIQy
 ggVv4KSbs+aKlXJvCuh3P2z3tmVKoijluHJ7vHvVi9iKfe3SjY/JDpKaQXKqaSRU
 iqm4PZjIP7VmY9+ZboEM7leu7M+4aD/K1jjC43kvvombZgDnDdHumbsZIusjHSMD
 rUdXdgT140zJdWMB5dYl
 =VFdD
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150907' into staging

target-arm queue:
 * cleanup to use g_new() and friends
 * support semihosting in A64
 * add SMBIOS support to mach-virt
 * remove hw_error() usages
 * fix bug in the AArch32:AArch64 register mapping
 * add a second PCI memory window in highmem on virt board
 * fix bug in arm_excp_unmasked()
 * add i.MX31 SoC
 * remove restriction on handling affinity values in virt board

# gpg: Signature made Mon 07 Sep 2015 10:40:48 BST 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-20150907: (27 commits)
  arm/virt: Add full-sized CPU affinity handling
  target-arm: Refactor CPU affinity handling
  i.MX: Add i2C devices to i.MX31 SOC
  i.MX: Add qtest support for I2C device emulator.
  i.MX: Add the i.MX25 PDK platform
  i.MX: Add SOC support for i.MX25
  i.MX: Add FEC Ethernet Emulator
  i.MX: Add I2C controller emulator
  i.MX: KZM: use standalone i.MX31 SOC support
  i.MX: Add SOC support for i.MX31
  target-arm: Fix arm_excp_unmasked() function
  hw/arm/virt: Add high MMIO PCI region, 512G in size
  target-arm: Fix AArch32:AArch64 general-purpose register mapping
  arm: Remove hw_error() usages.
  arm: cpu: assert() on no-EL2 virt IRQ error condition.
  smbios: implement smbios support for mach-virt
  smbios: add smbios 3.0 support
  target-arm: Wire up HLT 0xf000 as the A64 semihosting instruction
  target-arm/arm-semi.c: SYS_EXIT on A64 takes a parameter block
  target-arm/arm-semi.c: Implement A64 specific SyncCacheRange call
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-09-07 10:43:18 +01:00
commit 298fae3897
63 changed files with 3232 additions and 395 deletions

View file

@ -28,6 +28,7 @@ CONFIG_SSI_M25P80=y
CONFIG_LAN9118=y
CONFIG_SMC91C111=y
CONFIG_ALLWINNER_EMAC=y
CONFIG_IMX_FEC=y
CONFIG_DS1338=y
CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
@ -98,7 +99,13 @@ CONFIG_ALLWINNER_A10_PIT=y
CONFIG_ALLWINNER_A10_PIC=y
CONFIG_ALLWINNER_A10=y
CONFIG_FSL_IMX31=y
CONFIG_FSL_IMX25=y
CONFIG_IMX_I2C=y
CONFIG_XIO3130=y
CONFIG_IOH3420=y
CONFIG_I82801B11=y
CONFIG_ACPI=y
CONFIG_SMBIOS=y

View file

@ -1301,9 +1301,8 @@ send_packet:
%x - target_ulong argument printed in hex.
%lx - 64-bit argument printed in hex.
%s - string pointer (target_ulong) and length (int) pair. */
void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
{
va_list va;
char *p;
char *p_end;
target_ulong addr;
@ -1317,7 +1316,6 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
#ifndef CONFIG_USER_ONLY
vm_stop(RUN_STATE_DEBUG);
#endif
va_start(va, fmt);
p = s->syscall_buf;
p_end = &s->syscall_buf[sizeof(s->syscall_buf)];
*(p++) = 'F';
@ -1351,7 +1349,6 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
}
}
*p = 0;
va_end(va);
#ifdef CONFIG_USER_ONLY
put_packet(s, s->syscall_buf);
gdb_handlesig(s->c_cpu, 0);
@ -1366,6 +1363,15 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
#endif
}
void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
gdb_do_syscallv(cb, fmt, va);
va_end(va);
}
static void gdb_read_byte(GDBState *s, int ch)
{
int i, csum;

View file

@ -1,6 +1,6 @@
obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
obj-$(CONFIG_DIGIC) += digic_boards.o
obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
obj-$(CONFIG_ACPI) += virt-acpi-build.o
@ -13,3 +13,5 @@ obj-y += omap1.o omap2.o strongarm.o
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o

273
hw/arm/fsl-imx25.c Normal file
View file

@ -0,0 +1,273 @@
/*
* Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* i.MX25 SOC emulation.
*
* Based on hw/arm/xlnx-zynqmp.c
*
* Copyright (C) 2015 Xilinx Inc
* Written by Peter Crosthwaite <peter.crosthwaite@xilinx.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 "hw/arm/fsl-imx25.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
#include "hw/boards.h"
#include "sysemu/char.h"
static void fsl_imx25_init(Object *obj)
{
FslIMX25State *s = FSL_IMX25(obj);
int i;
object_initialize(&s->cpu, sizeof(s->cpu), "arm926-" TYPE_ARM_CPU);
object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
}
for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX_GPT);
qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus_get_default());
}
for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT);
qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default());
}
object_initialize(&s->fec, sizeof(s->fec), TYPE_IMX_FEC);
qdev_set_parent_bus(DEVICE(&s->fec), sysbus_get_default());
for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
}
}
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
{
FslIMX25State *s = FSL_IMX25(dev);
uint8_t i;
Error *err = NULL;
object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
object_property_set_bool(OBJECT(&s->avic), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX25_AVIC_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX25_CCM_ADDR);
/* Initialize all UARTs */
for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
static const struct {
hwaddr addr;
unsigned int irq;
} serial_table[FSL_IMX25_NUM_UARTS] = {
{ FSL_IMX25_UART1_ADDR, FSL_IMX25_UART1_IRQ },
{ FSL_IMX25_UART2_ADDR, FSL_IMX25_UART2_IRQ },
{ FSL_IMX25_UART3_ADDR, FSL_IMX25_UART3_IRQ },
{ FSL_IMX25_UART4_ADDR, FSL_IMX25_UART4_IRQ },
{ FSL_IMX25_UART5_ADDR, FSL_IMX25_UART5_IRQ }
};
if (i < MAX_SERIAL_PORTS) {
CharDriverState *chr;
chr = serial_hds[i];
if (!chr) {
char label[20];
snprintf(label, sizeof(label), "imx31.uart%d", i);
chr = qemu_chr_new(label, "null", NULL);
}
qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
}
object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
serial_table[i].irq));
}
/* Initialize all GPT timers */
for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
static const struct {
hwaddr addr;
unsigned int irq;
} gpt_table[FSL_IMX25_NUM_GPTS] = {
{ FSL_IMX25_GPT1_ADDR, FSL_IMX25_GPT1_IRQ },
{ FSL_IMX25_GPT2_ADDR, FSL_IMX25_GPT2_IRQ },
{ FSL_IMX25_GPT3_ADDR, FSL_IMX25_GPT3_IRQ },
{ FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
};
s->gpt[i].ccm = DEVICE(&s->ccm);
object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_table[i].addr);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
gpt_table[i].irq));
}
/* Initialize all EPIT timers */
for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
static const struct {
hwaddr addr;
unsigned int irq;
} epit_table[FSL_IMX25_NUM_EPITS] = {
{ FSL_IMX25_EPIT1_ADDR, FSL_IMX25_EPIT1_IRQ },
{ FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
};
s->epit[i].ccm = DEVICE(&s->ccm);
object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
epit_table[i].irq));
}
qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
object_property_set_bool(OBJECT(&s->fec), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fec), 0, FSL_IMX25_FEC_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0,
qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ));
/* Initialize all I2C */
for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
static const struct {
hwaddr addr;
unsigned int irq;
} i2c_table[FSL_IMX25_NUM_I2CS] = {
{ FSL_IMX25_I2C1_ADDR, FSL_IMX25_I2C1_IRQ },
{ FSL_IMX25_I2C2_ADDR, FSL_IMX25_I2C2_IRQ },
{ FSL_IMX25_I2C3_ADDR, FSL_IMX25_I2C3_IRQ }
};
object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
i2c_table[i].irq));
}
/* initialize 2 x 16 KB ROM */
memory_region_init_rom_device(&s->rom[0], NULL, NULL, NULL,
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR,
&s->rom[0]);
memory_region_init_rom_device(&s->rom[1], NULL, NULL, NULL,
"imx25.rom1", FSL_IMX25_ROM1_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM1_ADDR,
&s->rom[1]);
/* initialize internal RAM (128 KB) */
memory_region_init_ram(&s->iram, NULL, "imx25.iram", FSL_IMX25_IRAM_SIZE,
&err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ADDR,
&s->iram);
vmstate_register_ram_global(&s->iram);
/* internal RAM (128 KB) is aliased over 128 MB - 128 KB */
memory_region_init_alias(&s->iram_alias, NULL, "imx25.iram_alias",
&s->iram, 0, FSL_IMX25_IRAM_ALIAS_SIZE);
memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ALIAS_ADDR,
&s->iram_alias);
}
static void fsl_imx25_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = fsl_imx25_realize;
}
static const TypeInfo fsl_imx25_type_info = {
.name = TYPE_FSL_IMX25,
.parent = TYPE_DEVICE,
.instance_size = sizeof(FslIMX25State),
.instance_init = fsl_imx25_init,
.class_init = fsl_imx25_class_init,
};
static void fsl_imx25_register_types(void)
{
type_register_static(&fsl_imx25_type_info);
}
type_init(fsl_imx25_register_types)

246
hw/arm/fsl-imx31.c Normal file
View file

@ -0,0 +1,246 @@
/*
* Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* i.MX31 SOC emulation.
*
* Based on hw/arm/fsl-imx31.c
*
* 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 "hw/arm/fsl-imx31.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
#include "hw/boards.h"
#include "sysemu/char.h"
static void fsl_imx31_init(Object *obj)
{
FslIMX31State *s = FSL_IMX31(obj);
int i;
object_initialize(&s->cpu, sizeof(s->cpu), "arm1136-" TYPE_ARM_CPU);
object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
for (i = 0; i < FSL_IMX31_NUM_UARTS; i++) {
object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
}
object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT);
qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default());
for (i = 0; i < FSL_IMX31_NUM_EPITS; i++) {
object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT);
qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default());
}
for (i = 0; i < FSL_IMX31_NUM_I2CS; i++) {
object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
}
}
static void fsl_imx31_realize(DeviceState *dev, Error **errp)
{
FslIMX31State *s = FSL_IMX31(dev);
uint16_t i;
Error *err = NULL;
object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
object_property_set_bool(OBJECT(&s->avic), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX31_AVIC_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX31_CCM_ADDR);
/* Initialize all UARTS */
for (i = 0; i < FSL_IMX31_NUM_UARTS; i++) {
static const struct {
hwaddr addr;
unsigned int irq;
} serial_table[FSL_IMX31_NUM_UARTS] = {
{ FSL_IMX31_UART1_ADDR, FSL_IMX31_UART1_IRQ },
{ FSL_IMX31_UART2_ADDR, FSL_IMX31_UART2_IRQ },
};
if (i < MAX_SERIAL_PORTS) {
CharDriverState *chr;
chr = serial_hds[i];
if (!chr) {
char label[20];
snprintf(label, sizeof(label), "imx31.uart%d", i);
chr = qemu_chr_new(label, "null", NULL);
}
qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
}
object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
serial_table[i].irq));
}
s->gpt.ccm = DEVICE(&s->ccm);
object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt), 0, FSL_IMX31_GPT_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt), 0,
qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX31_GPT_IRQ));
/* Initialize all EPIT timers */
for (i = 0; i < FSL_IMX31_NUM_EPITS; i++) {
static const struct {
hwaddr addr;
unsigned int irq;
} epit_table[FSL_IMX31_NUM_EPITS] = {
{ FSL_IMX31_EPIT1_ADDR, FSL_IMX31_EPIT1_IRQ },
{ FSL_IMX31_EPIT2_ADDR, FSL_IMX31_EPIT2_IRQ },
};
s->epit[i].ccm = DEVICE(&s->ccm);
object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
epit_table[i].irq));
}
/* Initialize all I2C */
for (i = 0; i < FSL_IMX31_NUM_I2CS; i++) {
static const struct {
hwaddr addr;
unsigned int irq;
} i2c_table[FSL_IMX31_NUM_I2CS] = {
{ FSL_IMX31_I2C1_ADDR, FSL_IMX31_I2C1_IRQ },
{ FSL_IMX31_I2C2_ADDR, FSL_IMX31_I2C2_IRQ },
{ FSL_IMX31_I2C3_ADDR, FSL_IMX31_I2C3_IRQ }
};
/* Initialize the I2C */
object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
/* Map I2C memory */
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
/* Connect I2C IRQ to PIC */
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
i2c_table[i].irq));
}
/* On a real system, the first 16k is a `secure boot rom' */
memory_region_init_rom_device(&s->secure_rom, NULL, NULL, NULL,
"imx31.secure_rom",
FSL_IMX31_SECURE_ROM_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(get_system_memory(), FSL_IMX31_SECURE_ROM_ADDR,
&s->secure_rom);
/* There is also a 16k ROM */
memory_region_init_rom_device(&s->rom, NULL, NULL, NULL, "imx31.rom",
FSL_IMX31_ROM_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(get_system_memory(), FSL_IMX31_ROM_ADDR,
&s->rom);
/* initialize internal RAM (16 KB) */
memory_region_init_ram(&s->iram, NULL, "imx31.iram", FSL_IMX31_IRAM_SIZE,
&err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(get_system_memory(), FSL_IMX31_IRAM_ADDR,
&s->iram);
vmstate_register_ram_global(&s->iram);
/* internal RAM (16 KB) is aliased over 256 MB - 16 KB */
memory_region_init_alias(&s->iram_alias, NULL, "imx31.iram_alias",
&s->iram, 0, FSL_IMX31_IRAM_ALIAS_SIZE);
memory_region_add_subregion(get_system_memory(), FSL_IMX31_IRAM_ALIAS_ADDR,
&s->iram_alias);
}
static void fsl_imx31_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = fsl_imx31_realize;
}
static const TypeInfo fsl_imx31_type_info = {
.name = TYPE_FSL_IMX31,
.parent = TYPE_DEVICE,
.instance_size = sizeof(FslIMX31State),
.instance_init = fsl_imx31_init,
.class_init = fsl_imx31_class_init,
};
static void fsl_imx31_register_types(void)
{
type_register_static(&fsl_imx31_type_info);
}
type_init(fsl_imx31_register_types)

159
hw/arm/imx25_pdk.c Normal file
View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* PDK Board System emulation.
*
* Based on hw/arm/kzm.c
*
* Copyright (c) 2008 OKL and 2011 NICTA
* Written by Hans at OK-Labs
* Updated by Peter Chubb.
*
* 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 "hw/arm/fsl-imx25.h"
#include "hw/boards.h"
#include "qemu/error-report.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
#include "hw/i2c/i2c.h"
/* Memory map for PDK Emulation Baseboard:
* 0x00000000-0x7fffffff See i.MX25 SOC fr support
* 0x80000000-0x87ffffff RAM + Alias EMULATED
* 0x90000000-0x9fffffff RAM + Alias EMULATED
* 0xa0000000-0xa7ffffff Flash IGNORED
* 0xa8000000-0xafffffff Flash IGNORED
* 0xb0000000-0xb1ffffff SRAM IGNORED
* 0xb2000000-0xb3ffffff SRAM IGNORED
* 0xb4000000-0xb5ffffff CS4 IGNORED
* 0xb6000000-0xb8000fff Reserved IGNORED
* 0xb8001000-0xb8001fff SDRAM CTRL reg IGNORED
* 0xb8002000-0xb8002fff WEIM CTRL reg IGNORED
* 0xb8003000-0xb8003fff M3IF CTRL reg IGNORED
* 0xb8004000-0xb8004fff EMI CTRL reg IGNORED
* 0xb8005000-0xbaffffff Reserved IGNORED
* 0xbb000000-0xbb000fff NAND flash area buf IGNORED
* 0xbb001000-0xbb0011ff NAND flash reserved IGNORED
* 0xbb001200-0xbb001dff Reserved IGNORED
* 0xbb001e00-0xbb001fff NAN flash CTRL reg IGNORED
* 0xbb012000-0xbfffffff Reserved IGNORED
* 0xc0000000-0xffffffff Reserved IGNORED
*/
typedef struct IMX25PDK {
FslIMX25State soc;
MemoryRegion ram;
MemoryRegion ram_alias;
} IMX25PDK;
static struct arm_boot_info imx25_pdk_binfo;
static void imx25_pdk_init(MachineState *machine)
{
IMX25PDK *s = g_new0(IMX25PDK, 1);
Error *err = NULL;
unsigned int ram_size;
unsigned int alias_offset;
int i;
object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX25);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
&error_abort);
object_property_set_bool(OBJECT(&s->soc), true, "realized", &err);
if (err != NULL) {
error_report("%s", error_get_pretty(err));
exit(1);
}
/* We need to initialize our memory */
if (machine->ram_size > (FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE)) {
error_report("WARNING: RAM size " RAM_ADDR_FMT " above max supported, "
"reduced to %x", machine->ram_size,
FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE);
machine->ram_size = FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE;
}
memory_region_allocate_system_memory(&s->ram, NULL, "imx25.ram",
machine->ram_size);
memory_region_add_subregion(get_system_memory(), FSL_IMX25_SDRAM0_ADDR,
&s->ram);
/* initialize the alias memory if any */
for (i = 0, ram_size = machine->ram_size, alias_offset = 0;
(i < 2) && ram_size; i++) {
unsigned int size;
static const struct {
hwaddr addr;
unsigned int size;
} ram[2] = {
{ FSL_IMX25_SDRAM0_ADDR, FSL_IMX25_SDRAM0_SIZE },
{ FSL_IMX25_SDRAM1_ADDR, FSL_IMX25_SDRAM1_SIZE },
};
size = MIN(ram_size, ram[i].size);
ram_size -= size;
if (size < ram[i].size) {
memory_region_init_alias(&s->ram_alias, NULL, "ram.alias",
&s->ram, alias_offset, ram[i].size - size);
memory_region_add_subregion(get_system_memory(),
ram[i].addr + size, &s->ram_alias);
}
alias_offset += ram[i].size;
}
imx25_pdk_binfo.ram_size = machine->ram_size;
imx25_pdk_binfo.kernel_filename = machine->kernel_filename;
imx25_pdk_binfo.kernel_cmdline = machine->kernel_cmdline;
imx25_pdk_binfo.initrd_filename = machine->initrd_filename;
imx25_pdk_binfo.loader_start = FSL_IMX25_SDRAM0_ADDR;
imx25_pdk_binfo.board_id = 1771,
imx25_pdk_binfo.nb_cpus = 1;
/*
* We test explicitly for qtest here as it is not done (yet?) in
* arm_load_kernel(). Without this the "make check" command would
* fail.
*/
if (!qtest_enabled()) {
arm_load_kernel(&s->soc.cpu, &imx25_pdk_binfo);
} else {
/*
* This I2C device doesn't exist on the real board.
* We add it here (only on qtest usage) to be able to do a bit
* of simple qtest. See "make check" for details.
*/
i2c_create_slave((I2CBus *)qdev_get_child_bus(DEVICE(&s->soc.i2c[0]),
"i2c"),
"ds1338", 0x68);
}
}
static QEMUMachine imx25_pdk_machine = {
.name = "imx25_pdk",
.desc = "ARM i.MX25 PDK board (ARM926)",
.init = imx25_pdk_init,
};
static void imx25_pdk_machine_init(void)
{
qemu_register_machine(&imx25_pdk_machine);
}
machine_init(imx25_pdk_machine_init)

View file

@ -13,131 +13,130 @@
* i.MX31 SoC
*/
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "hw/hw.h"
#include "hw/arm/arm.h"
#include "hw/devices.h"
#include "net/net.h"
#include "sysemu/sysemu.h"
#include "hw/arm/fsl-imx31.h"
#include "hw/boards.h"
#include "qemu/error-report.h"
#include "exec/address-spaces.h"
#include "net/net.h"
#include "hw/devices.h"
#include "hw/char/serial.h"
#include "hw/intc/imx_avic.h"
#include "hw/arm/imx.h"
#include "sysemu/qtest.h"
/* Memory map for Kzm Emulation Baseboard:
* 0x00000000-0x00003fff 16k secure ROM IGNORED
* 0x00004000-0x00407fff Reserved IGNORED
* 0x00404000-0x00407fff ROM IGNORED
* 0x00408000-0x0fffffff Reserved IGNORED
* 0x10000000-0x1fffbfff RAM aliasing IGNORED
* 0x1fffc000-0x1fffffff RAM EMULATED
* 0x20000000-0x2fffffff Reserved IGNORED
* 0x30000000-0x7fffffff I.MX31 Internal Register Space
* 0x43f00000 IO_AREA0
* 0x43f90000 UART1 EMULATED
* 0x43f94000 UART2 EMULATED
* 0x68000000 AVIC EMULATED
* 0x53f80000 CCM EMULATED
* 0x53f94000 PIT 1 EMULATED
* 0x53f98000 PIT 2 EMULATED
* 0x53f90000 GPT EMULATED
* 0x80000000-0x87ffffff RAM EMULATED
* 0x88000000-0x8fffffff RAM Aliasing EMULATED
* 0xa0000000-0xafffffff NAND Flash IGNORED
* 0xb0000000-0xb3ffffff Unavailable IGNORED
* 0xb4000000-0xb4000fff 8-bit free space IGNORED
* 0xb4001000-0xb400100f Board control IGNORED
* 0xb4001003 DIP switch
* 0xb4001010-0xb400101f 7-segment LED IGNORED
* 0xb4001020-0xb400102f LED IGNORED
* 0xb4001030-0xb400103f LED IGNORED
* 0xb4001040-0xb400104f FPGA, UART EMULATED
* 0xb4001050-0xb400105f FPGA, UART EMULATED
* 0xb4001060-0xb40fffff FPGA IGNORED
* 0xb6000000-0xb61fffff LAN controller EMULATED
* 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
* 0xb6300000-0xb7ffffff Free IGNORED
* 0xb8000000-0xb8004fff Memory control registers IGNORED
* 0xc0000000-0xc3ffffff PCMCIA/CF IGNORED
* 0xc4000000-0xffffffff Reserved IGNORED
*/
/* Memory map for Kzm Emulation Baseboard:
* 0x00000000-0x7fffffff See i.MX31 SOC for support
* 0x80000000-0x8fffffff RAM EMULATED
* 0x90000000-0x9fffffff RAM EMULATED
* 0xa0000000-0xafffffff Flash IGNORED
* 0xb0000000-0xb3ffffff Unavailable IGNORED
* 0xb4000000-0xb4000fff 8-bit free space IGNORED
* 0xb4001000-0xb400100f Board control IGNORED
* 0xb4001003 DIP switch
* 0xb4001010-0xb400101f 7-segment LED IGNORED
* 0xb4001020-0xb400102f LED IGNORED
* 0xb4001030-0xb400103f LED IGNORED
* 0xb4001040-0xb400104f FPGA, UART EMULATED
* 0xb4001050-0xb400105f FPGA, UART EMULATED
* 0xb4001060-0xb40fffff FPGA IGNORED
* 0xb6000000-0xb61fffff LAN controller EMULATED
* 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
* 0xb6300000-0xb7ffffff Free IGNORED
* 0xb8000000-0xb8004fff Memory control registers IGNORED
* 0xc0000000-0xc3ffffff PCMCIA/CF IGNORED
* 0xc4000000-0xffffffff Reserved IGNORED
*/
#define KZM_RAMADDRESS (0x80000000)
#define KZM_FPGA (0xb4001040)
typedef struct IMX31KZM {
FslIMX31State soc;
MemoryRegion ram;
MemoryRegion ram_alias;
} IMX31KZM;
#define KZM_RAM_ADDR (FSL_IMX31_SDRAM0_ADDR)
#define KZM_FPGA_ADDR (FSL_IMX31_CS4_ADDR + 0x1040)
#define KZM_LAN9118_ADDR (FSL_IMX31_CS5_ADDR)
static struct arm_boot_info kzm_binfo = {
.loader_start = KZM_RAMADDRESS,
.loader_start = KZM_RAM_ADDR,
.board_id = 1722,
};
static void kzm_init(MachineState *machine)
{
ram_addr_t ram_size = machine->ram_size;
const char *cpu_model = machine->cpu_model;
const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline;
const char *initrd_filename = machine->initrd_filename;
ARMCPU *cpu;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *sram = g_new(MemoryRegion, 1);
MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
DeviceState *dev;
DeviceState *ccm;
IMX31KZM *s = g_new0(IMX31KZM, 1);
Error *err = NULL;
unsigned int ram_size;
unsigned int alias_offset;
unsigned int i;
if (!cpu_model) {
cpu_model = "arm1136";
}
object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX31);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
&error_abort);
cpu = cpu_arm_init(cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
object_property_set_bool(OBJECT(&s->soc), true, "realized", &err);
if (err != NULL) {
error_report("%s", error_get_pretty(err));
exit(1);
}
/* On a real system, the first 16k is a `secure boot rom' */
/* Check the amount of memory is compatible with the SOC */
if (machine->ram_size > (FSL_IMX31_SDRAM0_SIZE + FSL_IMX31_SDRAM1_SIZE)) {
error_report("WARNING: RAM size " RAM_ADDR_FMT " above max supported, "
"reduced to %x", machine->ram_size,
FSL_IMX31_SDRAM0_SIZE + FSL_IMX31_SDRAM1_SIZE);
machine->ram_size = FSL_IMX31_SDRAM0_SIZE + FSL_IMX31_SDRAM1_SIZE;
}
memory_region_allocate_system_memory(ram, NULL, "kzm.ram", ram_size);
memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
memory_region_allocate_system_memory(&s->ram, NULL, "kzm.ram",
machine->ram_size);
memory_region_add_subregion(get_system_memory(), FSL_IMX31_SDRAM0_ADDR,
&s->ram);
memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias);
/* initialize the alias memory if any */
for (i = 0, ram_size = machine->ram_size, alias_offset = 0;
(i < 2) && ram_size; i++) {
unsigned int size;
static const struct {
hwaddr addr;
unsigned int size;
} ram[2] = {
{ FSL_IMX31_SDRAM0_ADDR, FSL_IMX31_SDRAM0_SIZE },
{ FSL_IMX31_SDRAM1_ADDR, FSL_IMX31_SDRAM1_SIZE },
};
memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000, &error_abort);
memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
size = MIN(ram_size, ram[i].size);
dev = sysbus_create_varargs(TYPE_IMX_AVIC, 0x68000000,
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
NULL);
ram_size -= size;
imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
if (size < ram[i].size) {
memory_region_init_alias(&s->ram_alias, NULL, "ram.alias",
&s->ram, alias_offset, ram[i].size - size);
memory_region_add_subregion(get_system_memory(),
ram[i].addr + size, &s->ram_alias);
}
ccm = sysbus_create_simple(TYPE_IMX_CCM, 0x53f80000, NULL);
imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm);
imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm);
imx_timerg_create(0x53f90000, qdev_get_gpio_in(dev, 29), ccm);
alias_offset += ram[i].size;
}
if (nd_table[0].used) {
lan9118_init(&nd_table[0], 0xb6000000, qdev_get_gpio_in(dev, 52));
lan9118_init(&nd_table[0], KZM_LAN9118_ADDR,
qdev_get_gpio_in(DEVICE(&s->soc.avic), 52));
}
if (serial_hds[2]) { /* touchscreen */
serial_mm_init(address_space_mem, KZM_FPGA+0x10, 0,
qdev_get_gpio_in(dev, 52),
14745600, serial_hds[2],
DEVICE_NATIVE_ENDIAN);
serial_mm_init(get_system_memory(), KZM_FPGA_ADDR+0x10, 0,
qdev_get_gpio_in(DEVICE(&s->soc.avic), 52),
14745600, serial_hds[2], DEVICE_NATIVE_ENDIAN);
}
kzm_binfo.ram_size = ram_size;
kzm_binfo.kernel_filename = kernel_filename;
kzm_binfo.kernel_cmdline = kernel_cmdline;
kzm_binfo.initrd_filename = initrd_filename;
kzm_binfo.ram_size = machine->ram_size;
kzm_binfo.kernel_filename = machine->kernel_filename;
kzm_binfo.kernel_cmdline = machine->kernel_cmdline;
kzm_binfo.initrd_filename = machine->initrd_filename;
kzm_binfo.nb_cpus = 1;
arm_load_kernel(cpu, &kzm_binfo);
if (!qtest_enabled()) {
arm_load_kernel(&s->soc.cpu, &kzm_binfo);
}
}
static QEMUMachine kzm_machine = {

View file

@ -258,8 +258,7 @@ static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory,
hwaddr base,
qemu_irq irq, omap_clk clk)
{
struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
g_malloc0(sizeof(struct omap_mpu_timer_s));
struct omap_mpu_timer_s *s = g_new0(struct omap_mpu_timer_s, 1);
s->irq = irq;
s->clk = clk;
@ -388,8 +387,7 @@ static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory,
hwaddr base,
qemu_irq irq, omap_clk clk)
{
struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
g_malloc0(sizeof(struct omap_watchdog_timer_s));
struct omap_watchdog_timer_s *s = g_new0(struct omap_watchdog_timer_s, 1);
s->timer.irq = irq;
s->timer.clk = clk;
@ -495,8 +493,7 @@ static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
hwaddr base,
qemu_irq irq, omap_clk clk)
{
struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
g_malloc0(sizeof(struct omap_32khz_timer_s));
struct omap_32khz_timer_s *s = g_new0(struct omap_32khz_timer_s, 1);
s->timer.irq = irq;
s->timer.clk = clk;
@ -1236,8 +1233,7 @@ static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
MemoryRegion *memory, hwaddr base,
qemu_irq abort_irq, omap_clk clk)
{
struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
g_malloc0(sizeof(struct omap_tipb_bridge_s));
struct omap_tipb_bridge_s *s = g_new0(struct omap_tipb_bridge_s, 1);
s->abort = abort_irq;
omap_tipb_bridge_reset(s);
@ -2099,8 +2095,7 @@ static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
omap_clk clk)
{
struct omap_mpuio_s *s = (struct omap_mpuio_s *)
g_malloc0(sizeof(struct omap_mpuio_s));
struct omap_mpuio_s *s = g_new0(struct omap_mpuio_s, 1);
s->irq = gpio_int;
s->kbd_irq = kbd_int;
@ -2292,8 +2287,7 @@ static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory,
qemu_irq dma,
omap_clk clk)
{
struct omap_uwire_s *s = (struct omap_uwire_s *)
g_malloc0(sizeof(struct omap_uwire_s));
struct omap_uwire_s *s = g_new0(struct omap_uwire_s, 1);
s->txirq = txirq;
s->rxirq = rxirq;
@ -2932,8 +2926,7 @@ static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,
qemu_irq timerirq, qemu_irq alarmirq,
omap_clk clk)
{
struct omap_rtc_s *s = (struct omap_rtc_s *)
g_malloc0(sizeof(struct omap_rtc_s));
struct omap_rtc_s *s = g_new0(struct omap_rtc_s, 1);
s->irq = timerirq;
s->alarm = alarmirq;
@ -3468,8 +3461,7 @@ static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
qemu_irq txirq, qemu_irq rxirq,
qemu_irq *dma, omap_clk clk)
{
struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
g_malloc0(sizeof(struct omap_mcbsp_s));
struct omap_mcbsp_s *s = g_new0(struct omap_mcbsp_s, 1);
s->txirq = txirq;
s->rxirq = rxirq;
@ -3648,8 +3640,7 @@ static void omap_lpg_clk_update(void *opaque, int line, int on)
static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
hwaddr base, omap_clk clk)
{
struct omap_lpg_s *s = (struct omap_lpg_s *)
g_malloc0(sizeof(struct omap_lpg_s));
struct omap_lpg_s *s = g_new0(struct omap_lpg_s, 1);
s->tm = timer_new_ms(QEMU_CLOCK_VIRTUAL, omap_lpg_tick, s);
@ -3853,8 +3844,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
const char *core)
{
int i;
struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
g_malloc0(sizeof(struct omap_mpu_state_s));
struct omap_mpu_state_s *s = g_new0(struct omap_mpu_state_s, 1);
qemu_irq dma_irqs[6];
DriveInfo *dinfo;
SysBusDevice *busdev;

View file

@ -596,8 +596,7 @@ static const MemoryRegionOps omap_eac_ops = {
static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
{
struct omap_eac_s *s = (struct omap_eac_s *)
g_malloc0(sizeof(struct omap_eac_s));
struct omap_eac_s *s = g_new0(struct omap_eac_s, 1);
s->irq = irq;
s->codec.rxdrq = *drq ++;
@ -788,8 +787,7 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
hwaddr channel_base, qemu_irq irq, omap_clk clk,
CharDriverState *chr)
{
struct omap_sti_s *s = (struct omap_sti_s *)
g_malloc0(sizeof(struct omap_sti_s));
struct omap_sti_s *s = g_new0(struct omap_sti_s, 1);
s->irq = irq;
omap_sti_reset(s);
@ -1806,8 +1804,7 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
struct omap_mpu_state_s *mpu)
{
struct omap_prcm_s *s = (struct omap_prcm_s *)
g_malloc0(sizeof(struct omap_prcm_s));
struct omap_prcm_s *s = g_new0(struct omap_prcm_s, 1);
s->irq[0] = mpu_int;
s->irq[1] = dsp_int;
@ -2185,8 +2182,7 @@ static void omap_sysctl_reset(struct omap_sysctl_s *s)
static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
omap_clk iclk, struct omap_mpu_state_s *mpu)
{
struct omap_sysctl_s *s = (struct omap_sysctl_s *)
g_malloc0(sizeof(struct omap_sysctl_s));
struct omap_sysctl_s *s = g_new0(struct omap_sysctl_s, 1);
s->mpu = mpu;
omap_sysctl_reset(s);
@ -2248,8 +2244,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
unsigned long sdram_size,
const char *core)
{
struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
g_malloc0(sizeof(struct omap_mpu_state_s));
struct omap_mpu_state_s *s = g_new0(struct omap_mpu_state_s, 1);
qemu_irq dma_irqs[4];
DriveInfo *dinfo;
int i;

View file

@ -1731,8 +1731,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
hwaddr base,
qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
{
PXA2xxI2SState *s = (PXA2xxI2SState *)
g_malloc0(sizeof(PXA2xxI2SState));
PXA2xxI2SState *s = g_new0(PXA2xxI2SState, 1);
s->irq = irq;
s->rx_dma = rx_dma;
@ -2061,7 +2060,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
PXA2xxState *s;
int i;
DriveInfo *dinfo;
s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
s = g_new0(PXA2xxState, 1);
if (revision && strncmp(revision, "pxa27", 5)) {
fprintf(stderr, "Machine requires a PXA27x processor.\n");
@ -2157,7 +2156,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
for (i = 0; pxa27x_ssp[i].io_base; i ++);
s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
s->ssp = g_new0(SSIBus *, i);
for (i = 0; pxa27x_ssp[i].io_base; i ++) {
DeviceState *dev;
dev = sysbus_create_simple(TYPE_PXA2XX_SSP, pxa27x_ssp[i].io_base,
@ -2202,7 +2201,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
int i;
DriveInfo *dinfo;
s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
s = g_new0(PXA2xxState, 1);
s->cpu = cpu_arm_init("pxa255");
if (s->cpu == NULL) {
@ -2290,7 +2289,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
for (i = 0; pxa255_ssp[i].io_base; i ++);
s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
s->ssp = g_new0(SSIBus *, i);
for (i = 0; pxa255_ssp[i].io_base; i ++) {
DeviceState *dev;
dev = sysbus_create_simple(TYPE_PXA2XX_SSP, pxa255_ssp[i].io_base,

View file

@ -675,7 +675,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
{
ssys_state *s;
s = (ssys_state *)g_malloc0(sizeof(ssys_state));
s = g_new0(ssys_state, 1);
s->irq = irq;
s->board = board;
/* Most devices come preprogrammed with a MAC address in the user data. */

View file

@ -1588,7 +1588,7 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
StrongARMState *s;
int i;
s = g_malloc0(sizeof(StrongARMState));
s = g_new0(StrongARMState, 1);
if (!rev) {
rev = "sa1110-b5";

View file

@ -159,7 +159,8 @@ static void acpi_dsdt_add_virtio(Aml *scope,
}
}
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq)
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
bool use_highmem)
{
Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
int i, bus_no;
@ -234,6 +235,17 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq)
AML_ENTIRE_RANGE, 0x0000, 0x0000, size_pio - 1, base_pio,
size_pio));
if (use_highmem) {
hwaddr base_mmio_high = memmap[VIRT_PCIE_MMIO_HIGH].base;
hwaddr size_mmio_high = memmap[VIRT_PCIE_MMIO_HIGH].size;
aml_append(rbuf,
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000,
base_mmio_high, base_mmio_high, 0x0000,
size_mmio_high));
}
aml_append(method, aml_name_decl("RBUF", rbuf));
aml_append(method, aml_return(rbuf));
aml_append(dev, method);
@ -510,7 +522,8 @@ build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO],
(irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS);
acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE));
acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE),
guest_info->use_highmem);
aml_append(dsdt, scope);

View file

@ -50,6 +50,7 @@
#include "hw/arm/fdt.h"
#include "hw/intc/arm_gic_common.h"
#include "kvm_arm.h"
#include "hw/smbios/smbios.h"
/* Number of external interrupt lines to configure the GIC with */
#define NUM_IRQS 256
@ -79,6 +80,7 @@ typedef struct {
typedef struct {
MachineState parent;
bool secure;
bool highmem;
} VirtMachineState;
#define TYPE_VIRT_MACHINE "virt"
@ -119,6 +121,8 @@ static const MemMapEntry a15memmap[] = {
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
[VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 },
/* Second PCIe window, 512GB wide at the 512GB boundary */
[VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
};
static const int a15irqmap[] = {
@ -284,9 +288,32 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
{
int cpu;
int addr_cells = 1;
/*
* From Documentation/devicetree/bindings/arm/cpus.txt
* On ARM v8 64-bit systems value should be set to 2,
* that corresponds to the MPIDR_EL1 register size.
* If MPIDR_EL1[63:32] value is equal to 0 on all CPUs
* in the system, #address-cells can be set to 1, since
* MPIDR_EL1[63:32] bits are not used for CPUs
* identification.
*
* Here we actually don't know whether our system is 32- or 64-bit one.
* The simplest way to go is to examine affinity IDs of all our CPUs. If
* at least one of them has Aff3 populated, we set #address-cells to 2.
*/
for (cpu = 0; cpu < vbi->smp_cpus; cpu++) {
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
if (armcpu->mp_affinity & ARM_AFF3_MASK) {
addr_cells = 2;
break;
}
}
qemu_fdt_add_subnode(vbi->fdt, "/cpus");
qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1);
qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", addr_cells);
qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
for (cpu = vbi->smp_cpus - 1; cpu >= 0; cpu--) {
@ -303,7 +330,14 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
"enable-method", "psci");
}
qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", armcpu->mp_affinity);
if (addr_cells == 2) {
qemu_fdt_setprop_u64(vbi->fdt, nodename, "reg",
armcpu->mp_affinity);
} else {
qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg",
armcpu->mp_affinity);
}
g_free(nodename);
}
}
@ -666,10 +700,13 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle,
0x7 /* PCI irq */);
}
static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic)
static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
bool use_highmem)
{
hwaddr base_mmio = vbi->memmap[VIRT_PCIE_MMIO].base;
hwaddr size_mmio = vbi->memmap[VIRT_PCIE_MMIO].size;
hwaddr base_mmio_high = vbi->memmap[VIRT_PCIE_MMIO_HIGH].base;
hwaddr size_mmio_high = vbi->memmap[VIRT_PCIE_MMIO_HIGH].size;
hwaddr base_pio = vbi->memmap[VIRT_PCIE_PIO].base;
hwaddr size_pio = vbi->memmap[VIRT_PCIE_PIO].size;
hwaddr base_ecam = vbi->memmap[VIRT_PCIE_ECAM].base;
@ -706,6 +743,16 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic)
mmio_reg, base_mmio, size_mmio);
memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias);
if (use_highmem) {
/* Map high MMIO space */
MemoryRegion *high_mmio_alias = g_new0(MemoryRegion, 1);
memory_region_init_alias(high_mmio_alias, OBJECT(dev), "pcie-mmio-high",
mmio_reg, base_mmio_high, size_mmio_high);
memory_region_add_subregion(get_system_memory(), base_mmio_high,
high_mmio_alias);
}
/* Map IO port space */
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
@ -727,11 +774,23 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic)
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
2, base_ecam, 2, size_ecam);
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
1, FDT_PCI_RANGE_IOPORT, 2, 0,
2, base_pio, 2, size_pio,
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
2, base_mmio, 2, size_mmio);
if (use_highmem) {
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
1, FDT_PCI_RANGE_IOPORT, 2, 0,
2, base_pio, 2, size_pio,
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
2, base_mmio, 2, size_mmio,
1, FDT_PCI_RANGE_MMIO_64BIT,
2, base_mmio_high,
2, base_mmio_high, 2, size_mmio_high);
} else {
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
1, FDT_PCI_RANGE_IOPORT, 2, 0,
2, base_pio, 2, size_pio,
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
2, base_mmio, 2, size_mmio);
}
qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1);
create_pcie_irq_map(vbi, vbi->gic_phandle, irq, nodename);
@ -788,12 +847,37 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
return board->fdt;
}
static void virt_build_smbios(VirtGuestInfo *guest_info)
{
FWCfgState *fw_cfg = guest_info->fw_cfg;
uint8_t *smbios_tables, *smbios_anchor;
size_t smbios_tables_len, smbios_anchor_len;
if (!fw_cfg) {
return;
}
smbios_set_defaults("QEMU", "QEMU Virtual Machine",
"1.0", false, true, SMBIOS_ENTRY_POINT_30);
smbios_get_tables(NULL, 0, &smbios_tables, &smbios_tables_len,
&smbios_anchor, &smbios_anchor_len);
if (smbios_anchor) {
fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables",
smbios_tables, smbios_tables_len);
fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor",
smbios_anchor, smbios_anchor_len);
}
}
static
void virt_guest_info_machine_done(Notifier *notifier, void *data)
{
VirtGuestInfoState *guest_info_state = container_of(notifier,
VirtGuestInfoState, machine_done);
virt_acpi_setup(&guest_info_state->info);
virt_build_smbios(&guest_info_state->info);
}
static void machvirt_init(MachineState *machine)
@ -889,7 +973,7 @@ static void machvirt_init(MachineState *machine)
create_rtc(vbi, pic);
create_pcie(vbi, pic);
create_pcie(vbi, pic, vms->highmem);
/* Create mmio transports, so the user can create virtio backends
* (which will be automatically plugged in to the transports). If
@ -904,6 +988,7 @@ static void machvirt_init(MachineState *machine)
guest_info->fw_cfg = fw_cfg_find();
guest_info->memmap = vbi->memmap;
guest_info->irqmap = vbi->irqmap;
guest_info->use_highmem = vms->highmem;
guest_info_state->machine_done.notify = virt_guest_info_machine_done;
qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
@ -941,6 +1026,20 @@ static void virt_set_secure(Object *obj, bool value, Error **errp)
vms->secure = value;
}
static bool virt_get_highmem(Object *obj, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
return vms->highmem;
}
static void virt_set_highmem(Object *obj, bool value, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
vms->highmem = value;
}
static void virt_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@ -953,6 +1052,15 @@ static void virt_instance_init(Object *obj)
"Set on/off to enable/disable the ARM "
"Security Extensions (TrustZone)",
NULL);
/* High memory is enabled by default */
vms->highmem = true;
object_property_add_bool(obj, "highmem", virt_get_highmem,
virt_set_highmem, NULL);
object_property_set_description(obj, "highmem",
"Set on/off to enable/disable using "
"physical address space above 32 bits",
NULL);
}
static void virt_class_init(ObjectClass *oc, void *data)

View file

@ -21,7 +21,6 @@
#include "hw/char/imx_serial.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
#include "hw/arm/imx.h"
//#define DEBUG_SERIAL 1
#ifdef DEBUG_SERIAL
@ -334,40 +333,6 @@ static void imx_serial_init(Object *obj)
sysbus_init_irq(sbd, &s->irq);
}
void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
{
DeviceState *dev;
SysBusDevice *bus;
CharDriverState *chr;
const char chr_name[] = "serial";
char label[ARRAY_SIZE(chr_name) + 1];
dev = qdev_create(NULL, TYPE_IMX_SERIAL);
if (uart >= MAX_SERIAL_PORTS) {
hw_error("Cannot assign uart %d: QEMU supports only %d ports\n",
uart, MAX_SERIAL_PORTS);
}
chr = serial_hds[uart];
if (!chr) {
snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, uart);
chr = qemu_chr_new(label, "null", NULL);
if (!(chr)) {
hw_error("Can't assign serial port to imx-uart%d.\n", uart);
}
}
qdev_prop_set_chr(dev, "chardev", chr);
bus = SYS_BUS_DEVICE(dev);
qdev_init_nofail(dev);
if (addr != (hwaddr)-1) {
sysbus_mmio_map(bus, 0, addr);
}
sysbus_connect_irq(bus, 0, irq);
}
static Property imx_serial_properties[] = {
DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
DEFINE_PROP_END_OF_LIST(),

View file

@ -55,8 +55,7 @@ struct omap_uart_s *omap_uart_init(hwaddr base,
qemu_irq txdma, qemu_irq rxdma,
const char *label, CharDriverState *chr)
{
struct omap_uart_s *s = (struct omap_uart_s *)
g_malloc0(sizeof(struct omap_uart_s));
struct omap_uart_s *s = g_new0(struct omap_uart_s, 1);
s->base = base;
s->fclk = fclk;

View file

@ -1051,8 +1051,7 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
omap_clk fck1, omap_clk fck2, omap_clk ck54m,
omap_clk ick1, omap_clk ick2)
{
struct omap_dss_s *s = (struct omap_dss_s *)
g_malloc0(sizeof(struct omap_dss_s));
struct omap_dss_s *s = g_new0(struct omap_dss_s, 1);
s->irq = irq;
s->drq = drq;

View file

@ -403,8 +403,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
struct omap_dma_lcd_channel_s *dma,
omap_clk clk)
{
struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *)
g_malloc0(sizeof(struct omap_lcd_panel_s));
struct omap_lcd_panel_s *s = g_new0(struct omap_lcd_panel_s, 1);
s->irq = irq;
s->dma = dma;

View file

@ -1626,8 +1626,7 @@ struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs,
enum omap_dma_model model)
{
int num_irqs, memsize, i;
struct omap_dma_s *s = (struct omap_dma_s *)
g_malloc0(sizeof(struct omap_dma_s));
struct omap_dma_s *s = g_new0(struct omap_dma_s, 1);
if (model <= omap_dma_3_1) {
num_irqs = 6;
@ -2061,8 +2060,7 @@ struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs,
int chans, omap_clk iclk, omap_clk fclk)
{
int i;
struct omap_dma_s *s = (struct omap_dma_s *)
g_malloc0(sizeof(struct omap_dma_s));
struct omap_dma_s *s = g_new0(struct omap_dma_s, 1);
s->model = omap_dma_4;
s->chans = chans;

View file

@ -710,8 +710,8 @@ static int omap2_gpio_init(SysBusDevice *sbd)
} else {
s->modulecount = 6;
}
s->modules = g_malloc0(s->modulecount * sizeof(struct omap2_gpio_s));
s->handler = g_malloc0(s->modulecount * 32 * sizeof(qemu_irq));
s->modules = g_new0(struct omap2_gpio_s, s->modulecount);
s->handler = g_new0(qemu_irq, s->modulecount * 32);
qdev_init_gpio_in(dev, omap2_gpio_set, s->modulecount * 32);
qdev_init_gpio_out(dev, s->handler, s->modulecount * 32);
for (i = 0; i < s->modulecount; i++) {

View file

@ -4,4 +4,5 @@ common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
common-obj-$(CONFIG_APM) += pm_smbus.o
common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
obj-$(CONFIG_OMAP) += omap_i2c.o

334
hw/i2c/imx_i2c.c Normal file
View file

@ -0,0 +1,334 @@
/*
* i.MX I2C Bus Serial Interface Emulation
*
* Copyright (C) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
*
* 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 "hw/i2c/imx_i2c.h"
#include "hw/i2c/i2c.h"
#ifndef IMX_I2C_DEBUG
#define IMX_I2C_DEBUG 0
#endif
#if IMX_I2C_DEBUG
#define DPRINT(fmt, args...) \
do { fprintf(stderr, "%s: "fmt, __func__, ## args); } while (0)
static const char *imx_i2c_get_regname(unsigned offset)
{
switch (offset) {
case IADR_ADDR:
return "IADR";
case IFDR_ADDR:
return "IFDR";
case I2CR_ADDR:
return "I2CR";
case I2SR_ADDR:
return "I2SR";
case I2DR_ADDR:
return "I2DR";
default:
return "[?]";
}
}
#else
#define DPRINT(fmt, args...) do { } while (0)
#endif
static inline bool imx_i2c_is_enabled(IMXI2CState *s)
{
return s->i2cr & I2CR_IEN;
}
static inline bool imx_i2c_interrupt_is_enabled(IMXI2CState *s)
{
return s->i2cr & I2CR_IIEN;
}
static inline bool imx_i2c_is_master(IMXI2CState *s)
{
return s->i2cr & I2CR_MSTA;
}
static void imx_i2c_reset(DeviceState *dev)
{
IMXI2CState *s = IMX_I2C(dev);
if (s->address != ADDR_RESET) {
i2c_end_transfer(s->bus);
}
s->address = ADDR_RESET;
s->iadr = IADR_RESET;
s->ifdr = IFDR_RESET;
s->i2cr = I2CR_RESET;
s->i2sr = I2SR_RESET;
s->i2dr_read = I2DR_RESET;
s->i2dr_write = I2DR_RESET;
}
static inline void imx_i2c_raise_interrupt(IMXI2CState *s)
{
/*
* raise an interrupt if the device is enabled and it is configured
* to generate some interrupts.
*/
if (imx_i2c_is_enabled(s) && imx_i2c_interrupt_is_enabled(s)) {
s->i2sr |= I2SR_IIF;
qemu_irq_raise(s->irq);
}
}
static uint64_t imx_i2c_read(void *opaque, hwaddr offset,
unsigned size)
{
uint16_t value;
IMXI2CState *s = IMX_I2C(opaque);
switch (offset) {
case IADR_ADDR:
value = s->iadr;
break;
case IFDR_ADDR:
value = s->ifdr;
break;
case I2CR_ADDR:
value = s->i2cr;
break;
case I2SR_ADDR:
value = s->i2sr;
break;
case I2DR_ADDR:
value = s->i2dr_read;
if (imx_i2c_is_master(s)) {
int ret = 0xff;
if (s->address == ADDR_RESET) {
/* something is wrong as the address is not set */
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Trying to read "
"without specifying the slave address\n",
TYPE_IMX_I2C, __func__);
} else if (s->i2cr & I2CR_MTX) {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Trying to read "
"but MTX is set\n", TYPE_IMX_I2C, __func__);
} else {
/* get the next byte */
ret = i2c_recv(s->bus);
if (ret >= 0) {
imx_i2c_raise_interrupt(s);
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: read failed "
"for device 0x%02x\n", TYPE_IMX_I2C,
__func__, s->address);
ret = 0xff;
}
}
s->i2dr_read = ret;
} else {
qemu_log_mask(LOG_UNIMP, "%s[%s]: slave mode not implemented\n",
TYPE_IMX_I2C, __func__);
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_I2C, __func__, s->address);
value = 0;
break;
}
DPRINT("read %s [0x%02x] -> 0x%02x\n", imx_i2c_get_regname(offset),
(unsigned int)offset, value);
return (uint64_t)value;
}
static void imx_i2c_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
IMXI2CState *s = IMX_I2C(opaque);
DPRINT("write %s [0x%02x] <- 0x%02x\n", imx_i2c_get_regname(offset),
(unsigned int)offset, (int)value);
value &= 0xff;
switch (offset) {
case IADR_ADDR:
s->iadr = value & IADR_MASK;
/* i2c_set_slave_address(s->bus, (uint8_t)s->iadr); */
break;
case IFDR_ADDR:
s->ifdr = value & IFDR_MASK;
break;
case I2CR_ADDR:
if (imx_i2c_is_enabled(s) && ((value & I2CR_IEN) == 0)) {
/* This is a soft reset. IADR is preserved during soft resets */
uint16_t iadr = s->iadr;
imx_i2c_reset(DEVICE(s));
s->iadr = iadr;
} else { /* normal write */
s->i2cr = value & I2CR_MASK;
if (imx_i2c_is_master(s)) {
/* set the bus to busy */
s->i2sr |= I2SR_IBB;
} else { /* slave mode */
/* bus is not busy anymore */
s->i2sr &= ~I2SR_IBB;
/*
* if we unset the master mode then it ends the ongoing
* transfer if any
*/
if (s->address != ADDR_RESET) {
i2c_end_transfer(s->bus);
s->address = ADDR_RESET;
}
}
if (s->i2cr & I2CR_RSTA) { /* Restart */
/* if this is a restart then it ends the ongoing transfer */
if (s->address != ADDR_RESET) {
i2c_end_transfer(s->bus);
s->address = ADDR_RESET;
s->i2cr &= ~I2CR_RSTA;
}
}
}
break;
case I2SR_ADDR:
/*
* if the user writes 0 to IIF then lower the interrupt and
* reset the bit
*/
if ((s->i2sr & I2SR_IIF) && !(value & I2SR_IIF)) {
s->i2sr &= ~I2SR_IIF;
qemu_irq_lower(s->irq);
}
/*
* if the user writes 0 to IAL, reset the bit
*/
if ((s->i2sr & I2SR_IAL) && !(value & I2SR_IAL)) {
s->i2sr &= ~I2SR_IAL;
}
break;
case I2DR_ADDR:
/* if the device is not enabled, nothing to do */
if (!imx_i2c_is_enabled(s)) {
break;
}
s->i2dr_write = value & I2DR_MASK;
if (imx_i2c_is_master(s)) {
/* If this is the first write cycle then it is the slave addr */
if (s->address == ADDR_RESET) {
if (i2c_start_transfer(s->bus, extract32(s->i2dr_write, 1, 7),
extract32(s->i2dr_write, 0, 1))) {
/* if non zero is returned, the adress is not valid */
s->i2sr |= I2SR_RXAK;
} else {
s->address = s->i2dr_write;
s->i2sr &= ~I2SR_RXAK;
imx_i2c_raise_interrupt(s);
}
} else { /* This is a normal data write */
if (i2c_send(s->bus, s->i2dr_write)) {
/* if the target return non zero then end the transfer */
s->i2sr |= I2SR_RXAK;
s->address = ADDR_RESET;
i2c_end_transfer(s->bus);
} else {
s->i2sr &= ~I2SR_RXAK;
imx_i2c_raise_interrupt(s);
}
}
} else {
qemu_log_mask(LOG_UNIMP, "%s[%s]: slave mode not implemented\n",
TYPE_IMX_I2C, __func__);
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_I2C, __func__, s->address);
break;
}
}
static const MemoryRegionOps imx_i2c_ops = {
.read = imx_i2c_read,
.write = imx_i2c_write,
.valid.min_access_size = 1,
.valid.max_access_size = 2,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static const VMStateDescription imx_i2c_vmstate = {
.name = TYPE_IMX_I2C,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT16(address, IMXI2CState),
VMSTATE_UINT16(iadr, IMXI2CState),
VMSTATE_UINT16(ifdr, IMXI2CState),
VMSTATE_UINT16(i2cr, IMXI2CState),
VMSTATE_UINT16(i2sr, IMXI2CState),
VMSTATE_UINT16(i2dr_read, IMXI2CState),
VMSTATE_UINT16(i2dr_write, IMXI2CState),
VMSTATE_END_OF_LIST()
}
};
static void imx_i2c_realize(DeviceState *dev, Error **errp)
{
IMXI2CState *s = IMX_I2C(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &imx_i2c_ops, s, TYPE_IMX_I2C,
IMX_I2C_MEM_SIZE);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
s->bus = i2c_init_bus(DEVICE(dev), "i2c");
}
static void imx_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &imx_i2c_vmstate;
dc->reset = imx_i2c_reset;
dc->realize = imx_i2c_realize;
}
static const TypeInfo imx_i2c_type_info = {
.name = TYPE_IMX_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXI2CState),
.class_init = imx_i2c_class_init,
};
static void imx_i2c_register_types(void)
{
type_register_static(&imx_i2c_type_info);
}
type_init(imx_i2c_register_types)

View file

@ -173,7 +173,8 @@ static void pc_init1(MachineState *machine)
MachineClass *mc = MACHINE_GET_CLASS(machine);
/* These values are guest ABI, do not change */
smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
mc->name, smbios_legacy_mode, smbios_uuid_encoded);
mc->name, smbios_legacy_mode, smbios_uuid_encoded,
SMBIOS_ENTRY_POINT_21);
}
/* allocate ram and load rom/bios */

View file

@ -165,7 +165,8 @@ static void pc_q35_init(MachineState *machine)
if (smbios_defaults) {
/* These values are guest ABI, do not change */
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
mc->name, smbios_legacy_mode, smbios_uuid_encoded);
mc->name, smbios_legacy_mode, smbios_uuid_encoded,
SMBIOS_ENTRY_POINT_21);
}
/* allocate ram and load rom/bios */

View file

@ -75,8 +75,8 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
gamepad_state *s;
int i;
s = (gamepad_state *)g_malloc0(sizeof (gamepad_state));
s->buttons = (gamepad_button *)g_malloc0(n * sizeof (gamepad_button));
s = g_new0(gamepad_state, 1);
s->buttons = g_new0(gamepad_button, n);
for (i = 0; i < n; i++) {
s->buttons[i].irq = irq[i];
s->buttons[i].keycode = keycode[i];

View file

@ -1239,7 +1239,7 @@ void omap_clk_init(struct omap_mpu_state_s *mpu)
for (i = onchip_clks, count = 0; *i; i ++)
if ((*i)->flags & flag)
count ++;
mpu->clks = (struct clk *) g_malloc0(sizeof(struct clk) * (count + 1));
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));

View file

@ -826,8 +826,7 @@ struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu,
qemu_irq irq, qemu_irq drq)
{
int cs;
struct omap_gpmc_s *s = (struct omap_gpmc_s *)
g_malloc0(sizeof(struct omap_gpmc_s));
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);

View file

@ -157,8 +157,7 @@ static const MemoryRegionOps omap_sdrc_ops = {
struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem,
hwaddr base)
{
struct omap_sdrc_s *s = (struct omap_sdrc_s *)
g_malloc0(sizeof(struct omap_sdrc_s));
struct omap_sdrc_s *s = g_new0(struct omap_sdrc_s, 1);
omap_sdrc_reset(s);

View file

@ -19,6 +19,7 @@ common-obj-$(CONFIG_XGMAC) += xgmac.o
common-obj-$(CONFIG_MIPSNET) += mipsnet.o
common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
common-obj-$(CONFIG_ALLWINNER_EMAC) += allwinner_emac.o
common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
common-obj-$(CONFIG_CADENCE) += cadence_gem.o
common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o

709
hw/net/imx_fec.c Normal file
View file

@ -0,0 +1,709 @@
/*
* i.MX Fast Ethernet Controller emulation.
*
* Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
*
* Based on Coldfire Fast Ethernet Controller emulation.
*
* Copyright (c) 2007 CodeSourcery.
*
* 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 "hw/net/imx_fec.h"
#include "sysemu/dma.h"
/* For crc32 */
#include <zlib.h>
#ifndef IMX_FEC_DEBUG
#define IMX_FEC_DEBUG 0
#endif
#ifndef IMX_PHY_DEBUG
#define IMX_PHY_DEBUG 0
#endif
#if IMX_FEC_DEBUG
#define FEC_PRINTF(fmt, ...) \
do { fprintf(stderr, "%s[%s]: " fmt , TYPE_IMX_FEC, __func__, \
## __VA_ARGS__); \
} while (0)
#else
#define FEC_PRINTF(fmt, ...) do {} while (0)
#endif
#if IMX_PHY_DEBUG
#define PHY_PRINTF(fmt, ...) \
do { fprintf(stderr, "%s.phy[%s]: " fmt , TYPE_IMX_FEC, __func__, \
## __VA_ARGS__); \
} while (0)
#else
#define PHY_PRINTF(fmt, ...) do {} while (0)
#endif
static const VMStateDescription vmstate_imx_fec = {
.name = TYPE_IMX_FEC,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(irq_state, IMXFECState),
VMSTATE_UINT32(eir, IMXFECState),
VMSTATE_UINT32(eimr, IMXFECState),
VMSTATE_UINT32(rx_enabled, IMXFECState),
VMSTATE_UINT32(rx_descriptor, IMXFECState),
VMSTATE_UINT32(tx_descriptor, IMXFECState),
VMSTATE_UINT32(ecr, IMXFECState),
VMSTATE_UINT32(mmfr, IMXFECState),
VMSTATE_UINT32(mscr, IMXFECState),
VMSTATE_UINT32(mibc, IMXFECState),
VMSTATE_UINT32(rcr, IMXFECState),
VMSTATE_UINT32(tcr, IMXFECState),
VMSTATE_UINT32(tfwr, IMXFECState),
VMSTATE_UINT32(frsr, IMXFECState),
VMSTATE_UINT32(erdsr, IMXFECState),
VMSTATE_UINT32(etdsr, IMXFECState),
VMSTATE_UINT32(emrbr, IMXFECState),
VMSTATE_UINT32(miigsk_cfgr, IMXFECState),
VMSTATE_UINT32(miigsk_enr, IMXFECState),
VMSTATE_UINT32(phy_status, IMXFECState),
VMSTATE_UINT32(phy_control, IMXFECState),
VMSTATE_UINT32(phy_advertise, IMXFECState),
VMSTATE_UINT32(phy_int, IMXFECState),
VMSTATE_UINT32(phy_int_mask, IMXFECState),
VMSTATE_END_OF_LIST()
}
};
#define PHY_INT_ENERGYON (1 << 7)
#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
#define PHY_INT_FAULT (1 << 5)
#define PHY_INT_DOWN (1 << 4)
#define PHY_INT_AUTONEG_LP (1 << 3)
#define PHY_INT_PARFAULT (1 << 2)
#define PHY_INT_AUTONEG_PAGE (1 << 1)
static void imx_fec_update(IMXFECState *s);
/*
* The MII phy could raise a GPIO to the processor which in turn
* could be handled as an interrpt by the OS.
* For now we don't handle any GPIO/interrupt line, so the OS will
* have to poll for the PHY status.
*/
static void phy_update_irq(IMXFECState *s)
{
imx_fec_update(s);
}
static void phy_update_link(IMXFECState *s)
{
/* Autonegotiation status mirrors link status. */
if (qemu_get_queue(s->nic)->link_down) {
PHY_PRINTF("link is down\n");
s->phy_status &= ~0x0024;
s->phy_int |= PHY_INT_DOWN;
} else {
PHY_PRINTF("link is up\n");
s->phy_status |= 0x0024;
s->phy_int |= PHY_INT_ENERGYON;
s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
}
phy_update_irq(s);
}
static void imx_fec_set_link(NetClientState *nc)
{
phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
}
static void phy_reset(IMXFECState *s)
{
s->phy_status = 0x7809;
s->phy_control = 0x3000;
s->phy_advertise = 0x01e1;
s->phy_int_mask = 0;
s->phy_int = 0;
phy_update_link(s);
}
static uint32_t do_phy_read(IMXFECState *s, int reg)
{
uint32_t val;
if (reg > 31) {
/* we only advertise one phy */
return 0;
}
switch (reg) {
case 0: /* Basic Control */
val = s->phy_control;
break;
case 1: /* Basic Status */
val = s->phy_status;
break;
case 2: /* ID1 */
val = 0x0007;
break;
case 3: /* ID2 */
val = 0xc0d1;
break;
case 4: /* Auto-neg advertisement */
val = s->phy_advertise;
break;
case 5: /* Auto-neg Link Partner Ability */
val = 0x0f71;
break;
case 6: /* Auto-neg Expansion */
val = 1;
break;
case 29: /* Interrupt source. */
val = s->phy_int;
s->phy_int = 0;
phy_update_irq(s);
break;
case 30: /* Interrupt mask */
val = s->phy_int_mask;
break;
case 17:
case 18:
case 27:
case 31:
qemu_log_mask(LOG_UNIMP, "%s.phy[%s]: reg %d not implemented\n",
TYPE_IMX_FEC, __func__, reg);
val = 0;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, reg);
val = 0;
break;
}
PHY_PRINTF("read 0x%04x @ %d\n", val, reg);
return val;
}
static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
{
PHY_PRINTF("write 0x%04x @ %d\n", val, reg);
if (reg > 31) {
/* we only advertise one phy */
return;
}
switch (reg) {
case 0: /* Basic Control */
if (val & 0x8000) {
phy_reset(s);
} else {
s->phy_control = val & 0x7980;
/* Complete autonegotiation immediately. */
if (val & 0x1000) {
s->phy_status |= 0x0020;
}
}
break;
case 4: /* Auto-neg advertisement */
s->phy_advertise = (val & 0x2d7f) | 0x80;
break;
case 30: /* Interrupt mask */
s->phy_int_mask = val & 0xff;
phy_update_irq(s);
break;
case 17:
case 18:
case 27:
case 31:
qemu_log_mask(LOG_UNIMP, "%s.phy[%s]: reg %d not implemented\n",
TYPE_IMX_FEC, __func__, reg);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s.phy[%s]: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, reg);
break;
}
}
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
{
dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
}
static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr)
{
dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd));
}
static void imx_fec_update(IMXFECState *s)
{
uint32_t active;
uint32_t changed;
active = s->eir & s->eimr;
changed = active ^ s->irq_state;
if (changed) {
qemu_set_irq(s->irq, active);
}
s->irq_state = active;
}
static void imx_fec_do_tx(IMXFECState *s)
{
int frame_size = 0;
uint8_t frame[FEC_MAX_FRAME_SIZE];
uint8_t *ptr = frame;
uint32_t addr = s->tx_descriptor;
while (1) {
IMXFECBufDesc bd;
int len;
imx_fec_read_bd(&bd, addr);
FEC_PRINTF("tx_bd %x flags %04x len %d data %08x\n",
addr, bd.flags, bd.length, bd.data);
if ((bd.flags & FEC_BD_R) == 0) {
/* Run out of descriptors to transmit. */
break;
}
len = bd.length;
if (frame_size + len > FEC_MAX_FRAME_SIZE) {
len = FEC_MAX_FRAME_SIZE - frame_size;
s->eir |= FEC_INT_BABT;
}
dma_memory_read(&address_space_memory, bd.data, ptr, len);
ptr += len;
frame_size += len;
if (bd.flags & FEC_BD_L) {
/* Last buffer in frame. */
qemu_send_packet(qemu_get_queue(s->nic), frame, len);
ptr = frame;
frame_size = 0;
s->eir |= FEC_INT_TXF;
}
s->eir |= FEC_INT_TXB;
bd.flags &= ~FEC_BD_R;
/* Write back the modified descriptor. */
imx_fec_write_bd(&bd, addr);
/* Advance to the next descriptor. */
if ((bd.flags & FEC_BD_W) != 0) {
addr = s->etdsr;
} else {
addr += 8;
}
}
s->tx_descriptor = addr;
imx_fec_update(s);
}
static void imx_fec_enable_rx(IMXFECState *s)
{
IMXFECBufDesc bd;
uint32_t tmp;
imx_fec_read_bd(&bd, s->rx_descriptor);
tmp = ((bd.flags & FEC_BD_E) != 0);
if (!tmp) {
FEC_PRINTF("RX buffer full\n");
} else if (!s->rx_enabled) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
s->rx_enabled = tmp;
}
static void imx_fec_reset(DeviceState *d)
{
IMXFECState *s = IMX_FEC(d);
/* Reset the FEC */
s->eir = 0;
s->eimr = 0;
s->rx_enabled = 0;
s->ecr = 0;
s->mscr = 0;
s->mibc = 0xc0000000;
s->rcr = 0x05ee0001;
s->tcr = 0;
s->tfwr = 0;
s->frsr = 0x500;
s->miigsk_cfgr = 0;
s->miigsk_enr = 0x6;
/* We also reset the PHY */
phy_reset(s);
}
static uint64_t imx_fec_read(void *opaque, hwaddr addr, unsigned size)
{
IMXFECState *s = IMX_FEC(opaque);
FEC_PRINTF("reading from @ 0x%03x\n", (int)addr);
switch (addr & 0x3ff) {
case 0x004:
return s->eir;
case 0x008:
return s->eimr;
case 0x010:
return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
case 0x014:
return 0; /* TDAR */
case 0x024:
return s->ecr;
case 0x040:
return s->mmfr;
case 0x044:
return s->mscr;
case 0x064:
return s->mibc; /* MIBC */
case 0x084:
return s->rcr;
case 0x0c4:
return s->tcr;
case 0x0e4: /* PALR */
return (s->conf.macaddr.a[0] << 24)
| (s->conf.macaddr.a[1] << 16)
| (s->conf.macaddr.a[2] << 8)
| s->conf.macaddr.a[3];
break;
case 0x0e8: /* PAUR */
return (s->conf.macaddr.a[4] << 24)
| (s->conf.macaddr.a[5] << 16)
| 0x8808;
case 0x0ec:
return 0x10000; /* OPD */
case 0x118:
return 0;
case 0x11c:
return 0;
case 0x120:
return 0;
case 0x124:
return 0;
case 0x144:
return s->tfwr;
case 0x14c:
return 0x600;
case 0x150:
return s->frsr;
case 0x180:
return s->erdsr;
case 0x184:
return s->etdsr;
case 0x188:
return s->emrbr;
case 0x300:
return s->miigsk_cfgr;
case 0x308:
return s->miigsk_enr;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, (int)addr);
return 0;
}
}
static void imx_fec_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
IMXFECState *s = IMX_FEC(opaque);
FEC_PRINTF("writing 0x%08x @ 0x%03x\n", (int)value, (int)addr);
switch (addr & 0x3ff) {
case 0x004: /* EIR */
s->eir &= ~value;
break;
case 0x008: /* EIMR */
s->eimr = value;
break;
case 0x010: /* RDAR */
if ((s->ecr & FEC_EN) && !s->rx_enabled) {
imx_fec_enable_rx(s);
}
break;
case 0x014: /* TDAR */
if (s->ecr & FEC_EN) {
imx_fec_do_tx(s);
}
break;
case 0x024: /* ECR */
s->ecr = value;
if (value & FEC_RESET) {
imx_fec_reset(DEVICE(s));
}
if ((s->ecr & FEC_EN) == 0) {
s->rx_enabled = 0;
}
break;
case 0x040: /* MMFR */
/* store the value */
s->mmfr = value;
if (extract32(value, 28, 1)) {
do_phy_write(s, extract32(value, 18, 9), extract32(value, 0, 16));
} else {
s->mmfr = do_phy_read(s, extract32(value, 18, 9));
}
/* raise the interrupt as the PHY operation is done */
s->eir |= FEC_INT_MII;
break;
case 0x044: /* MSCR */
s->mscr = value & 0xfe;
break;
case 0x064: /* MIBC */
/* TODO: Implement MIB. */
s->mibc = (value & 0x80000000) ? 0xc0000000 : 0;
break;
case 0x084: /* RCR */
s->rcr = value & 0x07ff003f;
/* TODO: Implement LOOP mode. */
break;
case 0x0c4: /* TCR */
/* We transmit immediately, so raise GRA immediately. */
s->tcr = value;
if (value & 1) {
s->eir |= FEC_INT_GRA;
}
break;
case 0x0e4: /* PALR */
s->conf.macaddr.a[0] = value >> 24;
s->conf.macaddr.a[1] = value >> 16;
s->conf.macaddr.a[2] = value >> 8;
s->conf.macaddr.a[3] = value;
break;
case 0x0e8: /* PAUR */
s->conf.macaddr.a[4] = value >> 24;
s->conf.macaddr.a[5] = value >> 16;
break;
case 0x0ec: /* OPDR */
break;
case 0x118: /* IAUR */
case 0x11c: /* IALR */
case 0x120: /* GAUR */
case 0x124: /* GALR */
/* TODO: implement MAC hash filtering. */
break;
case 0x144: /* TFWR */
s->tfwr = value & 3;
break;
case 0x14c: /* FRBR */
/* FRBR writes ignored. */
break;
case 0x150: /* FRSR */
s->frsr = (value & 0x3fc) | 0x400;
break;
case 0x180: /* ERDSR */
s->erdsr = value & ~3;
s->rx_descriptor = s->erdsr;
break;
case 0x184: /* ETDSR */
s->etdsr = value & ~3;
s->tx_descriptor = s->etdsr;
break;
case 0x188: /* EMRBR */
s->emrbr = value & 0x7f0;
break;
case 0x300: /* MIIGSK_CFGR */
s->miigsk_cfgr = value & 0x53;
break;
case 0x308: /* MIIGSK_ENR */
s->miigsk_enr = (value & 0x2) ? 0x6 : 0;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, (int)addr);
break;
}
imx_fec_update(s);
}
static int imx_fec_can_receive(NetClientState *nc)
{
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
return s->rx_enabled;
}
static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
size_t len)
{
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
IMXFECBufDesc bd;
uint32_t flags = 0;
uint32_t addr;
uint32_t crc;
uint32_t buf_addr;
uint8_t *crc_ptr;
unsigned int buf_len;
size_t size = len;
FEC_PRINTF("len %d\n", (int)size);
if (!s->rx_enabled) {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Unexpected packet\n",
TYPE_IMX_FEC, __func__);
return 0;
}
/* 4 bytes for the CRC. */
size += 4;
crc = cpu_to_be32(crc32(~0, buf, size));
crc_ptr = (uint8_t *) &crc;
/* Huge frames are truncted. */
if (size > FEC_MAX_FRAME_SIZE) {
size = FEC_MAX_FRAME_SIZE;
flags |= FEC_BD_TR | FEC_BD_LG;
}
/* Frames larger than the user limit just set error flags. */
if (size > (s->rcr >> 16)) {
flags |= FEC_BD_LG;
}
addr = s->rx_descriptor;
while (size > 0) {
imx_fec_read_bd(&bd, addr);
if ((bd.flags & FEC_BD_E) == 0) {
/* No descriptors available. Bail out. */
/*
* FIXME: This is wrong. We should probably either
* save the remainder for when more RX buffers are
* available, or flag an error.
*/
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Lost end of frame\n",
TYPE_IMX_FEC, __func__);
break;
}
buf_len = (size <= s->emrbr) ? size : s->emrbr;
bd.length = buf_len;
size -= buf_len;
FEC_PRINTF("rx_bd %x length %d\n", addr, bd.length);
/* The last 4 bytes are the CRC. */
if (size < 4) {
buf_len += size - 4;
}
buf_addr = bd.data;
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
buf += buf_len;
if (size < 4) {
dma_memory_write(&address_space_memory, buf_addr + buf_len,
crc_ptr, 4 - size);
crc_ptr += 4 - size;
}
bd.flags &= ~FEC_BD_E;
if (size == 0) {
/* Last buffer in frame. */
bd.flags |= flags | FEC_BD_L;
FEC_PRINTF("rx frame flags %04x\n", bd.flags);
s->eir |= FEC_INT_RXF;
} else {
s->eir |= FEC_INT_RXB;
}
imx_fec_write_bd(&bd, addr);
/* Advance to the next descriptor. */
if ((bd.flags & FEC_BD_W) != 0) {
addr = s->erdsr;
} else {
addr += 8;
}
}
s->rx_descriptor = addr;
imx_fec_enable_rx(s);
imx_fec_update(s);
return len;
}
static const MemoryRegionOps imx_fec_ops = {
.read = imx_fec_read,
.write = imx_fec_write,
.valid.min_access_size = 4,
.valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void imx_fec_cleanup(NetClientState *nc)
{
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
s->nic = NULL;
}
static NetClientInfo net_imx_fec_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = imx_fec_can_receive,
.receive = imx_fec_receive,
.cleanup = imx_fec_cleanup,
.link_status_changed = imx_fec_set_link,
};
static void imx_fec_realize(DeviceState *dev, Error **errp)
{
IMXFECState *s = IMX_FEC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
memory_region_init_io(&s->iomem, OBJECT(dev), &imx_fec_ops, s,
TYPE_IMX_FEC, 0x400);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->conf.peers.ncs[0] = nd_table[0].netdev;
s->nic = qemu_new_nic(&net_imx_fec_info, &s->conf,
object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
static Property imx_fec_properties[] = {
DEFINE_NIC_PROPERTIES(IMXFECState, conf),
DEFINE_PROP_END_OF_LIST(),
};
static void imx_fec_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_imx_fec;
dc->reset = imx_fec_reset;
dc->props = imx_fec_properties;
dc->realize = imx_fec_realize;
}
static const TypeInfo imx_fec_info = {
.name = TYPE_IMX_FEC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXFECState),
.class_init = imx_fec_class_init,
};
static void imx_fec_register_types(void)
{
type_register_static(&imx_fec_info);
}
type_init(imx_fec_register_types)

View file

@ -578,8 +578,7 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
BlockBackend *blk,
qemu_irq irq, qemu_irq dma[], omap_clk clk)
{
struct omap_mmc_s *s = (struct omap_mmc_s *)
g_malloc0(sizeof(struct omap_mmc_s));
struct omap_mmc_s *s = g_new0(struct omap_mmc_s, 1);
s->irq = irq;
s->dma = dma;
@ -605,8 +604,7 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
BlockBackend *blk, qemu_irq irq, qemu_irq dma[],
omap_clk fclk, omap_clk iclk)
{
struct omap_mmc_s *s = (struct omap_mmc_s *)
g_malloc0(sizeof(struct omap_mmc_s));
struct omap_mmc_s *s = g_new0(struct omap_mmc_s, 1);
s->irq = irq;
s->dma = dma;

View file

@ -55,7 +55,9 @@ static uint8_t *smbios_tables;
static size_t smbios_tables_len;
static unsigned smbios_table_max;
static unsigned smbios_table_cnt;
static struct smbios_entry_point ep;
static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_21;
static SmbiosEntryPoint ep;
static int smbios_type4_count = 0;
static bool smbios_immutable;
@ -771,11 +773,12 @@ void smbios_set_cpuid(uint32_t version, uint32_t features)
void smbios_set_defaults(const char *manufacturer, const char *product,
const char *version, bool legacy_mode,
bool uuid_encoded)
bool uuid_encoded, SmbiosEntryPointType ep_type)
{
smbios_have_defaults = true;
smbios_legacy = legacy_mode;
smbios_uuid_encoded = uuid_encoded;
smbios_ep_type = ep_type;
/* drop unwanted version of command-line file blob(s) */
if (smbios_legacy) {
@ -808,26 +811,53 @@ void smbios_set_defaults(const char *manufacturer, const char *product,
static void smbios_entry_point_setup(void)
{
memcpy(ep.anchor_string, "_SM_", 4);
memcpy(ep.intermediate_anchor_string, "_DMI_", 5);
ep.length = sizeof(struct smbios_entry_point);
ep.entry_point_revision = 0; /* formatted_area reserved, per spec v2.1+ */
memset(ep.formatted_area, 0, 5);
switch (smbios_ep_type) {
case SMBIOS_ENTRY_POINT_21:
memcpy(ep.ep21.anchor_string, "_SM_", 4);
memcpy(ep.ep21.intermediate_anchor_string, "_DMI_", 5);
ep.ep21.length = sizeof(struct smbios_21_entry_point);
ep.ep21.entry_point_revision = 0; /* formatted_area reserved */
memset(ep.ep21.formatted_area, 0, 5);
/* compliant with smbios spec v2.8 */
ep.smbios_major_version = 2;
ep.smbios_minor_version = 8;
ep.smbios_bcd_revision = 0x28;
/* compliant with smbios spec v2.8 */
ep.ep21.smbios_major_version = 2;
ep.ep21.smbios_minor_version = 8;
ep.ep21.smbios_bcd_revision = 0x28;
/* set during table construction, but BIOS may override: */
ep.structure_table_length = cpu_to_le16(smbios_tables_len);
ep.max_structure_size = cpu_to_le16(smbios_table_max);
ep.number_of_structures = cpu_to_le16(smbios_table_cnt);
/* set during table construction, but BIOS may override: */
ep.ep21.structure_table_length = cpu_to_le16(smbios_tables_len);
ep.ep21.max_structure_size = cpu_to_le16(smbios_table_max);
ep.ep21.number_of_structures = cpu_to_le16(smbios_table_cnt);
/* BIOS must recalculate: */
ep.checksum = 0;
ep.intermediate_checksum = 0;
ep.structure_table_address = cpu_to_le32(0);
/* BIOS must recalculate */
ep.ep21.checksum = 0;
ep.ep21.intermediate_checksum = 0;
ep.ep21.structure_table_address = cpu_to_le32(0);
break;
case SMBIOS_ENTRY_POINT_30:
memcpy(ep.ep30.anchor_string, "_SM3_", 5);
ep.ep30.length = sizeof(struct smbios_30_entry_point);
ep.ep30.entry_point_revision = 1;
ep.ep30.reserved = 0;
/* compliant with smbios spec 3.0 */
ep.ep30.smbios_major_version = 3;
ep.ep30.smbios_minor_version = 0;
ep.ep30.smbios_doc_rev = 0;
/* set during table construct, but BIOS might override */
ep.ep30.structure_table_max_size = cpu_to_le32(smbios_tables_len);
/* BIOS must recalculate */
ep.ep30.checksum = 0;
ep.ep30.structure_table_address = cpu_to_le64(0);
break;
default:
abort();
break;
}
}
void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
@ -885,7 +915,15 @@ void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
*tables = smbios_tables;
*tables_len = smbios_tables_len;
*anchor = (uint8_t *)&ep;
*anchor_len = sizeof(struct smbios_entry_point);
/* calculate length based on anchor string */
if (!strncmp((char *)&ep, "_SM_", 4)) {
*anchor_len = sizeof(struct smbios_21_entry_point);
} else if (!strncmp((char *)&ep, "_SM3_", 5)) {
*anchor_len = sizeof(struct smbios_30_entry_point);
} else {
abort();
}
}
static void save_opt(const char **dest, QemuOpts *opts, const char *name)

View file

@ -342,8 +342,7 @@ static const MemoryRegionOps omap_mcspi_ops = {
struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
{
struct omap_mcspi_s *s = (struct omap_mcspi_s *)
g_malloc0(sizeof(struct omap_mcspi_s));
struct omap_mcspi_s *s = g_new0(struct omap_mcspi_s, 1);
struct omap_mcspi_ch_s *ch = s->ch;
s->irq = irq;

View file

@ -12,7 +12,6 @@
*
*/
#include "hw/arm/imx.h"
#include "hw/timer/imx_epit.h"
#include "hw/misc/imx_ccm.h"
#include "qemu/main-loop.h"
@ -287,16 +286,6 @@ static void imx_epit_cmp(void *opaque)
imx_epit_update_int(s);
}
void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
{
IMXEPITState *pp;
DeviceState *dev;
dev = sysbus_create_simple(TYPE_IMX_EPIT, addr, irq);
pp = IMX_EPIT(dev);
pp->ccm = ccm;
}
static const MemoryRegionOps imx_epit_ops = {
.read = imx_epit_read,
.write = imx_epit_write,

View file

@ -12,7 +12,6 @@
*
*/
#include "hw/arm/imx.h"
#include "hw/timer/imx_gpt.h"
#include "hw/misc/imx_ccm.h"
#include "qemu/main-loop.h"
@ -449,16 +448,6 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
s->timer = ptimer_init(bh);
}
void imx_timerg_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
{
IMXGPTState *pp;
DeviceState *dev;
dev = sysbus_create_simple(TYPE_IMX_GPT, addr, irq);
pp = IMX_GPT(dev);
pp->ccm = ccm;
}
static void imx_gpt_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);

View file

@ -468,8 +468,7 @@ static const MemoryRegionOps omap_gp_timer_ops = {
struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
qemu_irq irq, omap_clk fclk, omap_clk iclk)
{
struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
g_malloc0(sizeof(struct omap_gp_timer_s));
struct omap_gp_timer_s *s = g_new0(struct omap_gp_timer_s, 1);
s->ta = ta;
s->irq = irq;

View file

@ -14,7 +14,34 @@
typedef void (*gdb_syscall_complete_cb)(CPUState *cpu,
target_ulong ret, target_ulong err);
/**
* gdb_do_syscall:
* @cb: function to call when the system call has completed
* @fmt: gdb syscall format string
* ...: list of arguments to interpolate into @fmt
*
* Send a GDB syscall request. This function will return immediately;
* the callback function will be called later when the remote system
* call has completed.
*
* @fmt should be in the 'call-id,parameter,parameter...' format documented
* for the F request packet in the GDB remote protocol. A limited set of
* printf-style format specifiers is supported:
* %x - target_ulong argument printed in hex
* %lx - 64-bit argument printed in hex
* %s - string pointer (target_ulong) and length (int) pair
*/
void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
/**
* gdb_do_syscallv:
* @cb: function to call when the system call has completed
* @fmt: gdb syscall format string
* @va: arguments to interpolate into @fmt
*
* As gdb_do_syscall, but taking a va_list rather than a variable
* argument list.
*/
void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va);
int use_gdb_syscalls(void);
void gdb_set_stop_cpu(CPUState *cpu);
void gdb_exit(CPUArchState *, int);

View file

@ -9,6 +9,14 @@
#ifndef SOFTMMU_SEMI_H
#define SOFTMMU_SEMI_H 1
static inline uint64_t softmmu_tget64(CPUArchState *env, target_ulong addr)
{
uint64_t val;
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 8, 0);
return tswap64(val);
}
static inline uint32_t softmmu_tget32(CPUArchState *env, target_ulong addr)
{
uint32_t val;
@ -16,6 +24,7 @@ static inline uint32_t softmmu_tget32(CPUArchState *env, target_ulong addr)
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 0);
return tswap32(val);
}
static inline uint32_t softmmu_tget8(CPUArchState *env, target_ulong addr)
{
uint8_t val;
@ -24,16 +33,25 @@ static inline uint32_t softmmu_tget8(CPUArchState *env, target_ulong addr)
return val;
}
#define get_user_u64(arg, p) ({ arg = softmmu_tget64(env, p); 0; })
#define get_user_u32(arg, p) ({ arg = softmmu_tget32(env, p) ; 0; })
#define get_user_u8(arg, p) ({ arg = softmmu_tget8(env, p) ; 0; })
#define get_user_ual(arg, p) get_user_u32(arg, p)
static inline void softmmu_tput64(CPUArchState *env,
target_ulong addr, uint64_t val)
{
val = tswap64(val);
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 8, 1);
}
static inline void softmmu_tput32(CPUArchState *env,
target_ulong addr, uint32_t val)
{
val = tswap32(val);
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 1);
}
#define put_user_u64(arg, p) ({ softmmu_tput64(env, p, arg) ; 0; })
#define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
#define put_user_ual(arg, p) put_user_u32(arg, p)

234
include/hw/arm/fsl-imx25.h Normal file
View file

@ -0,0 +1,234 @@
/*
* Freescale i.MX25 SoC emulation
*
* Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* 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.
*/
#ifndef FSL_IMX25_H
#define FSL_IMX25_H
#include "hw/arm/arm.h"
#include "hw/intc/imx_avic.h"
#include "hw/misc/imx_ccm.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
#include "hw/timer/imx_epit.h"
#include "hw/net/imx_fec.h"
#include "hw/i2c/imx_i2c.h"
#include "exec/memory.h"
#define TYPE_FSL_IMX25 "fsl,imx25"
#define FSL_IMX25(obj) OBJECT_CHECK(FslIMX25State, (obj), TYPE_FSL_IMX25)
#define FSL_IMX25_NUM_UARTS 5
#define FSL_IMX25_NUM_GPTS 4
#define FSL_IMX25_NUM_EPITS 2
#define FSL_IMX25_NUM_I2CS 3
typedef struct FslIMX25State {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
ARMCPU cpu;
IMXAVICState avic;
IMXCCMState ccm;
IMXSerialState uart[FSL_IMX25_NUM_UARTS];
IMXGPTState gpt[FSL_IMX25_NUM_GPTS];
IMXEPITState epit[FSL_IMX25_NUM_EPITS];
IMXFECState fec;
IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
MemoryRegion rom[2];
MemoryRegion iram;
MemoryRegion iram_alias;
} FslIMX25State;
/**
* i.MX25 memory map
****************************************************************
* 0x0000_0000 0x0000_3FFF 16 Kbytes ROM (36 Kbytes)
* 0x0000_4000 0x0040_3FFF 4 Mbytes Reserved
* 0x0040_4000 0x0040_8FFF 20 Kbytes ROM (36 Kbytes)
* 0x0040_9000 0x0FFF_FFFF 252 Mbytes (minus 36 Kbytes) Reserved
* 0x1000_0000 0x1FFF_FFFF 256 Mbytes Reserved
* 0x2000_0000 0x2FFF_FFFF 256 Mbytes Reserved
* 0x3000_0000 0x3FFF_FFFF 256 Mbytes Reserved
* 0x4000_0000 0x43EF_FFFF 63 Mbytes Reserved
* 0x43F0_0000 0x43F0_3FFF 16 Kbytes AIPS A control registers
* 0x43F0_4000 0x43F0_7FFF 16 Kbytes ARM926 platform MAX
* 0x43F0_8000 0x43F0_BFFF 16 Kbytes ARM926 platform CLKCTL
* 0x43F0_C000 0x43F0_FFFF 16 Kbytes ARM926 platform ETB registers
* 0x43F1_0000 0x43F1_3FFF 16 Kbytes ARM926 platform ETB memory
* 0x43F1_4000 0x43F1_7FFF 16 Kbytes ARM926 platform AAPE registers
* 0x43F1_8000 0x43F7_FFFF 416 Kbytes Reserved
* 0x43F8_0000 0x43F8_3FFF 16 Kbytes I2C-1
* 0x43F8_4000 0x43F8_7FFF 16 Kbytes I2C-3
* 0x43F8_8000 0x43F8_BFFF 16 Kbytes CAN-1
* 0x43F8_C000 0x43F8_FFFF 16 Kbytes CAN-2
* 0x43F9_0000 0x43F9_3FFF 16 Kbytes UART-1
* 0x43F9_4000 0x43F9_7FFF 16 Kbytes UART-2
* 0x43F9_8000 0x43F9_BFFF 16 Kbytes I2C-2
* 0x43F9_C000 0x43F9_FFFF 16 Kbytes 1-Wire
* 0x43FA_0000 0x43FA_3FFF 16 Kbytes ATA (CPU side)
* 0x43FA_4000 0x43FA_7FFF 16 Kbytes CSPI-1
* 0x43FA_8000 0x43FA_BFFF 16 Kbytes KPP
* 0x43FA_C000 0x43FA_FFFF 16 Kbytes IOMUXC
* 0x43FB_0000 0x43FB_3FFF 16 Kbytes AUDMUX
* 0x43FB_4000 0x43FB_7FFF 16 Kbytes Reserved
* 0x43FB_8000 0x43FB_BFFF 16 Kbytes ECT (IP BUS A)
* 0x43FB_C000 0x43FB_FFFF 16 Kbytes ECT (IP BUS B)
* 0x43FC_0000 0x43FF_FFFF 256 Kbytes Reserved AIPS A off-platform slots
* 0x4400_0000 0x4FFF_FFFF 192 Mbytes Reserved
* 0x5000_0000 0x5000_3FFF 16 Kbytes SPBA base address
* 0x5000_4000 0x5000_7FFF 16 Kbytes CSPI-3
* 0x5000_8000 0x5000_BFFF 16 Kbytes UART-4
* 0x5000_C000 0x5000_FFFF 16 Kbytes UART-3
* 0x5001_0000 0x5001_3FFF 16 Kbytes CSPI-2
* 0x5001_4000 0x5001_7FFF 16 Kbytes SSI-2
* 0x5001_C000 0x5001_FFFF 16 Kbytes Reserved
* 0x5002_0000 0x5002_3FFF 16 Kbytes ATA
* 0x5002_4000 0x5002_7FFF 16 Kbytes SIM-1
* 0x5002_8000 0x5002_BFFF 16 Kbytes SIM-2
* 0x5002_C000 0x5002_FFFF 16 Kbytes UART-5
* 0x5003_0000 0x5003_3FFF 16 Kbytes TSC
* 0x5003_4000 0x5003_7FFF 16 Kbytes SSI-1
* 0x5003_8000 0x5003_BFFF 16 Kbytes FEC
* 0x5003_C000 0x5003_FFFF 16 Kbytes SPBA registers
* 0x5004_0000 0x51FF_FFFF 32 Mbytes (minus 256 Kbytes)
* 0x5200_0000 0x53EF_FFFF 31 Mbytes Reserved
* 0x53F0_0000 0x53F0_3FFF 16 Kbytes AIPS B control registers
* 0x53F0_4000 0x53F7_FFFF 496 Kbytes Reserved
* 0x53F8_0000 0x53F8_3FFF 16 Kbytes CCM
* 0x53F8_4000 0x53F8_7FFF 16 Kbytes GPT-4
* 0x53F8_8000 0x53F8_BFFF 16 Kbytes GPT-3
* 0x53F8_C000 0x53F8_FFFF 16 Kbytes GPT-2
* 0x53F9_0000 0x53F9_3FFF 16 Kbytes GPT-1
* 0x53F9_4000 0x53F9_7FFF 16 Kbytes EPIT-1
* 0x53F9_8000 0x53F9_BFFF 16 Kbytes EPIT-2
* 0x53F9_C000 0x53F9_FFFF 16 Kbytes GPIO-4
* 0x53FA_0000 0x53FA_3FFF 16 Kbytes PWM-2
* 0x53FA_4000 0x53FA_7FFF 16 Kbytes GPIO-3
* 0x53FA_8000 0x53FA_BFFF 16 Kbytes PWM-3
* 0x53FA_C000 0x53FA_FFFF 16 Kbytes SCC
* 0x53FB_0000 0x53FB_3FFF 16 Kbytes RNGB
* 0x53FB_4000 0x53FB_7FFF 16 Kbytes eSDHC-1
* 0x53FB_8000 0x53FB_BFFF 16 Kbytes eSDHC-2
* 0x53FB_C000 0x53FB_FFFF 16 Kbytes LCDC
* 0x53FC_0000 0x53FC_3FFF 16 Kbytes SLCDC
* 0x53FC_4000 0x53FC_7FFF 16 Kbytes Reserved
* 0x53FC_8000 0x53FC_BFFF 16 Kbytes PWM-4
* 0x53FC_C000 0x53FC_FFFF 16 Kbytes GPIO-1
* 0x53FD_0000 0x53FD_3FFF 16 Kbytes GPIO-2
* 0x53FD_4000 0x53FD_7FFF 16 Kbytes SDMA
* 0x53FD_8000 0x53FD_BFFF 16 Kbytes Reserved
* 0x53FD_C000 0x53FD_FFFF 16 Kbytes WDOG
* 0x53FE_0000 0x53FE_3FFF 16 Kbytes PWM-1
* 0x53FE_4000 0x53FE_7FFF 16 Kbytes Reserved
* 0x53FE_8000 0x53FE_BFFF 16 Kbytes Reserved
* 0x53FE_C000 0x53FE_FFFF 16 Kbytes RTICv3
* 0x53FF_0000 0x53FF_3FFF 16 Kbytes IIM
* 0x53FF_4000 0x53FF_7FFF 16 Kbytes USB
* 0x53FF_8000 0x53FF_BFFF 16 Kbytes CSI
* 0x53FF_C000 0x53FF_FFFF 16 Kbytes DryIce
* 0x5400_0000 0x5FFF_FFFF 192 Mbytes Reserved (aliased AIPS B slots)
* 0x6000_0000 0x67FF_FFFF 128 Mbytes ARM926 platform ROMPATCH
* 0x6800_0000 0x6FFF_FFFF 128 Mbytes ARM926 platform ASIC
* 0x7000_0000 0x77FF_FFFF 128 Mbytes Reserved
* 0x7800_0000 0x7801_FFFF 128 Kbytes RAM
* 0x7802_0000 0x7FFF_FFFF 128 Mbytes (minus 128 Kbytes)
* 0x8000_0000 0x8FFF_FFFF 256 Mbytes SDRAM bank 0
* 0x9000_0000 0x9FFF_FFFF 256 Mbytes SDRAM bank 1
* 0xA000_0000 0xA7FF_FFFF 128 Mbytes WEIM CS0 (flash 128) 1
* 0xA800_0000 0xAFFF_FFFF 128 Mbytes WEIM CS1 (flash 64) 1
* 0xB000_0000 0xB1FF_FFFF 32 Mbytes WEIM CS2 (SRAM)
* 0xB200_0000 0xB3FF_FFFF 32 Mbytes WEIM CS3 (SRAM)
* 0xB400_0000 0xB5FF_FFFF 32 Mbytes WEIM CS4
* 0xB600_0000 0xB7FF_FFFF 32 Mbytes Reserved
* 0xB800_0000 0xB800_0FFF 4 Kbytes Reserved
* 0xB800_1000 0xB800_1FFF 4 Kbytes SDRAM control registers
* 0xB800_2000 0xB800_2FFF 4 Kbytes WEIM control registers
* 0xB800_3000 0xB800_3FFF 4 Kbytes M3IF control registers
* 0xB800_4000 0xB800_4FFF 4 Kbytes EMI control registers
* 0xB800_5000 0xBAFF_FFFF 32 Mbytes (minus 20 Kbytes)
* 0xBB00_0000 0xBB00_0FFF 4 Kbytes NAND flash main area buffer
* 0xBB00_1000 0xBB00_11FF 512 B NAND flash spare area buffer
* 0xBB00_1200 0xBB00_1DFF 3 Kbytes Reserved
* 0xBB00_1E00 0xBB00_1FFF 512 B NAND flash control regisers
* 0xBB01_2000 0xBFFF_FFFF 96 Mbytes (minus 8 Kbytes) Reserved
* 0xC000_0000 0xFFFF_FFFF 1024 Mbytes Reserved
*/
#define FSL_IMX25_ROM0_ADDR 0x00000000
#define FSL_IMX25_ROM0_SIZE 0x4000
#define FSL_IMX25_ROM1_ADDR 0x00404000
#define FSL_IMX25_ROM1_SIZE 0x4000
#define FSL_IMX25_I2C1_ADDR 0x43F80000
#define FSL_IMX25_I2C1_SIZE 0x4000
#define FSL_IMX25_I2C3_ADDR 0x43F84000
#define FSL_IMX25_I2C3_SIZE 0x4000
#define FSL_IMX25_UART1_ADDR 0x43F90000
#define FSL_IMX25_UART1_SIZE 0x4000
#define FSL_IMX25_UART2_ADDR 0x43F94000
#define FSL_IMX25_UART2_SIZE 0x4000
#define FSL_IMX25_I2C2_ADDR 0x43F98000
#define FSL_IMX25_I2C2_SIZE 0x4000
#define FSL_IMX25_UART4_ADDR 0x50008000
#define FSL_IMX25_UART4_SIZE 0x4000
#define FSL_IMX25_UART3_ADDR 0x5000C000
#define FSL_IMX25_UART3_SIZE 0x4000
#define FSL_IMX25_UART5_ADDR 0x5002C000
#define FSL_IMX25_UART5_SIZE 0x4000
#define FSL_IMX25_FEC_ADDR 0x50038000
#define FSL_IMX25_FEC_SIZE 0x4000
#define FSL_IMX25_CCM_ADDR 0x53F80000
#define FSL_IMX25_CCM_SIZE 0x4000
#define FSL_IMX25_GPT4_ADDR 0x53F84000
#define FSL_IMX25_GPT4_SIZE 0x4000
#define FSL_IMX25_GPT3_ADDR 0x53F88000
#define FSL_IMX25_GPT3_SIZE 0x4000
#define FSL_IMX25_GPT2_ADDR 0x53F8C000
#define FSL_IMX25_GPT2_SIZE 0x4000
#define FSL_IMX25_GPT1_ADDR 0x53F90000
#define FSL_IMX25_GPT1_SIZE 0x4000
#define FSL_IMX25_EPIT1_ADDR 0x53F94000
#define FSL_IMX25_EPIT1_SIZE 0x4000
#define FSL_IMX25_EPIT2_ADDR 0x53F98000
#define FSL_IMX25_EPIT2_SIZE 0x4000
#define FSL_IMX25_AVIC_ADDR 0x68000000
#define FSL_IMX25_AVIC_SIZE 0x4000
#define FSL_IMX25_IRAM_ADDR 0x78000000
#define FSL_IMX25_IRAM_SIZE 0x20000
#define FSL_IMX25_IRAM_ALIAS_ADDR 0x78020000
#define FSL_IMX25_IRAM_ALIAS_SIZE 0x7FE0000
#define FSL_IMX25_SDRAM0_ADDR 0x80000000
#define FSL_IMX25_SDRAM0_SIZE 0x10000000
#define FSL_IMX25_SDRAM1_ADDR 0x90000000
#define FSL_IMX25_SDRAM1_SIZE 0x10000000
#define FSL_IMX25_UART1_IRQ 45
#define FSL_IMX25_UART2_IRQ 32
#define FSL_IMX25_UART3_IRQ 18
#define FSL_IMX25_UART4_IRQ 5
#define FSL_IMX25_UART5_IRQ 40
#define FSL_IMX25_GPT1_IRQ 54
#define FSL_IMX25_GPT2_IRQ 53
#define FSL_IMX25_GPT3_IRQ 29
#define FSL_IMX25_GPT4_IRQ 1
#define FSL_IMX25_EPIT1_IRQ 28
#define FSL_IMX25_EPIT2_IRQ 27
#define FSL_IMX25_FEC_IRQ 57
#define FSL_IMX25_I2C1_IRQ 3
#define FSL_IMX25_I2C2_IRQ 4
#define FSL_IMX25_I2C3_IRQ 10
#endif /* FSL_IMX25_H */

110
include/hw/arm/fsl-imx31.h Normal file
View file

@ -0,0 +1,110 @@
/*
* Freescale i.MX31 SoC emulation
*
* Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* 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.
*/
#ifndef FSL_IMX31_H
#define FSL_IMX31_H
#include "hw/arm/arm.h"
#include "hw/intc/imx_avic.h"
#include "hw/misc/imx_ccm.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
#include "hw/timer/imx_epit.h"
#include "hw/i2c/imx_i2c.h"
#include "exec/memory.h"
#define TYPE_FSL_IMX31 "fsl,imx31"
#define FSL_IMX31(obj) OBJECT_CHECK(FslIMX31State, (obj), TYPE_FSL_IMX31)
#define FSL_IMX31_NUM_UARTS 2
#define FSL_IMX31_NUM_EPITS 2
#define FSL_IMX31_NUM_I2CS 3
typedef struct FslIMX31State {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
ARMCPU cpu;
IMXAVICState avic;
IMXCCMState ccm;
IMXSerialState uart[FSL_IMX31_NUM_UARTS];
IMXGPTState gpt;
IMXEPITState epit[FSL_IMX31_NUM_EPITS];
IMXI2CState i2c[FSL_IMX31_NUM_I2CS];
MemoryRegion secure_rom;
MemoryRegion rom;
MemoryRegion iram;
MemoryRegion iram_alias;
} FslIMX31State;
#define FSL_IMX31_SECURE_ROM_ADDR 0x00000000
#define FSL_IMX31_SECURE_ROM_SIZE 0x4000
#define FSL_IMX31_ROM_ADDR 0x00404000
#define FSL_IMX31_ROM_SIZE 0x4000
#define FSL_IMX31_IRAM_ALIAS_ADDR 0x10000000
#define FSL_IMX31_IRAM_ALIAS_SIZE 0xFFC0000
#define FSL_IMX31_IRAM_ADDR 0x1FFFC000
#define FSL_IMX31_IRAM_SIZE 0x4000
#define FSL_IMX31_I2C1_ADDR 0x43F80000
#define FSL_IMX31_I2C1_SIZE 0x4000
#define FSL_IMX31_I2C3_ADDR 0x43F84000
#define FSL_IMX31_I2C3_SIZE 0x4000
#define FSL_IMX31_UART1_ADDR 0x43F90000
#define FSL_IMX31_UART1_SIZE 0x4000
#define FSL_IMX31_UART2_ADDR 0x43F94000
#define FSL_IMX31_UART2_SIZE 0x4000
#define FSL_IMX31_I2C2_ADDR 0x43F98000
#define FSL_IMX31_I2C2_SIZE 0x4000
#define FSL_IMX31_CCM_ADDR 0x53F80000
#define FSL_IMX31_CCM_SIZE 0x4000
#define FSL_IMX31_GPT_ADDR 0x53F90000
#define FSL_IMX31_GPT_SIZE 0x4000
#define FSL_IMX31_EPIT1_ADDR 0x53F94000
#define FSL_IMX31_EPIT1_SIZE 0x4000
#define FSL_IMX31_EPIT2_ADDR 0x53F98000
#define FSL_IMX31_EPIT2_SIZE 0x4000
#define FSL_IMX31_AVIC_ADDR 0x68000000
#define FSL_IMX31_AVIC_SIZE 0x100
#define FSL_IMX31_SDRAM0_ADDR 0x80000000
#define FSL_IMX31_SDRAM0_SIZE 0x10000000
#define FSL_IMX31_SDRAM1_ADDR 0x90000000
#define FSL_IMX31_SDRAM1_SIZE 0x10000000
#define FSL_IMX31_FLASH0_ADDR 0xA0000000
#define FSL_IMX31_FLASH0_SIZE 0x8000000
#define FSL_IMX31_FLASH1_ADDR 0xA8000000
#define FSL_IMX31_FLASH1_SIZE 0x8000000
#define FSL_IMX31_CS2_ADDR 0xB0000000
#define FSL_IMX31_CS2_SIZE 0x2000000
#define FSL_IMX31_CS3_ADDR 0xB2000000
#define FSL_IMX31_CS3_SIZE 0x2000000
#define FSL_IMX31_CS4_ADDR 0xB4000000
#define FSL_IMX31_CS4_SIZE 0x2000000
#define FSL_IMX31_CS5_ADDR 0xB6000000
#define FSL_IMX31_CS5_SIZE 0x2000000
#define FSL_IMX31_NAND_ADDR 0xB8000000
#define FSL_IMX31_NAND_SIZE 0x1000
#define FSL_IMX31_EPIT2_IRQ 27
#define FSL_IMX31_EPIT1_IRQ 28
#define FSL_IMX31_GPT_IRQ 29
#define FSL_IMX31_UART2_IRQ 32
#define FSL_IMX31_UART1_IRQ 45
#define FSL_IMX31_I2C1_IRQ 10
#define FSL_IMX31_I2C2_IRQ 4
#define FSL_IMX31_I2C3_IRQ 3
#endif /* FSL_IMX31_H */

View file

@ -1,26 +0,0 @@
/*
* i.MX31 emulation
*
* Copyright (C) 2012 Peter Chubb
* NICTA
*
* This code is released under the GPL, version 2.0 or later
* See the file `../COPYING' for details.
*/
#ifndef IMX_H
#define IMX_H
#include "hw/misc/imx_ccm.h"
void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq);
void imx_timerp_create(const hwaddr addr,
qemu_irq irq,
DeviceState *ccm);
void imx_timerg_create(const hwaddr addr,
qemu_irq irq,
DeviceState *ccm);
#endif /* IMX_H */

View file

@ -31,6 +31,7 @@ typedef struct VirtGuestInfo {
FWCfgState *fw_cfg;
const MemMapEntry *memmap;
const int *irqmap;
bool use_highmem;
} VirtGuestInfo;

View file

@ -56,6 +56,7 @@ enum {
VIRT_PCIE_ECAM,
VIRT_GIC_V2M,
VIRT_PLATFORM_BUS,
VIRT_PCIE_MMIO_HIGH,
};
typedef struct MemMapEntry {

87
include/hw/i2c/imx_i2c.h Normal file
View file

@ -0,0 +1,87 @@
/*
* i.MX I2C Bus Serial Interface registers definition
*
* Copyright (C) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
*
* 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/>.
*
*/
#ifndef __IMX_I2C_H_
#define __IMX_I2C_H_
#include <hw/sysbus.h>
#define TYPE_IMX_I2C "imx.i2c"
#define IMX_I2C(obj) OBJECT_CHECK(IMXI2CState, (obj), TYPE_IMX_I2C)
#define IMX_I2C_MEM_SIZE 0x14
/* i.MX I2C memory map */
#define IADR_ADDR 0x00 /* address register */
#define IFDR_ADDR 0x04 /* frequency divider register */
#define I2CR_ADDR 0x08 /* control register */
#define I2SR_ADDR 0x0c /* status register */
#define I2DR_ADDR 0x10 /* data register */
#define IADR_MASK 0xFE
#define IADR_RESET 0
#define IFDR_MASK 0x3F
#define IFDR_RESET 0
#define I2CR_IEN (1 << 7)
#define I2CR_IIEN (1 << 6)
#define I2CR_MSTA (1 << 5)
#define I2CR_MTX (1 << 4)
#define I2CR_TXAK (1 << 3)
#define I2CR_RSTA (1 << 2)
#define I2CR_MASK 0xFC
#define I2CR_RESET 0
#define I2SR_ICF (1 << 7)
#define I2SR_IAAF (1 << 6)
#define I2SR_IBB (1 << 5)
#define I2SR_IAL (1 << 4)
#define I2SR_SRW (1 << 2)
#define I2SR_IIF (1 << 1)
#define I2SR_RXAK (1 << 0)
#define I2SR_MASK 0xE9
#define I2SR_RESET 0x81
#define I2DR_MASK 0xFF
#define I2DR_RESET 0
#define ADDR_RESET 0xFF00
typedef struct IMXI2CState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
I2CBus *bus;
qemu_irq irq;
uint16_t address;
uint16_t iadr;
uint16_t ifdr;
uint16_t i2cr;
uint16_t i2sr;
uint16_t i2dr_read;
uint16_t i2dr_write;
} IMXI2CState;
#endif /* __IMX_I2C_H_ */

113
include/hw/net/imx_fec.h Normal file
View file

@ -0,0 +1,113 @@
/*
* i.MX Fast Ethernet Controller emulation.
*
* Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
*
* Based on Coldfire Fast Ethernet Controller emulation.
*
* Copyright (c) 2007 CodeSourcery.
*
* 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/>.
*/
#ifndef IMX_FEC_H
#define IMX_FEC_H
#define TYPE_IMX_FEC "imx.fec"
#define IMX_FEC(obj) OBJECT_CHECK(IMXFECState, (obj), TYPE_IMX_FEC)
#include "hw/sysbus.h"
#include "net/net.h"
#define FEC_MAX_FRAME_SIZE 2032
#define FEC_INT_HB (1 << 31)
#define FEC_INT_BABR (1 << 30)
#define FEC_INT_BABT (1 << 29)
#define FEC_INT_GRA (1 << 28)
#define FEC_INT_TXF (1 << 27)
#define FEC_INT_TXB (1 << 26)
#define FEC_INT_RXF (1 << 25)
#define FEC_INT_RXB (1 << 24)
#define FEC_INT_MII (1 << 23)
#define FEC_INT_EBERR (1 << 22)
#define FEC_INT_LC (1 << 21)
#define FEC_INT_RL (1 << 20)
#define FEC_INT_UN (1 << 19)
#define FEC_EN 2
#define FEC_RESET 1
/* Buffer Descriptor. */
typedef struct {
uint16_t length;
uint16_t flags;
uint32_t data;
} IMXFECBufDesc;
#define FEC_BD_R (1 << 15)
#define FEC_BD_E (1 << 15)
#define FEC_BD_O1 (1 << 14)
#define FEC_BD_W (1 << 13)
#define FEC_BD_O2 (1 << 12)
#define FEC_BD_L (1 << 11)
#define FEC_BD_TC (1 << 10)
#define FEC_BD_ABC (1 << 9)
#define FEC_BD_M (1 << 8)
#define FEC_BD_BC (1 << 7)
#define FEC_BD_MC (1 << 6)
#define FEC_BD_LG (1 << 5)
#define FEC_BD_NO (1 << 4)
#define FEC_BD_CR (1 << 2)
#define FEC_BD_OV (1 << 1)
#define FEC_BD_TR (1 << 0)
typedef struct IMXFECState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
NICState *nic;
NICConf conf;
qemu_irq irq;
MemoryRegion iomem;
uint32_t irq_state;
uint32_t eir;
uint32_t eimr;
uint32_t rx_enabled;
uint32_t rx_descriptor;
uint32_t tx_descriptor;
uint32_t ecr;
uint32_t mmfr;
uint32_t mscr;
uint32_t mibc;
uint32_t rcr;
uint32_t tcr;
uint32_t tfwr;
uint32_t frsr;
uint32_t erdsr;
uint32_t etdsr;
uint32_t emrbr;
uint32_t miigsk_cfgr;
uint32_t miigsk_enr;
uint32_t phy_status;
uint32_t phy_control;
uint32_t phy_advertise;
uint32_t phy_int;
uint32_t phy_int_mask;
} IMXFECState;
#endif

View file

@ -23,25 +23,27 @@ struct smbios_phys_mem_area {
uint64_t length;
};
void smbios_entry_add(QemuOpts *opts);
void smbios_set_cpuid(uint32_t version, uint32_t features);
void smbios_set_defaults(const char *manufacturer, const char *product,
const char *version, bool legacy_mode,
bool uuid_encoded);
uint8_t *smbios_get_table_legacy(size_t *length);
void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
const unsigned int mem_array_size,
uint8_t **tables, size_t *tables_len,
uint8_t **anchor, size_t *anchor_len);
/*
* SMBIOS spec defined tables
*/
typedef enum SmbiosEntryPointType {
SMBIOS_ENTRY_POINT_21,
SMBIOS_ENTRY_POINT_30,
} SmbiosEntryPointType;
/* SMBIOS entry point (anchor).
* BIOS must place this at a 16-bit-aligned address between 0xf0000 and 0xfffff.
/* SMBIOS Entry Point
* There are two types of entry points defined in the SMBIOS specification
* (see below). BIOS must place the entry point(s) at a 16-bit-aligned
* address between 0xf0000 and 0xfffff. Note that either entry point type
* can be used in a 64-bit target system, except that SMBIOS 2.1 entry point
* only allows the SMBIOS struct table to reside below 4GB address space.
*/
struct smbios_entry_point {
/* SMBIOS 2.1 (32-bit) Entry Point
* - introduced since SMBIOS 2.1
* - supports structure table below 4GB only
*/
struct smbios_21_entry_point {
uint8_t anchor_string[4];
uint8_t checksum;
uint8_t length;
@ -58,6 +60,28 @@ struct smbios_entry_point {
uint8_t smbios_bcd_revision;
} QEMU_PACKED;
/* SMBIOS 3.0 (64-bit) Entry Point
* - introduced since SMBIOS 3.0
* - supports structure table at 64-bit address space
*/
struct smbios_30_entry_point {
uint8_t anchor_string[5];
uint8_t checksum;
uint8_t length;
uint8_t smbios_major_version;
uint8_t smbios_minor_version;
uint8_t smbios_doc_rev;
uint8_t entry_point_revision;
uint8_t reserved;
uint32_t structure_table_max_size;
uint64_t structure_table_address;
} QEMU_PACKED;
typedef union {
struct smbios_21_entry_point ep21;
struct smbios_30_entry_point ep30;
} QEMU_PACKED SmbiosEntryPoint;
/* This goes at the beginning of every SMBIOS structure. */
struct smbios_structure_header {
uint8_t type;
@ -232,4 +256,14 @@ struct smbios_type_127 {
struct smbios_structure_header header;
} QEMU_PACKED;
void smbios_entry_add(QemuOpts *opts);
void smbios_set_cpuid(uint32_t version, uint32_t features);
void smbios_set_defaults(const char *manufacturer, const char *product,
const char *version, bool legacy_mode,
bool uuid_encoded, SmbiosEntryPointType ep_type);
uint8_t *smbios_get_table_legacy(size_t *length);
void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
const unsigned int mem_array_size,
uint8_t **tables, size_t *tables_len,
uint8_t **anchor, size_t *anchor_len);
#endif /*QEMU_SMBIOS_H */

View file

@ -1052,6 +1052,9 @@ void cpu_loop(CPUARMState *env)
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP_SEMIHOST:
env->xregs[0] = do_arm_semihosting(env);
break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);

View file

@ -1412,7 +1412,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
"-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n"
" [,asset=str][,part=str][,speed=%d]\n"
" specify SMBIOS type 17 fields\n",
QEMU_ARCH_I386)
QEMU_ARCH_I386 | QEMU_ARCH_ARM)
STEXI
@item -smbios file=@var{binary}
@findex -smbios

View file

@ -58,6 +58,7 @@
#define TARGET_SYS_GET_CMDLINE 0x15
#define TARGET_SYS_HEAPINFO 0x16
#define TARGET_SYS_EXIT 0x18
#define TARGET_SYS_SYNCCACHE 0x19
/* ADP_Stopped_ApplicationExit is used for exit(0),
* anything else is implemented as exit(1) */
@ -134,6 +135,7 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
#ifdef CONFIG_USER_ONLY
TaskState *ts = cs->opaque;
#endif
target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
if (ret == (target_ulong)-1) {
#ifdef CONFIG_USER_ONLY
@ -141,22 +143,46 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
#else
syscall_err = err;
#endif
env->regs[0] = ret;
reg0 = ret;
} else {
/* Fixup syscalls that use nonstardard return conventions. */
switch (env->regs[0]) {
switch (reg0) {
case TARGET_SYS_WRITE:
case TARGET_SYS_READ:
env->regs[0] = arm_semi_syscall_len - ret;
reg0 = arm_semi_syscall_len - ret;
break;
case TARGET_SYS_SEEK:
env->regs[0] = 0;
reg0 = 0;
break;
default:
env->regs[0] = ret;
reg0 = ret;
break;
}
}
if (is_a64(env)) {
env->xregs[0] = reg0;
} else {
env->regs[0] = reg0;
}
}
static target_ulong arm_flen_buf(ARMCPU *cpu)
{
/* Return an address in target memory of 64 bytes where the remote
* gdb should write its stat struct. (The format of this structure
* is defined by GDB's remote protocol and is not target-specific.)
* We put this on the guest's stack just below SP.
*/
CPUARMState *env = &cpu->env;
target_ulong sp;
if (is_a64(env)) {
sp = env->xregs[31];
} else {
sp = env->regs[13];
}
return sp - 64;
}
static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
@ -166,8 +192,13 @@ static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
/* The size is always stored in big-endian order, extract
the value. We assume the size always fit in 32 bits. */
uint32_t size;
cpu_memory_rw_debug(cs, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
env->regs[0] = be32_to_cpu(size);
cpu_memory_rw_debug(cs, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
size = be32_to_cpu(size);
if (is_a64(env)) {
env->xregs[0] = size;
} else {
env->regs[0] = size;
}
#ifdef CONFIG_USER_ONLY
((TaskState *)cs->opaque)->swi_errno = err;
#else
@ -175,17 +206,46 @@ static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
#endif
}
static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
const char *fmt, ...)
{
va_list va;
CPUARMState *env = &cpu->env;
va_start(va, fmt);
gdb_do_syscallv(cb, fmt, va);
va_end(va);
/* FIXME: we are implicitly relying on the syscall completing
* before this point, which is not guaranteed. We should
* put in an explicit synchronization between this and
* the callback function.
*/
return is_a64(env) ? env->xregs[0] : env->regs[0];
}
/* Read the input value from the argument block; fail the semihosting
* call if the memory read fails.
*/
#define GET_ARG(n) do { \
if (get_user_ual(arg ## n, args + (n) * 4)) { \
return (uint32_t)-1; \
if (is_a64(env)) { \
if (get_user_u64(arg ## n, args + (n) * 8)) { \
return -1; \
} \
} else { \
if (get_user_u32(arg ## n, args + (n) * 4)) { \
return -1; \
} \
} \
} while (0)
#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4)
uint32_t do_arm_semihosting(CPUARMState *env)
#define SET_ARG(n, val) \
(is_a64(env) ? \
put_user_u64(val, args + (n) * 8) : \
put_user_u32(val, args + (n) * 4))
target_ulong do_arm_semihosting(CPUARMState *env)
{
ARMCPU *cpu = arm_env_get_cpu(env);
CPUState *cs = CPU(cpu);
@ -201,8 +261,15 @@ uint32_t do_arm_semihosting(CPUARMState *env)
CPUARMState *ts = env;
#endif
nr = env->regs[0];
args = env->regs[1];
if (is_a64(env)) {
/* Note that the syscall number is in W0, not X0 */
nr = env->xregs[0] & 0xffffffffU;
args = env->xregs[1];
} else {
nr = env->regs[0];
args = env->regs[1];
}
switch (nr) {
case TARGET_SYS_OPEN:
GET_ARG(0);
@ -223,9 +290,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
return result_fileno;
}
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", arg0,
(int)arg2+1, gdb_open_modeflags[arg1]);
ret = env->regs[0];
ret = arm_gdb_syscall(cpu, arm_semi_cb, "open,%s,%x,1a4", arg0,
(int)arg2+1, gdb_open_modeflags[arg1]);
} else {
ret = set_swi_errno(ts, open(s, open_modeflags[arg1], 0644));
}
@ -234,8 +300,7 @@ uint32_t do_arm_semihosting(CPUARMState *env)
case TARGET_SYS_CLOSE:
GET_ARG(0);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "close,%x", arg0);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", arg0);
} else {
return set_swi_errno(ts, close(arg0));
}
@ -248,8 +313,7 @@ uint32_t do_arm_semihosting(CPUARMState *env)
return (uint32_t)-1;
/* Write to debug console. stderr is near enough. */
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "write,2,%x,1", args);
} else {
return write(STDERR_FILENO, &c, 1);
}
@ -260,8 +324,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
return (uint32_t)-1;
len = strlen(s);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
ret = env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "write,2,%x,%x",
args, len);
} else {
ret = write(STDERR_FILENO, s, len);
}
@ -274,8 +338,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
len = arg2;
if (use_gdb_syscalls()) {
arm_semi_syscall_len = len;
gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", arg0, arg1, len);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
arg0, arg1, len);
} else {
s = lock_user(VERIFY_READ, arg1, len, 1);
if (!s) {
@ -295,8 +359,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
len = arg2;
if (use_gdb_syscalls()) {
arm_semi_syscall_len = len;
gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", arg0, arg1, len);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
arg0, arg1, len);
} else {
s = lock_user(VERIFY_WRITE, arg1, len, 0);
if (!s) {
@ -317,8 +381,7 @@ uint32_t do_arm_semihosting(CPUARMState *env)
case TARGET_SYS_ISTTY:
GET_ARG(0);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "isatty,%x", arg0);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", arg0);
} else {
return isatty(arg0);
}
@ -326,8 +389,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
GET_ARG(0);
GET_ARG(1);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", arg0, arg1);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
arg0, arg1);
} else {
ret = set_swi_errno(ts, lseek(arg0, arg1, SEEK_SET));
if (ret == (uint32_t)-1)
@ -337,9 +400,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
case TARGET_SYS_FLEN:
GET_ARG(0);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",
arg0, env->regs[13]-64);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
arg0, arm_flen_buf(cpu));
} else {
struct stat buf;
ret = set_swi_errno(ts, fstat(arg0, &buf));
@ -354,8 +416,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
GET_ARG(0);
GET_ARG(1);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "unlink,%s", arg0, (int)arg1+1);
ret = env->regs[0];
ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
arg0, (int)arg1+1);
} else {
s = lock_user_string(arg0);
if (!s) {
@ -372,9 +434,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
GET_ARG(2);
GET_ARG(3);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
arg0, (int)arg1+1, arg2, (int)arg3+1);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
arg0, (int)arg1+1, arg2, (int)arg3+1);
} else {
char *s2;
s = lock_user_string(arg0);
@ -398,8 +459,8 @@ uint32_t do_arm_semihosting(CPUARMState *env)
GET_ARG(0);
GET_ARG(1);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "system,%s", arg0, (int)arg1+1);
return env->regs[0];
return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
arg0, (int)arg1+1);
} else {
s = lock_user_string(arg0);
if (!s) {
@ -558,11 +619,35 @@ uint32_t do_arm_semihosting(CPUARMState *env)
return 0;
}
case TARGET_SYS_EXIT:
/* ARM specifies only Stopped_ApplicationExit as normal
* exit, everything else is considered an error */
ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
if (is_a64(env)) {
/* The A64 version of this call takes a parameter block,
* so the application-exit type can return a subcode which
* is the exit status code from the application.
*/
GET_ARG(0);
GET_ARG(1);
if (arg0 == ADP_Stopped_ApplicationExit) {
ret = arg1;
} else {
ret = 1;
}
} else {
/* ARM specifies only Stopped_ApplicationExit as normal
* exit, everything else is considered an error */
ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
}
gdb_exit(env, ret);
exit(ret);
case TARGET_SYS_SYNCCACHE:
/* Clean the D-cache and invalidate the I-cache for the specified
* virtual address range. This is a nop for us since we don't
* implement caches. This is only present on A64.
*/
if (is_a64(env)) {
return 0;
}
/* fall through -- invalid for A32/T32 */
default:
fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
cpu_dump_state(cs, stderr, fprintf, 0);

View file

@ -227,6 +227,19 @@ void arm_gt_vtimer_cb(void *opaque);
void arm_gt_htimer_cb(void *opaque);
void arm_gt_stimer_cb(void *opaque);
#define ARM_AFF0_SHIFT 0
#define ARM_AFF0_MASK (0xFFULL << ARM_AFF0_SHIFT)
#define ARM_AFF1_SHIFT 8
#define ARM_AFF1_MASK (0xFFULL << ARM_AFF1_SHIFT)
#define ARM_AFF2_SHIFT 16
#define ARM_AFF2_MASK (0xFFULL << ARM_AFF2_SHIFT)
#define ARM_AFF3_SHIFT 32
#define ARM_AFF3_MASK (0xFFULL << ARM_AFF3_SHIFT)
#define ARM32_AFFINITY_MASK (ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK)
#define ARM64_AFFINITY_MASK \
(ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK|ARM_AFF3_MASK)
#ifdef TARGET_AARCH64
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);

View file

@ -331,10 +331,7 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
switch (irq) {
case ARM_CPU_VIRQ:
case ARM_CPU_VFIQ:
if (!arm_feature(env, ARM_FEATURE_EL2)) {
hw_error("%s: Virtual interrupt line %d with no EL2 support\n",
__func__, irq);
}
assert(arm_feature(env, ARM_FEATURE_EL2));
/* fall through */
case ARM_CPU_IRQ:
case ARM_CPU_FIQ:
@ -345,7 +342,7 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
}
break;
default:
hw_error("arm_cpu_set_irq: Bad interrupt line %d\n", irq);
g_assert_not_reached();
}
}
@ -364,7 +361,7 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
break;
default:
hw_error("arm_cpu_kvm_set_irq: Bad interrupt line %d\n", irq);
g_assert_not_reached();
}
kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
@ -459,7 +456,7 @@ static void arm_cpu_initfn(Object *obj)
*/
Aff1 = cs->cpu_index / ARM_CPUS_PER_CLUSTER;
Aff0 = cs->cpu_index % ARM_CPUS_PER_CLUSTER;
cpu->mp_affinity = (Aff1 << 8) | Aff0;
cpu->mp_affinity = (Aff1 << ARM_AFF1_SHIFT) | Aff0;
#ifndef CONFIG_USER_ONLY
/* Our inbound IRQ and FIQ lines */

View file

@ -56,6 +56,7 @@
#define EXCP_SMC 13 /* Secure Monitor Call */
#define EXCP_VIRQ 14
#define EXCP_VFIQ 15
#define EXCP_SEMIHOST 16 /* semihosting call (A64 only) */
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
@ -504,7 +505,7 @@ typedef struct CPUARMState {
ARMCPU *cpu_arm_init(const char *cpu_model);
int cpu_arm_exec(CPUState *cpu);
uint32_t do_arm_semihosting(CPUARMState *env);
target_ulong do_arm_semihosting(CPUARMState *env);
void aarch64_sync_32_to_64(CPUARMState *env);
void aarch64_sync_64_to_32(CPUARMState *env);
@ -1519,8 +1520,8 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
CPUARMState *env = cs->env_ptr;
unsigned int cur_el = arm_current_el(env);
bool secure = arm_is_secure(env);
uint32_t scr;
uint32_t hcr;
bool scr;
bool hcr;
bool pstate_unmasked;
int8_t unmasked = 0;
@ -1547,7 +1548,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
* set then FIQs can be masked by CPSR.F when non-secure but only
* when FIQs are only routed to EL3.
*/
scr &= !((env->cp15.scr_el3 & SCR_FW) && !hcr);
scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr);
pstate_unmasked = !(env->daif & PSTATE_F);
break;

View file

@ -514,6 +514,12 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
case EXCP_VFIQ:
addr += 0x100;
break;
case EXCP_SEMIHOST:
qemu_log_mask(CPU_LOG_INT,
"...handling as semihosting call 0x%" PRIx64 "\n",
env->xregs[0]);
env->xregs[0] = do_arm_semihosting(env);
return;
default:
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
}

View file

@ -4990,7 +4990,7 @@ int bank_number(int mode)
case ARM_CPU_MODE_MON:
return 7;
}
hw_error("bank number requested for bad CPSR mode value 0x%x\n", mode);
g_assert_not_reached();
}
void switch_mode(CPUARMState *env, int mode)
@ -5228,8 +5228,10 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
if (nr == 0xab) {
env->regs[15] += 2;
qemu_log_mask(CPU_LOG_INT,
"...handling as semihosting call 0x%x\n",
env->regs[0]);
env->regs[0] = do_arm_semihosting(env);
qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
return;
}
}
@ -5322,35 +5324,35 @@ void aarch64_sync_32_to_64(CPUARMState *env)
}
if (mode == ARM_CPU_MODE_IRQ) {
env->xregs[16] = env->regs[13];
env->xregs[17] = env->regs[14];
env->xregs[16] = env->regs[14];
env->xregs[17] = env->regs[13];
} else {
env->xregs[16] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)];
env->xregs[17] = env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)];
env->xregs[16] = env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)];
env->xregs[17] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)];
}
if (mode == ARM_CPU_MODE_SVC) {
env->xregs[18] = env->regs[13];
env->xregs[19] = env->regs[14];
env->xregs[18] = env->regs[14];
env->xregs[19] = env->regs[13];
} else {
env->xregs[18] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)];
env->xregs[19] = env->banked_r14[bank_number(ARM_CPU_MODE_SVC)];
env->xregs[18] = env->banked_r14[bank_number(ARM_CPU_MODE_SVC)];
env->xregs[19] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)];
}
if (mode == ARM_CPU_MODE_ABT) {
env->xregs[20] = env->regs[13];
env->xregs[21] = env->regs[14];
env->xregs[20] = env->regs[14];
env->xregs[21] = env->regs[13];
} else {
env->xregs[20] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)];
env->xregs[21] = env->banked_r14[bank_number(ARM_CPU_MODE_ABT)];
env->xregs[20] = env->banked_r14[bank_number(ARM_CPU_MODE_ABT)];
env->xregs[21] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)];
}
if (mode == ARM_CPU_MODE_UND) {
env->xregs[22] = env->regs[13];
env->xregs[23] = env->regs[14];
env->xregs[22] = env->regs[14];
env->xregs[23] = env->regs[13];
} else {
env->xregs[22] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)];
env->xregs[23] = env->banked_r14[bank_number(ARM_CPU_MODE_UND)];
env->xregs[22] = env->banked_r14[bank_number(ARM_CPU_MODE_UND)];
env->xregs[23] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)];
}
/* Registers x24-x30 are mapped to r8-r14 in FIQ mode. If we are in FIQ
@ -5427,35 +5429,35 @@ void aarch64_sync_64_to_32(CPUARMState *env)
}
if (mode == ARM_CPU_MODE_IRQ) {
env->regs[13] = env->xregs[16];
env->regs[14] = env->xregs[17];
env->regs[14] = env->xregs[16];
env->regs[13] = env->xregs[17];
} else {
env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16];
env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[17];
env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16];
env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[17];
}
if (mode == ARM_CPU_MODE_SVC) {
env->regs[13] = env->xregs[18];
env->regs[14] = env->xregs[19];
env->regs[14] = env->xregs[18];
env->regs[13] = env->xregs[19];
} else {
env->banked_r13[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18];
env->banked_r14[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[19];
env->banked_r14[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18];
env->banked_r13[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[19];
}
if (mode == ARM_CPU_MODE_ABT) {
env->regs[13] = env->xregs[20];
env->regs[14] = env->xregs[21];
env->regs[14] = env->xregs[20];
env->regs[13] = env->xregs[21];
} else {
env->banked_r13[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20];
env->banked_r14[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[21];
env->banked_r14[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20];
env->banked_r13[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[21];
}
if (mode == ARM_CPU_MODE_UND) {
env->regs[13] = env->xregs[22];
env->regs[14] = env->xregs[23];
env->regs[14] = env->xregs[22];
env->regs[13] = env->xregs[23];
} else {
env->banked_r13[bank_number(ARM_CPU_MODE_UND)] = env->xregs[22];
env->banked_r14[bank_number(ARM_CPU_MODE_UND)] = env->xregs[23];
env->banked_r14[bank_number(ARM_CPU_MODE_UND)] = env->xregs[22];
env->banked_r13[bank_number(ARM_CPU_MODE_UND)] = env->xregs[23];
}
/* Registers x24-x30 are mapped to r8-r14 in FIQ mode. If we are in FIQ
@ -5549,8 +5551,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
if (((mask == 0x123456 && !env->thumb)
|| (mask == 0xab && env->thumb))
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
qemu_log_mask(CPU_LOG_INT,
"...handling as semihosting call 0x%x\n",
env->regs[0]);
env->regs[0] = do_arm_semihosting(env);
qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
return;
}
}
@ -5567,8 +5571,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
if (mask == 0xab
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
env->regs[15] += 2;
qemu_log_mask(CPU_LOG_INT,
"...handling as semihosting call 0x%x\n",
env->regs[0]);
env->regs[0] = do_arm_semihosting(env);
qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
return;
}
}

View file

@ -36,6 +36,7 @@ static inline bool excp_is_internal(int excp)
|| excp == EXCP_HALTED
|| excp == EXCP_EXCEPTION_EXIT
|| excp == EXCP_KERNEL_TRAP
|| excp == EXCP_SEMIHOST
|| excp == EXCP_STREX;
}
@ -58,6 +59,7 @@ static const char * const excnames[] = {
[EXCP_SMC] = "Secure Monitor Call",
[EXCP_VIRQ] = "Virtual IRQ",
[EXCP_VFIQ] = "Virtual FIQ",
[EXCP_SEMIHOST] = "Semihosting call",
};
static inline void arm_log_exception(int idx)

View file

@ -181,7 +181,6 @@ int kvm_arm_cpreg_level(uint64_t regidx)
return KVM_PUT_RUNTIME_STATE;
}
#define ARM_MPIDR_HWID_BITMASK 0xFFFFFF
#define ARM_CPU_ID_MPIDR 0, 0, 0, 5
int kvm_arch_init_vcpu(CPUState *cs)
@ -234,7 +233,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (ret) {
return ret;
}
cpu->mp_affinity = mpidr & ARM_MPIDR_HWID_BITMASK;
cpu->mp_affinity = mpidr & ARM32_AFFINITY_MASK;
return kvm_arm_init_cpreg_list(cpu);
}

View file

@ -77,7 +77,6 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
return true;
}
#define ARM_MPIDR_HWID_BITMASK 0xFF00FFFFFFULL
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
int kvm_arch_init_vcpu(CPUState *cs)
@ -120,7 +119,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (ret) {
return ret;
}
cpu->mp_affinity = mpidr & ARM_MPIDR_HWID_BITMASK;
cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
return kvm_arm_init_cpreg_list(cpu);
}

View file

@ -30,6 +30,7 @@
#include "internals.h"
#include "qemu/host-utils.h"
#include "exec/semihost.h"
#include "exec/gen-icount.h"
#include "exec/helper-proto.h"
@ -1553,8 +1554,27 @@ static void disas_exc(DisasContext *s, uint32_t insn)
unallocated_encoding(s);
break;
}
/* HLT */
unsupported_encoding(s, insn);
/* HLT. This has two purposes.
* Architecturally, it is an external halting debug instruction.
* Since QEMU doesn't implement external debug, we treat this as
* it is required for halting debug disabled: it will UNDEF.
* Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
*/
if (semihosting_enabled() && imm16 == 0xf000) {
#ifndef CONFIG_USER_ONLY
/* In system mode, don't allow userspace access to semihosting,
* to provide some semblance of security (and for consistency
* with our 32-bit semihosting).
*/
if (s->current_el == 0) {
unsupported_encoding(s, insn);
break;
}
#endif
gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
} else {
unsupported_encoding(s, insn);
}
break;
case 5:
if (op2_ll < 1 || op2_ll > 3) {

View file

@ -201,6 +201,7 @@ check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
gcov-files-sparc-y += hw/timer/m48t59.c
gcov-files-sparc64-y += hw/timer/m48t59.c
check-qtest-arm-y = tests/tmp105-test$(EXESUF)
check-qtest-arm-y = tests/ds1338-test$(EXESUF)
gcov-files-arm-y += hw/misc/tmp105.c
check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
@ -358,6 +359,7 @@ libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
libqos-pc-obj-y += tests/libqos/ahci.o
libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o
libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
@ -372,6 +374,7 @@ tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)

View file

@ -50,7 +50,7 @@ typedef struct {
int rsdt_tables_nr;
GArray *tables;
uint32_t smbios_ep_addr;
struct smbios_entry_point smbios_ep_table;
struct smbios_21_entry_point smbios_ep_table;
} test_data;
#define LOW(x) ((x) & 0xff)
@ -601,7 +601,7 @@ static void test_acpi_asl(test_data *data)
static bool smbios_ep_table_ok(test_data *data)
{
struct smbios_entry_point *ep_table = &data->smbios_ep_table;
struct smbios_21_entry_point *ep_table = &data->smbios_ep_table;
uint32_t addr = data->smbios_ep_addr;
ACPI_READ_ARRAY(ep_table->anchor_string, addr);
@ -681,7 +681,7 @@ static inline bool smbios_single_instance(uint8_t type)
static void test_smbios_structs(test_data *data)
{
DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 };
struct smbios_entry_point *ep_table = &data->smbios_ep_table;
struct smbios_21_entry_point *ep_table = &data->smbios_ep_table;
uint32_t addr = ep_table->structure_table_address;
int i, len, max_len = 0;
uint8_t type, prv, crt;

78
tests/ds1338-test.c Normal file
View file

@ -0,0 +1,78 @@
/*
* QTest testcase for the DS1338 RTC
*
* Copyright (c) 2013 Jean-Christophe Dubois
*
* 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 "libqtest.h"
#include "libqos/i2c.h"
#include <glib.h>
#define IMX25_I2C_0_BASE 0x43F80000
#define DS1338_ADDR 0x68
static I2CAdapter *i2c;
static uint8_t addr;
static inline uint8_t bcd2bin(uint8_t x)
{
return ((x) & 0x0f) + ((x) >> 4) * 10;
}
static void send_and_receive(void)
{
uint8_t cmd[1];
uint8_t resp[7];
time_t now = time(NULL);
struct tm *tm_ptr = gmtime(&now);
/* reset the index in the RTC memory */
cmd[0] = 0;
i2c_send(i2c, addr, cmd, 1);
/* retrieve the date */
i2c_recv(i2c, addr, resp, 7);
/* check retrieved time againt local time */
g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday);
g_assert_cmpuint(bcd2bin(resp[5]), == , 1 + tm_ptr->tm_mon);
g_assert_cmpuint(2000 + bcd2bin(resp[6]), == , 1900 + tm_ptr->tm_year);
}
int main(int argc, char **argv)
{
QTestState *s = NULL;
int ret;
g_test_init(&argc, &argv, NULL);
s = qtest_start("-display none -machine imx25_pdk");
i2c = imx_i2c_create(IMX25_I2C_0_BASE);
addr = DS1338_ADDR;
qtest_add_func("/ds1338/tx-rx", send_and_receive);
ret = g_test_run();
if (s) {
qtest_quit(s);
}
g_free(i2c);
return ret;
}

209
tests/libqos/i2c-imx.c Normal file
View file

@ -0,0 +1,209 @@
/*
* QTest i.MX I2C driver
*
* Copyright (c) 2013 Jean-Christophe Dubois
*
* 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 "libqos/i2c.h"
#include <glib.h>
#include <string.h>
#include "qemu/osdep.h"
#include "libqtest.h"
#include "hw/i2c/imx_i2c.h"
enum IMXI2CDirection {
IMX_I2C_READ,
IMX_I2C_WRITE,
};
typedef struct IMXI2C {
I2CAdapter parent;
uint64_t addr;
} IMXI2C;
static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr,
enum IMXI2CDirection direction)
{
writeb(s->addr + I2DR_ADDR, (addr << 1) |
(direction == IMX_I2C_READ ? 1 : 0));
}
static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr,
const uint8_t *buf, uint16_t len)
{
IMXI2C *s = (IMXI2C *)i2c;
uint8_t data;
uint8_t status;
uint16_t size = 0;
if (!len) {
return;
}
/* set the bus for write */
data = I2CR_IEN |
I2CR_IIEN |
I2CR_MSTA |
I2CR_MTX |
I2CR_TXAK;
writeb(s->addr + I2CR_ADDR, data);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IBB) != 0);
/* set the slave address */
imx_i2c_set_slave_addr(s, addr, IMX_I2C_WRITE);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) != 0);
g_assert((status & I2SR_RXAK) == 0);
/* ack the interrupt */
writeb(s->addr + I2SR_ADDR, 0);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) == 0);
while (size < len) {
/* check we are still busy */
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IBB) != 0);
/* write the data */
writeb(s->addr + I2DR_ADDR, buf[size]);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) != 0);
g_assert((status & I2SR_RXAK) == 0);
/* ack the interrupt */
writeb(s->addr + I2SR_ADDR, 0);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) == 0);
size++;
}
/* release the bus */
data &= ~(I2CR_MSTA | I2CR_MTX);
writeb(s->addr + I2CR_ADDR, data);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IBB) == 0);
}
static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr,
uint8_t *buf, uint16_t len)
{
IMXI2C *s = (IMXI2C *)i2c;
uint8_t data;
uint8_t status;
uint16_t size = 0;
if (!len) {
return;
}
/* set the bus for write */
data = I2CR_IEN |
I2CR_IIEN |
I2CR_MSTA |
I2CR_MTX |
I2CR_TXAK;
writeb(s->addr + I2CR_ADDR, data);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IBB) != 0);
/* set the slave address */
imx_i2c_set_slave_addr(s, addr, IMX_I2C_READ);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) != 0);
g_assert((status & I2SR_RXAK) == 0);
/* ack the interrupt */
writeb(s->addr + I2SR_ADDR, 0);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) == 0);
/* set the bus for read */
data &= ~I2CR_MTX;
/* if only one byte don't ack */
if (len != 1) {
data &= ~I2CR_TXAK;
}
writeb(s->addr + I2CR_ADDR, data);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IBB) != 0);
/* dummy read */
readb(s->addr + I2DR_ADDR);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) != 0);
/* ack the interrupt */
writeb(s->addr + I2SR_ADDR, 0);
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) == 0);
while (size < len) {
/* check we are still busy */
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IBB) != 0);
if (size == (len - 1)) {
/* stop the read transaction */
data &= ~(I2CR_MSTA | I2CR_MTX);
} else {
/* ack the data read */
data |= I2CR_TXAK;
}
writeb(s->addr + I2CR_ADDR, data);
/* read the data */
buf[size] = readb(s->addr + I2DR_ADDR);
if (size != (len - 1)) {
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) != 0);
/* ack the interrupt */
writeb(s->addr + I2SR_ADDR, 0);
}
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IIF) == 0);
size++;
}
status = readb(s->addr + I2SR_ADDR);
g_assert((status & I2SR_IBB) == 0);
}
I2CAdapter *imx_i2c_create(uint64_t addr)
{
IMXI2C *s = g_malloc0(sizeof(*s));
I2CAdapter *i2c = (I2CAdapter *)s;
s->addr = addr;
i2c->send = imx_i2c_send;
i2c->recv = imx_i2c_recv;
return i2c;
}

View file

@ -27,4 +27,7 @@ void i2c_recv(I2CAdapter *i2c, uint8_t addr,
/* libi2c-omap.c */
I2CAdapter *omap_i2c_create(uint64_t addr);
/* libi2c-imx.c */
I2CAdapter *imx_i2c_create(uint64_t addr);
#endif