target-arm queue:

* tests/acceptance: Add a test for the canon-a1100 machine
  * docs/system: Document some of the Arm development boards
  * linux-user: make BKPT insn cause SIGTRAP, not be a syscall
  * target/arm: Remove unused GEN_NEON_INTEGER_OP macro
  * fsl-imx25, fsl-imx31, fsl-imx6, fsl-imx6ul, fsl-imx7: implement watchdog
  * hw/arm: Use qemu_log_mask() instead of hw_error() in various places
  * ARM: PL061: Introduce N_GPIOS
  * target/arm: Improve clear_vec_high() usage
  * target/arm: Allow user-mode code to write CPSR.E via MSR
  * linux-user/arm: Reset CPSR_E when entering a signal handler
  * linux-user/arm/signal.c: Drop TARGET_CONFIG_CPU_32
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl7G7SwZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3qlND/0bnTGXns6FdYfWahEchgzJ
 2C3LbE7ELund+vmn8BQX+TNsxC3sypbNa0HTx5uiAaRt3ohD6f/lYmvKjGkLJJ0l
 g/6KQNXz2Tru5uB3wXWJuSQhX5qEei4EAHoHLo5lseslQq8pF8xpZvkj7P6TYJGp
 ReEd48OPQJwrs6nlHahQkLX1TveDGNI/GTvUxVG6wTXZnYP6+/LK71yCZDplaKFb
 j2vD7Q9kgFBHmjRiBMvYRhxQXRMnRe+5Y4khDSyiQdZId+2zD0PkxoL6qujSU0Ty
 /P6vWzqdn66n3nD86PzthuWT2294xdsKGx6+otxIsJevMlZxZ7jNP/z7eJEIEvMI
 Pqd28iStpdheiU2siM0NwunRWyr+c/zX6J1KYGBFrVFb869eePaDmIrn0AGKOh9S
 IEO4n7t+M+IkYbc5RfdU2UhE2ubijLDrWnm/mZ7cCd7jT3SwPitVLqtcQWYFI0fL
 GUEJlRstsuSXTWI4g5Cwpuv6U90sc/sIERAVW5qP45FoSnhRaK3+ySzmlTTqZ+jq
 k8xywFjAijITplrvsbIsN0Y074PHFiOuk6e+FXaCyBOc9TA9sZKQUNk/XLuYzhYr
 86jSELIt+YHrpHwxkplrvO+3MvqV95+6AU77cuNAC9O2E5HgE4SPE4RnfRTG8ULj
 FtzVM8JOjCLKha+oAD9ucA==
 =bh3x
 -----END PGP SIGNATURE-----

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

target-arm queue:
 * tests/acceptance: Add a test for the canon-a1100 machine
 * docs/system: Document some of the Arm development boards
 * linux-user: make BKPT insn cause SIGTRAP, not be a syscall
 * target/arm: Remove unused GEN_NEON_INTEGER_OP macro
 * fsl-imx25, fsl-imx31, fsl-imx6, fsl-imx6ul, fsl-imx7: implement watchdog
 * hw/arm: Use qemu_log_mask() instead of hw_error() in various places
 * ARM: PL061: Introduce N_GPIOS
 * target/arm: Improve clear_vec_high() usage
 * target/arm: Allow user-mode code to write CPSR.E via MSR
 * linux-user/arm: Reset CPSR_E when entering a signal handler
 * linux-user/arm/signal.c: Drop TARGET_CONFIG_CPU_32

# gpg: Signature made Thu 21 May 2020 22:05:48 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20200521-1: (29 commits)
  linux-user/arm/signal.c: Drop TARGET_CONFIG_CPU_32
  linux-user/arm: Reset CPSR_E when entering a signal handler
  target/arm: Allow user-mode code to write CPSR.E via MSR
  target/arm: Use clear_vec_high more effectively
  target/arm: Use tcg_gen_gvec_mov for clear_vec_high
  ARM: PL061: Introduce N_GPIOS
  hw/timer/exynos4210_mct: Replace hw_error() by qemu_log_mask()
  hw/char/xilinx_uartlite: Replace hw_error() by qemu_log_mask()
  hw/arm/pxa2xx: Replace hw_error() by qemu_log_mask()
  hw/arm/integratorcp: Replace hw_error() by qemu_log_mask()
  hw/arm/fsl-imx7: Connect watchdog interrupts
  hw/arm/fsl-imx7: Instantiate various unimplemented devices
  hw/arm/fsl-imx6ul: Connect watchdog interrupts
  hw/arm/fsl-imx6: Connect watchdog interrupts
  hw/arm/fsl-imx31: Wire up watchdog
  hw/arm/fsl-imx25: Wire up watchdog
  hw/watchdog: Implement full i.MX watchdog support
  hw: Move i.MX watchdog driver to hw/watchdog
  target/arm: Remove unused GEN_NEON_INTEGER_OP macro
  linux-user/arm: Fix identification of syscall numbers
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-05-21 22:06:56 +01:00
commit d19f1ab0de
37 changed files with 855 additions and 292 deletions

View File

@ -608,6 +608,7 @@ S: Odd Fixes
F: include/hw/arm/digic.h
F: hw/*/digic*
F: include/hw/*/digic*
F: tests/acceptance/machine_arm_canona1100.py
Goldfish RTC
M: Anup Patel <anup.patel@wdc.com>
@ -632,8 +633,10 @@ S: Odd Fixes
F: hw/arm/fsl-imx25.c
F: hw/arm/imx25_pdk.c
F: hw/misc/imx25_ccm.c
F: hw/watchdog/wdt_imx2.c
F: include/hw/arm/fsl-imx25.h
F: include/hw/misc/imx25_ccm.h
F: include/hw/watchdog/wdt_imx2.h
i.MX31 (kzm)
M: Peter Chubb <peter.chubb@nicta.com.au>
@ -700,12 +703,14 @@ F: hw/misc/armsse-cpuid.c
F: include/hw/misc/armsse-cpuid.h
F: hw/misc/armsse-mhu.c
F: include/hw/misc/armsse-mhu.h
F: docs/system/arm/mps2.rst
Musca
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/musca.c
F: docs/system/arm/musca.rst
Musicpal
M: Jan Kiszka <jan.kiszka@web.de>
@ -827,6 +832,7 @@ M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/vexpress.c
F: docs/system/arm/vexpress.rst
Versatile PB
M: Peter Maydell <peter.maydell@linaro.org>

View File

@ -1,5 +1,5 @@
Integrator/CP (``integratorcp``)
================================
Arm Integrator/CP (``integratorcp``)
====================================
The Arm Integrator/CP board is emulated with the following devices:

29
docs/system/arm/mps2.rst Normal file
View File

@ -0,0 +1,29 @@
Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
================================================================================
These board models all use Arm M-profile CPUs.
The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
FPGA but is otherwise the same as the 2). Since the CPU itself
and most of the devices are in the FPGA, the details of the board
as seen by the guest depend significantly on the FPGA image.
QEMU models the following FPGA images:
``mps2-an385``
Cortex-M3 as documented in ARM Application Note AN385
``mps2-an511``
Cortex-M3 'DesignStart' as documented in AN511
``mps2-an505``
Cortex-M33 as documented in ARM Application Note AN505
``mps2-an521``
Dual Cortex-M33 as documented in Application Note AN521
Differences between QEMU and real hardware:
- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
if zbt_boot_ctrl is always zero)
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
visible difference is that the LAN9118 doesn't support checksum
offloading

31
docs/system/arm/musca.rst Normal file
View File

@ -0,0 +1,31 @@
Arm Musca boards (``musca-a``, ``musca-b1``)
============================================
The Arm Musca development boards are a reference implementation
of a system using the SSE-200 Subsystem for Embedded. They are
dual Cortex-M33 systems.
QEMU provides models of the A and B1 variants of this board.
Unimplemented devices:
- SPI
- |I2C|
- |I2S|
- PWM
- QSPI
- Timer
- SCC
- GPIO
- eFlash
- MHU
- PVT
- SDIO
- CryptoCell
Note that (like the real hardware) the Musca-A machine is
asymmetric: CPU 0 does not have the FPU or DSP extensions,
but CPU 1 does. Also like the real hardware, the memory maps
for the A and B1 variants differ significantly, so guest
software must be built for the right variant.

View File

@ -0,0 +1,60 @@
Arm Versatile Express boards (``vexpress-a9``, ``vexpress-a15``)
================================================================
QEMU models two variants of the Arm Versatile Express development
board family:
- ``vexpress-a9`` models the combination of the Versatile Express
motherboard and the CoreTile Express A9x4 daughterboard
- ``vexpress-a15`` models the combination of the Versatile Express
motherboard and the CoreTile Express A15x2 daughterboard
Note that as this hardware does not have PCI, IDE or SCSI,
the only available storage option is emulated SD card.
Implemented devices:
- PL041 audio
- PL181 SD controller
- PL050 keyboard and mouse
- PL011 UARTs
- SP804 timers
- I2C controller
- PL031 RTC
- PL111 LCD display controller
- Flash memory
- LAN9118 ethernet
Unimplemented devices:
- SP810 system control block
- PCI-express
- USB controller (Philips ISP1761)
- Local DAP ROM
- CoreSight interfaces
- PL301 AXI interconnect
- SCC
- System counter
- HDLCD controller (``vexpress-a15``)
- SP805 watchdog
- PL341 dynamic memory controller
- DMA330 DMA controller
- PL354 static memory controller
- BP147 TrustZone Protection Controller
- TrustZone Address Space Controller
Other differences between the hardware and the QEMU model:
- QEMU will default to creating one CPU unless you pass a different
``-smp`` argument
- QEMU allows the amount of RAM provided to be specified with the
``-m`` argument
- QEMU defaults to providing a CPU which does not provide either
TrustZone or the Virtualization Extensions: if you want these you
must enable them with ``-machine secure=on`` and ``-machine
virtualization=on``
- QEMU provides 4 virtio-mmio virtio transports; these start at
address ``0x10013000`` for ``vexpress-a9`` and at ``0x1c130000`` for
``vexpress-a15``, and have IRQs from 40 upwards. If a dtb is
provided on the command line then QEMU will edit it to include
suitable entries describing these transports for the guest.

View File

@ -67,19 +67,27 @@ Unfortunately many of the Arm boards QEMU supports are currently
undocumented; you can get a complete list by running
``qemu-system-aarch64 --machine help``.
..
This table of contents should be kept sorted alphabetically
by the title text of each file, which isn't the same ordering
as an alphabetical sort by filename.
.. toctree::
:maxdepth: 1
arm/integratorcp
arm/versatile
arm/mps2
arm/musca
arm/realview
arm/xscale
arm/palm
arm/nseries
arm/stellaris
arm/versatile
arm/vexpress
arm/musicpal
arm/sx1
arm/nseries
arm/orangepi
arm/palm
arm/xscale
arm/sx1
arm/stellaris
Arm CPU features
================

View File

@ -359,6 +359,7 @@ config FSL_IMX25
select IMX
select IMX_FEC
select IMX_I2C
select WDT_IMX2
select DS1338
config FSL_IMX31
@ -366,6 +367,7 @@ config FSL_IMX31
select SERIAL
select IMX
select IMX_I2C
select WDT_IMX2
select LAN9118
config FSL_IMX6
@ -375,6 +377,7 @@ config FSL_IMX6
select IMX_FEC
select IMX_I2C
select IMX_USBPHY
select WDT_IMX2
select SDHCI
config ASPEED_SOC
@ -412,6 +415,7 @@ config FSL_IMX7
select IMX
select IMX_FEC
select IMX_I2C
select WDT_IMX2
select PCI_EXPRESS_DESIGNWARE
select SDHCI
select UNIMP
@ -425,6 +429,7 @@ config FSL_IMX6UL
select IMX
select IMX_FEC
select IMX_I2C
select WDT_IMX2
select SDHCI
select UNIMP

View File

@ -87,6 +87,7 @@ static void fsl_imx25_init(Object *obj)
TYPE_CHIPIDEA);
}
sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT);
}
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
@ -302,6 +303,15 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
usb_table[i].irq));
}
/* Watchdog */
object_property_set_bool(OBJECT(&s->wdt), true, "pretimeout-support",
&error_abort);
object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX25_WDT_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt), 0,
qdev_get_gpio_in(DEVICE(&s->avic),
FSL_IMX25_WDT_IRQ));
/* initialize 2 x 16 KB ROM */
memory_region_init_rom(&s->rom[0], OBJECT(dev), "imx25.rom0",
FSL_IMX25_ROM0_SIZE, &err);

View File

@ -63,6 +63,8 @@ static void fsl_imx31_init(Object *obj)
sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]),
TYPE_IMX_GPIO);
}
sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT);
}
static void fsl_imx31_realize(DeviceState *dev, Error **errp)
@ -205,6 +207,10 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
gpio_table[i].irq));
}
/* Watchdog */
object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX31_WDT_ADDR);
/* On a real system, the first 16k is a `secure boot rom' */
memory_region_init_rom(&s->secure_rom, OBJECT(dev), "imx31.secure_rom",
FSL_IMX31_SECURE_ROM_SIZE, &err);

View File

@ -433,11 +433,20 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
FSL_IMX6_WDOG1_ADDR,
FSL_IMX6_WDOG2_ADDR,
};
static const int FSL_IMX6_WDOGn_IRQ[FSL_IMX6_NUM_WDTS] = {
FSL_IMX6_WDOG1_IRQ,
FSL_IMX6_WDOG2_IRQ,
};
object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support",
&error_abort);
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX6_WDOGn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a9mpcore),
FSL_IMX6_WDOGn_IRQ[i]));
}
/* ROM memory */

View File

@ -531,12 +531,22 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
FSL_IMX6UL_WDOG2_ADDR,
FSL_IMX6UL_WDOG3_ADDR,
};
static const int FSL_IMX6UL_WDOGn_IRQ[FSL_IMX6UL_NUM_WDTS] = {
FSL_IMX6UL_WDOG1_IRQ,
FSL_IMX6UL_WDOG2_IRQ,
FSL_IMX6UL_WDOG3_IRQ,
};
object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support",
&error_abort);
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
FSL_IMX6UL_WDOGn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_WDOGn_IRQ[i]));
}
/*

View File

@ -447,11 +447,22 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
FSL_IMX7_WDOG3_ADDR,
FSL_IMX7_WDOG4_ADDR,
};
static const int FSL_IMX7_WDOGn_IRQ[FSL_IMX7_NUM_WDTS] = {
FSL_IMX7_WDOG1_IRQ,
FSL_IMX7_WDOG2_IRQ,
FSL_IMX7_WDOG3_IRQ,
FSL_IMX7_WDOG4_IRQ,
};
object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support",
&error_abort);
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX7_WDOGn_IRQ[i]));
}
/*
@ -459,6 +470,30 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
*/
create_unimplemented_device("sdma", FSL_IMX7_SDMA_ADDR, FSL_IMX7_SDMA_SIZE);
/*
* CAAM
*/
create_unimplemented_device("caam", FSL_IMX7_CAAM_ADDR, FSL_IMX7_CAAM_SIZE);
/*
* PWM
*/
create_unimplemented_device("pwm1", FSL_IMX7_PWM1_ADDR, FSL_IMX7_PWMn_SIZE);
create_unimplemented_device("pwm2", FSL_IMX7_PWM2_ADDR, FSL_IMX7_PWMn_SIZE);
create_unimplemented_device("pwm3", FSL_IMX7_PWM3_ADDR, FSL_IMX7_PWMn_SIZE);
create_unimplemented_device("pwm4", FSL_IMX7_PWM4_ADDR, FSL_IMX7_PWMn_SIZE);
/*
* CAN
*/
create_unimplemented_device("can1", FSL_IMX7_CAN1_ADDR, FSL_IMX7_CANn_SIZE);
create_unimplemented_device("can2", FSL_IMX7_CAN2_ADDR, FSL_IMX7_CANn_SIZE);
/*
* OCOTP
*/
create_unimplemented_device("ocotp", FSL_IMX7_OCOTP_ADDR,
FSL_IMX7_OCOTP_SIZE);
object_property_set_bool(OBJECT(&s->gpr), true, "realized",
&error_abort);

View File

@ -20,6 +20,7 @@
#include "exec/address-spaces.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "hw/char/pl011.h"
#include "hw/hw.h"
@ -144,8 +145,9 @@ static uint64_t integratorcm_read(void *opaque, hwaddr offset,
/* ??? Voltage control unimplemented. */
return 0;
default:
hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
(int)offset);
qemu_log_mask(LOG_UNIMP,
"%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
return 0;
}
}
@ -252,8 +254,9 @@ static void integratorcm_write(void *opaque, hwaddr offset,
/* ??? Voltage control unimplemented. */
break;
default:
hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
(int)offset);
qemu_log_mask(LOG_UNIMP,
"%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
}
@ -394,7 +397,8 @@ static uint64_t icp_pic_read(void *opaque, hwaddr offset,
case 5: /* INT_SOFTCLR */
case 11: /* FRQ_ENABLECLR */
default:
printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
return 0;
}
}
@ -430,7 +434,8 @@ static void icp_pic_write(void *opaque, hwaddr offset,
case 8: /* FRQ_STATUS */
case 9: /* FRQ_RAWSTAT */
default:
printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
return;
}
icp_pic_update(s);
@ -504,7 +509,8 @@ static uint64_t icp_control_read(void *opaque, hwaddr offset,
case 3: /* CP_DECODE */
return 0x11;
default:
hw_error("icp_control_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
return 0;
}
}
@ -524,7 +530,8 @@ static void icp_control_write(void *opaque, hwaddr offset,
/* Nothing interesting implemented yet. */
break;
default:
hw_error("icp_control_write: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
}
}

View File

@ -9,7 +9,6 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
@ -199,7 +198,8 @@ static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset,
return s->status[bank];
default:
hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
}
return 0;
@ -252,7 +252,8 @@ static void pxa2xx_gpio_write(void *opaque, hwaddr offset,
break;
default:
hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
}
}

View File

@ -23,7 +23,7 @@
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
@ -135,7 +135,8 @@ uart_write(void *opaque, hwaddr addr,
switch (addr)
{
case R_STATUS:
hw_error("write to UART STATUS?\n");
qemu_log_mask(LOG_GUEST_ERROR, "%s: write to UART STATUS\n",
__func__);
break;
case R_CTRL:

View File

@ -11,7 +11,7 @@
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "qemu/log.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "ui/console.h"
@ -407,7 +407,8 @@ static uint64_t pxa2xx_lcdc_read(void *opaque, hwaddr offset,
default:
fail:
hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
}
return 0;
@ -562,7 +563,8 @@ static void pxa2xx_lcdc_write(void *opaque, hwaddr offset,
default:
fail:
hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
}
}

View File

@ -9,6 +9,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
@ -268,7 +269,8 @@ static uint64_t pxa2xx_dma_read(void *opaque, hwaddr offset,
unsigned int channel;
if (size != 4) {
hw_error("%s: Bad access width\n", __func__);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad access width %u\n",
__func__, size);
return 5;
}
@ -315,8 +317,8 @@ static uint64_t pxa2xx_dma_read(void *opaque, hwaddr offset,
return s->chan[channel].cmd;
}
}
hw_error("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
return 7;
}
@ -327,7 +329,8 @@ static void pxa2xx_dma_write(void *opaque, hwaddr offset,
unsigned int channel;
if (size != 4) {
hw_error("%s: Bad access width\n", __func__);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad access width %u\n",
__func__, size);
return;
}
@ -420,7 +423,8 @@ static void pxa2xx_dma_write(void *opaque, hwaddr offset,
break;
}
fail:
hw_error("%s: Bad offset " TARGET_FMT_plx "\n", __func__, offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
}
}

View File

@ -36,6 +36,8 @@ static const uint8_t pl061_id_luminary[12] =
#define TYPE_PL061 "pl061"
#define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061)
#define N_GPIOS 8
typedef struct PL061State {
SysBusDevice parent_obj;
@ -62,7 +64,7 @@ typedef struct PL061State {
uint32_t cr;
uint32_t amsel;
qemu_irq irq;
qemu_irq out[8];
qemu_irq out[N_GPIOS];
const unsigned char *id;
uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */
} PL061State;
@ -112,7 +114,7 @@ static void pl061_update(PL061State *s)
changed = s->old_out_data ^ out;
if (changed) {
s->old_out_data = out;
for (i = 0; i < 8; i++) {
for (i = 0; i < N_GPIOS; i++) {
mask = 1 << i;
if (changed & mask) {
DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
@ -125,7 +127,7 @@ static void pl061_update(PL061State *s)
changed = (s->old_in_data ^ s->data) & ~s->dir;
if (changed) {
s->old_in_data = s->data;
for (i = 0; i < 8; i++) {
for (i = 0; i < N_GPIOS; i++) {
mask = 1 << i;
if (changed & mask) {
DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0);
@ -364,8 +366,8 @@ static void pl061_init(Object *obj)
memory_region_init_io(&s->iomem, obj, &pl061_ops, s, "pl061", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
qdev_init_gpio_in(dev, pl061_set_irq, 8);
qdev_init_gpio_out(dev, s->out, 8);
qdev_init_gpio_in(dev, pl061_set_irq, N_GPIOS);
qdev_init_gpio_out(dev, s->out, N_GPIOS);
}
static void pl061_class_init(ObjectClass *klass, void *data)

View File

@ -44,7 +44,6 @@ common-obj-$(CONFIG_IMX) += imx6_ccm.o
common-obj-$(CONFIG_IMX) += imx6ul_ccm.o
obj-$(CONFIG_IMX) += imx6_src.o
common-obj-$(CONFIG_IMX) += imx7_ccm.o
common-obj-$(CONFIG_IMX) += imx2_wdt.o
common-obj-$(CONFIG_IMX) += imx7_snvs.o
common-obj-$(CONFIG_IMX) += imx7_gpr.o
common-obj-$(CONFIG_IMX) += imx_rngc.o

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 2018, Impinj, Inc.
*
* i.MX2 Watchdog IP block
*
* Author: Andrey Smirnov <andrew.smirnov@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "qemu/module.h"
#include "sysemu/watchdog.h"
#include "hw/misc/imx2_wdt.h"
#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */
#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */
static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
unsigned int size)
{
return 0;
}
static void imx2_wdt_write(void *opaque, hwaddr addr,
uint64_t value, unsigned int size)
{
if (addr == IMX2_WDT_WCR &&
(~value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
watchdog_perform_action();
}
}
static const MemoryRegionOps imx2_wdt_ops = {
.read = imx2_wdt_read,
.write = imx2_wdt_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl = {
/*
* Our device would not work correctly if the guest was doing
* unaligned access. This might not be a limitation on the
* real device but in practice there is no reason for a guest
* to access this device unaligned.
*/
.min_access_size = 4,
.max_access_size = 4,
.unaligned = false,
},
};
static void imx2_wdt_realize(DeviceState *dev, Error **errp)
{
IMX2WdtState *s = IMX2_WDT(dev);
memory_region_init_io(&s->mmio, OBJECT(dev),
&imx2_wdt_ops, s,
TYPE_IMX2_WDT".mmio",
IMX2_WDT_REG_NUM * sizeof(uint16_t));
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
}
static void imx2_wdt_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = imx2_wdt_realize;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo imx2_wdt_info = {
.name = TYPE_IMX2_WDT,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMX2WdtState),
.class_init = imx2_wdt_class_init,
};
static WatchdogTimerModel model = {
.wdt_name = "imx2-watchdog",
.wdt_description = "i.MX2 Watchdog",
};
static void imx2_wdt_register_type(void)
{
watchdog_add_model(&model);
type_register_static(&imx2_wdt_info);
}
type_init(imx2_wdt_register_type)

View File

@ -54,7 +54,6 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "migration/vmstate.h"
#include "qemu/timer.h"
@ -62,7 +61,6 @@
#include "hw/ptimer.h"
#include "hw/arm/exynos4210.h"
#include "hw/hw.h"
#include "hw/irq.h"
//#define DEBUG_MCT
@ -1062,7 +1060,7 @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset,
int index;
int shift;
uint64_t count;
uint32_t value;
uint32_t value = 0;
int lt_i;
switch (offset) {
@ -1158,8 +1156,8 @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset,
break;
default:
hw_error("exynos4210.mct: bad read offset "
TARGET_FMT_plx "\n", offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
return value;
@ -1484,8 +1482,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
break;
default:
hw_error("exynos4210.mct: bad write offset "
TARGET_FMT_plx "\n", offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
}

View File

@ -14,3 +14,6 @@ config WDT_IB700
config WDT_DIAG288
bool
config WDT_IMX2
bool

View File

@ -4,3 +4,4 @@ common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o
common-obj-$(CONFIG_WDT_IMX2) += wdt_imx2.o

304
hw/watchdog/wdt_imx2.c Normal file
View File

@ -0,0 +1,304 @@
/*
* Copyright (c) 2018, Impinj, Inc.
*
* i.MX2 Watchdog IP block
*
* Author: Andrey Smirnov <andrew.smirnov@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "qemu/module.h"
#include "sysemu/watchdog.h"
#include "migration/vmstate.h"
#include "hw/qdev-properties.h"
#include "hw/watchdog/wdt_imx2.h"
static void imx2_wdt_interrupt(void *opaque)
{
IMX2WdtState *s = IMX2_WDT(opaque);
s->wicr |= IMX2_WDT_WICR_WTIS;
qemu_set_irq(s->irq, 1);
}
static void imx2_wdt_expired(void *opaque)
{
IMX2WdtState *s = IMX2_WDT(opaque);
s->wrsr = IMX2_WDT_WRSR_TOUT;
/* Perform watchdog action if watchdog is enabled */
if (s->wcr & IMX2_WDT_WCR_WDE) {
s->wrsr = IMX2_WDT_WRSR_TOUT;
watchdog_perform_action();
}
}
static void imx2_wdt_reset(DeviceState *dev)
{
IMX2WdtState *s = IMX2_WDT(dev);
ptimer_transaction_begin(s->timer);
ptimer_stop(s->timer);
ptimer_transaction_commit(s->timer);
if (s->pretimeout_support) {
ptimer_transaction_begin(s->itimer);
ptimer_stop(s->itimer);
ptimer_transaction_commit(s->itimer);
}
s->wicr_locked = false;
s->wcr_locked = false;
s->wcr_wde_locked = false;
s->wcr = IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS;
s->wsr = 0;
s->wrsr &= ~(IMX2_WDT_WRSR_TOUT | IMX2_WDT_WRSR_SFTW);
s->wicr = IMX2_WDT_WICR_WICT_DEF;
s->wmcr = IMX2_WDT_WMCR_PDE;
}
static uint64_t imx2_wdt_read(void *opaque, hwaddr addr, unsigned int size)
{
IMX2WdtState *s = IMX2_WDT(opaque);
switch (addr) {
case IMX2_WDT_WCR:
return s->wcr;
case IMX2_WDT_WSR:
return s->wsr;
case IMX2_WDT_WRSR:
return s->wrsr;
case IMX2_WDT_WICR:
return s->wicr;
case IMX2_WDT_WMCR:
return s->wmcr;
}
return 0;
}
static void imx_wdt2_update_itimer(IMX2WdtState *s, bool start)
{
bool running = (s->wcr & IMX2_WDT_WCR_WDE) && (s->wcr & IMX2_WDT_WCR_WT);
bool enabled = s->wicr & IMX2_WDT_WICR_WIE;
ptimer_transaction_begin(s->itimer);
if (start || !enabled) {
ptimer_stop(s->itimer);
}
if (running && enabled) {
int count = ptimer_get_count(s->timer);
int pretimeout = s->wicr & IMX2_WDT_WICR_WICT;
/*
* Only (re-)start pretimeout timer if its counter value is larger
* than 0. Otherwise it will fire right away and we'll get an
* interrupt loop.
*/
if (count > pretimeout) {
ptimer_set_count(s->itimer, count - pretimeout);
if (start) {
ptimer_run(s->itimer, 1);
}
}
}
ptimer_transaction_commit(s->itimer);
}
static void imx_wdt2_update_timer(IMX2WdtState *s, bool start)
{
ptimer_transaction_begin(s->timer);
if (start) {
ptimer_stop(s->timer);
}
if ((s->wcr & IMX2_WDT_WCR_WDE) && (s->wcr & IMX2_WDT_WCR_WT)) {
int count = (s->wcr & IMX2_WDT_WCR_WT) >> 8;
/* A value of 0 reflects one period (0.5s). */
ptimer_set_count(s->timer, count + 1);
if (start) {
ptimer_run(s->timer, 1);
}
}
ptimer_transaction_commit(s->timer);
if (s->pretimeout_support) {
imx_wdt2_update_itimer(s, start);
}
}
static void imx2_wdt_write(void *opaque, hwaddr addr,
uint64_t value, unsigned int size)
{
IMX2WdtState *s = IMX2_WDT(opaque);
switch (addr) {
case IMX2_WDT_WCR:
if (s->wcr_locked) {
value &= ~IMX2_WDT_WCR_LOCK_MASK;
value |= (s->wicr & IMX2_WDT_WCR_LOCK_MASK);
}
s->wcr_locked = true;
if (s->wcr_wde_locked) {
value &= ~IMX2_WDT_WCR_WDE;
value |= (s->wicr & ~IMX2_WDT_WCR_WDE);
} else if (value & IMX2_WDT_WCR_WDE) {
s->wcr_wde_locked = true;
}
if (s->wcr_wdt_locked) {
value &= ~IMX2_WDT_WCR_WDT;
value |= (s->wicr & ~IMX2_WDT_WCR_WDT);
} else if (value & IMX2_WDT_WCR_WDT) {
s->wcr_wdt_locked = true;
}
s->wcr = value;
if (!(value & IMX2_WDT_WCR_SRS)) {
s->wrsr = IMX2_WDT_WRSR_SFTW;
}
if (!(value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS)) ||
(!(value & IMX2_WDT_WCR_WT) && (value & IMX2_WDT_WCR_WDE))) {
watchdog_perform_action();
}
s->wcr |= IMX2_WDT_WCR_SRS;
imx_wdt2_update_timer(s, true);
break;
case IMX2_WDT_WSR:
if (s->wsr == IMX2_WDT_SEQ1 && value == IMX2_WDT_SEQ2) {
imx_wdt2_update_timer(s, false);
}
s->wsr = value;
break;
case IMX2_WDT_WRSR:
break;
case IMX2_WDT_WICR:
if (!s->pretimeout_support) {
return;
}
value &= IMX2_WDT_WICR_LOCK_MASK | IMX2_WDT_WICR_WTIS;
if (s->wicr_locked) {
value &= IMX2_WDT_WICR_WTIS;
value |= (s->wicr & IMX2_WDT_WICR_LOCK_MASK);
}
s->wicr = value | (s->wicr & IMX2_WDT_WICR_WTIS);
if (value & IMX2_WDT_WICR_WTIS) {
s->wicr &= ~IMX2_WDT_WICR_WTIS;
qemu_set_irq(s->irq, 0);
}
imx_wdt2_update_itimer(s, true);
s->wicr_locked = true;
break;
case IMX2_WDT_WMCR:
s->wmcr = value & IMX2_WDT_WMCR_PDE;
break;
}
}
static const MemoryRegionOps imx2_wdt_ops = {
.read = imx2_wdt_read,
.write = imx2_wdt_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl = {
/*
* Our device would not work correctly if the guest was doing
* unaligned access. This might not be a limitation on the
* real device but in practice there is no reason for a guest
* to access this device unaligned.
*/
.min_access_size = 2,
.max_access_size = 2,
.unaligned = false,
},
};
static const VMStateDescription vmstate_imx2_wdt = {
.name = "imx2.wdt",
.fields = (VMStateField[]) {
VMSTATE_PTIMER(timer, IMX2WdtState),
VMSTATE_PTIMER(itimer, IMX2WdtState),
VMSTATE_BOOL(wicr_locked, IMX2WdtState),
VMSTATE_BOOL(wcr_locked, IMX2WdtState),
VMSTATE_BOOL(wcr_wde_locked, IMX2WdtState),
VMSTATE_BOOL(wcr_wdt_locked, IMX2WdtState),
VMSTATE_UINT16(wcr, IMX2WdtState),
VMSTATE_UINT16(wsr, IMX2WdtState),
VMSTATE_UINT16(wrsr, IMX2WdtState),
VMSTATE_UINT16(wmcr, IMX2WdtState),
VMSTATE_UINT16(wicr, IMX2WdtState),
VMSTATE_END_OF_LIST()
}
};
static void imx2_wdt_realize(DeviceState *dev, Error **errp)
{
IMX2WdtState *s = IMX2_WDT(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
memory_region_init_io(&s->mmio, OBJECT(dev),
&imx2_wdt_ops, s,
TYPE_IMX2_WDT,
IMX2_WDT_MMIO_SIZE);
sysbus_init_mmio(sbd, &s->mmio);
sysbus_init_irq(sbd, &s->irq);
s->timer = ptimer_init(imx2_wdt_expired, s,
PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
ptimer_transaction_begin(s->timer);
ptimer_set_freq(s->timer, 2);
ptimer_set_limit(s->timer, 0xff, 1);
ptimer_transaction_commit(s->timer);
if (s->pretimeout_support) {
s->itimer = ptimer_init(imx2_wdt_interrupt, s,
PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
ptimer_transaction_begin(s->itimer);
ptimer_set_freq(s->itimer, 2);
ptimer_set_limit(s->itimer, 0xff, 1);
ptimer_transaction_commit(s->itimer);
}
}
static Property imx2_wdt_properties[] = {
DEFINE_PROP_BOOL("pretimeout-support", IMX2WdtState, pretimeout_support,
false),
DEFINE_PROP_END_OF_LIST()
};
static void imx2_wdt_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
device_class_set_props(dc, imx2_wdt_properties);
dc->realize = imx2_wdt_realize;
dc->reset = imx2_wdt_reset;
dc->vmsd = &vmstate_imx2_wdt;
dc->desc = "i.MX watchdog timer";
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo imx2_wdt_info = {
.name = TYPE_IMX2_WDT,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMX2WdtState),
.class_init = imx2_wdt_class_init,
};
static WatchdogTimerModel model = {
.wdt_name = "imx2-watchdog",
.wdt_description = "i.MX2 Watchdog",
};
static void imx2_wdt_register_type(void)
{
watchdog_add_model(&model);
type_register_static(&imx2_wdt_info);
}
type_init(imx2_wdt_register_type)

View File

@ -29,6 +29,7 @@
#include "hw/gpio/imx_gpio.h"
#include "hw/sd/sdhci.h"
#include "hw/usb/chipidea.h"
#include "hw/watchdog/wdt_imx2.h"
#include "exec/memory.h"
#include "target/arm/cpu.h"
@ -60,6 +61,7 @@ typedef struct FslIMX25State {
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
ChipideaState usb[FSL_IMX25_NUM_USBS];
IMX2WdtState wdt;
MemoryRegion rom[2];
MemoryRegion iram;
MemoryRegion iram_alias;
@ -229,6 +231,8 @@ typedef struct FslIMX25State {
#define FSL_IMX25_GPIO1_SIZE 0x4000
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
#define FSL_IMX25_GPIO2_SIZE 0x4000
#define FSL_IMX25_WDT_ADDR 0x53FDC000
#define FSL_IMX25_WDT_SIZE 0x4000
#define FSL_IMX25_USB1_ADDR 0x53FF4000
#define FSL_IMX25_USB1_SIZE 0x0200
#define FSL_IMX25_USB2_ADDR 0x53FF4400
@ -268,5 +272,6 @@ typedef struct FslIMX25State {
#define FSL_IMX25_ESDHC2_IRQ 8
#define FSL_IMX25_USB1_IRQ 37
#define FSL_IMX25_USB2_IRQ 35
#define FSL_IMX25_WDT_IRQ 55
#endif /* FSL_IMX25_H */

View File

@ -25,6 +25,7 @@
#include "hw/timer/imx_epit.h"
#include "hw/i2c/imx_i2c.h"
#include "hw/gpio/imx_gpio.h"
#include "hw/watchdog/wdt_imx2.h"
#include "exec/memory.h"
#include "target/arm/cpu.h"
@ -49,6 +50,7 @@ typedef struct FslIMX31State {
IMXEPITState epit[FSL_IMX31_NUM_EPITS];
IMXI2CState i2c[FSL_IMX31_NUM_I2CS];
IMXGPIOState gpio[FSL_IMX31_NUM_GPIOS];
IMX2WdtState wdt;
MemoryRegion secure_rom;
MemoryRegion rom;
MemoryRegion iram;
@ -87,6 +89,8 @@ typedef struct FslIMX31State {
#define FSL_IMX31_GPIO1_SIZE 0x4000
#define FSL_IMX31_GPIO2_ADDR 0x53FD0000
#define FSL_IMX31_GPIO2_SIZE 0x4000
#define FSL_IMX31_WDT_ADDR 0x53FDC000
#define FSL_IMX31_WDT_SIZE 0x4000
#define FSL_IMX31_AVIC_ADDR 0x68000000
#define FSL_IMX31_AVIC_SIZE 0x100
#define FSL_IMX31_SDRAM0_ADDR 0x80000000

View File

@ -21,7 +21,7 @@
#include "hw/cpu/a9mpcore.h"
#include "hw/misc/imx6_ccm.h"
#include "hw/misc/imx6_src.h"
#include "hw/misc/imx2_wdt.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
#include "hw/timer/imx_epit.h"

View File

@ -24,7 +24,7 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx7_gpr.h"
#include "hw/intc/imx_gpcv2.h"
#include "hw/misc/imx2_wdt.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"

View File

@ -26,7 +26,7 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx7_gpr.h"
#include "hw/misc/imx6_src.h"
#include "hw/misc/imx2_wdt.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
@ -113,6 +113,9 @@ enum FslIMX7MemoryMap {
FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
FSL_IMX7_IOMUXCn_SIZE = 0x1000,
FSL_IMX7_OCOTP_ADDR = 0x30350000,
FSL_IMX7_OCOTP_SIZE = 0x10000,
FSL_IMX7_ANALOG_ADDR = 0x30360000,
FSL_IMX7_SNVS_ADDR = 0x30370000,
FSL_IMX7_CCM_ADDR = 0x30380000,
@ -124,11 +127,24 @@ enum FslIMX7MemoryMap {
FSL_IMX7_ADC2_ADDR = 0x30620000,
FSL_IMX7_ADCn_SIZE = 0x1000,
FSL_IMX7_PWM1_ADDR = 0x30660000,
FSL_IMX7_PWM2_ADDR = 0x30670000,
FSL_IMX7_PWM3_ADDR = 0x30680000,
FSL_IMX7_PWM4_ADDR = 0x30690000,
FSL_IMX7_PWMn_SIZE = 0x10000,
FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
FSL_IMX7_PCIE_PHY_SIZE = 0x10000,
FSL_IMX7_GPC_ADDR = 0x303A0000,
FSL_IMX7_CAAM_ADDR = 0x30900000,
FSL_IMX7_CAAM_SIZE = 0x40000,
FSL_IMX7_CAN1_ADDR = 0x30A00000,
FSL_IMX7_CAN2_ADDR = 0x30A10000,
FSL_IMX7_CANn_SIZE = 0x10000,
FSL_IMX7_I2C1_ADDR = 0x30A20000,
FSL_IMX7_I2C2_ADDR = 0x30A30000,
FSL_IMX7_I2C3_ADDR = 0x30A40000,
@ -212,6 +228,11 @@ enum FslIMX7IRQs {
FSL_IMX7_USB2_IRQ = 42,
FSL_IMX7_USB3_IRQ = 40,
FSL_IMX7_WDOG1_IRQ = 78,
FSL_IMX7_WDOG2_IRQ = 79,
FSL_IMX7_WDOG3_IRQ = 10,
FSL_IMX7_WDOG4_IRQ = 109,
FSL_IMX7_PCI_INTA_IRQ = 125,
FSL_IMX7_PCI_INTB_IRQ = 124,
FSL_IMX7_PCI_INTC_IRQ = 123,

View File

@ -1,33 +0,0 @@
/*
* Copyright (c) 2017, Impinj, Inc.
*
* i.MX2 Watchdog IP block
*
* Author: Andrey Smirnov <andrew.smirnov@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef IMX2_WDT_H
#define IMX2_WDT_H
#include "hw/sysbus.h"
#define TYPE_IMX2_WDT "imx2.wdt"
#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
enum IMX2WdtRegisters {
IMX2_WDT_WCR = 0x0000,
IMX2_WDT_REG_NUM = 0x0008 / sizeof(uint16_t) + 1,
};
typedef struct IMX2WdtState {
/* <private> */
SysBusDevice parent_obj;
MemoryRegion mmio;
} IMX2WdtState;
#endif /* IMX2_WDT_H */

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2017, Impinj, Inc.
*
* i.MX2 Watchdog IP block
*
* Author: Andrey Smirnov <andrew.smirnov@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef IMX2_WDT_H
#define IMX2_WDT_H
#include "qemu/bitops.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/ptimer.h"
#define TYPE_IMX2_WDT "imx2.wdt"
#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
enum IMX2WdtRegisters {
IMX2_WDT_WCR = 0x0000, /* Control Register */
IMX2_WDT_WSR = 0x0002, /* Service Register */
IMX2_WDT_WRSR = 0x0004, /* Reset Status Register */
IMX2_WDT_WICR = 0x0006, /* Interrupt Control Register */
IMX2_WDT_WMCR = 0x0008, /* Misc Register */
};
#define IMX2_WDT_MMIO_SIZE 0x000a
/* Control Register definitions */
#define IMX2_WDT_WCR_WT (0xFF << 8) /* Watchdog Timeout Field */
#define IMX2_WDT_WCR_WDW BIT(7) /* WDOG Disable for Wait */
#define IMX2_WDT_WCR_WDA BIT(5) /* WDOG Assertion */
#define IMX2_WDT_WCR_SRS BIT(4) /* Software Reset Signal */
#define IMX2_WDT_WCR_WDT BIT(3) /* WDOG Timeout Assertion */
#define IMX2_WDT_WCR_WDE BIT(2) /* Watchdog Enable */
#define IMX2_WDT_WCR_WDBG BIT(1) /* Watchdog Debug Enable */
#define IMX2_WDT_WCR_WDZST BIT(0) /* Watchdog Timer Suspend */
#define IMX2_WDT_WCR_LOCK_MASK (IMX2_WDT_WCR_WDZST | IMX2_WDT_WCR_WDBG \
| IMX2_WDT_WCR_WDW)
/* Service Register definitions */
#define IMX2_WDT_SEQ1 0x5555 /* service sequence 1 */
#define IMX2_WDT_SEQ2 0xAAAA /* service sequence 2 */
/* Reset Status Register definitions */
#define IMX2_WDT_WRSR_TOUT BIT(1) /* Reset due to Timeout */
#define IMX2_WDT_WRSR_SFTW BIT(0) /* Reset due to software reset */
/* Interrupt Control Register definitions */
#define IMX2_WDT_WICR_WIE BIT(15) /* Interrupt Enable */
#define IMX2_WDT_WICR_WTIS BIT(14) /* Interrupt Status */
#define IMX2_WDT_WICR_WICT 0xff /* Interrupt Timeout */
#define IMX2_WDT_WICR_WICT_DEF 0x04 /* Default interrupt timeout (2s) */
#define IMX2_WDT_WICR_LOCK_MASK (IMX2_WDT_WICR_WIE | IMX2_WDT_WICR_WICT)
/* Misc Control Register definitions */
#define IMX2_WDT_WMCR_PDE BIT(0) /* Power-Down Enable */
typedef struct IMX2WdtState {
/* <private> */
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion mmio;
qemu_irq irq;
struct ptimer_state *timer;
struct ptimer_state *itimer;
bool pretimeout_support;
bool wicr_locked;
uint16_t wcr;
uint16_t wsr;
uint16_t wrsr;
uint16_t wicr;
uint16_t wmcr;
bool wcr_locked; /* affects WDZST, WDBG, and WDW */
bool wcr_wde_locked; /* affects WDE */
bool wcr_wdt_locked; /* affects WDT (never cleared) */
} IMX2WdtState;
#endif /* IMX2_WDT_H */

View File

@ -295,84 +295,100 @@ void cpu_loop(CPUARMState *env)
}
break;
case EXCP_SWI:
case EXCP_BKPT:
{
env->eabi = 1;
/* system call */
if (trapnr == EXCP_BKPT) {
if (env->thumb) {
/* FIXME - what to do if get_user() fails? */
get_user_code_u16(insn, env->regs[15], env);
n = insn & 0xff;
env->regs[15] += 2;
} else {
/* FIXME - what to do if get_user() fails? */
get_user_code_u32(insn, env->regs[15], env);
n = (insn & 0xf) | ((insn >> 4) & 0xff0);
env->regs[15] += 4;
}
if (env->thumb) {
/* Thumb is always EABI style with syscall number in r7 */
n = env->regs[7];
} else {
if (env->thumb) {
/* FIXME - what to do if get_user() fails? */
get_user_code_u16(insn, env->regs[15] - 2, env);
n = insn & 0xff;
/*
* Equivalent of kernel CONFIG_OABI_COMPAT: read the
* Arm SVC insn to extract the immediate, which is the
* syscall number in OABI.
*/
/* FIXME - what to do if get_user() fails? */
get_user_code_u32(insn, env->regs[15] - 4, env);
n = insn & 0xffffff;
if (n == 0) {
/* zero immediate: EABI, syscall number in r7 */
n = env->regs[7];
} else {
/* FIXME - what to do if get_user() fails? */
get_user_code_u32(insn, env->regs[15] - 4, env);
n = insn & 0xffffff;
/*
* This XOR matches the kernel code: an immediate
* in the valid range (0x900000 .. 0x9fffff) is
* converted into the correct EABI-style syscall
* number; invalid immediates end up as values
* > 0xfffff and are handled below as out-of-range.
*/
n ^= ARM_SYSCALL_BASE;
env->eabi = 0;
}
}
if (n == ARM_NR_cacheflush) {
/* nop */
} else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
/* linux syscall */
if (env->thumb || n == 0) {
n = env->regs[7];
} else {
n -= ARM_SYSCALL_BASE;
env->eabi = 0;
}
if ( n > ARM_NR_BASE) {
switch (n) {
case ARM_NR_cacheflush:
/* nop */
break;
case ARM_NR_set_tls:
cpu_set_tls(env, env->regs[0]);
env->regs[0] = 0;
break;
case ARM_NR_breakpoint:
env->regs[15] -= env->thumb ? 2 : 4;
goto excp_debug;
case ARM_NR_get_tls:
env->regs[0] = cpu_get_tls(env);
break;
default:
if (n > ARM_NR_BASE) {
switch (n) {
case ARM_NR_cacheflush:
/* nop */
break;
case ARM_NR_set_tls:
cpu_set_tls(env, env->regs[0]);
env->regs[0] = 0;
break;
case ARM_NR_breakpoint:
env->regs[15] -= env->thumb ? 2 : 4;
goto excp_debug;
case ARM_NR_get_tls:
env->regs[0] = cpu_get_tls(env);
break;
default:
if (n < 0xf0800) {
/*
* Syscalls 0xf0000..0xf07ff (or 0x9f0000..
* 0x9f07ff in OABI numbering) are defined
* to return -ENOSYS rather than raising
* SIGILL. Note that we have already
* removed the 0x900000 prefix.
*/
qemu_log_mask(LOG_UNIMP,
"qemu: Unsupported ARM syscall: 0x%x\n",
"qemu: Unsupported ARM syscall: 0x%x\n",
n);
env->regs[0] = -TARGET_ENOSYS;
break;
}
} else {
ret = do_syscall(env,
n,
env->regs[0],
env->regs[1],
env->regs[2],
env->regs[3],
env->regs[4],
env->regs[5],
0, 0);
if (ret == -TARGET_ERESTARTSYS) {
env->regs[15] -= env->thumb ? 2 : 4;
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
env->regs[0] = ret;
} else {
/*
* Otherwise SIGILL. This includes any SWI with
* immediate not originally 0x9fxxxx, because
* of the earlier XOR.
*/
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLTRP;
info._sifields._sigfault._addr = env->regs[15];
if (env->thumb) {
info._sifields._sigfault._addr -= 2;
} else {
info._sifields._sigfault._addr -= 4;
}
queue_signal(env, info.si_signo,
QEMU_SI_FAULT, &info);
}
break;
}
} else {
goto error;
ret = do_syscall(env,
n,
env->regs[0],
env->regs[1],
env->regs[2],
env->regs[3],
env->regs[4],
env->regs[5],
0, 0);
if (ret == -TARGET_ERESTARTSYS) {
env->regs[15] -= env->thumb ? 2 : 4;
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
env->regs[0] = ret;
}
}
}
break;
@ -396,6 +412,7 @@ void cpu_loop(CPUARMState *env)
}
break;
case EXCP_DEBUG:
case EXCP_BKPT:
excp_debug:
info.si_signo = TARGET_SIGTRAP;
info.si_errno = 0;

View File

@ -126,8 +126,6 @@ struct rt_sigframe_v2
abi_ulong retcode[4];
};
#define TARGET_CONFIG_CPU_32 1
/*
* For ARM syscalls, we encode the syscall number into the instruction.
*/
@ -187,9 +185,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
__put_user(env->regs[13], &sc->arm_sp);
__put_user(env->regs[14], &sc->arm_lr);
__put_user(env->regs[15], &sc->arm_pc);
#ifdef TARGET_CONFIG_CPU_32
__put_user(cpsr_read(env), &sc->arm_cpsr);
#endif
__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
__put_user(/* current->thread.error_code */ 0, &sc->error_code);
@ -244,6 +240,11 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
} else {
cpsr &= ~CPSR_T;
}
if (env->cp15.sctlr_el[1] & SCTLR_E0E) {
cpsr |= CPSR_E;
} else {
cpsr &= ~CPSR_E;
}
if (ka->sa_flags & TARGET_SA_RESTORER) {
if (is_fdpic) {
@ -287,7 +288,8 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
env->regs[13] = frame_addr;
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
cpsr_write(env, cpsr, CPSR_IT | CPSR_T | CPSR_E, CPSRWriteByInstr);
arm_rebuild_hflags(env);
return 0;
}
@ -543,10 +545,9 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
__get_user(env->regs[13], &sc->arm_sp);
__get_user(env->regs[14], &sc->arm_lr);
__get_user(env->regs[15], &sc->arm_pc);
#ifdef TARGET_CONFIG_CPU_32
__get_user(cpsr, &sc->arm_cpsr);
cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
#endif
arm_rebuild_hflags(env);
err |= !valid_user_regs(env);

View File

@ -1230,7 +1230,7 @@ void pmu_init(ARMCPU *cpu);
#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
| CPSR_NZCV)
/* Bits writable in user mode. */
#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE | CPSR_E)
/* Execution state bits. MRS read as zero, MSR writes ignored. */
#define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J | CPSR_IL)

View File

@ -496,14 +496,8 @@ static void clear_vec_high(DisasContext *s, bool is_q, int rd)
unsigned ofs = fp_reg_offset(s, rd, MO_64);
unsigned vsz = vec_full_reg_size(s);
if (!is_q) {
TCGv_i64 tcg_zero = tcg_const_i64(0);
tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8);
tcg_temp_free_i64(tcg_zero);
}
if (vsz > 16) {
tcg_gen_gvec_dup_imm(MO_64, ofs + 16, vsz - 16, vsz - 16, 0);
}
/* Nop move, with side effect of clearing the tail. */
tcg_gen_gvec_mov(MO_64, ofs, ofs, is_q ? 16 : 8, vsz);
}
void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
@ -906,11 +900,10 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
{
/* This always zero-extends and writes to a full 128 bit wide vector */
TCGv_i64 tmplo = tcg_temp_new_i64();
TCGv_i64 tmphi;
TCGv_i64 tmphi = NULL;
if (size < 4) {
MemOp memop = s->be_data + size;
tmphi = tcg_const_i64(0);
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
} else {
bool be = s->be_data == MO_BE;
@ -928,12 +921,13 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
}
tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
tcg_temp_free_i64(tmplo);
tcg_temp_free_i64(tmphi);
clear_vec_high(s, true, destidx);
if (tmphi) {
tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
tcg_temp_free_i64(tmphi);
}
clear_vec_high(s, tmphi != NULL, destidx);
}
/*
@ -6940,7 +6934,6 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn)
read_vec_element(s, tcg_resh, rm, 0, MO_64);
do_ext64(s, tcg_resh, tcg_resl, pos);
}
tcg_gen_movi_i64(tcg_resh, 0);
} else {
TCGv_i64 tcg_hh;
typedef struct {
@ -6970,9 +6963,11 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn)
write_vec_element(s, tcg_resl, rd, 0, MO_64);
tcg_temp_free_i64(tcg_resl);
write_vec_element(s, tcg_resh, rd, 1, MO_64);
if (is_q) {
write_vec_element(s, tcg_resh, rd, 1, MO_64);
}
tcg_temp_free_i64(tcg_resh);
clear_vec_high(s, true, rd);
clear_vec_high(s, is_q, rd);
}
/* TBL/TBX
@ -7009,17 +7004,21 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
* the input.
*/
tcg_resl = tcg_temp_new_i64();
tcg_resh = tcg_temp_new_i64();
tcg_resh = NULL;
if (is_tblx) {
read_vec_element(s, tcg_resl, rd, 0, MO_64);
} else {
tcg_gen_movi_i64(tcg_resl, 0);
}
if (is_tblx && is_q) {
read_vec_element(s, tcg_resh, rd, 1, MO_64);
} else {
tcg_gen_movi_i64(tcg_resh, 0);
if (is_q) {
tcg_resh = tcg_temp_new_i64();
if (is_tblx) {
read_vec_element(s, tcg_resh, rd, 1, MO_64);
} else {
tcg_gen_movi_i64(tcg_resh, 0);
}
}
tcg_idx = tcg_temp_new_i64();
@ -7039,9 +7038,12 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
write_vec_element(s, tcg_resl, rd, 0, MO_64);
tcg_temp_free_i64(tcg_resl);
write_vec_element(s, tcg_resh, rd, 1, MO_64);
tcg_temp_free_i64(tcg_resh);
clear_vec_high(s, true, rd);
if (is_q) {
write_vec_element(s, tcg_resh, rd, 1, MO_64);
tcg_temp_free_i64(tcg_resh);
}
clear_vec_high(s, is_q, rd);
}
/* ZIP/UZP/TRN
@ -7078,7 +7080,7 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
}
tcg_resl = tcg_const_i64(0);
tcg_resh = tcg_const_i64(0);
tcg_resh = is_q ? tcg_const_i64(0) : NULL;
tcg_res = tcg_temp_new_i64();
for (i = 0; i < elements; i++) {
@ -7129,9 +7131,12 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
write_vec_element(s, tcg_resl, rd, 0, MO_64);
tcg_temp_free_i64(tcg_resl);
write_vec_element(s, tcg_resh, rd, 1, MO_64);
tcg_temp_free_i64(tcg_resh);
clear_vec_high(s, true, rd);
if (is_q) {
write_vec_element(s, tcg_resh, rd, 1, MO_64);
tcg_temp_free_i64(tcg_resh);
}
clear_vec_high(s, is_q, rd);
}
/*

View File

@ -3034,29 +3034,6 @@ static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
default: return 1; \
}} while (0)
#define GEN_NEON_INTEGER_OP(name) do { \
switch ((size << 1) | u) { \
case 0: \
gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
break; \
case 1: \
gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
break; \
case 2: \
gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
break; \
case 3: \
gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
break; \
case 4: \
gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
break; \
case 5: \
gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
break; \
default: return 1; \
}} while (0)
static TCGv_i32 neon_load_scratch(int scratch)
{
TCGv_i32 tmp = tcg_temp_new_i32();

View File

@ -0,0 +1,35 @@
# Functional test that boots the canon-a1100 machine with firmware
#
# Copyright (c) 2020 Red Hat, Inc.
#
# Author:
# Thomas Huth <thuth@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later. See the COPYING file in the top-level directory.
from avocado_qemu import Test
from avocado_qemu import wait_for_console_pattern
from avocado.utils import archive
class CanonA1100Machine(Test):
"""Boots the barebox firmware and checks that the console is operational"""
timeout = 90
def test_arm_canona1100(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:canon-a1100
:avocado: tags=device:pflash_cfi02
"""
tar_url = ('https://www.qemu-advent-calendar.org'
'/2018/download/day18.tar.xz')
tar_hash = '068b5fc4242b29381acee94713509f8a876e9db6'
file_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
archive.extract(file_path, self.workdir)
self.vm.set_console()
self.vm.add_args('-bios',
self.workdir + '/day18/barebox.canon-a1100.bin')
self.vm.launch()
wait_for_console_pattern(self, 'running /env/bin/init')