15aff1c07SPeter Maydell /*
25aff1c07SPeter Maydell * ARM V2M MPS2 board emulation, trustzone aware FPGA images
35aff1c07SPeter Maydell *
45aff1c07SPeter Maydell * Copyright (c) 2017 Linaro Limited
55aff1c07SPeter Maydell * Written by Peter Maydell
65aff1c07SPeter Maydell *
75aff1c07SPeter Maydell * This program is free software; you can redistribute it and/or modify
85aff1c07SPeter Maydell * it under the terms of the GNU General Public License version 2 or
95aff1c07SPeter Maydell * (at your option) any later version.
105aff1c07SPeter Maydell */
115aff1c07SPeter Maydell
125aff1c07SPeter Maydell /* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
135aff1c07SPeter Maydell * FPGA but is otherwise the same as the 2). Since the CPU itself
145aff1c07SPeter Maydell * and most of the devices are in the FPGA, the details of the board
155aff1c07SPeter Maydell * as seen by the guest depend significantly on the FPGA image.
165aff1c07SPeter Maydell * This source file covers the following FPGA images, for TrustZone cores:
175aff1c07SPeter Maydell * "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
1823f92423SPeter Maydell * "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
1925ff112aSPeter Maydell * "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
20eb09d533SPeter Maydell * "mps2-an547" -- Single Cortex-M55 as documented in Application Note AN547
215aff1c07SPeter Maydell *
225aff1c07SPeter Maydell * Links to the TRM for the board itself and to the various Application
235aff1c07SPeter Maydell * Notes which document the FPGA images can be found here:
245aff1c07SPeter Maydell * https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
255aff1c07SPeter Maydell *
265aff1c07SPeter Maydell * Board TRM:
2750b52b18SPeter Maydell * https://developer.arm.com/documentation/100112/latest/
285aff1c07SPeter Maydell * Application Note AN505:
2950b52b18SPeter Maydell * https://developer.arm.com/documentation/dai0505/latest/
3023f92423SPeter Maydell * Application Note AN521:
3150b52b18SPeter Maydell * https://developer.arm.com/documentation/dai0521/latest/
3225ff112aSPeter Maydell * Application Note AN524:
3325ff112aSPeter Maydell * https://developer.arm.com/documentation/dai0524/latest/
34eb09d533SPeter Maydell * Application Note AN547:
35e212fb05SPeter Maydell * https://developer.arm.com/documentation/dai0547/latest/
365aff1c07SPeter Maydell *
375aff1c07SPeter Maydell * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
385aff1c07SPeter Maydell * (ARM ECM0601256) for the details of some of the device layout:
3950b52b18SPeter Maydell * https://developer.arm.com/documentation/ecm0601256/latest
4025ff112aSPeter Maydell * Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
4123f92423SPeter Maydell * most of the device layout:
4250b52b18SPeter Maydell * https://developer.arm.com/documentation/101104/latest/
43eb09d533SPeter Maydell * and the AN547 uses the SSE-300, whose layout is in the SSE-300 TRM:
44eb09d533SPeter Maydell * https://developer.arm.com/documentation/101773/latest/
455aff1c07SPeter Maydell */
465aff1c07SPeter Maydell
475aff1c07SPeter Maydell #include "qemu/osdep.h"
48eba59997SPhilippe Mathieu-Daudé #include "qemu/units.h"
4970a2cb8eSIgor Mammedov #include "qemu/cutils.h"
505aff1c07SPeter Maydell #include "qapi/error.h"
5131805a0aSKevin Wolf #include "qapi/qmp/qlist.h"
525aff1c07SPeter Maydell #include "qemu/error-report.h"
5312ec8bd5SPeter Maydell #include "hw/arm/boot.h"
545aff1c07SPeter Maydell #include "hw/arm/armv7m.h"
555aff1c07SPeter Maydell #include "hw/or-irq.h"
565aff1c07SPeter Maydell #include "hw/boards.h"
575aff1c07SPeter Maydell #include "exec/address-spaces.h"
585aff1c07SPeter Maydell #include "sysemu/sysemu.h"
59f1dfab0dSPeter Maydell #include "sysemu/reset.h"
605aff1c07SPeter Maydell #include "hw/misc/unimp.h"
615aff1c07SPeter Maydell #include "hw/char/cmsdk-apb-uart.h"
625aff1c07SPeter Maydell #include "hw/timer/cmsdk-apb-timer.h"
635aff1c07SPeter Maydell #include "hw/misc/mps2-scc.h"
645aff1c07SPeter Maydell #include "hw/misc/mps2-fpgaio.h"
65665670aaSPeter Maydell #include "hw/misc/tz-mpc.h"
6628e56f05SPeter Maydell #include "hw/misc/tz-msc.h"
676eee5d24SPeter Maydell #include "hw/arm/armsse.h"
6828e56f05SPeter Maydell #include "hw/dma/pl080.h"
6941745d20SPeter Maydell #include "hw/rtc/pl031.h"
700d49759bSPeter Maydell #include "hw/ssi/pl022.h"
712e34818fSPhilippe Mathieu-Daudé #include "hw/i2c/arm_sbcon_i2c.h"
7294630665SPhilippe Mathieu-Daudé #include "hw/net/lan9118.h"
735aff1c07SPeter Maydell #include "net/net.h"
745aff1c07SPeter Maydell #include "hw/core/split-irq.h"
75dee1515bSPeter Maydell #include "hw/qdev-clock.h"
76db1015e9SEduardo Habkost #include "qom/object.h"
77f1dfab0dSPeter Maydell #include "hw/irq.h"
785aff1c07SPeter Maydell
79eb09d533SPeter Maydell #define MPS2TZ_NUMIRQ_MAX 96
80eb09d533SPeter Maydell #define MPS2TZ_RAM_MAX 5
814a30dc1cSPeter Maydell
825aff1c07SPeter Maydell typedef enum MPS2TZFPGAType {
835aff1c07SPeter Maydell FPGA_AN505,
844a30dc1cSPeter Maydell FPGA_AN521,
8525ff112aSPeter Maydell FPGA_AN524,
86eb09d533SPeter Maydell FPGA_AN547,
875aff1c07SPeter Maydell } MPS2TZFPGAType;
885aff1c07SPeter Maydell
894fec32dbSPeter Maydell /*
904fec32dbSPeter Maydell * Define the layout of RAM in a board, including which parts are
914fec32dbSPeter Maydell * behind which MPCs.
924fec32dbSPeter Maydell * mrindex specifies the index into mms->ram[] to use for the backing RAM;
934fec32dbSPeter Maydell * -1 means "use the system RAM".
944fec32dbSPeter Maydell */
954fec32dbSPeter Maydell typedef struct RAMInfo {
964fec32dbSPeter Maydell const char *name;
974fec32dbSPeter Maydell uint32_t base;
984fec32dbSPeter Maydell uint32_t size;
994fec32dbSPeter Maydell int mpc; /* MPC number, -1 for "not behind an MPC" */
1004fec32dbSPeter Maydell int mrindex;
1014fec32dbSPeter Maydell int flags;
1024fec32dbSPeter Maydell } RAMInfo;
1034fec32dbSPeter Maydell
1044fec32dbSPeter Maydell /*
1054fec32dbSPeter Maydell * Flag values:
1064fec32dbSPeter Maydell * IS_ALIAS: this RAM area is an alias to the upstream end of the
1074fec32dbSPeter Maydell * MPC specified by its .mpc value
108b89918fcSPeter Maydell * IS_ROM: this RAM area is read-only
1094fec32dbSPeter Maydell */
1104fec32dbSPeter Maydell #define IS_ALIAS 1
111b89918fcSPeter Maydell #define IS_ROM 2
1124fec32dbSPeter Maydell
113db1015e9SEduardo Habkost struct MPS2TZMachineClass {
1145aff1c07SPeter Maydell MachineClass parent;
1155aff1c07SPeter Maydell MPS2TZFPGAType fpga_type;
1165aff1c07SPeter Maydell uint32_t scc_id;
117a3e24690SPeter Maydell uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
118ad28ca7eSPeter Maydell uint32_t apb_periph_frq; /* APB peripheral frequency in Hz */
119f7c71b21SPeter Maydell uint32_t len_oscclk;
120f7c71b21SPeter Maydell const uint32_t *oscclk;
121de77e8f4SPeter Maydell uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
122de77e8f4SPeter Maydell bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
12339901aeaSPeter Maydell bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
12411e1d412SPeter Maydell int numirq; /* Number of external interrupts */
1258b4b5c23SPeter Maydell int uart_overflow_irq; /* number of the combined UART overflow IRQ */
1269fe1ea11SPeter Maydell uint32_t init_svtor; /* init-svtor setting for SSE */
127902b28aeSPeter Maydell uint32_t sram_addr_width; /* SRAM_ADDR_WIDTH setting for SSE */
128e73b8bb8SPeter Maydell uint32_t cpu0_mpu_ns; /* CPU0_MPU_NS setting for SSE */
129e73b8bb8SPeter Maydell uint32_t cpu0_mpu_s; /* CPU0_MPU_S setting for SSE */
130e73b8bb8SPeter Maydell uint32_t cpu1_mpu_ns; /* CPU1_MPU_NS setting for SSE */
131e73b8bb8SPeter Maydell uint32_t cpu1_mpu_s; /* CPU1_MPU_S setting for SSE */
1324fec32dbSPeter Maydell const RAMInfo *raminfo;
13323f92423SPeter Maydell const char *armsse_type;
1342f12dca0SPeter Maydell uint32_t boot_ram_size; /* size of ram at address 0; 0 == find in raminfo */
135db1015e9SEduardo Habkost };
1365aff1c07SPeter Maydell
137db1015e9SEduardo Habkost struct MPS2TZMachineState {
1385aff1c07SPeter Maydell MachineState parent;
1395aff1c07SPeter Maydell
14093dbd103SPeter Maydell ARMSSE iotkit;
1414fec32dbSPeter Maydell MemoryRegion ram[MPS2TZ_RAM_MAX];
142a9597753SPeter Maydell MemoryRegion eth_usb_container;
143a9597753SPeter Maydell
1445aff1c07SPeter Maydell MPS2SCC scc;
1455aff1c07SPeter Maydell MPS2FPGAIO fpgaio;
1465aff1c07SPeter Maydell TZPPC ppc[5];
1474fec32dbSPeter Maydell TZMPC mpc[3];
1480d49759bSPeter Maydell PL022State spi[5];
14925ff112aSPeter Maydell ArmSbconI2CState i2c[5];
1505aff1c07SPeter Maydell UnimplementedDeviceState i2s_audio;
151519655e6SPeter Maydell UnimplementedDeviceState gpio[4];
1525aff1c07SPeter Maydell UnimplementedDeviceState gfx;
15325ff112aSPeter Maydell UnimplementedDeviceState cldc;
154a9597753SPeter Maydell UnimplementedDeviceState usb;
15541745d20SPeter Maydell PL031State rtc;
15628e56f05SPeter Maydell PL080State dma[4];
15728e56f05SPeter Maydell TZMSC msc[4];
15825ff112aSPeter Maydell CMSDKAPBUART uart[6];
1595aff1c07SPeter Maydell SplitIRQ sec_resp_splitter;
160e844f0c5SPhilippe Mathieu-Daudé OrIRQState uart_irq_orgate;
161519655e6SPeter Maydell DeviceState *lan9118;
16211e1d412SPeter Maydell SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
163dee1515bSPeter Maydell Clock *sysclk;
164dee1515bSPeter Maydell Clock *s32kclk;
165f1dfab0dSPeter Maydell
166f1dfab0dSPeter Maydell bool remap;
167f1dfab0dSPeter Maydell qemu_irq remap_irq;
168db1015e9SEduardo Habkost };
1695aff1c07SPeter Maydell
1705aff1c07SPeter Maydell #define TYPE_MPS2TZ_MACHINE "mps2tz"
1715aff1c07SPeter Maydell #define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
17223f92423SPeter Maydell #define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
17325ff112aSPeter Maydell #define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
174eb09d533SPeter Maydell #define TYPE_MPS3TZ_AN547_MACHINE MACHINE_TYPE_NAME("mps3-an547")
1755aff1c07SPeter Maydell
176a489d195SEduardo Habkost OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
1775aff1c07SPeter Maydell
178dee1515bSPeter Maydell /* Slow 32Khz S32KCLK frequency in Hz */
179dee1515bSPeter Maydell #define S32KCLK_FRQ (32 * 1000)
1805aff1c07SPeter Maydell
18125ff112aSPeter Maydell /*
18225ff112aSPeter Maydell * The MPS3 DDR is 2GiB, but on a 32-bit host QEMU doesn't permit
18325ff112aSPeter Maydell * emulation of that much guest RAM, so artificially make it smaller.
18425ff112aSPeter Maydell */
18525ff112aSPeter Maydell #if HOST_LONG_BITS == 32
18625ff112aSPeter Maydell #define MPS3_DDR_SIZE (1 * GiB)
18725ff112aSPeter Maydell #else
18825ff112aSPeter Maydell #define MPS3_DDR_SIZE (2 * GiB)
18925ff112aSPeter Maydell #endif
19025ff112aSPeter Maydell
191e73b8bb8SPeter Maydell /* For cpu{0,1}_mpu_{ns,s}, means "leave at SSE's default value" */
192e73b8bb8SPeter Maydell #define MPU_REGION_DEFAULT UINT32_MAX
193e73b8bb8SPeter Maydell
194f7c71b21SPeter Maydell static const uint32_t an505_oscclk[] = {
195f7c71b21SPeter Maydell 40000000,
196f7c71b21SPeter Maydell 24580000,
197f7c71b21SPeter Maydell 25000000,
198f7c71b21SPeter Maydell };
199f7c71b21SPeter Maydell
20025ff112aSPeter Maydell static const uint32_t an524_oscclk[] = {
20125ff112aSPeter Maydell 24000000,
20225ff112aSPeter Maydell 32000000,
20325ff112aSPeter Maydell 50000000,
20425ff112aSPeter Maydell 50000000,
20525ff112aSPeter Maydell 24576000,
20625ff112aSPeter Maydell 23750000,
20725ff112aSPeter Maydell };
20825ff112aSPeter Maydell
2094fec32dbSPeter Maydell static const RAMInfo an505_raminfo[] = { {
2104fec32dbSPeter Maydell .name = "ssram-0",
2114fec32dbSPeter Maydell .base = 0x00000000,
2124fec32dbSPeter Maydell .size = 0x00400000,
2134fec32dbSPeter Maydell .mpc = 0,
2144fec32dbSPeter Maydell .mrindex = 0,
2154fec32dbSPeter Maydell }, {
2164fec32dbSPeter Maydell .name = "ssram-1",
2174fec32dbSPeter Maydell .base = 0x28000000,
2184fec32dbSPeter Maydell .size = 0x00200000,
2194fec32dbSPeter Maydell .mpc = 1,
2204fec32dbSPeter Maydell .mrindex = 1,
2214fec32dbSPeter Maydell }, {
2224fec32dbSPeter Maydell .name = "ssram-2",
2234fec32dbSPeter Maydell .base = 0x28200000,
2244fec32dbSPeter Maydell .size = 0x00200000,
2254fec32dbSPeter Maydell .mpc = 2,
2264fec32dbSPeter Maydell .mrindex = 2,
2274fec32dbSPeter Maydell }, {
2284fec32dbSPeter Maydell .name = "ssram-0-alias",
2294fec32dbSPeter Maydell .base = 0x00400000,
2304fec32dbSPeter Maydell .size = 0x00400000,
2314fec32dbSPeter Maydell .mpc = 0,
2324fec32dbSPeter Maydell .mrindex = 3,
2334fec32dbSPeter Maydell .flags = IS_ALIAS,
2344fec32dbSPeter Maydell }, {
2354fec32dbSPeter Maydell /* Use the largest bit of contiguous RAM as our "system memory" */
2364fec32dbSPeter Maydell .name = "mps.ram",
2374fec32dbSPeter Maydell .base = 0x80000000,
2384fec32dbSPeter Maydell .size = 16 * MiB,
2394fec32dbSPeter Maydell .mpc = -1,
2404fec32dbSPeter Maydell .mrindex = -1,
2414fec32dbSPeter Maydell }, {
2424fec32dbSPeter Maydell .name = NULL,
2434fec32dbSPeter Maydell },
2444fec32dbSPeter Maydell };
2454fec32dbSPeter Maydell
246f1dfab0dSPeter Maydell /*
247f1dfab0dSPeter Maydell * Note that the addresses and MPC numbering here should match up
248f1dfab0dSPeter Maydell * with those used in remap_memory(), which can swap the BRAM and QSPI.
249f1dfab0dSPeter Maydell */
25025ff112aSPeter Maydell static const RAMInfo an524_raminfo[] = { {
25125ff112aSPeter Maydell .name = "bram",
25225ff112aSPeter Maydell .base = 0x00000000,
25325ff112aSPeter Maydell .size = 512 * KiB,
25425ff112aSPeter Maydell .mpc = 0,
25525ff112aSPeter Maydell .mrindex = 0,
25625ff112aSPeter Maydell }, {
25725ff112aSPeter Maydell /* We don't model QSPI flash yet; for now expose it as simple ROM */
25825ff112aSPeter Maydell .name = "QSPI",
25925ff112aSPeter Maydell .base = 0x28000000,
26025ff112aSPeter Maydell .size = 8 * MiB,
26125ff112aSPeter Maydell .mpc = 1,
262b6889c5aSPeter Maydell .mrindex = 1,
26325ff112aSPeter Maydell .flags = IS_ROM,
26425ff112aSPeter Maydell }, {
26525ff112aSPeter Maydell .name = "DDR",
26625ff112aSPeter Maydell .base = 0x60000000,
26725ff112aSPeter Maydell .size = MPS3_DDR_SIZE,
26825ff112aSPeter Maydell .mpc = 2,
26925ff112aSPeter Maydell .mrindex = -1,
27025ff112aSPeter Maydell }, {
27125ff112aSPeter Maydell .name = NULL,
27225ff112aSPeter Maydell },
27325ff112aSPeter Maydell };
27425ff112aSPeter Maydell
275eb09d533SPeter Maydell static const RAMInfo an547_raminfo[] = { {
276eb09d533SPeter Maydell .name = "sram",
277eb09d533SPeter Maydell .base = 0x01000000,
278eb09d533SPeter Maydell .size = 2 * MiB,
279eb09d533SPeter Maydell .mpc = 0,
280eb09d533SPeter Maydell .mrindex = 1,
281eb09d533SPeter Maydell }, {
282eb09d533SPeter Maydell .name = "sram 2",
283eb09d533SPeter Maydell .base = 0x21000000,
284eb09d533SPeter Maydell .size = 4 * MiB,
285eb09d533SPeter Maydell .mpc = -1,
286eb09d533SPeter Maydell .mrindex = 3,
287eb09d533SPeter Maydell }, {
288eb09d533SPeter Maydell /* We don't model QSPI flash yet; for now expose it as simple ROM */
289eb09d533SPeter Maydell .name = "QSPI",
290eb09d533SPeter Maydell .base = 0x28000000,
291eb09d533SPeter Maydell .size = 8 * MiB,
292eb09d533SPeter Maydell .mpc = 1,
293eb09d533SPeter Maydell .mrindex = 4,
294eb09d533SPeter Maydell .flags = IS_ROM,
295eb09d533SPeter Maydell }, {
296eb09d533SPeter Maydell .name = "DDR",
297eb09d533SPeter Maydell .base = 0x60000000,
298eb09d533SPeter Maydell .size = MPS3_DDR_SIZE,
299eb09d533SPeter Maydell .mpc = 2,
300eb09d533SPeter Maydell .mrindex = -1,
301eb09d533SPeter Maydell }, {
302eb09d533SPeter Maydell .name = NULL,
303eb09d533SPeter Maydell },
304eb09d533SPeter Maydell };
305eb09d533SPeter Maydell
find_raminfo_for_mpc(MPS2TZMachineState * mms,int mpc)3064fec32dbSPeter Maydell static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
3074fec32dbSPeter Maydell {
3084fec32dbSPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
3094fec32dbSPeter Maydell const RAMInfo *p;
31091c0a798SPeter Maydell const RAMInfo *found = NULL;
3114fec32dbSPeter Maydell
3124fec32dbSPeter Maydell for (p = mmc->raminfo; p->name; p++) {
3134fec32dbSPeter Maydell if (p->mpc == mpc && !(p->flags & IS_ALIAS)) {
31491c0a798SPeter Maydell /* There should only be one entry in the array for this MPC */
31591c0a798SPeter Maydell g_assert(!found);
31691c0a798SPeter Maydell found = p;
3174fec32dbSPeter Maydell }
3184fec32dbSPeter Maydell }
3194fec32dbSPeter Maydell /* if raminfo array doesn't have an entry for each MPC this is a bug */
32091c0a798SPeter Maydell assert(found);
32191c0a798SPeter Maydell return found;
3224fec32dbSPeter Maydell }
3234fec32dbSPeter Maydell
mr_for_raminfo(MPS2TZMachineState * mms,const RAMInfo * raminfo)3244fec32dbSPeter Maydell static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
3254fec32dbSPeter Maydell const RAMInfo *raminfo)
3264fec32dbSPeter Maydell {
3274fec32dbSPeter Maydell /* Return an initialized MemoryRegion for the RAMInfo. */
3284fec32dbSPeter Maydell MemoryRegion *ram;
3294fec32dbSPeter Maydell
3304fec32dbSPeter Maydell if (raminfo->mrindex < 0) {
3314fec32dbSPeter Maydell /* Means this RAMInfo is for QEMU's "system memory" */
3324fec32dbSPeter Maydell MachineState *machine = MACHINE(mms);
333b89918fcSPeter Maydell assert(!(raminfo->flags & IS_ROM));
3344fec32dbSPeter Maydell return machine->ram;
3354fec32dbSPeter Maydell }
3364fec32dbSPeter Maydell
3374fec32dbSPeter Maydell assert(raminfo->mrindex < MPS2TZ_RAM_MAX);
3384fec32dbSPeter Maydell ram = &mms->ram[raminfo->mrindex];
3394fec32dbSPeter Maydell
3404fec32dbSPeter Maydell memory_region_init_ram(ram, NULL, raminfo->name,
3414fec32dbSPeter Maydell raminfo->size, &error_fatal);
342b89918fcSPeter Maydell if (raminfo->flags & IS_ROM) {
343b89918fcSPeter Maydell memory_region_set_readonly(ram, true);
344b89918fcSPeter Maydell }
3454fec32dbSPeter Maydell return ram;
3464fec32dbSPeter Maydell }
3474fec32dbSPeter Maydell
3485aff1c07SPeter Maydell /* Create an alias of an entire original MemoryRegion @orig
3495aff1c07SPeter Maydell * located at @base in the memory map.
3505aff1c07SPeter Maydell */
make_ram_alias(MemoryRegion * mr,const char * name,MemoryRegion * orig,hwaddr base)3515aff1c07SPeter Maydell static void make_ram_alias(MemoryRegion *mr, const char *name,
3525aff1c07SPeter Maydell MemoryRegion *orig, hwaddr base)
3535aff1c07SPeter Maydell {
3545aff1c07SPeter Maydell memory_region_init_alias(mr, NULL, name, orig, 0,
3555aff1c07SPeter Maydell memory_region_size(orig));
3565aff1c07SPeter Maydell memory_region_add_subregion(get_system_memory(), base, mr);
3575aff1c07SPeter Maydell }
3585aff1c07SPeter Maydell
get_sse_irq_in(MPS2TZMachineState * mms,int irqno)3594a30dc1cSPeter Maydell static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
3604a30dc1cSPeter Maydell {
361fee887a7SPeter Maydell /*
362fee887a7SPeter Maydell * Return a qemu_irq which will signal IRQ n to all CPUs in the
363fee887a7SPeter Maydell * SSE. The irqno should be as the CPU sees it, so the first
364fee887a7SPeter Maydell * external-to-the-SSE interrupt is 32.
365fee887a7SPeter Maydell */
366ba94ffd7SPeter Maydell MachineClass *mc = MACHINE_GET_CLASS(mms);
36711e1d412SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
3684a30dc1cSPeter Maydell
369fee887a7SPeter Maydell assert(irqno >= 32 && irqno < (mmc->numirq + 32));
370fee887a7SPeter Maydell
371fee887a7SPeter Maydell /*
372fee887a7SPeter Maydell * Convert from "CPU irq number" (as listed in the FPGA image
373fee887a7SPeter Maydell * documentation) to the SSE external-interrupt number.
374fee887a7SPeter Maydell */
375fee887a7SPeter Maydell irqno -= 32;
3764a30dc1cSPeter Maydell
377ba94ffd7SPeter Maydell if (mc->max_cpus > 1) {
3784a30dc1cSPeter Maydell return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
379ba94ffd7SPeter Maydell } else {
380ba94ffd7SPeter Maydell return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
3814a30dc1cSPeter Maydell }
3824a30dc1cSPeter Maydell }
3834a30dc1cSPeter Maydell
384e6f79acdSPeter Maydell /* Union describing the device-specific extra data we pass to the devfn. */
385e6f79acdSPeter Maydell typedef union PPCExtraData {
38668e57951SPeter Maydell bool i2c_internal;
387e6f79acdSPeter Maydell } PPCExtraData;
388e6f79acdSPeter Maydell
3895aff1c07SPeter Maydell /* Most of the devices in the AN505 FPGA image sit behind
3905aff1c07SPeter Maydell * Peripheral Protection Controllers. These data structures
3915aff1c07SPeter Maydell * define the layout of which devices sit behind which PPCs.
3925aff1c07SPeter Maydell * The devfn for each port is a function which creates, configures
3935aff1c07SPeter Maydell * and initializes the device, returning the MemoryRegion which
3945aff1c07SPeter Maydell * needs to be plugged into the downstream end of the PPC port.
3955aff1c07SPeter Maydell */
3965aff1c07SPeter Maydell typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
39742418279SPeter Maydell const char *name, hwaddr size,
398e6f79acdSPeter Maydell const int *irqs,
399e6f79acdSPeter Maydell const PPCExtraData *extradata);
4005aff1c07SPeter Maydell
4015aff1c07SPeter Maydell typedef struct PPCPortInfo {
4025aff1c07SPeter Maydell const char *name;
4035aff1c07SPeter Maydell MakeDevFn *devfn;
4045aff1c07SPeter Maydell void *opaque;
4055aff1c07SPeter Maydell hwaddr addr;
4065aff1c07SPeter Maydell hwaddr size;
40742418279SPeter Maydell int irqs[3]; /* currently no device needs more IRQ lines than this */
408e6f79acdSPeter Maydell PPCExtraData extradata; /* to pass device-specific info to the devfn */
4095aff1c07SPeter Maydell } PPCPortInfo;
4105aff1c07SPeter Maydell
4115aff1c07SPeter Maydell typedef struct PPCInfo {
4125aff1c07SPeter Maydell const char *name;
4135aff1c07SPeter Maydell PPCPortInfo ports[TZ_NUM_PORTS];
4145aff1c07SPeter Maydell } PPCInfo;
4155aff1c07SPeter Maydell
make_unimp_dev(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)4165aff1c07SPeter Maydell static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
4175aff1c07SPeter Maydell void *opaque,
41842418279SPeter Maydell const char *name, hwaddr size,
419e6f79acdSPeter Maydell const int *irqs,
420e6f79acdSPeter Maydell const PPCExtraData *extradata)
4215aff1c07SPeter Maydell {
4225aff1c07SPeter Maydell /* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
4235aff1c07SPeter Maydell * and return a pointer to its MemoryRegion.
4245aff1c07SPeter Maydell */
4255aff1c07SPeter Maydell UnimplementedDeviceState *uds = opaque;
4265aff1c07SPeter Maydell
4270074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uds, TYPE_UNIMPLEMENTED_DEVICE);
4285aff1c07SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", name);
4295aff1c07SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", size);
4300074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal);
4315aff1c07SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
4325aff1c07SPeter Maydell }
4335aff1c07SPeter Maydell
make_uart(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)4345aff1c07SPeter Maydell static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
43542418279SPeter Maydell const char *name, hwaddr size,
436e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
4375aff1c07SPeter Maydell {
4385a558be9SMarco Palumbi /* The irq[] array is rx, tx, combined, in that order */
439a3e24690SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
4405aff1c07SPeter Maydell CMSDKAPBUART *uart = opaque;
4415aff1c07SPeter Maydell int i = uart - &mms->uart[0];
4425aff1c07SPeter Maydell SysBusDevice *s;
4435aff1c07SPeter Maydell DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
4445aff1c07SPeter Maydell
4450074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
446fc38a112SPeter Maydell qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
447ad28ca7eSPeter Maydell qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->apb_periph_frq);
4480074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
4495aff1c07SPeter Maydell s = SYS_BUS_DEVICE(uart);
4505a558be9SMarco Palumbi sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[1]));
4515a558be9SMarco Palumbi sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[0]));
4525aff1c07SPeter Maydell sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
4535aff1c07SPeter Maydell sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
454b22c4e8bSPeter Maydell sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2]));
4555aff1c07SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
4565aff1c07SPeter Maydell }
4575aff1c07SPeter Maydell
make_scc(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)4585aff1c07SPeter Maydell static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
45942418279SPeter Maydell const char *name, hwaddr size,
460e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
4615aff1c07SPeter Maydell {
4625aff1c07SPeter Maydell MPS2SCC *scc = opaque;
4635aff1c07SPeter Maydell DeviceState *sccdev;
4645aff1c07SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
46531805a0aSKevin Wolf QList *oscclk;
466f7c71b21SPeter Maydell uint32_t i;
4675aff1c07SPeter Maydell
4680074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
4695aff1c07SPeter Maydell sccdev = DEVICE(scc);
470f1dfab0dSPeter Maydell qdev_prop_set_uint32(sccdev, "scc-cfg0", mms->remap ? 1 : 0);
4715aff1c07SPeter Maydell qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
472cb159db9SPeter Maydell qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
4735aff1c07SPeter Maydell qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
47431805a0aSKevin Wolf
47531805a0aSKevin Wolf oscclk = qlist_new();
476f7c71b21SPeter Maydell for (i = 0; i < mmc->len_oscclk; i++) {
47731805a0aSKevin Wolf qlist_append_int(oscclk, mmc->oscclk[i]);
478f7c71b21SPeter Maydell }
47931805a0aSKevin Wolf qdev_prop_set_array(sccdev, "oscclk", oscclk);
48031805a0aSKevin Wolf
4810074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
4825aff1c07SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
4835aff1c07SPeter Maydell }
4845aff1c07SPeter Maydell
make_fpgaio(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)4855aff1c07SPeter Maydell static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
48642418279SPeter Maydell const char *name, hwaddr size,
487e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
4885aff1c07SPeter Maydell {
4895aff1c07SPeter Maydell MPS2FPGAIO *fpgaio = opaque;
490de77e8f4SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
4915aff1c07SPeter Maydell
4920074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
493de77e8f4SPeter Maydell qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
494de77e8f4SPeter Maydell qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
49539901aeaSPeter Maydell qdev_prop_set_bit(DEVICE(fpgaio), "has-dbgctrl", mmc->fpgaio_has_dbgctrl);
4960074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
4975aff1c07SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
4985aff1c07SPeter Maydell }
4995aff1c07SPeter Maydell
make_eth_dev(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)500519655e6SPeter Maydell static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
50142418279SPeter Maydell const char *name, hwaddr size,
502e6f79acdSPeter Maydell const int *irqs,
503e6f79acdSPeter Maydell const PPCExtraData *extradata)
504519655e6SPeter Maydell {
505519655e6SPeter Maydell SysBusDevice *s;
506519655e6SPeter Maydell
507519655e6SPeter Maydell /* In hardware this is a LAN9220; the LAN9118 is software compatible
508519655e6SPeter Maydell * except that it doesn't support the checksum-offload feature.
509519655e6SPeter Maydell */
5103e80f690SMarkus Armbruster mms->lan9118 = qdev_new(TYPE_LAN9118);
511e8c003c4SDavid Woodhouse qemu_configure_nic_device(mms->lan9118, true, NULL);
512519655e6SPeter Maydell
513519655e6SPeter Maydell s = SYS_BUS_DEVICE(mms->lan9118);
5143c6ef471SMarkus Armbruster sysbus_realize_and_unref(s, &error_fatal);
515b22c4e8bSPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
516519655e6SPeter Maydell return sysbus_mmio_get_region(s, 0);
517519655e6SPeter Maydell }
518519655e6SPeter Maydell
make_eth_usb(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)519a9597753SPeter Maydell static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
520a9597753SPeter Maydell const char *name, hwaddr size,
521e6f79acdSPeter Maydell const int *irqs,
522e6f79acdSPeter Maydell const PPCExtraData *extradata)
523a9597753SPeter Maydell {
524a9597753SPeter Maydell /*
525a9597753SPeter Maydell * The AN524 makes the ethernet and USB share a PPC port.
526a9597753SPeter Maydell * irqs[] is the ethernet IRQ.
527a9597753SPeter Maydell */
528a9597753SPeter Maydell SysBusDevice *s;
529a9597753SPeter Maydell
530a9597753SPeter Maydell memory_region_init(&mms->eth_usb_container, OBJECT(mms),
531a9597753SPeter Maydell "mps2-tz-eth-usb-container", 0x200000);
532a9597753SPeter Maydell
533a9597753SPeter Maydell /*
534a9597753SPeter Maydell * In hardware this is a LAN9220; the LAN9118 is software compatible
535a9597753SPeter Maydell * except that it doesn't support the checksum-offload feature.
536a9597753SPeter Maydell */
537a9597753SPeter Maydell mms->lan9118 = qdev_new(TYPE_LAN9118);
538e8c003c4SDavid Woodhouse qemu_configure_nic_device(mms->lan9118, true, NULL);
539a9597753SPeter Maydell
540a9597753SPeter Maydell s = SYS_BUS_DEVICE(mms->lan9118);
541a9597753SPeter Maydell sysbus_realize_and_unref(s, &error_fatal);
542a9597753SPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
543a9597753SPeter Maydell
544a9597753SPeter Maydell memory_region_add_subregion(&mms->eth_usb_container,
545a9597753SPeter Maydell 0, sysbus_mmio_get_region(s, 0));
546a9597753SPeter Maydell
547a9597753SPeter Maydell /* The USB OTG controller is an ISP1763; we don't have a model of it. */
548a9597753SPeter Maydell object_initialize_child(OBJECT(mms), "usb-otg",
549a9597753SPeter Maydell &mms->usb, TYPE_UNIMPLEMENTED_DEVICE);
550a9597753SPeter Maydell qdev_prop_set_string(DEVICE(&mms->usb), "name", "usb-otg");
551a9597753SPeter Maydell qdev_prop_set_uint64(DEVICE(&mms->usb), "size", 0x100000);
552a9597753SPeter Maydell s = SYS_BUS_DEVICE(&mms->usb);
553a9597753SPeter Maydell sysbus_realize(s, &error_fatal);
554a9597753SPeter Maydell
555a9597753SPeter Maydell memory_region_add_subregion(&mms->eth_usb_container,
556a9597753SPeter Maydell 0x100000, sysbus_mmio_get_region(s, 0));
557a9597753SPeter Maydell
558a9597753SPeter Maydell return &mms->eth_usb_container;
559a9597753SPeter Maydell }
560a9597753SPeter Maydell
make_mpc(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)561665670aaSPeter Maydell static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
56242418279SPeter Maydell const char *name, hwaddr size,
563e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
564665670aaSPeter Maydell {
565665670aaSPeter Maydell TZMPC *mpc = opaque;
5664fec32dbSPeter Maydell int i = mpc - &mms->mpc[0];
567665670aaSPeter Maydell MemoryRegion *upstream;
5684fec32dbSPeter Maydell const RAMInfo *raminfo = find_raminfo_for_mpc(mms, i);
5694fec32dbSPeter Maydell MemoryRegion *ram = mr_for_raminfo(mms, raminfo);
570665670aaSPeter Maydell
5714fec32dbSPeter Maydell object_initialize_child(OBJECT(mms), name, mpc, TYPE_TZ_MPC);
5724fec32dbSPeter Maydell object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ram),
5735325cc34SMarkus Armbruster &error_fatal);
5740074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal);
575665670aaSPeter Maydell /* Map the upstream end of the MPC into system memory */
576665670aaSPeter Maydell upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
5774fec32dbSPeter Maydell memory_region_add_subregion(get_system_memory(), raminfo->base, upstream);
578665670aaSPeter Maydell /* and connect its interrupt to the IoTKit */
579665670aaSPeter Maydell qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
580665670aaSPeter Maydell qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
581665670aaSPeter Maydell "mpcexp_status", i));
582665670aaSPeter Maydell
583665670aaSPeter Maydell /* Return the register interface MR for our caller to map behind the PPC */
584665670aaSPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
585665670aaSPeter Maydell }
586665670aaSPeter Maydell
boot_mem_base(MPS2TZMachineState * mms)587f1dfab0dSPeter Maydell static hwaddr boot_mem_base(MPS2TZMachineState *mms)
588f1dfab0dSPeter Maydell {
589f1dfab0dSPeter Maydell /*
590f1dfab0dSPeter Maydell * Return the canonical address of the block which will be mapped
591f1dfab0dSPeter Maydell * at address 0x0 (i.e. where the vector table is).
592f1dfab0dSPeter Maydell * This is usually 0, but if the AN524 alternate memory map is
593f1dfab0dSPeter Maydell * enabled it will be the base address of the QSPI block.
594f1dfab0dSPeter Maydell */
595f1dfab0dSPeter Maydell return mms->remap ? 0x28000000 : 0;
596f1dfab0dSPeter Maydell }
597f1dfab0dSPeter Maydell
remap_memory(MPS2TZMachineState * mms,int map)598f1dfab0dSPeter Maydell static void remap_memory(MPS2TZMachineState *mms, int map)
599f1dfab0dSPeter Maydell {
600f1dfab0dSPeter Maydell /*
601f1dfab0dSPeter Maydell * Remap the memory for the AN524. 'map' is the value of
602f1dfab0dSPeter Maydell * SCC CFG_REG0 bit 0, i.e. 0 for the default map and 1
603f1dfab0dSPeter Maydell * for the "option 1" mapping where QSPI is at address 0.
604f1dfab0dSPeter Maydell *
605f1dfab0dSPeter Maydell * Effectively we need to swap around the "upstream" ends of
606f1dfab0dSPeter Maydell * MPC 0 and MPC 1.
607f1dfab0dSPeter Maydell */
608f1dfab0dSPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
609f1dfab0dSPeter Maydell int i;
610f1dfab0dSPeter Maydell
611f1dfab0dSPeter Maydell if (mmc->fpga_type != FPGA_AN524) {
612f1dfab0dSPeter Maydell return;
613f1dfab0dSPeter Maydell }
614f1dfab0dSPeter Maydell
615f1dfab0dSPeter Maydell memory_region_transaction_begin();
616f1dfab0dSPeter Maydell for (i = 0; i < 2; i++) {
617f1dfab0dSPeter Maydell TZMPC *mpc = &mms->mpc[i];
618f1dfab0dSPeter Maydell MemoryRegion *upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
619f1dfab0dSPeter Maydell hwaddr addr = (i ^ map) ? 0x28000000 : 0;
620f1dfab0dSPeter Maydell
621f1dfab0dSPeter Maydell memory_region_set_address(upstream, addr);
622f1dfab0dSPeter Maydell }
623f1dfab0dSPeter Maydell memory_region_transaction_commit();
624f1dfab0dSPeter Maydell }
625f1dfab0dSPeter Maydell
remap_irq_fn(void * opaque,int n,int level)626f1dfab0dSPeter Maydell static void remap_irq_fn(void *opaque, int n, int level)
627f1dfab0dSPeter Maydell {
628f1dfab0dSPeter Maydell MPS2TZMachineState *mms = opaque;
629f1dfab0dSPeter Maydell
630f1dfab0dSPeter Maydell remap_memory(mms, level);
631f1dfab0dSPeter Maydell }
632f1dfab0dSPeter Maydell
make_dma(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)63328e56f05SPeter Maydell static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
63442418279SPeter Maydell const char *name, hwaddr size,
635e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
63628e56f05SPeter Maydell {
637b22c4e8bSPeter Maydell /* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
63828e56f05SPeter Maydell PL080State *dma = opaque;
63928e56f05SPeter Maydell int i = dma - &mms->dma[0];
64028e56f05SPeter Maydell SysBusDevice *s;
64128e56f05SPeter Maydell char *mscname = g_strdup_printf("%s-msc", name);
64228e56f05SPeter Maydell TZMSC *msc = &mms->msc[i];
64328e56f05SPeter Maydell DeviceState *iotkitdev = DEVICE(&mms->iotkit);
64428e56f05SPeter Maydell MemoryRegion *msc_upstream;
64528e56f05SPeter Maydell MemoryRegion *msc_downstream;
64628e56f05SPeter Maydell
64728e56f05SPeter Maydell /*
64828e56f05SPeter Maydell * Each DMA device is a PL081 whose transaction master interface
64928e56f05SPeter Maydell * is guarded by a Master Security Controller. The downstream end of
65028e56f05SPeter Maydell * the MSC connects to the IoTKit AHB Slave Expansion port, so the
65128e56f05SPeter Maydell * DMA devices can see all devices and memory that the CPU does.
65228e56f05SPeter Maydell */
6530074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), mscname, msc, TYPE_TZ_MSC);
65428e56f05SPeter Maydell msc_downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(&mms->iotkit), 0);
6555325cc34SMarkus Armbruster object_property_set_link(OBJECT(msc), "downstream",
6565325cc34SMarkus Armbruster OBJECT(msc_downstream), &error_fatal);
6575325cc34SMarkus Armbruster object_property_set_link(OBJECT(msc), "idau", OBJECT(mms), &error_fatal);
6580074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(msc), &error_fatal);
65928e56f05SPeter Maydell
66028e56f05SPeter Maydell qdev_connect_gpio_out_named(DEVICE(msc), "irq", 0,
66128e56f05SPeter Maydell qdev_get_gpio_in_named(iotkitdev,
66228e56f05SPeter Maydell "mscexp_status", i));
66328e56f05SPeter Maydell qdev_connect_gpio_out_named(iotkitdev, "mscexp_clear", i,
66428e56f05SPeter Maydell qdev_get_gpio_in_named(DEVICE(msc),
66528e56f05SPeter Maydell "irq_clear", 0));
66628e56f05SPeter Maydell qdev_connect_gpio_out_named(iotkitdev, "mscexp_ns", i,
66728e56f05SPeter Maydell qdev_get_gpio_in_named(DEVICE(msc),
66828e56f05SPeter Maydell "cfg_nonsec", 0));
66928e56f05SPeter Maydell qdev_connect_gpio_out(DEVICE(&mms->sec_resp_splitter),
67028e56f05SPeter Maydell ARRAY_SIZE(mms->ppc) + i,
67128e56f05SPeter Maydell qdev_get_gpio_in_named(DEVICE(msc),
67228e56f05SPeter Maydell "cfg_sec_resp", 0));
67328e56f05SPeter Maydell msc_upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(msc), 0);
67428e56f05SPeter Maydell
6750074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, dma, TYPE_PL081);
6765325cc34SMarkus Armbruster object_property_set_link(OBJECT(dma), "downstream", OBJECT(msc_upstream),
6775325cc34SMarkus Armbruster &error_fatal);
6780074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(dma), &error_fatal);
67928e56f05SPeter Maydell
68028e56f05SPeter Maydell s = SYS_BUS_DEVICE(dma);
68128e56f05SPeter Maydell /* Wire up DMACINTR, DMACINTERR, DMACINTTC */
682b22c4e8bSPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
683b22c4e8bSPeter Maydell sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
684b22c4e8bSPeter Maydell sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqs[2]));
68528e56f05SPeter Maydell
6867081e9b6SPeter Maydell g_free(mscname);
68728e56f05SPeter Maydell return sysbus_mmio_get_region(s, 0);
68828e56f05SPeter Maydell }
68928e56f05SPeter Maydell
make_spi(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)6900d49759bSPeter Maydell static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
69142418279SPeter Maydell const char *name, hwaddr size,
692e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
6930d49759bSPeter Maydell {
6940d49759bSPeter Maydell /*
6950d49759bSPeter Maydell * The AN505 has five PL022 SPI controllers.
6960d49759bSPeter Maydell * One of these should have the LCD controller behind it; the others
6970d49759bSPeter Maydell * are connected only to the FPGA's "general purpose SPI connector"
6980d49759bSPeter Maydell * or "shield" expansion connectors.
6990d49759bSPeter Maydell * Note that if we do implement devices behind SPI, the chip select
7000d49759bSPeter Maydell * lines are set via the "MISC" register in the MPS2 FPGAIO device.
7010d49759bSPeter Maydell */
7020d49759bSPeter Maydell PL022State *spi = opaque;
7030d49759bSPeter Maydell SysBusDevice *s;
7040d49759bSPeter Maydell
7050074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, spi, TYPE_PL022);
7060074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(spi), &error_fatal);
7070d49759bSPeter Maydell s = SYS_BUS_DEVICE(spi);
708b22c4e8bSPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
7090d49759bSPeter Maydell return sysbus_mmio_get_region(s, 0);
7100d49759bSPeter Maydell }
7110d49759bSPeter Maydell
make_i2c(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)7122e34818fSPhilippe Mathieu-Daudé static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
71342418279SPeter Maydell const char *name, hwaddr size,
714e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
7152e34818fSPhilippe Mathieu-Daudé {
7162e34818fSPhilippe Mathieu-Daudé ArmSbconI2CState *i2c = opaque;
7172e34818fSPhilippe Mathieu-Daudé SysBusDevice *s;
7182e34818fSPhilippe Mathieu-Daudé
7192e34818fSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C);
7202e34818fSPhilippe Mathieu-Daudé s = SYS_BUS_DEVICE(i2c);
7212e34818fSPhilippe Mathieu-Daudé sysbus_realize(s, &error_fatal);
72268e57951SPeter Maydell
72368e57951SPeter Maydell /*
72468e57951SPeter Maydell * If this is an internal-use-only i2c bus, mark it full
72568e57951SPeter Maydell * so that user-created i2c devices are not plugged into it.
72668e57951SPeter Maydell * If we implement models of any on-board i2c devices that
72768e57951SPeter Maydell * plug in to one of the internal-use-only buses, then we will
72868e57951SPeter Maydell * need to create and plugging those in here before we mark the
72968e57951SPeter Maydell * bus as full.
73068e57951SPeter Maydell */
73168e57951SPeter Maydell if (extradata->i2c_internal) {
73268e57951SPeter Maydell BusState *qbus = qdev_get_child_bus(DEVICE(i2c), "i2c");
73368e57951SPeter Maydell qbus_mark_full(qbus);
73468e57951SPeter Maydell }
73568e57951SPeter Maydell
7362e34818fSPhilippe Mathieu-Daudé return sysbus_mmio_get_region(s, 0);
7372e34818fSPhilippe Mathieu-Daudé }
7382e34818fSPhilippe Mathieu-Daudé
make_rtc(MPS2TZMachineState * mms,void * opaque,const char * name,hwaddr size,const int * irqs,const PPCExtraData * extradata)73941745d20SPeter Maydell static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
74041745d20SPeter Maydell const char *name, hwaddr size,
741e6f79acdSPeter Maydell const int *irqs, const PPCExtraData *extradata)
74241745d20SPeter Maydell {
74341745d20SPeter Maydell PL031State *pl031 = opaque;
74441745d20SPeter Maydell SysBusDevice *s;
74541745d20SPeter Maydell
74641745d20SPeter Maydell object_initialize_child(OBJECT(mms), name, pl031, TYPE_PL031);
74741745d20SPeter Maydell s = SYS_BUS_DEVICE(pl031);
74841745d20SPeter Maydell sysbus_realize(s, &error_fatal);
74941745d20SPeter Maydell /*
75041745d20SPeter Maydell * The board docs don't give an IRQ number for the PL031, so
75141745d20SPeter Maydell * presumably it is not connected.
75241745d20SPeter Maydell */
75341745d20SPeter Maydell return sysbus_mmio_get_region(s, 0);
75441745d20SPeter Maydell }
75541745d20SPeter Maydell
create_non_mpc_ram(MPS2TZMachineState * mms)7564fec32dbSPeter Maydell static void create_non_mpc_ram(MPS2TZMachineState *mms)
7574fec32dbSPeter Maydell {
7584fec32dbSPeter Maydell /*
7594fec32dbSPeter Maydell * Handle the RAMs which are either not behind MPCs or which are
7604fec32dbSPeter Maydell * aliases to another MPC.
7614fec32dbSPeter Maydell */
7624fec32dbSPeter Maydell const RAMInfo *p;
7634fec32dbSPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
7644fec32dbSPeter Maydell
7654fec32dbSPeter Maydell for (p = mmc->raminfo; p->name; p++) {
7664fec32dbSPeter Maydell if (p->flags & IS_ALIAS) {
7674fec32dbSPeter Maydell SysBusDevice *mpc_sbd = SYS_BUS_DEVICE(&mms->mpc[p->mpc]);
7684fec32dbSPeter Maydell MemoryRegion *upstream = sysbus_mmio_get_region(mpc_sbd, 1);
7694fec32dbSPeter Maydell make_ram_alias(&mms->ram[p->mrindex], p->name, upstream, p->base);
7704fec32dbSPeter Maydell } else if (p->mpc == -1) {
7714fec32dbSPeter Maydell /* RAM not behind an MPC */
7724fec32dbSPeter Maydell MemoryRegion *mr = mr_for_raminfo(mms, p);
7734fec32dbSPeter Maydell memory_region_add_subregion(get_system_memory(), p->base, mr);
7744fec32dbSPeter Maydell }
7754fec32dbSPeter Maydell }
7764fec32dbSPeter Maydell }
7774fec32dbSPeter Maydell
boot_ram_size(MPS2TZMachineState * mms)778a113aef9SPeter Maydell static uint32_t boot_ram_size(MPS2TZMachineState *mms)
779a113aef9SPeter Maydell {
780a113aef9SPeter Maydell /* Return the size of the RAM block at guest address zero */
781a113aef9SPeter Maydell const RAMInfo *p;
782a113aef9SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
783a113aef9SPeter Maydell
7842f12dca0SPeter Maydell /*
7852f12dca0SPeter Maydell * Use a per-board specification (for when the boot RAM is in
7862f12dca0SPeter Maydell * the SSE and so doesn't have a RAMInfo list entry)
7872f12dca0SPeter Maydell */
7882f12dca0SPeter Maydell if (mmc->boot_ram_size) {
7892f12dca0SPeter Maydell return mmc->boot_ram_size;
7902f12dca0SPeter Maydell }
7912f12dca0SPeter Maydell
792a113aef9SPeter Maydell for (p = mmc->raminfo; p->name; p++) {
793f1dfab0dSPeter Maydell if (p->base == boot_mem_base(mms)) {
794a113aef9SPeter Maydell return p->size;
795a113aef9SPeter Maydell }
796a113aef9SPeter Maydell }
797a113aef9SPeter Maydell g_assert_not_reached();
798a113aef9SPeter Maydell }
799a113aef9SPeter Maydell
mps2tz_common_init(MachineState * machine)8005aff1c07SPeter Maydell static void mps2tz_common_init(MachineState *machine)
8015aff1c07SPeter Maydell {
8025aff1c07SPeter Maydell MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
8034a30dc1cSPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
8045aff1c07SPeter Maydell MachineClass *mc = MACHINE_GET_CLASS(machine);
8055aff1c07SPeter Maydell MemoryRegion *system_memory = get_system_memory();
8065aff1c07SPeter Maydell DeviceState *iotkitdev;
8075aff1c07SPeter Maydell DeviceState *dev_splitter;
808ef29e382SPeter Maydell const PPCInfo *ppcs;
809ef29e382SPeter Maydell int num_ppcs;
8105aff1c07SPeter Maydell int i;
8115aff1c07SPeter Maydell
81270a2cb8eSIgor Mammedov if (machine->ram_size != mc->default_ram_size) {
81370a2cb8eSIgor Mammedov char *sz = size_to_str(mc->default_ram_size);
81470a2cb8eSIgor Mammedov error_report("Invalid RAM size, should be %s", sz);
81570a2cb8eSIgor Mammedov g_free(sz);
81670a2cb8eSIgor Mammedov exit(EXIT_FAILURE);
81770a2cb8eSIgor Mammedov }
81870a2cb8eSIgor Mammedov
819dee1515bSPeter Maydell /* These clocks don't need migration because they are fixed-frequency */
820dee1515bSPeter Maydell mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
821a3e24690SPeter Maydell clock_set_hz(mms->sysclk, mmc->sysclk_frq);
822dee1515bSPeter Maydell mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
823dee1515bSPeter Maydell clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
824dee1515bSPeter Maydell
8250074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit,
8260074fce6SMarkus Armbruster mmc->armsse_type);
8275aff1c07SPeter Maydell iotkitdev = DEVICE(&mms->iotkit);
8285325cc34SMarkus Armbruster object_property_set_link(OBJECT(&mms->iotkit), "memory",
8295325cc34SMarkus Armbruster OBJECT(system_memory), &error_abort);
83011e1d412SPeter Maydell qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
8319fe1ea11SPeter Maydell qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
832e73b8bb8SPeter Maydell if (mmc->cpu0_mpu_ns != MPU_REGION_DEFAULT) {
833e73b8bb8SPeter Maydell qdev_prop_set_uint32(iotkitdev, "CPU0_MPU_NS", mmc->cpu0_mpu_ns);
834e73b8bb8SPeter Maydell }
835e73b8bb8SPeter Maydell if (mmc->cpu0_mpu_s != MPU_REGION_DEFAULT) {
836e73b8bb8SPeter Maydell qdev_prop_set_uint32(iotkitdev, "CPU0_MPU_S", mmc->cpu0_mpu_s);
837e73b8bb8SPeter Maydell }
838e73b8bb8SPeter Maydell if (object_property_find(OBJECT(iotkitdev), "CPU1_MPU_NS")) {
839e73b8bb8SPeter Maydell if (mmc->cpu1_mpu_ns != MPU_REGION_DEFAULT) {
840e73b8bb8SPeter Maydell qdev_prop_set_uint32(iotkitdev, "CPU1_MPU_NS", mmc->cpu1_mpu_ns);
841e73b8bb8SPeter Maydell }
842e73b8bb8SPeter Maydell if (mmc->cpu1_mpu_s != MPU_REGION_DEFAULT) {
843e73b8bb8SPeter Maydell qdev_prop_set_uint32(iotkitdev, "CPU1_MPU_S", mmc->cpu1_mpu_s);
844e73b8bb8SPeter Maydell }
845e73b8bb8SPeter Maydell }
846902b28aeSPeter Maydell qdev_prop_set_uint32(iotkitdev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
847dee1515bSPeter Maydell qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
848dee1515bSPeter Maydell qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
8490074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
8505aff1c07SPeter Maydell
8514a30dc1cSPeter Maydell /*
852ba94ffd7SPeter Maydell * If this board has more than one CPU, then we need to create splitters
853ba94ffd7SPeter Maydell * to feed the IRQ inputs for each CPU in the SSE from each device in the
854ba94ffd7SPeter Maydell * board. If there is only one CPU, we can just wire the device IRQ
855ba94ffd7SPeter Maydell * directly to the SSE's IRQ input.
8564a30dc1cSPeter Maydell */
85711e1d412SPeter Maydell assert(mmc->numirq <= MPS2TZ_NUMIRQ_MAX);
858ba94ffd7SPeter Maydell if (mc->max_cpus > 1) {
85911e1d412SPeter Maydell for (i = 0; i < mmc->numirq; i++) {
8604a30dc1cSPeter Maydell char *name = g_strdup_printf("mps2-irq-splitter%d", i);
8614a30dc1cSPeter Maydell SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
8624a30dc1cSPeter Maydell
8639fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(machine), name,
8644a30dc1cSPeter Maydell splitter, sizeof(*splitter),
8659fc7fc4dSMarkus Armbruster TYPE_SPLIT_IRQ, &error_fatal,
8669fc7fc4dSMarkus Armbruster NULL);
8674a30dc1cSPeter Maydell g_free(name);
8684a30dc1cSPeter Maydell
8695325cc34SMarkus Armbruster object_property_set_int(OBJECT(splitter), "num-lines", 2,
8704a30dc1cSPeter Maydell &error_fatal);
871ce189ab2SMarkus Armbruster qdev_realize(DEVICE(splitter), NULL, &error_fatal);
8724a30dc1cSPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 0,
8734a30dc1cSPeter Maydell qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
8744a30dc1cSPeter Maydell "EXP_IRQ", i));
8754a30dc1cSPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 1,
8764a30dc1cSPeter Maydell qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
8774a30dc1cSPeter Maydell "EXP_CPU1_IRQ", i));
8784a30dc1cSPeter Maydell }
8794a30dc1cSPeter Maydell }
8804a30dc1cSPeter Maydell
8815aff1c07SPeter Maydell /* The sec_resp_cfg output from the IoTKit must be split into multiple
88228e56f05SPeter Maydell * lines, one for each of the PPCs we create here, plus one per MSC.
8835aff1c07SPeter Maydell */
8847840938eSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(machine), "sec-resp-splitter",
8859fc7fc4dSMarkus Armbruster &mms->sec_resp_splitter, TYPE_SPLIT_IRQ);
8865325cc34SMarkus Armbruster object_property_set_int(OBJECT(&mms->sec_resp_splitter), "num-lines",
88728e56f05SPeter Maydell ARRAY_SIZE(mms->ppc) + ARRAY_SIZE(mms->msc),
8885325cc34SMarkus Armbruster &error_fatal);
889ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&mms->sec_resp_splitter), NULL, &error_fatal);
8905aff1c07SPeter Maydell dev_splitter = DEVICE(&mms->sec_resp_splitter);
8915aff1c07SPeter Maydell qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
8925aff1c07SPeter Maydell qdev_get_gpio_in(dev_splitter, 0));
8935aff1c07SPeter Maydell
8944fec32dbSPeter Maydell /*
8954fec32dbSPeter Maydell * The IoTKit sets up much of the memory layout, including
8965aff1c07SPeter Maydell * the aliases between secure and non-secure regions in the
8974fec32dbSPeter Maydell * address space, and also most of the devices in the system.
8984fec32dbSPeter Maydell * The FPGA itself contains various RAMs and some additional devices.
8994fec32dbSPeter Maydell * The FPGA images have an odd combination of different RAMs,
9005aff1c07SPeter Maydell * because in hardware they are different implementations and
9015aff1c07SPeter Maydell * connected to different buses, giving varying performance/size
9025aff1c07SPeter Maydell * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
9034fec32dbSPeter Maydell * call the largest lump our "system memory".
9045aff1c07SPeter Maydell */
9055aff1c07SPeter Maydell
9068cf68ed9SPeter Maydell /*
9078cf68ed9SPeter Maydell * The overflow IRQs for all UARTs are ORed together.
9085aff1c07SPeter Maydell * Tx, Rx and "combined" IRQs are sent to the NVIC separately.
9098cf68ed9SPeter Maydell * Create the OR gate for this: it has one input for the TX overflow
9108cf68ed9SPeter Maydell * and one for the RX overflow for each UART we might have.
9118cf68ed9SPeter Maydell * (If the board has fewer than the maximum possible number of UARTs
9128cf68ed9SPeter Maydell * those inputs are never wired up and are treated as always-zero.)
9135aff1c07SPeter Maydell */
9147840938eSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(mms), "uart-irq-orgate",
9159fc7fc4dSMarkus Armbruster &mms->uart_irq_orgate, TYPE_OR_IRQ);
9168cf68ed9SPeter Maydell object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines",
9178cf68ed9SPeter Maydell 2 * ARRAY_SIZE(mms->uart),
9185aff1c07SPeter Maydell &error_fatal);
919ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
9205aff1c07SPeter Maydell qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
9218b4b5c23SPeter Maydell get_sse_irq_in(mms, mmc->uart_overflow_irq));
9225aff1c07SPeter Maydell
9235aff1c07SPeter Maydell /* Most of the devices in the FPGA are behind Peripheral Protection
9245aff1c07SPeter Maydell * Controllers. The required order for initializing things is:
9255aff1c07SPeter Maydell * + initialize the PPC
9265aff1c07SPeter Maydell * + initialize, configure and realize downstream devices
9275aff1c07SPeter Maydell * + connect downstream device MemoryRegions to the PPC
9285aff1c07SPeter Maydell * + realize the PPC
9295aff1c07SPeter Maydell * + map the PPC's MemoryRegions to the places in the address map
9305aff1c07SPeter Maydell * where the downstream devices should appear
9315aff1c07SPeter Maydell * + wire up the PPC's control lines to the IoTKit object
9325aff1c07SPeter Maydell */
9335aff1c07SPeter Maydell
934ef29e382SPeter Maydell const PPCInfo an505_ppcs[] = { {
9355aff1c07SPeter Maydell .name = "apb_ppcexp0",
9365aff1c07SPeter Maydell .ports = {
9374fec32dbSPeter Maydell { "ssram-0-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
9384fec32dbSPeter Maydell { "ssram-1-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
9394fec32dbSPeter Maydell { "ssram-2-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
9405aff1c07SPeter Maydell },
9415aff1c07SPeter Maydell }, {
9425aff1c07SPeter Maydell .name = "apb_ppcexp1",
9435aff1c07SPeter Maydell .ports = {
944b22c4e8bSPeter Maydell { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000, { 51 } },
945b22c4e8bSPeter Maydell { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000, { 52 } },
946b22c4e8bSPeter Maydell { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000, { 53 } },
947b22c4e8bSPeter Maydell { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000, { 54 } },
948b22c4e8bSPeter Maydell { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000, { 55 } },
949b22c4e8bSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000, { 32, 33, 42 } },
950b22c4e8bSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000, { 34, 35, 43 } },
951b22c4e8bSPeter Maydell { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
952b22c4e8bSPeter Maydell { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
953b22c4e8bSPeter Maydell { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
95468e57951SPeter Maydell { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000, {},
95568e57951SPeter Maydell { .i2c_internal = true /* touchscreen */ } },
95668e57951SPeter Maydell { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000, {},
95768e57951SPeter Maydell { .i2c_internal = true /* audio conf */ } },
95868e57951SPeter Maydell { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000, {},
95968e57951SPeter Maydell { .i2c_internal = false /* shield 0 */ } },
96068e57951SPeter Maydell { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000, {},
96168e57951SPeter Maydell { .i2c_internal = false /* shield 1 */ } },
9625aff1c07SPeter Maydell },
9635aff1c07SPeter Maydell }, {
9645aff1c07SPeter Maydell .name = "apb_ppcexp2",
9655aff1c07SPeter Maydell .ports = {
9665aff1c07SPeter Maydell { "scc", make_scc, &mms->scc, 0x40300000, 0x1000 },
9675aff1c07SPeter Maydell { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
9685aff1c07SPeter Maydell 0x40301000, 0x1000 },
9695aff1c07SPeter Maydell { "fpgaio", make_fpgaio, &mms->fpgaio, 0x40302000, 0x1000 },
9705aff1c07SPeter Maydell },
9715aff1c07SPeter Maydell }, {
9725aff1c07SPeter Maydell .name = "ahb_ppcexp0",
9735aff1c07SPeter Maydell .ports = {
9745aff1c07SPeter Maydell { "gfx", make_unimp_dev, &mms->gfx, 0x41000000, 0x140000 },
9755aff1c07SPeter Maydell { "gpio0", make_unimp_dev, &mms->gpio[0], 0x40100000, 0x1000 },
9765aff1c07SPeter Maydell { "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
9775aff1c07SPeter Maydell { "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
9785aff1c07SPeter Maydell { "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
979b22c4e8bSPeter Maydell { "eth", make_eth_dev, NULL, 0x42000000, 0x100000, { 48 } },
9805aff1c07SPeter Maydell },
9815aff1c07SPeter Maydell }, {
9825aff1c07SPeter Maydell .name = "ahb_ppcexp1",
9835aff1c07SPeter Maydell .ports = {
984b22c4e8bSPeter Maydell { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000, { 58, 56, 57 } },
985b22c4e8bSPeter Maydell { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000, { 61, 59, 60 } },
986b22c4e8bSPeter Maydell { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000, { 64, 62, 63 } },
987b22c4e8bSPeter Maydell { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000, { 67, 65, 66 } },
9885aff1c07SPeter Maydell },
9895aff1c07SPeter Maydell },
9905aff1c07SPeter Maydell };
9915aff1c07SPeter Maydell
99225ff112aSPeter Maydell const PPCInfo an524_ppcs[] = { {
99325ff112aSPeter Maydell .name = "apb_ppcexp0",
99425ff112aSPeter Maydell .ports = {
99525ff112aSPeter Maydell { "bram-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
99625ff112aSPeter Maydell { "qspi-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
99725ff112aSPeter Maydell { "ddr-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
99825ff112aSPeter Maydell },
99925ff112aSPeter Maydell }, {
100025ff112aSPeter Maydell .name = "apb_ppcexp1",
100125ff112aSPeter Maydell .ports = {
100268e57951SPeter Maydell { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000, {},
100368e57951SPeter Maydell { .i2c_internal = true /* touchscreen */ } },
100468e57951SPeter Maydell { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000, {},
100568e57951SPeter Maydell { .i2c_internal = true /* audio conf */ } },
100625ff112aSPeter Maydell { "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
100725ff112aSPeter Maydell { "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
100825ff112aSPeter Maydell { "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
100968e57951SPeter Maydell { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000, {},
101068e57951SPeter Maydell { .i2c_internal = false /* shield 0 */ } },
101168e57951SPeter Maydell { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000, {},
101268e57951SPeter Maydell { .i2c_internal = false /* shield 1 */ } },
101325ff112aSPeter Maydell { /* port 7 reserved */ },
101468e57951SPeter Maydell { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000, {},
101568e57951SPeter Maydell { .i2c_internal = true /* DDR4 EEPROM */ } },
101625ff112aSPeter Maydell },
101725ff112aSPeter Maydell }, {
101825ff112aSPeter Maydell .name = "apb_ppcexp2",
101925ff112aSPeter Maydell .ports = {
102025ff112aSPeter Maydell { "scc", make_scc, &mms->scc, 0x41300000, 0x1000 },
102125ff112aSPeter Maydell { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
102225ff112aSPeter Maydell 0x41301000, 0x1000 },
102325ff112aSPeter Maydell { "fpgaio", make_fpgaio, &mms->fpgaio, 0x41302000, 0x1000 },
102425ff112aSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x41303000, 0x1000, { 32, 33, 42 } },
102525ff112aSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x41304000, 0x1000, { 34, 35, 43 } },
102625ff112aSPeter Maydell { "uart2", make_uart, &mms->uart[2], 0x41305000, 0x1000, { 36, 37, 44 } },
102725ff112aSPeter Maydell { "uart3", make_uart, &mms->uart[3], 0x41306000, 0x1000, { 38, 39, 45 } },
102825ff112aSPeter Maydell { "uart4", make_uart, &mms->uart[4], 0x41307000, 0x1000, { 40, 41, 46 } },
102925ff112aSPeter Maydell { "uart5", make_uart, &mms->uart[5], 0x41308000, 0x1000, { 124, 125, 126 } },
103025ff112aSPeter Maydell
103125ff112aSPeter Maydell { /* port 9 reserved */ },
103225ff112aSPeter Maydell { "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
103341745d20SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x4130b000, 0x1000 },
103425ff112aSPeter Maydell },
103525ff112aSPeter Maydell }, {
103625ff112aSPeter Maydell .name = "ahb_ppcexp0",
103725ff112aSPeter Maydell .ports = {
103825ff112aSPeter Maydell { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
103925ff112aSPeter Maydell { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
104025ff112aSPeter Maydell { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
104125ff112aSPeter Maydell { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
1042a9597753SPeter Maydell { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 48 } },
104325ff112aSPeter Maydell },
104425ff112aSPeter Maydell },
104525ff112aSPeter Maydell };
104625ff112aSPeter Maydell
1047eb09d533SPeter Maydell const PPCInfo an547_ppcs[] = { {
1048eb09d533SPeter Maydell .name = "apb_ppcexp0",
1049eb09d533SPeter Maydell .ports = {
1050eb09d533SPeter Maydell { "ssram-mpc", make_mpc, &mms->mpc[0], 0x57000000, 0x1000 },
1051eb09d533SPeter Maydell { "qspi-mpc", make_mpc, &mms->mpc[1], 0x57001000, 0x1000 },
1052eb09d533SPeter Maydell { "ddr-mpc", make_mpc, &mms->mpc[2], 0x57002000, 0x1000 },
1053eb09d533SPeter Maydell },
1054eb09d533SPeter Maydell }, {
1055eb09d533SPeter Maydell .name = "apb_ppcexp1",
1056eb09d533SPeter Maydell .ports = {
105768e57951SPeter Maydell { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000, {},
105868e57951SPeter Maydell { .i2c_internal = true /* touchscreen */ } },
105968e57951SPeter Maydell { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000, {},
106068e57951SPeter Maydell { .i2c_internal = true /* audio conf */ } },
1061eb09d533SPeter Maydell { "spi0", make_spi, &mms->spi[0], 0x49202000, 0x1000, { 53 } },
1062eb09d533SPeter Maydell { "spi1", make_spi, &mms->spi[1], 0x49203000, 0x1000, { 54 } },
1063eb09d533SPeter Maydell { "spi2", make_spi, &mms->spi[2], 0x49204000, 0x1000, { 55 } },
106468e57951SPeter Maydell { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000, {},
106568e57951SPeter Maydell { .i2c_internal = false /* shield 0 */ } },
106668e57951SPeter Maydell { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000, {},
106768e57951SPeter Maydell { .i2c_internal = false /* shield 1 */ } },
1068eb09d533SPeter Maydell { /* port 7 reserved */ },
106968e57951SPeter Maydell { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000, {},
107068e57951SPeter Maydell { .i2c_internal = true /* DDR4 EEPROM */ } },
1071eb09d533SPeter Maydell },
1072eb09d533SPeter Maydell }, {
1073eb09d533SPeter Maydell .name = "apb_ppcexp2",
1074eb09d533SPeter Maydell .ports = {
1075eb09d533SPeter Maydell { "scc", make_scc, &mms->scc, 0x49300000, 0x1000 },
1076eb09d533SPeter Maydell { "i2s-audio", make_unimp_dev, &mms->i2s_audio, 0x49301000, 0x1000 },
1077eb09d533SPeter Maydell { "fpgaio", make_fpgaio, &mms->fpgaio, 0x49302000, 0x1000 },
1078eb09d533SPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x49303000, 0x1000, { 33, 34, 43 } },
1079eb09d533SPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x49304000, 0x1000, { 35, 36, 44 } },
1080eb09d533SPeter Maydell { "uart2", make_uart, &mms->uart[2], 0x49305000, 0x1000, { 37, 38, 45 } },
1081eb09d533SPeter Maydell { "uart3", make_uart, &mms->uart[3], 0x49306000, 0x1000, { 39, 40, 46 } },
1082eb09d533SPeter Maydell { "uart4", make_uart, &mms->uart[4], 0x49307000, 0x1000, { 41, 42, 47 } },
1083eb09d533SPeter Maydell { "uart5", make_uart, &mms->uart[5], 0x49308000, 0x1000, { 125, 126, 127 } },
1084eb09d533SPeter Maydell
1085eb09d533SPeter Maydell { /* port 9 reserved */ },
1086eb09d533SPeter Maydell { "clcd", make_unimp_dev, &mms->cldc, 0x4930a000, 0x1000 },
1087eb09d533SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x4930b000, 0x1000 },
1088eb09d533SPeter Maydell },
1089eb09d533SPeter Maydell }, {
1090eb09d533SPeter Maydell .name = "ahb_ppcexp0",
1091eb09d533SPeter Maydell .ports = {
1092eb09d533SPeter Maydell { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
1093eb09d533SPeter Maydell { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
1094eb09d533SPeter Maydell { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
1095eb09d533SPeter Maydell { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
1096cc3b66acSJimmy Brisson { /* port 4 USER AHB interface 0 */ },
1097cc3b66acSJimmy Brisson { /* port 5 USER AHB interface 1 */ },
1098cc3b66acSJimmy Brisson { /* port 6 USER AHB interface 2 */ },
1099cc3b66acSJimmy Brisson { /* port 7 USER AHB interface 3 */ },
1100eb09d533SPeter Maydell { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 49 } },
1101eb09d533SPeter Maydell },
1102eb09d533SPeter Maydell },
1103eb09d533SPeter Maydell };
1104eb09d533SPeter Maydell
1105ef29e382SPeter Maydell switch (mmc->fpga_type) {
1106ef29e382SPeter Maydell case FPGA_AN505:
1107ef29e382SPeter Maydell case FPGA_AN521:
1108ef29e382SPeter Maydell ppcs = an505_ppcs;
1109ef29e382SPeter Maydell num_ppcs = ARRAY_SIZE(an505_ppcs);
1110ef29e382SPeter Maydell break;
111125ff112aSPeter Maydell case FPGA_AN524:
111225ff112aSPeter Maydell ppcs = an524_ppcs;
111325ff112aSPeter Maydell num_ppcs = ARRAY_SIZE(an524_ppcs);
111425ff112aSPeter Maydell break;
1115eb09d533SPeter Maydell case FPGA_AN547:
1116eb09d533SPeter Maydell ppcs = an547_ppcs;
1117eb09d533SPeter Maydell num_ppcs = ARRAY_SIZE(an547_ppcs);
1118eb09d533SPeter Maydell break;
1119ef29e382SPeter Maydell default:
1120ef29e382SPeter Maydell g_assert_not_reached();
1121ef29e382SPeter Maydell }
1122ef29e382SPeter Maydell
1123ef29e382SPeter Maydell for (i = 0; i < num_ppcs; i++) {
11245aff1c07SPeter Maydell const PPCInfo *ppcinfo = &ppcs[i];
11255aff1c07SPeter Maydell TZPPC *ppc = &mms->ppc[i];
11265aff1c07SPeter Maydell DeviceState *ppcdev;
11275aff1c07SPeter Maydell int port;
11285aff1c07SPeter Maydell char *gpioname;
11295aff1c07SPeter Maydell
11300074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), ppcinfo->name, ppc,
11310074fce6SMarkus Armbruster TYPE_TZ_PPC);
11325aff1c07SPeter Maydell ppcdev = DEVICE(ppc);
11335aff1c07SPeter Maydell
11345aff1c07SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) {
11355aff1c07SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port];
11365aff1c07SPeter Maydell MemoryRegion *mr;
11375aff1c07SPeter Maydell char *portname;
11385aff1c07SPeter Maydell
11395aff1c07SPeter Maydell if (!pinfo->devfn) {
11405aff1c07SPeter Maydell continue;
11415aff1c07SPeter Maydell }
11425aff1c07SPeter Maydell
114342418279SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
1144e6f79acdSPeter Maydell pinfo->irqs, &pinfo->extradata);
11455aff1c07SPeter Maydell portname = g_strdup_printf("port[%d]", port);
11465325cc34SMarkus Armbruster object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
11475325cc34SMarkus Armbruster &error_fatal);
11485aff1c07SPeter Maydell g_free(portname);
11495aff1c07SPeter Maydell }
11505aff1c07SPeter Maydell
11510074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(ppc), &error_fatal);
11525aff1c07SPeter Maydell
11535aff1c07SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) {
11545aff1c07SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port];
11555aff1c07SPeter Maydell
11565aff1c07SPeter Maydell if (!pinfo->devfn) {
11575aff1c07SPeter Maydell continue;
11585aff1c07SPeter Maydell }
11595aff1c07SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
11605aff1c07SPeter Maydell
11615aff1c07SPeter Maydell gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
11625aff1c07SPeter Maydell qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
11635aff1c07SPeter Maydell qdev_get_gpio_in_named(ppcdev,
11645aff1c07SPeter Maydell "cfg_nonsec",
11655aff1c07SPeter Maydell port));
11665aff1c07SPeter Maydell g_free(gpioname);
11675aff1c07SPeter Maydell gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
11685aff1c07SPeter Maydell qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
11695aff1c07SPeter Maydell qdev_get_gpio_in_named(ppcdev,
11705aff1c07SPeter Maydell "cfg_ap", port));
11715aff1c07SPeter Maydell g_free(gpioname);
11725aff1c07SPeter Maydell }
11735aff1c07SPeter Maydell
11745aff1c07SPeter Maydell gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
11755aff1c07SPeter Maydell qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
11765aff1c07SPeter Maydell qdev_get_gpio_in_named(ppcdev,
11775aff1c07SPeter Maydell "irq_enable", 0));
11785aff1c07SPeter Maydell g_free(gpioname);
11795aff1c07SPeter Maydell gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
11805aff1c07SPeter Maydell qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
11815aff1c07SPeter Maydell qdev_get_gpio_in_named(ppcdev,
11825aff1c07SPeter Maydell "irq_clear", 0));
11835aff1c07SPeter Maydell g_free(gpioname);
11845aff1c07SPeter Maydell gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
11855aff1c07SPeter Maydell qdev_connect_gpio_out_named(ppcdev, "irq", 0,
11865aff1c07SPeter Maydell qdev_get_gpio_in_named(iotkitdev,
11875aff1c07SPeter Maydell gpioname, 0));
11885aff1c07SPeter Maydell g_free(gpioname);
11895aff1c07SPeter Maydell
11905aff1c07SPeter Maydell qdev_connect_gpio_out(dev_splitter, i,
11915aff1c07SPeter Maydell qdev_get_gpio_in_named(ppcdev,
11925aff1c07SPeter Maydell "cfg_sec_resp", 0));
11935aff1c07SPeter Maydell }
11945aff1c07SPeter Maydell
11955aff1c07SPeter Maydell create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
11965aff1c07SPeter Maydell
1197eb09d533SPeter Maydell if (mmc->fpga_type == FPGA_AN547) {
1198eb09d533SPeter Maydell create_unimplemented_device("U55 timing adapter 0", 0x48102000, 0x1000);
1199eb09d533SPeter Maydell create_unimplemented_device("U55 timing adapter 1", 0x48103000, 0x1000);
1200eb09d533SPeter Maydell }
1201eb09d533SPeter Maydell
12024fec32dbSPeter Maydell create_non_mpc_ram(mms);
12034fec32dbSPeter Maydell
1204f1dfab0dSPeter Maydell if (mmc->fpga_type == FPGA_AN524) {
1205f1dfab0dSPeter Maydell /*
1206f1dfab0dSPeter Maydell * Connect the line from the SCC so that we can remap when the
1207f1dfab0dSPeter Maydell * guest updates that register.
1208f1dfab0dSPeter Maydell */
1209f1dfab0dSPeter Maydell mms->remap_irq = qemu_allocate_irq(remap_irq_fn, mms, 0);
1210f1dfab0dSPeter Maydell qdev_connect_gpio_out_named(DEVICE(&mms->scc), "remap", 0,
1211f1dfab0dSPeter Maydell mms->remap_irq);
1212f1dfab0dSPeter Maydell }
1213f1dfab0dSPeter Maydell
1214a113aef9SPeter Maydell armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
1215761c532aSPeter Maydell 0, boot_ram_size(mms));
12165aff1c07SPeter Maydell }
12175aff1c07SPeter Maydell
mps2_tz_idau_check(IDAUInterface * ii,uint32_t address,int * iregion,bool * exempt,bool * ns,bool * nsc)121828e56f05SPeter Maydell static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
121928e56f05SPeter Maydell int *iregion, bool *exempt, bool *ns, bool *nsc)
122028e56f05SPeter Maydell {
122128e56f05SPeter Maydell /*
122228e56f05SPeter Maydell * The MPS2 TZ FPGA images have IDAUs in them which are connected to
1223673d8215SMichael Tokarev * the Master Security Controllers. These have the same logic as
122428e56f05SPeter Maydell * is used by the IoTKit for the IDAU connected to the CPU, except
122528e56f05SPeter Maydell * that MSCs don't care about the NSC attribute.
122628e56f05SPeter Maydell */
122728e56f05SPeter Maydell int region = extract32(address, 28, 4);
122828e56f05SPeter Maydell
122928e56f05SPeter Maydell *ns = !(region & 1);
123028e56f05SPeter Maydell *nsc = false;
123128e56f05SPeter Maydell /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
123228e56f05SPeter Maydell *exempt = (address & 0xeff00000) == 0xe0000000;
123328e56f05SPeter Maydell *iregion = region;
123428e56f05SPeter Maydell }
123528e56f05SPeter Maydell
mps2_get_remap(Object * obj,Error ** errp)1236f1dfab0dSPeter Maydell static char *mps2_get_remap(Object *obj, Error **errp)
1237f1dfab0dSPeter Maydell {
1238f1dfab0dSPeter Maydell MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj);
1239f1dfab0dSPeter Maydell const char *val = mms->remap ? "QSPI" : "BRAM";
1240f1dfab0dSPeter Maydell return g_strdup(val);
1241f1dfab0dSPeter Maydell }
1242f1dfab0dSPeter Maydell
mps2_set_remap(Object * obj,const char * value,Error ** errp)1243f1dfab0dSPeter Maydell static void mps2_set_remap(Object *obj, const char *value, Error **errp)
1244f1dfab0dSPeter Maydell {
1245f1dfab0dSPeter Maydell MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj);
1246f1dfab0dSPeter Maydell
1247f1dfab0dSPeter Maydell if (!strcmp(value, "BRAM")) {
1248f1dfab0dSPeter Maydell mms->remap = false;
1249f1dfab0dSPeter Maydell } else if (!strcmp(value, "QSPI")) {
1250f1dfab0dSPeter Maydell mms->remap = true;
1251f1dfab0dSPeter Maydell } else {
1252f1dfab0dSPeter Maydell error_setg(errp, "Invalid remap value");
1253f1dfab0dSPeter Maydell error_append_hint(errp, "Valid values are BRAM and QSPI.\n");
1254f1dfab0dSPeter Maydell }
1255f1dfab0dSPeter Maydell }
1256f1dfab0dSPeter Maydell
mps2_machine_reset(MachineState * machine,ResetType type)1257*1b063fe2SJuraj Marcin static void mps2_machine_reset(MachineState *machine, ResetType type)
1258f1dfab0dSPeter Maydell {
1259f1dfab0dSPeter Maydell MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
1260f1dfab0dSPeter Maydell
1261f1dfab0dSPeter Maydell /*
1262f1dfab0dSPeter Maydell * Set the initial memory mapping before triggering the reset of
1263f1dfab0dSPeter Maydell * the rest of the system, so that the guest image loader and CPU
1264f1dfab0dSPeter Maydell * reset see the correct mapping.
1265f1dfab0dSPeter Maydell */
1266f1dfab0dSPeter Maydell remap_memory(mms, mms->remap);
1267*1b063fe2SJuraj Marcin qemu_devices_reset(type);
1268f1dfab0dSPeter Maydell }
1269f1dfab0dSPeter Maydell
mps2tz_class_init(ObjectClass * oc,void * data)12705aff1c07SPeter Maydell static void mps2tz_class_init(ObjectClass *oc, void *data)
12715aff1c07SPeter Maydell {
12725aff1c07SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc);
127328e56f05SPeter Maydell IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
1274e73b8bb8SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
12755aff1c07SPeter Maydell
12765aff1c07SPeter Maydell mc->init = mps2tz_common_init;
1277f1dfab0dSPeter Maydell mc->reset = mps2_machine_reset;
127828e56f05SPeter Maydell iic->check = mps2_tz_idau_check;
1279e73b8bb8SPeter Maydell
1280e73b8bb8SPeter Maydell /* Most machines leave these at the SSE defaults */
1281e73b8bb8SPeter Maydell mmc->cpu0_mpu_ns = MPU_REGION_DEFAULT;
1282e73b8bb8SPeter Maydell mmc->cpu0_mpu_s = MPU_REGION_DEFAULT;
1283e73b8bb8SPeter Maydell mmc->cpu1_mpu_ns = MPU_REGION_DEFAULT;
1284e73b8bb8SPeter Maydell mmc->cpu1_mpu_s = MPU_REGION_DEFAULT;
128518a8c3b3SPeter Maydell }
128618a8c3b3SPeter Maydell
mps2tz_set_default_ram_info(MPS2TZMachineClass * mmc)128718a8c3b3SPeter Maydell static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
128818a8c3b3SPeter Maydell {
128918a8c3b3SPeter Maydell /*
129018a8c3b3SPeter Maydell * Set mc->default_ram_size and default_ram_id from the
129118a8c3b3SPeter Maydell * information in mmc->raminfo.
129218a8c3b3SPeter Maydell */
129318a8c3b3SPeter Maydell MachineClass *mc = MACHINE_CLASS(mmc);
129418a8c3b3SPeter Maydell const RAMInfo *p;
129518a8c3b3SPeter Maydell
129618a8c3b3SPeter Maydell for (p = mmc->raminfo; p->name; p++) {
129718a8c3b3SPeter Maydell if (p->mrindex < 0) {
129818a8c3b3SPeter Maydell /* Found the entry for "system memory" */
129918a8c3b3SPeter Maydell mc->default_ram_size = p->size;
130018a8c3b3SPeter Maydell mc->default_ram_id = p->name;
130118a8c3b3SPeter Maydell return;
130218a8c3b3SPeter Maydell }
130318a8c3b3SPeter Maydell }
130418a8c3b3SPeter Maydell g_assert_not_reached();
13055aff1c07SPeter Maydell }
13065aff1c07SPeter Maydell
mps2tz_an505_class_init(ObjectClass * oc,void * data)13075aff1c07SPeter Maydell static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
13085aff1c07SPeter Maydell {
13095aff1c07SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc);
13105aff1c07SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
13113e71f4a7SGavin Shan static const char * const valid_cpu_types[] = {
13123e71f4a7SGavin Shan ARM_CPU_TYPE_NAME("cortex-m33"),
13133e71f4a7SGavin Shan NULL
13143e71f4a7SGavin Shan };
13155aff1c07SPeter Maydell
13165aff1c07SPeter Maydell mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
131723f92423SPeter Maydell mc->default_cpus = 1;
131823f92423SPeter Maydell mc->min_cpus = mc->default_cpus;
131923f92423SPeter Maydell mc->max_cpus = mc->default_cpus;
13205aff1c07SPeter Maydell mmc->fpga_type = FPGA_AN505;
13215aff1c07SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
13223e71f4a7SGavin Shan mc->valid_cpu_types = valid_cpu_types;
1323cb159db9SPeter Maydell mmc->scc_id = 0x41045050;
1324a3e24690SPeter Maydell mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
1325ad28ca7eSPeter Maydell mmc->apb_periph_frq = mmc->sysclk_frq;
1326f7c71b21SPeter Maydell mmc->oscclk = an505_oscclk;
1327f7c71b21SPeter Maydell mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
1328de77e8f4SPeter Maydell mmc->fpgaio_num_leds = 2;
1329de77e8f4SPeter Maydell mmc->fpgaio_has_switches = false;
133039901aeaSPeter Maydell mmc->fpgaio_has_dbgctrl = false;
133111e1d412SPeter Maydell mmc->numirq = 92;
13328b4b5c23SPeter Maydell mmc->uart_overflow_irq = 47;
13339fe1ea11SPeter Maydell mmc->init_svtor = 0x10000000;
1334902b28aeSPeter Maydell mmc->sram_addr_width = 15;
13354fec32dbSPeter Maydell mmc->raminfo = an505_raminfo;
133623f92423SPeter Maydell mmc->armsse_type = TYPE_IOTKIT;
13372f12dca0SPeter Maydell mmc->boot_ram_size = 0;
133818a8c3b3SPeter Maydell mps2tz_set_default_ram_info(mmc);
133923f92423SPeter Maydell }
134023f92423SPeter Maydell
mps2tz_an521_class_init(ObjectClass * oc,void * data)134123f92423SPeter Maydell static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
134223f92423SPeter Maydell {
134323f92423SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc);
134423f92423SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
13453e71f4a7SGavin Shan static const char * const valid_cpu_types[] = {
13463e71f4a7SGavin Shan ARM_CPU_TYPE_NAME("cortex-m33"),
13473e71f4a7SGavin Shan NULL
13483e71f4a7SGavin Shan };
134923f92423SPeter Maydell
135023f92423SPeter Maydell mc->desc = "ARM MPS2 with AN521 FPGA image for dual Cortex-M33";
135123f92423SPeter Maydell mc->default_cpus = 2;
135223f92423SPeter Maydell mc->min_cpus = mc->default_cpus;
135323f92423SPeter Maydell mc->max_cpus = mc->default_cpus;
135423f92423SPeter Maydell mmc->fpga_type = FPGA_AN521;
135523f92423SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
13563e71f4a7SGavin Shan mc->valid_cpu_types = valid_cpu_types;
135723f92423SPeter Maydell mmc->scc_id = 0x41045210;
1358a3e24690SPeter Maydell mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
1359ad28ca7eSPeter Maydell mmc->apb_periph_frq = mmc->sysclk_frq;
1360f7c71b21SPeter Maydell mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
1361f7c71b21SPeter Maydell mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
1362de77e8f4SPeter Maydell mmc->fpgaio_num_leds = 2;
1363de77e8f4SPeter Maydell mmc->fpgaio_has_switches = false;
136439901aeaSPeter Maydell mmc->fpgaio_has_dbgctrl = false;
136511e1d412SPeter Maydell mmc->numirq = 92;
13668b4b5c23SPeter Maydell mmc->uart_overflow_irq = 47;
13679fe1ea11SPeter Maydell mmc->init_svtor = 0x10000000;
1368902b28aeSPeter Maydell mmc->sram_addr_width = 15;
13694fec32dbSPeter Maydell mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
137023f92423SPeter Maydell mmc->armsse_type = TYPE_SSE200;
13712f12dca0SPeter Maydell mmc->boot_ram_size = 0;
137218a8c3b3SPeter Maydell mps2tz_set_default_ram_info(mmc);
13735aff1c07SPeter Maydell }
13745aff1c07SPeter Maydell
mps3tz_an524_class_init(ObjectClass * oc,void * data)137525ff112aSPeter Maydell static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
137625ff112aSPeter Maydell {
137725ff112aSPeter Maydell MachineClass *mc = MACHINE_CLASS(oc);
137825ff112aSPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
13793e71f4a7SGavin Shan static const char * const valid_cpu_types[] = {
13803e71f4a7SGavin Shan ARM_CPU_TYPE_NAME("cortex-m33"),
13813e71f4a7SGavin Shan NULL
13823e71f4a7SGavin Shan };
138325ff112aSPeter Maydell
138425ff112aSPeter Maydell mc->desc = "ARM MPS3 with AN524 FPGA image for dual Cortex-M33";
138525ff112aSPeter Maydell mc->default_cpus = 2;
138625ff112aSPeter Maydell mc->min_cpus = mc->default_cpus;
138725ff112aSPeter Maydell mc->max_cpus = mc->default_cpus;
138825ff112aSPeter Maydell mmc->fpga_type = FPGA_AN524;
138925ff112aSPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
13903e71f4a7SGavin Shan mc->valid_cpu_types = valid_cpu_types;
139125ff112aSPeter Maydell mmc->scc_id = 0x41045240;
139225ff112aSPeter Maydell mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
1393ad28ca7eSPeter Maydell mmc->apb_periph_frq = mmc->sysclk_frq;
139425ff112aSPeter Maydell mmc->oscclk = an524_oscclk;
139525ff112aSPeter Maydell mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
139625ff112aSPeter Maydell mmc->fpgaio_num_leds = 10;
139725ff112aSPeter Maydell mmc->fpgaio_has_switches = true;
139839901aeaSPeter Maydell mmc->fpgaio_has_dbgctrl = false;
139925ff112aSPeter Maydell mmc->numirq = 95;
14008b4b5c23SPeter Maydell mmc->uart_overflow_irq = 47;
14019fe1ea11SPeter Maydell mmc->init_svtor = 0x10000000;
1402902b28aeSPeter Maydell mmc->sram_addr_width = 15;
140325ff112aSPeter Maydell mmc->raminfo = an524_raminfo;
140425ff112aSPeter Maydell mmc->armsse_type = TYPE_SSE200;
14052f12dca0SPeter Maydell mmc->boot_ram_size = 0;
140625ff112aSPeter Maydell mps2tz_set_default_ram_info(mmc);
1407f1dfab0dSPeter Maydell
1408f1dfab0dSPeter Maydell object_class_property_add_str(oc, "remap", mps2_get_remap, mps2_set_remap);
1409f1dfab0dSPeter Maydell object_class_property_set_description(oc, "remap",
1410f1dfab0dSPeter Maydell "Set memory mapping. Valid values "
1411f1dfab0dSPeter Maydell "are BRAM (default) and QSPI.");
141225ff112aSPeter Maydell }
141325ff112aSPeter Maydell
mps3tz_an547_class_init(ObjectClass * oc,void * data)1414eb09d533SPeter Maydell static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
1415eb09d533SPeter Maydell {
1416eb09d533SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc);
1417eb09d533SPeter Maydell MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
14183e71f4a7SGavin Shan static const char * const valid_cpu_types[] = {
14193e71f4a7SGavin Shan ARM_CPU_TYPE_NAME("cortex-m55"),
14203e71f4a7SGavin Shan NULL
14213e71f4a7SGavin Shan };
1422eb09d533SPeter Maydell
1423eb09d533SPeter Maydell mc->desc = "ARM MPS3 with AN547 FPGA image for Cortex-M55";
1424eb09d533SPeter Maydell mc->default_cpus = 1;
1425eb09d533SPeter Maydell mc->min_cpus = mc->default_cpus;
1426eb09d533SPeter Maydell mc->max_cpus = mc->default_cpus;
1427eb09d533SPeter Maydell mmc->fpga_type = FPGA_AN547;
1428eb09d533SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m55");
14293e71f4a7SGavin Shan mc->valid_cpu_types = valid_cpu_types;
1430eb09d533SPeter Maydell mmc->scc_id = 0x41055470;
1431eb09d533SPeter Maydell mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
1432eb09d533SPeter Maydell mmc->apb_periph_frq = 25 * 1000 * 1000; /* 25MHz */
1433eb09d533SPeter Maydell mmc->oscclk = an524_oscclk; /* same as AN524 */
1434eb09d533SPeter Maydell mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
1435eb09d533SPeter Maydell mmc->fpgaio_num_leds = 10;
1436eb09d533SPeter Maydell mmc->fpgaio_has_switches = true;
1437eb09d533SPeter Maydell mmc->fpgaio_has_dbgctrl = true;
1438eb09d533SPeter Maydell mmc->numirq = 96;
1439eb09d533SPeter Maydell mmc->uart_overflow_irq = 48;
1440eb09d533SPeter Maydell mmc->init_svtor = 0x00000000;
1441e73b8bb8SPeter Maydell mmc->cpu0_mpu_s = mmc->cpu0_mpu_ns = 16;
1442902b28aeSPeter Maydell mmc->sram_addr_width = 21;
1443eb09d533SPeter Maydell mmc->raminfo = an547_raminfo;
1444eb09d533SPeter Maydell mmc->armsse_type = TYPE_SSE300;
14452f12dca0SPeter Maydell mmc->boot_ram_size = 512 * KiB;
1446eb09d533SPeter Maydell mps2tz_set_default_ram_info(mmc);
1447eb09d533SPeter Maydell }
1448eb09d533SPeter Maydell
14495aff1c07SPeter Maydell static const TypeInfo mps2tz_info = {
14505aff1c07SPeter Maydell .name = TYPE_MPS2TZ_MACHINE,
14515aff1c07SPeter Maydell .parent = TYPE_MACHINE,
14525aff1c07SPeter Maydell .abstract = true,
14535aff1c07SPeter Maydell .instance_size = sizeof(MPS2TZMachineState),
14545aff1c07SPeter Maydell .class_size = sizeof(MPS2TZMachineClass),
14555aff1c07SPeter Maydell .class_init = mps2tz_class_init,
145628e56f05SPeter Maydell .interfaces = (InterfaceInfo[]) {
145728e56f05SPeter Maydell { TYPE_IDAU_INTERFACE },
145828e56f05SPeter Maydell { }
145928e56f05SPeter Maydell },
14605aff1c07SPeter Maydell };
14615aff1c07SPeter Maydell
14625aff1c07SPeter Maydell static const TypeInfo mps2tz_an505_info = {
14635aff1c07SPeter Maydell .name = TYPE_MPS2TZ_AN505_MACHINE,
14645aff1c07SPeter Maydell .parent = TYPE_MPS2TZ_MACHINE,
14655aff1c07SPeter Maydell .class_init = mps2tz_an505_class_init,
14665aff1c07SPeter Maydell };
14675aff1c07SPeter Maydell
146823f92423SPeter Maydell static const TypeInfo mps2tz_an521_info = {
146923f92423SPeter Maydell .name = TYPE_MPS2TZ_AN521_MACHINE,
147023f92423SPeter Maydell .parent = TYPE_MPS2TZ_MACHINE,
147123f92423SPeter Maydell .class_init = mps2tz_an521_class_init,
147223f92423SPeter Maydell };
147323f92423SPeter Maydell
147425ff112aSPeter Maydell static const TypeInfo mps3tz_an524_info = {
147525ff112aSPeter Maydell .name = TYPE_MPS3TZ_AN524_MACHINE,
147625ff112aSPeter Maydell .parent = TYPE_MPS2TZ_MACHINE,
147725ff112aSPeter Maydell .class_init = mps3tz_an524_class_init,
147825ff112aSPeter Maydell };
147925ff112aSPeter Maydell
1480eb09d533SPeter Maydell static const TypeInfo mps3tz_an547_info = {
1481eb09d533SPeter Maydell .name = TYPE_MPS3TZ_AN547_MACHINE,
1482eb09d533SPeter Maydell .parent = TYPE_MPS2TZ_MACHINE,
1483eb09d533SPeter Maydell .class_init = mps3tz_an547_class_init,
1484eb09d533SPeter Maydell };
1485eb09d533SPeter Maydell
mps2tz_machine_init(void)14865aff1c07SPeter Maydell static void mps2tz_machine_init(void)
14875aff1c07SPeter Maydell {
14885aff1c07SPeter Maydell type_register_static(&mps2tz_info);
14895aff1c07SPeter Maydell type_register_static(&mps2tz_an505_info);
149023f92423SPeter Maydell type_register_static(&mps2tz_an521_info);
149125ff112aSPeter Maydell type_register_static(&mps3tz_an524_info);
1492eb09d533SPeter Maydell type_register_static(&mps3tz_an547_info);
14935aff1c07SPeter Maydell }
14945aff1c07SPeter Maydell
14955aff1c07SPeter Maydell type_init(mps2tz_machine_init);
1496