|
| 1 | +From 6c3dcb888a263dec0d0e47faf82f095204c1d32c Mon Sep 17 00:00:00 2001 |
| 2 | +From: Peter Maydell < [email protected]> |
| 3 | +Date: Mon, 12 Apr 2021 14:43:17 +0100 |
| 4 | +Subject: [PATCH 03/10] hw/arm/mps2-tz: Implement AN524 memory remapping via |
| 5 | + machine property |
| 6 | + |
| 7 | +The AN524 FPGA image supports two memory maps, which differ |
| 8 | +in where the QSPI and BRAM are. In the default map, the BRAM |
| 9 | +is at 0x0000_0000, and the QSPI at 0x2800_0000. In the second |
| 10 | +map, they are the other way around. |
| 11 | + |
| 12 | +In hardware, the initial mapping can be selected by the user |
| 13 | +by writing either "REMAP: BRAM" (the default) or "REMAP: QSPI" |
| 14 | +in the board configuration file. The guest can also dynamically |
| 15 | +change the mapping via the SCC CFG_REG0 register. |
| 16 | + |
| 17 | +Implement this functionality for QEMU, using a machine property |
| 18 | +"remap" with valid values "BRAM" and "QSPI" to allow the user to set |
| 19 | +the initial mapping, in the same way they can on the FPGA, and |
| 20 | +wiring up the bit from the SCC register to also switch the mapping. |
| 21 | + |
| 22 | +Signed-off-by: Peter Maydell < [email protected]> |
| 23 | +Reviewed-by: Richard Henderson < [email protected]> |
| 24 | +--- |
| 25 | + docs/system/arm/mps2.rst | 10 ++++ |
| 26 | + hw/arm/mps2-tz.c | 106 ++++++++++++++++++++++++++++++++++++++- |
| 27 | + 2 files changed, 115 insertions(+), 1 deletion(-) |
| 28 | + |
| 29 | +diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst |
| 30 | +index f83b151787..8a75beb3a0 100644 |
| 31 | +--- a/docs/system/arm/mps2.rst |
| 32 | ++++ b/docs/system/arm/mps2.rst |
| 33 | +@@ -45,3 +45,13 @@ Differences between QEMU and real hardware: |
| 34 | + flash, but only as simple ROM, so attempting to rewrite the flash |
| 35 | + from the guest will fail |
| 36 | + - QEMU does not model the USB controller in MPS3 boards |
| 37 | ++ |
| 38 | ++Machine-specific options |
| 39 | ++"""""""""""""""""""""""" |
| 40 | ++ |
| 41 | ++The following machine-specific options are supported: |
| 42 | ++ |
| 43 | ++remap |
| 44 | ++ Supported for ``mps3-an524`` only. |
| 45 | ++ Set ``BRAM``/``QSPI`` to select the initial memory mapping. The |
| 46 | ++ default is ``BRAM``. |
| 47 | +diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c |
| 48 | +index 25016e464d..e980677932 100644 |
| 49 | +--- a/hw/arm/mps2-tz.c |
| 50 | ++++ b/hw/arm/mps2-tz.c |
| 51 | +@@ -55,6 +55,7 @@ |
| 52 | + #include "hw/boards.h" |
| 53 | + #include "exec/address-spaces.h" |
| 54 | + #include "sysemu/sysemu.h" |
| 55 | ++#include "sysemu/reset.h" |
| 56 | + #include "hw/misc/unimp.h" |
| 57 | + #include "hw/char/cmsdk-apb-uart.h" |
| 58 | + #include "hw/timer/cmsdk-apb-timer.h" |
| 59 | +@@ -72,6 +73,7 @@ |
| 60 | + #include "hw/core/split-irq.h" |
| 61 | + #include "hw/qdev-clock.h" |
| 62 | + #include "qom/object.h" |
| 63 | ++#include "hw/irq.h" |
| 64 | + |
| 65 | + #define MPS2TZ_NUMIRQ_MAX 96 |
| 66 | + #define MPS2TZ_RAM_MAX 5 |
| 67 | +@@ -153,6 +155,9 @@ struct MPS2TZMachineState { |
| 68 | + SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX]; |
| 69 | + Clock *sysclk; |
| 70 | + Clock *s32kclk; |
| 71 | ++ |
| 72 | ++ int remap; |
| 73 | ++ qemu_irq remap_irq; |
| 74 | + }; |
| 75 | + |
| 76 | + #define TYPE_MPS2TZ_MACHINE "mps2tz" |
| 77 | +@@ -228,6 +233,10 @@ static const RAMInfo an505_raminfo[] = { { |
| 78 | + }, |
| 79 | + }; |
| 80 | + |
| 81 | ++/* |
| 82 | ++ * Note that the addresses and MPC numbering here should match up |
| 83 | ++ * with those used in remap_memory(), which can swap the BRAM and QSPI. |
| 84 | ++ */ |
| 85 | + static const RAMInfo an524_raminfo[] = { { |
| 86 | + .name = "bram", |
| 87 | + .base = 0x00000000, |
| 88 | +@@ -457,6 +466,7 @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque, |
| 89 | + |
| 90 | + object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC); |
| 91 | + sccdev = DEVICE(scc); |
| 92 | ++ qdev_prop_set_uint32(sccdev, "scc-cfg0", mms->remap); |
| 93 | + qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); |
| 94 | + qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008); |
| 95 | + qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); |
| 96 | +@@ -573,6 +583,50 @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque, |
| 97 | + return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); |
| 98 | + } |
| 99 | + |
| 100 | ++static hwaddr boot_mem_base(MPS2TZMachineState *mms) |
| 101 | ++{ |
| 102 | ++ /* |
| 103 | ++ * Return the canonical address of the block which will be mapped |
| 104 | ++ * at address 0x0 (i.e. where the vector table is). |
| 105 | ++ * This is usually 0, but if the AN524 alternate memory map is |
| 106 | ++ * enabled it will be the base address of the QSPI block. |
| 107 | ++ */ |
| 108 | ++ return mms->remap ? 0x28000000 : 0; |
| 109 | ++} |
| 110 | ++ |
| 111 | ++static void remap_memory(MPS2TZMachineState *mms, int map) |
| 112 | ++{ |
| 113 | ++ /* |
| 114 | ++ * Remap the memory for the AN524. 'map' is the value of |
| 115 | ++ * SCC CFG_REG0 bit 0, i.e. 0 for the default map and 1 |
| 116 | ++ * for the "option 1" mapping where QSPI is at address 0. |
| 117 | ++ * |
| 118 | ++ * Effectively we need to swap around the "upstream" ends of |
| 119 | ++ * MPC 0 and MPC 1. |
| 120 | ++ */ |
| 121 | ++ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); |
| 122 | ++ int i; |
| 123 | ++ |
| 124 | ++ if (mmc->fpga_type != FPGA_AN524) { |
| 125 | ++ return; |
| 126 | ++ } |
| 127 | ++ |
| 128 | ++ for (i = 0; i < 2; i++) { |
| 129 | ++ TZMPC *mpc = &mms->mpc[i]; |
| 130 | ++ MemoryRegion *upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); |
| 131 | ++ hwaddr addr = (i ^ map) ? 0x28000000 : 0; |
| 132 | ++ |
| 133 | ++ memory_region_set_address(upstream, addr); |
| 134 | ++ } |
| 135 | ++} |
| 136 | ++ |
| 137 | ++static void remap_irq_fn(void *opaque, int n, int level) |
| 138 | ++{ |
| 139 | ++ MPS2TZMachineState *mms = opaque; |
| 140 | ++ |
| 141 | ++ remap_memory(mms, level); |
| 142 | ++} |
| 143 | ++ |
| 144 | + static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque, |
| 145 | + const char *name, hwaddr size, |
| 146 | + const int *irqs) |
| 147 | +@@ -711,7 +765,7 @@ static uint32_t boot_ram_size(MPS2TZMachineState *mms) |
| 148 | + MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); |
| 149 | + |
| 150 | + for (p = mmc->raminfo; p->name; p++) { |
| 151 | +- if (p->base == 0) { |
| 152 | ++ if (p->base == boot_mem_base(mms)) { |
| 153 | + return p->size; |
| 154 | + } |
| 155 | + } |
| 156 | +@@ -1095,6 +1149,16 @@ static void mps2tz_common_init(MachineState *machine) |
| 157 | + |
| 158 | + create_non_mpc_ram(mms); |
| 159 | + |
| 160 | ++ if (mmc->fpga_type == FPGA_AN524) { |
| 161 | ++ /* |
| 162 | ++ * Connect the line from the SCC so that we can remap when the |
| 163 | ++ * guest updates that register. |
| 164 | ++ */ |
| 165 | ++ mms->remap_irq = qemu_allocate_irq(remap_irq_fn, mms, 0); |
| 166 | ++ qdev_connect_gpio_out_named(DEVICE(&mms->scc), "remap", 0, |
| 167 | ++ mms->remap_irq); |
| 168 | ++ } |
| 169 | ++ |
| 170 | + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, |
| 171 | + boot_ram_size(mms)); |
| 172 | + } |
| 173 | +@@ -1117,12 +1181,47 @@ static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address, |
| 174 | + *iregion = region; |
| 175 | + } |
| 176 | + |
| 177 | ++static char *mps2_get_remap(Object *obj, Error **errp) |
| 178 | ++{ |
| 179 | ++ MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj); |
| 180 | ++ const char *val = mms->remap ? "QSPI" : "BRAM"; |
| 181 | ++ return g_strdup(val); |
| 182 | ++} |
| 183 | ++ |
| 184 | ++static void mps2_set_remap(Object *obj, const char *value, Error **errp) |
| 185 | ++{ |
| 186 | ++ MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj); |
| 187 | ++ |
| 188 | ++ if (!strcmp(value, "BRAM")) { |
| 189 | ++ mms->remap = 0; |
| 190 | ++ } else if (!strcmp(value, "QSPI")) { |
| 191 | ++ mms->remap = 1; |
| 192 | ++ } else { |
| 193 | ++ error_setg(errp, "Invalid remap value"); |
| 194 | ++ error_append_hint(errp, "Valid values are BRAM and QSPI.\n"); |
| 195 | ++ } |
| 196 | ++} |
| 197 | ++ |
| 198 | ++static void mps2_machine_reset(MachineState *machine) |
| 199 | ++{ |
| 200 | ++ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine); |
| 201 | ++ |
| 202 | ++ /* |
| 203 | ++ * Set the initial memory mapping before triggering the reset of |
| 204 | ++ * the rest of the system, so that the guest image loader and CPU |
| 205 | ++ * reset see the correct mapping. |
| 206 | ++ */ |
| 207 | ++ remap_memory(mms, mms->remap); |
| 208 | ++ qemu_devices_reset(); |
| 209 | ++} |
| 210 | ++ |
| 211 | + static void mps2tz_class_init(ObjectClass *oc, void *data) |
| 212 | + { |
| 213 | + MachineClass *mc = MACHINE_CLASS(oc); |
| 214 | + IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc); |
| 215 | + |
| 216 | + mc->init = mps2tz_common_init; |
| 217 | ++ mc->reset = mps2_machine_reset; |
| 218 | + iic->check = mps2_tz_idau_check; |
| 219 | + } |
| 220 | + |
| 221 | +@@ -1225,6 +1324,11 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data) |
| 222 | + mmc->raminfo = an524_raminfo; |
| 223 | + mmc->armsse_type = TYPE_SSE200; |
| 224 | + mps2tz_set_default_ram_info(mmc); |
| 225 | ++ |
| 226 | ++ object_class_property_add_str(oc, "remap", mps2_get_remap, mps2_set_remap); |
| 227 | ++ object_class_property_set_description(oc, "remap", |
| 228 | ++ "Set memory mapping. Valid values " |
| 229 | ++ "are BRAM (default) and QSPI."); |
| 230 | + } |
| 231 | + |
| 232 | + static void mps3tz_an547_class_init(ObjectClass *oc, void *data) |
| 233 | +-- |
| 234 | +2.30.2 |
| 235 | + |
0 commit comments