1
target-arm queue: this clears out a bunch of patches I'd sent over
1
Nuvoton new board models, and some more minor stuff. I also put
2
the last coupled of weeks that have now got reviewed. Mostly
2
in the deprecation patches for unicore32 and lm32.
3
this is MPS2 device support improvements, put there is also
4
more of the incremental work towards supporting AArch32 Hyp mode,
5
a floating point bugfix, and the raspi framebuffer viewport support.
6
3
7
thanks
4
thanks
8
-- PMM
5
-- PMM
9
6
10
The following changes since commit 5ccac548faf041ff5229a8e8342e3be14a34c8af:
7
The following changes since commit a68694cd1f3e5448cca814ff39b871f9ebd71ed5:
11
8
12
Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging (2018-08-23 17:35:48 +0100)
9
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/edk2-next-20200914' into staging (2020-09-14 12:18:58 +0100)
13
10
14
are available in the Git repository at:
11
are available in the Git repository at:
15
12
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180824
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200914
17
14
18
for you to fetch changes up to 30a719e3cb5c5367f3651eba8fa935634bfee286:
15
for you to fetch changes up to dd44ae00fc5342ed99acb68ec3508f76a71d523a:
19
16
20
hw/arm/mps2: Fix ID register errors on AN511 and AN385 (2018-08-24 10:22:44 +0100)
17
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller (2020-09-14 14:27:08 +0100)
21
18
22
----------------------------------------------------------------
19
----------------------------------------------------------------
23
target-arm queue:
20
target-arm queue:
24
* Fix rounding errors in scaling float-to-int and int-to-float operations
21
* hw/misc/a9scu: Do not allow invalid CPU count
25
* Connect virtualization-related IRQs and memory regions of GICv2
22
* hw/misc/a9scu: Minor cleanups
26
in boards that use Cortex-A7 or Cortex-A15
23
* hw/timer/armv7m_systick: assert that board code set system_clock_scale
27
* Support taking exceptions to AArch32 Hyp mode
24
* decodetree: Improve identifier matching
28
* Clear CPSR.IL and CPSR.J on 32-bit exception entry
25
* target/arm: Clean up neon fp insn size field decode
29
(a minor bug fix that won't affect non-buggy guest code)
26
* target/arm: Remove KVM support for 32-bit Arm hosts
30
* mps2-an505: Implement various missing devices:
27
* hw/arm/mps2: New board models mps2-an386, mps2-an500
31
dual timer, watchdogs, counters in the FPGAIO registers,
28
* Deprecate Unicore32 port
32
some missing ID/control registers, TrustZone Master Security
29
* Deprecate lm32 port
33
Controllers, PL081 DMA controllers, PL022 SPI controllers
30
* target/arm: Count PMU events when MDCR.SPME is set
34
* correct ID register values for mps2-an385, -an511, -an505
31
* hw/arm: versal-virt: Correct the tx/rx GEM clocks
35
* fix some hardcoded tabs in untouched backwaters of the
32
* New Nuvoton iBMC board models npcm750-evb, quanta-gsj
36
target/arm codebase
33
* xlnx-zynqmp: implement ZynqMP CAN controllers
37
* raspi: Refactor framebuffer property handling code and implement
38
support for the virtual framebuffer/viewport
39
34
40
----------------------------------------------------------------
35
----------------------------------------------------------------
41
Peter Maydell (48):
36
Aaron Lindsay (1):
42
hw/intc/arm_gic: Make per-cpu GICH memory regions 0x200 bytes large
37
target/arm: Count PMU events when MDCR.SPME is set
43
hw/arm/vexpress: Connect VIRQ and VFIQ
44
hw/arm/highbank: Connect VIRQ and VFIQ
45
hw/arm/fsl-imx6ul: Connect VIRQ and VFIQ
46
hw/arm/fsl-imx6ul: Connect VIRQ and VFIQ
47
hw/cpu/a15mpcore: If CPU has EL2, enable it on the GIC and wire it up
48
hw/arm/vexpress: Don't set info->secure_boot if CPU doesn't have EL3
49
hw/arm/vexpress: Add "virtualization" property controlling presence of EL2
50
target/arm: Implement RAZ/WI HACTLR2
51
target/arm: Implement AArch32 HCR and HCR2
52
target/arm: Factor out code for taking an AArch32 exception
53
target/arm: Implement support for taking exceptions to Hyp mode
54
target/arm: Clear CPSR.IL and CPSR.J on 32-bit exception entry
55
hw/arm/boot: AArch32 kernels should be started in Hyp mode if available
56
hw/misc/mps2-fpgaio: Implement 1Hz and 100Hz counters
57
hw/misc/mps2-fpgaio: Implement PSCNTR and COUNTER
58
hw/timer/cmsdk-apb-dualtimer: Implement CMSDK dual timer module
59
hw/arm/iotkit: Wire up the dualtimer
60
hw/arm/mps2: Wire up dual-timer in mps2-an385 and mps2-an511
61
hw/arm/iotkit: Wire up the watchdogs
62
hw/arm/iotkit: Wire up the S32KTIMER
63
hw/misc/iotkit-sysctl: Implement IoTKit system control element
64
hw/misc/iotkit-sysinfo: Implement IoTKit system information block
65
hw/misc/iotkit: Wire up the sysctl and sysinfo register blocks
66
hw/misc/tz-msc: Model TrustZone Master Security Controller
67
hw/misc/iotkit-secctl: Wire up registers for controlling MSCs
68
hw/arm/iotkit: Wire up the lines for MSCs
69
hw/arm/mps2-tz: Create PL081s and MSCs
70
hw/ssi/pl022: Allow use as embedded-struct device
71
hw/ssi/pl022: Set up reset function in class init
72
hw/ssi/pl022: Don't directly call vmstate_register()
73
hw/ssi/pl022: Use DeviceState::realize rather than SysBusDevice::init
74
hw/ssi/pl022: Correct wrong value for PL022_INT_RT
75
hw/ssi/pl022: Correct wrong DMACR and ICR handling
76
hw/arm/mps2-tz: Instantiate SPI controllers
77
hw/arm/mps2-tz: Fix MPS2 SCC config register values
78
target/arm: Untabify translate.c
79
target/arm: Untabify iwmmxt_helper.c
80
target/arm: Remove a handful of stray tabs
81
hw/misc/bcm2835_fb: Move config fields to their own struct
82
hw/misc/bcm2835_property: Track fb settings using BCM2835FBConfig
83
hw/display/bcm2835_fb: Drop unused size and pitch fields
84
hw/display/bcm2835_fb: Reset resolution, etc correctly
85
hw/display/bcm2835_fb: Abstract out calculation of pitch, size
86
hw/display/bcm2835_fb: Fix handling of virtual framebuffer
87
hw/display/bcm2835_fb: Validate config settings
88
hw/display/bcm2835_fb: Validate bcm2835_fb_mbox_push() config
89
hw/arm/mps2: Fix ID register errors on AN511 and AN385
90
38
91
Richard Henderson (4):
39
Edgar E. Iglesias (1):
92
softfloat: Add scaling int-to-float routines
40
hw/arm: versal-virt: Correct the tx/rx GEM clocks
93
softfloat: Add scaling float-to-int routines
94
target/arm: Use the int-to-float-scale softfloat routines
95
target/arm: Use the float-to-int-scale softfloat routines
96
41
97
hw/misc/Makefile.objs | 3 +
42
Havard Skinnemoen (14):
98
hw/timer/Makefile.objs | 1 +
43
hw/misc: Add NPCM7xx System Global Control Registers device model
99
include/fpu/softfloat.h | 169 +++++++---
44
hw/misc: Add NPCM7xx Clock Controller device model
100
include/hw/arm/iotkit.h | 25 +-
45
hw/timer: Add NPCM7xx Timer device model
101
include/hw/display/bcm2835_fb.h | 59 +++-
46
hw/arm: Add NPCM730 and NPCM750 SoC models
102
include/hw/misc/iotkit-secctl.h | 14 +
47
hw/arm: Add two NPCM7xx-based machines
103
include/hw/misc/iotkit-sysctl.h | 49 +++
48
roms: Add virtual Boot ROM for NPCM7xx SoCs
104
include/hw/misc/iotkit-sysinfo.h | 37 +++
49
hw/arm: Load -bios image as a boot ROM for npcm7xx
105
include/hw/misc/mps2-fpgaio.h | 10 +
50
hw/nvram: NPCM7xx OTP device model
106
include/hw/misc/tz-msc.h | 79 +++++
51
hw/mem: Stubbed out NPCM7xx Memory Controller model
107
include/hw/ssi/pl022.h | 51 +++
52
hw/ssi: NPCM7xx Flash Interface Unit device model
108
include/hw/timer/cmsdk-apb-dualtimer.h | 72 ++++
53
hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj
109
target/arm/cpu.h | 16 +-
54
hw/arm/npcm7xx: add board setup stub for CPU and UART clocks
110
fpu/softfloat.c | 579 ++++++++++++++++++++++++++-------
55
docs/system: Add Nuvoton machine documentation
111
hw/arm/boot.c | 11 +
56
tests/acceptance: console boot tests for quanta-gsj
112
hw/arm/fsl-imx6ul.c | 4 +
113
hw/arm/fsl-imx7.c | 4 +
114
hw/arm/highbank.c | 6 +
115
hw/arm/iotkit.c | 114 ++++++-
116
hw/arm/mps2-tz.c | 142 +++++++-
117
hw/arm/mps2.c | 17 +-
118
hw/arm/vexpress.c | 64 +++-
119
hw/cpu/a15mpcore.c | 31 +-
120
hw/display/bcm2835_fb.c | 218 ++++++++-----
121
hw/intc/arm_gic.c | 2 +-
122
hw/misc/bcm2835_property.c | 123 ++++---
123
hw/misc/iotkit-secctl.c | 73 ++++-
124
hw/misc/iotkit-sysctl.c | 261 +++++++++++++++
125
hw/misc/iotkit-sysinfo.c | 128 ++++++++
126
hw/misc/mps2-fpgaio.c | 146 ++++++++-
127
hw/misc/tz-msc.c | 308 ++++++++++++++++++
128
hw/ssi/pl022.c | 57 ++--
129
hw/timer/cmsdk-apb-dualtimer.c | 515 +++++++++++++++++++++++++++++
130
target/arm/arm-semi.c | 2 +-
131
target/arm/helper.c | 342 +++++++++++++------
132
target/arm/iwmmxt_helper.c | 234 ++++++-------
133
target/arm/translate.c | 122 +++----
134
MAINTAINERS | 10 +
135
default-configs/arm-softmmu.mak | 4 +
136
hw/misc/trace-events | 16 +
137
hw/timer/trace-events | 5 +
138
41 files changed, 3405 insertions(+), 718 deletions(-)
139
create mode 100644 include/hw/misc/iotkit-sysctl.h
140
create mode 100644 include/hw/misc/iotkit-sysinfo.h
141
create mode 100644 include/hw/misc/tz-msc.h
142
create mode 100644 include/hw/ssi/pl022.h
143
create mode 100644 include/hw/timer/cmsdk-apb-dualtimer.h
144
create mode 100644 hw/misc/iotkit-sysctl.c
145
create mode 100644 hw/misc/iotkit-sysinfo.c
146
create mode 100644 hw/misc/tz-msc.c
147
create mode 100644 hw/timer/cmsdk-apb-dualtimer.c
148
57
58
Peter Maydell (11):
59
hw/timer/armv7m_systick: assert that board code set system_clock_scale
60
target/arm: Convert Neon 3-same-fp size field to MO_* in decode
61
target/arm: Convert Neon VCVT fp size field to MO_* in decode
62
target/arm: Convert VCMLA, VCADD size field to MO_* in decode
63
target/arm: Remove KVM support for 32-bit Arm hosts
64
target/arm: Remove no-longer-reachable 32-bit KVM code
65
hw/arm/mps2: New board model mps2-an386
66
hw/arm/mps2: New board model mps2-an500
67
docs/system/arm/mps2.rst: Make board list consistent
68
Deprecate Unicore32 port
69
Deprecate lm32 port
70
71
Philippe Mathieu-Daudé (4):
72
hw/misc/a9scu: Do not allow invalid CPU count
73
hw/misc/a9scu: Simplify setting MemoryRegionOps::valid fields
74
hw/misc/a9scu: Simplify setting MemoryRegionOps::impl fields
75
hw/misc/a9scu: Report unimplemented accesses with qemu_log_mask(UNIMP)
76
77
Richard Henderson (1):
78
decodetree: Improve identifier matching
79
80
Vikram Garhwal (4):
81
hw/net/can: Introduce Xilinx ZynqMP CAN controller
82
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
83
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
84
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
85
86
docs/system/arm/mps2.rst | 20 +-
87
docs/system/arm/nuvoton.rst | 92 +++
88
docs/system/deprecated.rst | 32 +-
89
docs/system/target-arm.rst | 1 +
90
configure | 2 +-
91
default-configs/arm-softmmu.mak | 1 +
92
include/hw/arm/npcm7xx.h | 112 +++
93
include/hw/arm/xlnx-zynqmp.h | 8 +
94
include/hw/mem/npcm7xx_mc.h | 36 +
95
include/hw/misc/npcm7xx_clk.h | 48 ++
96
include/hw/misc/npcm7xx_gcr.h | 43 ++
97
include/hw/net/xlnx-zynqmp-can.h | 78 +++
98
include/hw/nvram/npcm7xx_otp.h | 79 +++
99
include/hw/ssi/npcm7xx_fiu.h | 73 ++
100
include/hw/timer/npcm7xx_timer.h | 78 +++
101
target/arm/kvm-consts.h | 7 -
102
target/arm/kvm_arm.h | 6 -
103
target/arm/neon-dp.decode | 18 +-
104
target/arm/neon-shared.decode | 18 +-
105
tests/decode/succ_ident1.decode | 7 +
106
hw/arm/mps2.c | 97 ++-
107
hw/arm/npcm7xx.c | 532 +++++++++++++++
108
hw/arm/npcm7xx_boards.c | 197 ++++++
109
hw/arm/xlnx-versal-virt.c | 2 +-
110
hw/arm/xlnx-zcu102.c | 20 +
111
hw/arm/xlnx-zynqmp.c | 34 +
112
hw/mem/npcm7xx_mc.c | 84 +++
113
hw/misc/a9scu.c | 59 +-
114
hw/misc/npcm7xx_clk.c | 266 ++++++++
115
hw/misc/npcm7xx_gcr.c | 269 ++++++++
116
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++++
117
hw/nvram/npcm7xx_otp.c | 440 ++++++++++++
118
hw/ssi/npcm7xx_fiu.c | 572 ++++++++++++++++
119
hw/timer/armv7m_systick.c | 8 +
120
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++
121
target/arm/cpu.c | 101 ++-
122
target/arm/helper.c | 2 +-
123
target/arm/kvm.c | 7 -
124
target/arm/kvm32.c | 595 ----------------
125
tests/qtest/xlnx-can-test.c | 359 ++++++++++
126
.gitmodules | 3 +
127
MAINTAINERS | 18 +
128
hw/arm/Kconfig | 9 +
129
hw/arm/meson.build | 1 +
130
hw/mem/meson.build | 1 +
131
hw/misc/meson.build | 4 +
132
hw/misc/trace-events | 8 +
133
hw/net/can/meson.build | 1 +
134
hw/nvram/meson.build | 1 +
135
hw/ssi/meson.build | 1 +
136
hw/ssi/trace-events | 11 +
137
hw/timer/meson.build | 1 +
138
hw/timer/trace-events | 5 +
139
pc-bios/README | 6 +
140
pc-bios/meson.build | 1 +
141
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
142
roms/Makefile | 7 +
143
roms/vbootrom | 1 +
144
scripts/decodetree.py | 46 +-
145
target/arm/meson.build | 5 +-
146
target/arm/translate-neon.c.inc | 42 +-
147
tests/acceptance/boot_linux_console.py | 83 +++
148
tests/qtest/meson.build | 1 +
149
63 files changed, 5584 insertions(+), 783 deletions(-)
150
create mode 100644 docs/system/arm/nuvoton.rst
151
create mode 100644 include/hw/arm/npcm7xx.h
152
create mode 100644 include/hw/mem/npcm7xx_mc.h
153
create mode 100644 include/hw/misc/npcm7xx_clk.h
154
create mode 100644 include/hw/misc/npcm7xx_gcr.h
155
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
156
create mode 100644 include/hw/nvram/npcm7xx_otp.h
157
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
158
create mode 100644 include/hw/timer/npcm7xx_timer.h
159
create mode 100644 tests/decode/succ_ident1.decode
160
create mode 100644 hw/arm/npcm7xx.c
161
create mode 100644 hw/arm/npcm7xx_boards.c
162
create mode 100644 hw/mem/npcm7xx_mc.c
163
create mode 100644 hw/misc/npcm7xx_clk.c
164
create mode 100644 hw/misc/npcm7xx_gcr.c
165
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
166
create mode 100644 hw/nvram/npcm7xx_otp.c
167
create mode 100644 hw/ssi/npcm7xx_fiu.c
168
create mode 100644 hw/timer/npcm7xx_timer.c
169
delete mode 100644 target/arm/kvm32.c
170
create mode 100644 tests/qtest/xlnx-can-test.c
171
create mode 100644 pc-bios/npcm7xx_bootrom.bin
172
create mode 160000 roms/vbootrom
173
diff view generated by jsdifflib
1
The AN505 FPGA image includes four PL081 DMA controllers, each
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
of which is gated by a Master Security Controller that allows
3
the guest to prevent a non-secure DMA controller from accessing
4
memory that is used by secure guest code. Create and wire
5
up these devices.
6
2
3
Per the datasheet (DDI0407 r2p0):
4
5
"The SCU connects one to four Cortex-A9 processors to
6
the memory system through the AXI interfaces."
7
8
Change the instance_init() handler to a device_realize()
9
one so we can verify the property is in range, and return
10
an error to the caller if not.
11
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200901144100.116742-2-f4bug@amsat.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20180820141116.9118-15-peter.maydell@linaro.org
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
16
---
12
hw/arm/mps2-tz.c | 100 +++++++++++++++++++++++++++++++++++++++++++----
17
hw/misc/a9scu.c | 18 +++++++++++++-----
13
1 file changed, 93 insertions(+), 7 deletions(-)
18
1 file changed, 13 insertions(+), 5 deletions(-)
14
19
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
20
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
22
--- a/hw/misc/a9scu.c
18
+++ b/hw/arm/mps2-tz.c
23
+++ b/hw/misc/a9scu.c
19
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
20
#include "hw/misc/mps2-scc.h"
25
#include "hw/misc/a9scu.h"
21
#include "hw/misc/mps2-fpgaio.h"
26
#include "hw/qdev-properties.h"
22
#include "hw/misc/tz-mpc.h"
27
#include "migration/vmstate.h"
23
+#include "hw/misc/tz-msc.h"
28
+#include "qapi/error.h"
24
#include "hw/arm/iotkit.h"
29
#include "qemu/module.h"
25
+#include "hw/dma/pl080.h"
30
26
#include "hw/devices.h"
31
+#define A9_SCU_CPU_MAX 4
27
#include "net/net.h"
32
+
28
#include "hw/core/split-irq.h"
33
static uint64_t a9_scu_read(void *opaque, hwaddr offset,
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
34
unsigned size)
30
UnimplementedDeviceState i2c[4];
35
{
31
UnimplementedDeviceState i2s_audio;
36
@@ -XXX,XX +XXX,XX @@ static void a9_scu_reset(DeviceState *dev)
32
UnimplementedDeviceState gpio[4];
37
s->control = 0;
33
- UnimplementedDeviceState dma[4];
34
UnimplementedDeviceState gfx;
35
+ PL080State dma[4];
36
+ TZMSC msc[4];
37
CMSDKAPBUART uart[5];
38
SplitIRQ sec_resp_splitter;
39
qemu_or_irq uart_irq_orgate;
40
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
41
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
42
}
38
}
43
39
44
+static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
40
-static void a9_scu_init(Object *obj)
45
+ const char *name, hwaddr size)
41
+static void a9_scu_realize(DeviceState *dev, Error **errp)
46
+{
42
{
47
+ PL080State *dma = opaque;
43
- A9SCUState *s = A9_SCU(obj);
48
+ int i = dma - &mms->dma[0];
44
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
49
+ SysBusDevice *s;
45
+ A9SCUState *s = A9_SCU(dev);
50
+ char *mscname = g_strdup_printf("%s-msc", name);
46
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
51
+ TZMSC *msc = &mms->msc[i];
47
52
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
48
- memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
53
+ MemoryRegion *msc_upstream;
49
+ if (!s->num_cpu || s->num_cpu > A9_SCU_CPU_MAX) {
54
+ MemoryRegion *msc_downstream;
50
+ error_setg(errp, "Illegal CPU count: %u", s->num_cpu);
51
+ return;
52
+ }
55
+
53
+
56
+ /*
54
+ memory_region_init_io(&s->iomem, OBJECT(s), &a9_scu_ops, s,
57
+ * Each DMA device is a PL081 whose transaction master interface
55
"a9-scu", 0x100);
58
+ * is guarded by a Master Security Controller. The downstream end of
56
sysbus_init_mmio(sbd, &s->iomem);
59
+ * the MSC connects to the IoTKit AHB Slave Expansion port, so the
60
+ * DMA devices can see all devices and memory that the CPU does.
61
+ */
62
+ sysbus_init_child_obj(OBJECT(mms), mscname, msc, sizeof(*msc), TYPE_TZ_MSC);
63
+ msc_downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(&mms->iotkit), 0);
64
+ object_property_set_link(OBJECT(msc), OBJECT(msc_downstream),
65
+ "downstream", &error_fatal);
66
+ object_property_set_link(OBJECT(msc), OBJECT(mms),
67
+ "idau", &error_fatal);
68
+ object_property_set_bool(OBJECT(msc), true, "realized", &error_fatal);
69
+
70
+ qdev_connect_gpio_out_named(DEVICE(msc), "irq", 0,
71
+ qdev_get_gpio_in_named(iotkitdev,
72
+ "mscexp_status", i));
73
+ qdev_connect_gpio_out_named(iotkitdev, "mscexp_clear", i,
74
+ qdev_get_gpio_in_named(DEVICE(msc),
75
+ "irq_clear", 0));
76
+ qdev_connect_gpio_out_named(iotkitdev, "mscexp_ns", i,
77
+ qdev_get_gpio_in_named(DEVICE(msc),
78
+ "cfg_nonsec", 0));
79
+ qdev_connect_gpio_out(DEVICE(&mms->sec_resp_splitter),
80
+ ARRAY_SIZE(mms->ppc) + i,
81
+ qdev_get_gpio_in_named(DEVICE(msc),
82
+ "cfg_sec_resp", 0));
83
+ msc_upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(msc), 0);
84
+
85
+ sysbus_init_child_obj(OBJECT(mms), name, dma, sizeof(*dma), TYPE_PL081);
86
+ object_property_set_link(OBJECT(dma), OBJECT(msc_upstream),
87
+ "downstream", &error_fatal);
88
+ object_property_set_bool(OBJECT(dma), true, "realized", &error_fatal);
89
+
90
+ s = SYS_BUS_DEVICE(dma);
91
+ /* Wire up DMACINTR, DMACINTERR, DMACINTTC */
92
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
93
+ "EXP_IRQ", 58 + i * 3));
94
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
95
+ "EXP_IRQ", 56 + i * 3));
96
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in_named(iotkitdev,
97
+ "EXP_IRQ", 57 + i * 3));
98
+
99
+ return sysbus_mmio_get_region(s, 0);
100
+}
101
+
102
static void mps2tz_common_init(MachineState *machine)
103
{
104
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
105
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
106
&error_fatal);
107
108
/* The sec_resp_cfg output from the IoTKit must be split into multiple
109
- * lines, one for each of the PPCs we create here.
110
+ * lines, one for each of the PPCs we create here, plus one per MSC.
111
*/
112
object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
113
TYPE_SPLIT_IRQ);
114
object_property_add_child(OBJECT(machine), "sec-resp-splitter",
115
OBJECT(&mms->sec_resp_splitter), &error_abort);
116
- object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
117
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter),
118
+ ARRAY_SIZE(mms->ppc) + ARRAY_SIZE(mms->msc),
119
"num-lines", &error_fatal);
120
object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
121
"realized", &error_fatal);
122
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
123
}, {
124
.name = "ahb_ppcexp1",
125
.ports = {
126
- { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
127
- { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
128
- { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
129
- { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
130
+ { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 },
131
+ { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 },
132
+ { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 },
133
+ { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 },
134
},
135
},
136
};
137
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
138
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
139
}
57
}
140
58
@@ -XXX,XX +XXX,XX @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
141
+static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
59
device_class_set_props(dc, a9_scu_properties);
142
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
60
dc->vmsd = &vmstate_a9_scu;
143
+{
61
dc->reset = a9_scu_reset;
144
+ /*
62
+ dc->realize = a9_scu_realize;
145
+ * The MPS2 TZ FPGA images have IDAUs in them which are connected to
146
+ * the Master Security Controllers. Thes have the same logic as
147
+ * is used by the IoTKit for the IDAU connected to the CPU, except
148
+ * that MSCs don't care about the NSC attribute.
149
+ */
150
+ int region = extract32(address, 28, 4);
151
+
152
+ *ns = !(region & 1);
153
+ *nsc = false;
154
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
155
+ *exempt = (address & 0xeff00000) == 0xe0000000;
156
+ *iregion = region;
157
+}
158
+
159
static void mps2tz_class_init(ObjectClass *oc, void *data)
160
{
161
MachineClass *mc = MACHINE_CLASS(oc);
162
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
163
164
mc->init = mps2tz_common_init;
165
mc->max_cpus = 1;
166
+ iic->check = mps2_tz_idau_check;
167
}
63
}
168
64
169
static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
65
static const TypeInfo a9_scu_info = {
170
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_info = {
66
.name = TYPE_A9_SCU,
171
.instance_size = sizeof(MPS2TZMachineState),
67
.parent = TYPE_SYS_BUS_DEVICE,
172
.class_size = sizeof(MPS2TZMachineClass),
68
.instance_size = sizeof(A9SCUState),
173
.class_init = mps2tz_class_init,
69
- .instance_init = a9_scu_init,
174
+ .interfaces = (InterfaceInfo[]) {
70
.class_init = a9_scu_class_init,
175
+ { TYPE_IDAU_INTERFACE },
176
+ { }
177
+ },
178
};
71
};
179
72
180
static const TypeInfo mps2tz_an505_info = {
181
--
73
--
182
2.18.0
74
2.20.1
183
75
184
76
diff view generated by jsdifflib
1
The bcm2835_fb's initial resolution and other parameters are set
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
via QOM properties. We should reset to those initial values on
3
device reset, which means we need to save the QOM property
4
values somewhere that they are not overwritten by guest
5
changes to the framebuffer configuration.
6
2
3
Per the datasheet (DDI0407 r2p0):
4
5
"All SCU registers are byte accessible" and are 32-bit aligned.
6
7
Set MemoryRegionOps::valid min/max fields and simplify the write()
8
handler.
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200901144100.116742-3-f4bug@amsat.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180814144436.679-5-peter.maydell@linaro.org
10
---
14
---
11
include/hw/display/bcm2835_fb.h | 1 +
15
hw/misc/a9scu.c | 21 +++++----------------
12
hw/display/bcm2835_fb.c | 27 +++++++++++++++------------
16
1 file changed, 5 insertions(+), 16 deletions(-)
13
2 files changed, 16 insertions(+), 12 deletions(-)
14
17
15
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
18
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/display/bcm2835_fb.h
20
--- a/hw/misc/a9scu.c
18
+++ b/include/hw/display/bcm2835_fb.h
21
+++ b/hw/misc/a9scu.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
20
bool lock, invalidate, pending;
23
uint64_t value, unsigned size)
21
24
{
22
BCM2835FBConfig config;
25
A9SCUState *s = (A9SCUState *)opaque;
23
+ BCM2835FBConfig initial_config;
26
- uint32_t mask;
24
} BCM2835FBState;
27
+ uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
25
28
uint32_t shift;
26
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
29
- switch (size) {
27
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
30
- case 1:
28
index XXXXXXX..XXXXXXX 100644
31
- mask = 0xff;
29
--- a/hw/display/bcm2835_fb.c
32
- break;
30
+++ b/hw/display/bcm2835_fb.c
33
- case 2:
31
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_reset(DeviceState *dev)
34
- mask = 0xffff;
32
35
- break;
33
s->pending = false;
36
- case 4:
34
37
- mask = 0xffffffff;
35
- s->config.xres_virtual = s->config.xres;
38
- break;
36
- s->config.yres_virtual = s->config.yres;
39
- default:
37
- s->config.xoffset = 0;
40
- fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
38
- s->config.yoffset = 0;
41
- size, (unsigned)offset);
39
- s->config.base = s->vcram_base + BCM2835_FB_OFFSET;
42
- return;
40
+ s->config = s->initial_config;
43
- }
41
44
42
s->invalidate = true;
45
switch (offset) {
43
s->lock = false;
46
case 0x00: /* Control */
44
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_realize(DeviceState *dev, Error **errp)
47
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
45
return;
48
static const MemoryRegionOps a9_scu_ops = {
46
}
49
.read = a9_scu_read,
47
50
.write = a9_scu_write,
48
+ /* Fill in the parts of initial_config that are not set by QOM properties */
51
+ .valid = {
49
+ s->initial_config.xres_virtual = s->initial_config.xres;
52
+ .min_access_size = 1,
50
+ s->initial_config.yres_virtual = s->initial_config.yres;
53
+ .max_access_size = 4,
51
+ s->initial_config.xoffset = 0;
54
+ },
52
+ s->initial_config.yoffset = 0;
55
.endianness = DEVICE_NATIVE_ENDIAN,
53
+ s->initial_config.base = s->vcram_base + BCM2835_FB_OFFSET;
54
+
55
s->dma_mr = MEMORY_REGION(obj);
56
address_space_init(&s->dma_as, s->dma_mr, NULL);
57
58
@@ -XXX,XX +XXX,XX @@ static Property bcm2835_fb_props[] = {
59
DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/
60
DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size,
61
DEFAULT_VCRAM_SIZE),
62
- DEFINE_PROP_UINT32("xres", BCM2835FBState, config.xres, 640),
63
- DEFINE_PROP_UINT32("yres", BCM2835FBState, config.yres, 480),
64
- DEFINE_PROP_UINT32("bpp", BCM2835FBState, config.bpp, 16),
65
- DEFINE_PROP_UINT32("pixo",
66
- BCM2835FBState, config.pixo, 1), /* 1=RGB, 0=BGR */
67
- DEFINE_PROP_UINT32("alpha",
68
- BCM2835FBState, config.alpha, 2), /* alpha ignored */
69
+ DEFINE_PROP_UINT32("xres", BCM2835FBState, initial_config.xres, 640),
70
+ DEFINE_PROP_UINT32("yres", BCM2835FBState, initial_config.yres, 480),
71
+ DEFINE_PROP_UINT32("bpp", BCM2835FBState, initial_config.bpp, 16),
72
+ DEFINE_PROP_UINT32("pixo", BCM2835FBState,
73
+ initial_config.pixo, 1), /* 1=RGB, 0=BGR */
74
+ DEFINE_PROP_UINT32("alpha", BCM2835FBState,
75
+ initial_config.alpha, 2), /* alpha ignored */
76
DEFINE_PROP_END_OF_LIST()
77
};
56
};
78
57
79
--
58
--
80
2.18.0
59
2.20.1
81
60
82
61
diff view generated by jsdifflib
1
Refactor bcm2835_fb_mbox_push() to work by calling
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
bcm2835_fb_validate_config() and bcm2835_fb_reconfigure(),
3
so that config set this way is also validated.
4
2
3
This model implementation is designed for 32-bit accesses.
4
We can simplify setting the MemoryRegionOps::impl min/max
5
fields to 32-bit (memory::access_with_adjusted_size() will
6
take care of the 8/16-bit accesses).
7
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200901144100.116742-4-f4bug@amsat.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180814144436.679-9-peter.maydell@linaro.org
8
---
12
---
9
hw/display/bcm2835_fb.c | 63 ++++++++++++++++++++---------------------
13
hw/misc/a9scu.c | 16 +++++-----------
10
1 file changed, 31 insertions(+), 32 deletions(-)
14
1 file changed, 5 insertions(+), 11 deletions(-)
11
15
12
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
16
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/display/bcm2835_fb.c
18
--- a/hw/misc/a9scu.c
15
+++ b/hw/display/bcm2835_fb.c
19
+++ b/hw/misc/a9scu.c
16
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_validate_config(BCM2835FBConfig *config)
20
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
17
}
21
return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
18
}
22
case 0x08: /* CPU Power Status */
19
23
return s->status;
20
-static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
24
- case 0x09: /* CPU status. */
21
-{
25
- return s->status >> 8;
22
- uint32_t pitch;
26
- case 0x0a: /* CPU status. */
23
- uint32_t size;
27
- return s->status >> 16;
24
-
28
- case 0x0b: /* CPU status. */
25
- value &= ~0xf;
29
- return s->status >> 24;
26
-
30
case 0x0c: /* Invalidate All Registers In Secure State */
27
- s->lock = true;
31
return 0;
28
-
32
case 0x40: /* Filtering Start Address Register */
29
- s->config.xres = ldl_le_phys(&s->dma_as, value);
33
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
30
- s->config.yres = ldl_le_phys(&s->dma_as, value + 4);
34
uint64_t value, unsigned size)
31
- s->config.xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
32
- s->config.yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
33
- s->config.bpp = ldl_le_phys(&s->dma_as, value + 20);
34
- s->config.xoffset = ldl_le_phys(&s->dma_as, value + 24);
35
- s->config.yoffset = ldl_le_phys(&s->dma_as, value + 28);
36
-
37
- s->config.base = s->vcram_base | (value & 0xc0000000);
38
- s->config.base += BCM2835_FB_OFFSET;
39
-
40
- pitch = bcm2835_fb_get_pitch(&s->config);
41
- size = bcm2835_fb_get_size(&s->config);
42
-
43
- stl_le_phys(&s->dma_as, value + 16, pitch);
44
- stl_le_phys(&s->dma_as, value + 32, s->config.base);
45
- stl_le_phys(&s->dma_as, value + 36, size);
46
-
47
- s->invalidate = true;
48
- qemu_console_resize(s->con, s->config.xres, s->config.yres);
49
- s->lock = false;
50
-}
51
-
52
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
53
{
35
{
54
s->lock = true;
36
A9SCUState *s = (A9SCUState *)opaque;
55
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
37
- uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
56
s->lock = false;
38
- uint32_t shift;
57
}
39
58
40
switch (offset) {
59
+static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
41
case 0x00: /* Control */
60
+{
42
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
61
+ uint32_t pitch;
43
case 0x4: /* Configuration: RO */
62
+ uint32_t size;
44
break;
63
+ BCM2835FBConfig newconf;
45
case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
64
+
46
- shift = (offset - 0x8) * 8;
65
+ value &= ~0xf;
47
- s->status &= ~(mask << shift);
66
+
48
- s->status |= ((value & mask) << shift);
67
+ newconf.xres = ldl_le_phys(&s->dma_as, value);
49
+ s->status = value;
68
+ newconf.yres = ldl_le_phys(&s->dma_as, value + 4);
50
break;
69
+ newconf.xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
51
case 0x0c: /* Invalidate All Registers In Secure State */
70
+ newconf.yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
52
/* no-op as we do not implement caches */
71
+ newconf.bpp = ldl_le_phys(&s->dma_as, value + 20);
53
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
72
+ newconf.xoffset = ldl_le_phys(&s->dma_as, value + 24);
54
static const MemoryRegionOps a9_scu_ops = {
73
+ newconf.yoffset = ldl_le_phys(&s->dma_as, value + 28);
55
.read = a9_scu_read,
74
+
56
.write = a9_scu_write,
75
+ newconf.base = s->vcram_base | (value & 0xc0000000);
57
+ .impl = {
76
+ newconf.base += BCM2835_FB_OFFSET;
58
+ .min_access_size = 4,
77
+
59
+ .max_access_size = 4,
78
+ bcm2835_fb_validate_config(&newconf);
60
+ },
79
+
61
.valid = {
80
+ pitch = bcm2835_fb_get_pitch(&newconf);
62
.min_access_size = 1,
81
+ size = bcm2835_fb_get_size(&newconf);
63
.max_access_size = 4,
82
+
83
+ stl_le_phys(&s->dma_as, value + 16, pitch);
84
+ stl_le_phys(&s->dma_as, value + 32, newconf.base);
85
+ stl_le_phys(&s->dma_as, value + 36, size);
86
+
87
+ bcm2835_fb_reconfigure(s, &newconf);
88
+}
89
+
90
static uint64_t bcm2835_fb_read(void *opaque, hwaddr offset, unsigned size)
91
{
92
BCM2835FBState *s = opaque;
93
--
64
--
94
2.18.0
65
2.20.1
95
66
96
67
diff view generated by jsdifflib
1
Currently the PL022 calls pl022_reset() from its class init
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
function. Make it register a DeviceState reset method instead,
3
so that we reset the device on system reset.
4
2
3
Report unimplemented register accesses using qemu_log_mask(UNIMP).
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200901144100.116742-5-f4bug@amsat.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20180820141116.9118-17-peter.maydell@linaro.org
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
9
---
10
hw/ssi/pl022.c | 7 +++++--
10
hw/misc/a9scu.c | 6 ++++++
11
1 file changed, 5 insertions(+), 2 deletions(-)
11
1 file changed, 6 insertions(+)
12
12
13
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
13
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/ssi/pl022.c
15
--- a/hw/misc/a9scu.c
16
+++ b/hw/ssi/pl022.c
16
+++ b/hw/misc/a9scu.c
17
@@ -XXX,XX +XXX,XX @@ static void pl022_write(void *opaque, hwaddr offset,
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/qdev-properties.h"
19
#include "migration/vmstate.h"
20
#include "qapi/error.h"
21
+#include "qemu/log.h"
22
#include "qemu/module.h"
23
24
#define A9_SCU_CPU_MAX 4
25
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
26
case 0x54: /* SCU Non-secure Access Control Register */
27
/* unimplemented, fall through */
28
default:
29
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n",
30
+ __func__, offset);
31
return 0;
18
}
32
}
19
}
33
}
20
34
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
21
-static void pl022_reset(PL022State *s)
35
case 0x54: /* SCU Non-secure Access Control Register */
22
+static void pl022_reset(DeviceState *dev)
36
/* unimplemented, fall through */
23
{
37
default:
24
+ PL022State *s = PL022(dev);
38
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx
25
+
39
+ " value 0x%"PRIx64"\n",
26
s->rx_fifo_len = 0;
40
+ __func__, offset, value);
27
s->tx_fifo_len = 0;
41
break;
28
s->im = 0;
42
}
29
@@ -XXX,XX +XXX,XX @@ static int pl022_init(SysBusDevice *sbd)
30
sysbus_init_mmio(sbd, &s->iomem);
31
sysbus_init_irq(sbd, &s->irq);
32
s->ssi = ssi_create_bus(dev, "ssi");
33
- pl022_reset(s);
34
vmstate_register(dev, -1, &vmstate_pl022, s);
35
return 0;
36
}
43
}
37
@@ -XXX,XX +XXX,XX @@ static int pl022_init(SysBusDevice *sbd)
38
static void pl022_class_init(ObjectClass *klass, void *data)
39
{
40
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
41
+ DeviceClass *dc = DEVICE_CLASS(klass);
42
43
sdc->init = pl022_init;
44
+ dc->reset = pl022_reset;
45
}
46
47
static const TypeInfo pl022_info = {
48
--
44
--
49
2.18.0
45
2.20.1
50
46
51
47
diff view generated by jsdifflib
1
Move from the legacy SysBusDevice::init method to using
1
It is the responsibility of board code for an armv7m system to set
2
DeviceState::realize.
2
system_clock_scale appropriately for the CPU speed of the core.
3
If it forgets to do this, then QEMU will hang if the guest tries
4
to use the systick timer in the "tick at the CPU clock frequency" mode.
5
6
We forgot that in a couple of our boards (see commits ce4f70e81ed23c93f,
7
e7e5a9595ab1136). Add an assertion in the systick reset method so
8
we don't let any new boards in with the same bug.
3
9
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20180820141116.9118-19-peter.maydell@linaro.org
12
Message-id: 20200825160847.18091-1-peter.maydell@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
13
---
9
hw/ssi/pl022.c | 8 +++-----
14
hw/timer/armv7m_systick.c | 8 ++++++++
10
1 file changed, 3 insertions(+), 5 deletions(-)
15
1 file changed, 8 insertions(+)
11
16
12
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
17
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/ssi/pl022.c
19
--- a/hw/timer/armv7m_systick.c
15
+++ b/hw/ssi/pl022.c
20
+++ b/hw/timer/armv7m_systick.c
16
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl022 = {
21
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
17
}
18
};
19
20
-static int pl022_init(SysBusDevice *sbd)
21
+static void pl022_realize(DeviceState *dev, Error **errp)
22
{
22
{
23
- DeviceState *dev = DEVICE(sbd);
23
SysTickState *s = SYSTICK(dev);
24
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
24
25
PL022State *s = PL022(dev);
25
+ /*
26
26
+ * Forgetting to set system_clock_scale is always a board code
27
memory_region_init_io(&s->iomem, OBJECT(s), &pl022_ops, s, "pl022", 0x1000);
27
+ * bug. We can't check this earlier because for some boards
28
sysbus_init_mmio(sbd, &s->iomem);
28
+ * (like stellaris) it is not yet configured at the point where
29
sysbus_init_irq(sbd, &s->irq);
29
+ * the systick device is realized.
30
s->ssi = ssi_create_bus(dev, "ssi");
30
+ */
31
- return 0;
31
+ assert(system_clock_scale != 0);
32
}
32
+
33
33
s->control = 0;
34
static void pl022_class_init(ObjectClass *klass, void *data)
34
s->reload = 0;
35
{
35
s->tick = 0;
36
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
37
DeviceClass *dc = DEVICE_CLASS(klass);
38
39
- sdc->init = pl022_init;
40
dc->reset = pl022_reset;
41
dc->vmsd = &vmstate_pl022;
42
+ dc->realize = pl022_realize;
43
}
44
45
static const TypeInfo pl022_info = {
46
--
36
--
47
2.18.0
37
2.20.1
48
38
49
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Only argument set members have to be C identifiers, everything
4
else gets prefixed during conversion to C. Some places just
5
checked the leading character, and some places matched a leading
6
character plus a C identifier.
7
8
Convert everything to match full identifiers, including the
9
[&%@&] prefix, and drop the full C identifier requirement.
10
11
Reported-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180814002653.12828-4-richard.henderson@linaro.org
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20200903192334.1603773-1-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
16
---
8
target/arm/helper.c | 29 +++++------------------------
17
tests/decode/succ_ident1.decode | 7 +++++
9
1 file changed, 5 insertions(+), 24 deletions(-)
18
scripts/decodetree.py | 46 +++++++++++++++++++++------------
19
2 files changed, 37 insertions(+), 16 deletions(-)
20
create mode 100644 tests/decode/succ_ident1.decode
10
21
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/tests/decode/succ_ident1.decode b/tests/decode/succ_ident1.decode
23
new file mode 100644
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/tests/decode/succ_ident1.decode
27
@@ -XXX,XX +XXX,XX @@
28
+%1f 0:8
29
+%2f 8:8
30
+%3f 16:8
31
+
32
+&3arg a b c
33
+@3arg ........ ........ ........ ........ &3arg a=%1f b=%2f c=%3f
34
+3insn 00000000 ........ ........ ........ @3arg
35
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
12
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
37
--- a/scripts/decodetree.py
14
+++ b/target/arm/helper.c
38
+++ b/scripts/decodetree.py
15
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
39
@@ -XXX,XX +XXX,XX @@ output_fd = None
16
#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
40
insntype = 'uint32_t'
17
float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
41
decode_function = 'decode'
18
void *fpstp) \
42
19
-{ \
43
-re_ident = '[a-zA-Z][a-zA-Z0-9_]*'
20
- float_status *fpst = fpstp; \
44
+# An identifier for C.
21
- float##fsz tmp; \
45
+re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*'
22
- tmp = itype##_to_##float##fsz(x, fpst); \
46
23
- return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
47
+# Identifiers for Arguments, Fields, Formats and Patterns.
24
-}
48
+re_arg_ident = '&[a-zA-Z0-9_]*'
25
+{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
49
+re_fld_ident = '%[a-zA-Z0-9_]*'
26
50
+re_fmt_ident = '@[a-zA-Z0-9_]*'
27
/* Notice that we want only input-denormal exception flags from the
51
+re_pat_ident = '[a-zA-Z0-9_]*'
28
* scalbn operation: the other possible flags (overflow+inexact if
52
29
@@ -XXX,XX +XXX,XX @@ VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
53
def error_with_file(file, lineno, *args):
30
#undef VFP_CONV_FLOAT_FIX_ROUND
54
"""Print an error message from file:line and args and exit."""
31
#undef VFP_CONV_FIX_A64
55
@@ -XXX,XX +XXX,XX @@ class ExcMultiPattern(MultiPattern):
32
56
def parse_field(lineno, name, toks):
33
-/* Conversion to/from f16 can overflow to infinity before/after scaling.
57
"""Parse one instruction field from TOKS at LINENO"""
34
- * Therefore we convert to f64, scale, and then convert f64 to f16; or
58
global fields
35
- * vice versa for conversion to integer.
59
- global re_ident
36
- *
60
global insnwidth
37
- * For 16- and 32-bit integers, the conversion to f64 never rounds.
61
38
- * For 64-bit integers, any integer that would cause rounding will also
62
# A "simple" field will have only one entry;
39
- * overflow to f16 infinity, so there is no double rounding problem.
63
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
40
- */
64
width = 0
41
-
65
func = None
42
-static float16 do_postscale_fp16(float64 f, int shift, float_status *fpst)
66
for t in toks:
43
-{
67
- if re.fullmatch('!function=' + re_ident, t):
44
- return float64_to_float16(float64_scalbn(f, -shift, fpst), true, fpst);
68
+ if re.match('^!function=', t):
45
-}
69
if func:
46
-
70
error(lineno, 'duplicate function')
47
uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
71
func = t.split('=')
48
{
72
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
49
- return do_postscale_fp16(int32_to_float64(x, fpst), shift, fpst);
73
def parse_arguments(lineno, name, toks):
50
+ return int32_to_float16_scalbn(x, -shift, fpst);
74
"""Parse one argument set from TOKS at LINENO"""
51
}
75
global arguments
52
76
- global re_ident
53
uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
77
+ global re_C_ident
54
{
78
global anyextern
55
- return do_postscale_fp16(uint32_to_float64(x, fpst), shift, fpst);
79
56
+ return uint32_to_float16_scalbn(x, -shift, fpst);
80
flds = []
57
}
81
@@ -XXX,XX +XXX,XX @@ def parse_arguments(lineno, name, toks):
58
82
extern = True
59
uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
83
anyextern = True
60
{
84
continue
61
- return do_postscale_fp16(int64_to_float64(x, fpst), shift, fpst);
85
- if not re.fullmatch(re_ident, t):
62
+ return int64_to_float16_scalbn(x, -shift, fpst);
86
+ if not re.fullmatch(re_C_ident, t):
63
}
87
error(lineno, 'invalid argument set token "{0}"'.format(t))
64
88
if t in flds:
65
uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
89
error(lineno, 'duplicate argument "{0}"'.format(t))
66
{
90
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
67
- return do_postscale_fp16(uint64_to_float64(x, fpst), shift, fpst);
91
global arguments
68
+ return uint64_to_float16_scalbn(x, -shift, fpst);
92
global formats
69
}
93
global allpatterns
70
94
- global re_ident
71
static float64 do_prescale_fp16(float16 f, int shift, float_status *fpst)
95
+ global re_arg_ident
96
+ global re_fld_ident
97
+ global re_fmt_ident
98
+ global re_C_ident
99
global insnwidth
100
global insnmask
101
global variablewidth
102
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
103
fmt = None
104
for t in toks:
105
# '&Foo' gives a format an explcit argument set.
106
- if t[0] == '&':
107
+ if re.fullmatch(re_arg_ident, t):
108
tt = t[1:]
109
if arg:
110
error(lineno, 'multiple argument sets')
111
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
112
continue
113
114
# '@Foo' gives a pattern an explicit format.
115
- if t[0] == '@':
116
+ if re.fullmatch(re_fmt_ident, t):
117
tt = t[1:]
118
if fmt:
119
error(lineno, 'multiple formats')
120
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
121
continue
122
123
# '%Foo' imports a field.
124
- if t[0] == '%':
125
+ if re.fullmatch(re_fld_ident, t):
126
tt = t[1:]
127
flds = add_field_byname(lineno, flds, tt, tt)
128
continue
129
130
# 'Foo=%Bar' imports a field with a different name.
131
- if re.fullmatch(re_ident + '=%' + re_ident, t):
132
+ if re.fullmatch(re_C_ident + '=' + re_fld_ident, t):
133
(fname, iname) = t.split('=%')
134
flds = add_field_byname(lineno, flds, fname, iname)
135
continue
136
137
# 'Foo=number' sets an argument field to a constant value
138
- if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
139
+ if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t):
140
(fname, value) = t.split('=')
141
value = int(value)
142
flds = add_field(lineno, flds, fname, ConstField(value))
143
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
144
fixedmask = (fixedmask << shift) | fms
145
undefmask = (undefmask << shift) | ubm
146
# Otherwise, fieldname:fieldwidth
147
- elif re.fullmatch(re_ident + ':s?[0-9]+', t):
148
+ elif re.fullmatch(re_C_ident + ':s?[0-9]+', t):
149
(fname, flen) = t.split(':')
150
sign = False
151
if flen[0] == 's':
152
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
153
154
def parse_file(f, parent_pat):
155
"""Parse all of the patterns within a file"""
156
+ global re_arg_ident
157
+ global re_fld_ident
158
+ global re_fmt_ident
159
+ global re_pat_ident
160
161
# Read all of the lines of the file. Concatenate lines
162
# ending in backslash; discard empty lines and comments.
163
@@ -XXX,XX +XXX,XX @@ def parse_file(f, parent_pat):
164
continue
165
166
# Determine the type of object needing to be parsed.
167
- if name[0] == '%':
168
+ if re.fullmatch(re_fld_ident, name):
169
parse_field(start_lineno, name[1:], toks)
170
- elif name[0] == '&':
171
+ elif re.fullmatch(re_arg_ident, name):
172
parse_arguments(start_lineno, name[1:], toks)
173
- elif name[0] == '@':
174
+ elif re.fullmatch(re_fmt_ident, name):
175
parse_generic(start_lineno, None, name[1:], toks)
176
- else:
177
+ elif re.fullmatch(re_pat_ident, name):
178
parse_generic(start_lineno, parent_pat, name, toks)
179
+ else:
180
+ error(lineno, 'invalid token "{0}"'.format(name))
181
toks = []
182
183
if nesting != 0:
72
--
184
--
73
2.18.0
185
2.20.1
74
186
75
187
diff view generated by jsdifflib
1
The raspi framebuffir in bcm2835_fb supports the definition
1
In the Neon instructions, some instruction formats have a 2-bit size
2
of a virtual "viewport", which is smaller than the full
2
field which corresponds exactly to QEMU's MO_8/16/32/64. However the
3
physical framebuffer size and at an adjustable offset within
3
floating-point insns in the 3-same group have a 1-bit size field
4
it. Only the viewport area is sent to the screen. This allows
4
which is "0 for 32-bit float and 1 for 16-bit float". Currently we
5
the guest to do things like double buffering, or scrolling
5
pass these values directly through to trans_ functions, which means
6
by adjusting the viewport origin. Currently QEMU doesn't
6
that when reading a particular trans_ function you need to know if
7
implement this at all.
7
that insn uses a 2-bit size or a 1-bit size.
8
8
9
Add support for this feature:
9
Move the handling of the 1-bit size to the decodetree file, so that
10
* the property mailbox code needs to distinguish the
10
all these insns consistently pass a size to the trans_ function which
11
virtual width/height from the physical width/height
11
is an MO_8/16/32/64 value.
12
* the framebuffer code needs to do something with the
13
virtual width/height/origin information
14
12
15
Note that the wiki documentation on the semantics of the
13
In this commit we switch over the insns using the 3same_fp and
16
virtual and physical height and width has it the wrong way
14
3same_fp_q0 formats.
17
around -- the virtual size is the size of the allocated
18
buffer, and the physical size is the size of the display,
19
so the virtual size is always the same as or larger than
20
the physical.
21
22
If the viewport size is set smaller than the physical
23
screen size, we ignore the viewport settings completely
24
and just display the physical screen area.
25
15
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20180814144436.679-7-peter.maydell@linaro.org
18
Message-id: 20200903133209.5141-2-peter.maydell@linaro.org
29
---
19
---
30
include/hw/display/bcm2835_fb.h | 6 ++++--
20
target/arm/neon-dp.decode | 15 ++++++++++-----
31
hw/display/bcm2835_fb.c | 28 ++++++++++++++++++++++------
21
target/arm/translate-neon.c.inc | 16 +++++++++++-----
32
hw/misc/bcm2835_property.c | 21 +++++++++++++++------
22
2 files changed, 21 insertions(+), 10 deletions(-)
33
3 files changed, 41 insertions(+), 14 deletions(-)
34
23
35
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
24
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
36
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/display/bcm2835_fb.h
26
--- a/target/arm/neon-dp.decode
38
+++ b/include/hw/display/bcm2835_fb.h
27
+++ b/target/arm/neon-dp.decode
39
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
28
@@ -XXX,XX +XXX,XX @@
40
*/
29
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
41
static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
30
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
42
{
31
43
- return config->xres * (config->bpp >> 3);
32
-# For FP insns the high bit of 'size' is used as part of opcode decode
44
+ uint32_t xres = MAX(config->xres, config->xres_virtual);
33
-@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
45
+ return xres * (config->bpp >> 3);
34
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
35
-@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
36
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
37
+# For FP insns the high bit of 'size' is used as part of opcode decode,
38
+# and the 'size' bit is 0 for 32-bit float and 1 for 16-bit float.
39
+# This converts this encoding to the same MO_8/16/32/64 values that the
40
+# integer neon insns use.
41
+%3same_fp_size 20:1 !function=neon_3same_fp_size
42
+
43
+@3same_fp .... ... . . . . . .... .... .... . q:1 . . .... \
44
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%3same_fp_size
45
+@3same_fp_q0 .... ... . . . . . .... .... .... . 0 . . .... \
46
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 size=%3same_fp_size
47
48
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
49
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
50
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-neon.c.inc
53
+++ b/target/arm/translate-neon.c.inc
54
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
55
return 8 - x;
46
}
56
}
47
57
48
/**
58
+static inline int neon_3same_fp_size(DisasContext *s, int x)
49
@@ -XXX,XX +XXX,XX @@ static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
50
*/
51
static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
52
{
53
- return config->yres * bcm2835_fb_get_pitch(config);
54
+ uint32_t yres = MAX(config->yres, config->yres_virtual);
55
+ return yres * bcm2835_fb_get_pitch(config);
56
}
57
58
#endif
59
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/display/bcm2835_fb.c
62
+++ b/hw/display/bcm2835_fb.c
63
@@ -XXX,XX +XXX,XX @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
64
}
65
}
66
67
+static bool fb_use_offsets(BCM2835FBConfig *config)
68
+{
59
+{
69
+ /*
60
+ /* Convert 0==fp32, 1==fp16 into a MO_* value */
70
+ * Return true if we should use the viewport offsets.
61
+ return MO_32 - x;
71
+ * Experimentally, the hardware seems to do this only if the
72
+ * viewport size is larger than the physical screen. (It doesn't
73
+ * prevent the guest setting this silly viewport setting, though...)
74
+ */
75
+ return config->xres_virtual > config->xres &&
76
+ config->yres_virtual > config->yres;
77
+}
62
+}
78
+
63
+
79
static void fb_update_display(void *opaque)
64
/* Include the generated Neon decoder */
80
{
65
#include "decode-neon-dp.c.inc"
81
BCM2835FBState *s = opaque;
66
#include "decode-neon-ls.c.inc"
82
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
67
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
83
int last = 0;
68
WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \
84
int src_width = 0;
69
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
85
int dest_width = 0;
70
{ \
86
+ uint32_t xoff = 0, yoff = 0;
71
- if (a->size != 0) { \
87
72
+ if (a->size == MO_16) { \
88
if (s->lock || !s->config.xres) {
73
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
89
return;
74
return false; \
75
} \
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
77
return false;
90
}
78
}
91
79
92
src_width = bcm2835_fb_get_pitch(&s->config);
80
- if (a->size != 0) {
93
+ if (fb_use_offsets(&s->config)) {
81
+ if (a->size == MO_16) {
94
+ xoff = s->config.xoffset;
82
if (!dc_isar_feature(aa32_fp16_arith, s)) {
95
+ yoff = s->config.yoffset;
83
return false;
96
+ }
84
}
97
+
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
98
dest_width = s->config.xres;
86
return false;
99
100
switch (surface_bits_per_pixel(surface)) {
101
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
102
}
87
}
103
88
104
if (s->invalidate) {
89
- if (a->size != 0) {
105
+ hwaddr base = s->config.base + xoff + yoff * src_width;
90
+ if (a->size == MO_16) {
106
framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
91
if (!dc_isar_feature(aa32_fp16_arith, s)) {
107
- s->config.base,
92
return false;
108
+ base,
93
}
109
s->config.yres, src_width);
94
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
110
}
95
assert(a->q == 0); /* enforced by decode patterns */
111
96
112
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
97
113
draw_line_src16, s, &first, &last);
98
- fpstatus = fpstatus_ptr(a->size != 0 ? FPST_STD_F16 : FPST_STD);
114
99
+ fpstatus = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
115
if (first >= 0) {
100
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
116
- dpy_gfx_update(s->con, 0, first, s->config.xres, last - first + 1);
101
vfp_reg_offset(1, a->vn),
117
+ dpy_gfx_update(s->con, 0, first, s->config.xres,
102
vfp_reg_offset(1, a->vm),
118
+ last - first + 1);
103
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
119
}
104
#define DO_3S_FP_PAIR(INSN,FUNC) \
120
105
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
121
s->invalidate = false;
106
{ \
122
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
107
- if (a->size != 0) { \
123
s->config.base = s->vcram_base | (value & 0xc0000000);
108
+ if (a->size == MO_16) { \
124
s->config.base += BCM2835_FB_OFFSET;
109
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
125
110
return false; \
126
- /* TODO - Manage properly virtual resolution */
111
} \
127
-
128
pitch = bcm2835_fb_get_pitch(&s->config);
129
size = bcm2835_fb_get_size(&s->config);
130
131
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
132
133
s->config = *newconfig;
134
135
- /* TODO - Manage properly virtual resolution */
136
-
137
s->invalidate = true;
138
qemu_console_resize(s->con, s->config.xres, s->config.yres);
139
s->lock = false;
140
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/hw/misc/bcm2835_property.c
143
+++ b/hw/misc/bcm2835_property.c
144
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
145
case 0x00040002: /* Blank screen */
146
resplen = 4;
147
break;
148
- case 0x00040003: /* Get display width/height */
149
- case 0x00040004:
150
+ case 0x00040003: /* Get physical display width/height */
151
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
152
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
153
resplen = 8;
154
break;
155
- case 0x00044003: /* Test display width/height */
156
- case 0x00044004:
157
+ case 0x00040004: /* Get virtual display width/height */
158
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
159
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
160
resplen = 8;
161
break;
162
- case 0x00048003: /* Set display width/height */
163
- case 0x00048004:
164
+ case 0x00044003: /* Test physical display width/height */
165
+ case 0x00044004: /* Test virtual display width/height */
166
+ resplen = 8;
167
+ break;
168
+ case 0x00048003: /* Set physical display width/height */
169
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
170
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
171
fbconfig_updated = true;
172
resplen = 8;
173
break;
174
+ case 0x00048004: /* Set virtual display width/height */
175
+ fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
176
+ fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
177
+ fbconfig_updated = true;
178
+ resplen = 8;
179
+ break;
180
case 0x00040005: /* Get depth */
181
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
182
resplen = 4;
183
--
112
--
184
2.18.0
113
2.20.1
185
114
186
115
diff view generated by jsdifflib
1
Refactor the fb property setting code so that rather than
1
Convert the insns using the 2reg_vcvt and 2reg_vcvt_f16 formats
2
using a set of pointers to local variables to track
2
to pass the size through to the trans function as a MO_* value
3
whether a config value has been updated in the current
3
rather than the '0==f32, 1==f16' used in the fp 3-same encodings.
4
mbox and if so what its new value is, we just copy
5
all the current settings of the fb at the start, and
6
then update that copy as we go along, before asking
7
the fb to switch to it at the end.
8
4
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180814144436.679-3-peter.maydell@linaro.org
7
Message-id: 20200903133209.5141-3-peter.maydell@linaro.org
12
---
8
---
13
include/hw/display/bcm2835_fb.h | 4 +-
9
target/arm/neon-dp.decode | 3 +--
14
hw/display/bcm2835_fb.c | 27 ++---------
10
target/arm/translate-neon.c.inc | 4 ++--
15
hw/misc/bcm2835_property.c | 80 ++++++++++++++-------------------
11
2 files changed, 3 insertions(+), 4 deletions(-)
16
3 files changed, 37 insertions(+), 74 deletions(-)
17
12
18
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/display/bcm2835_fb.h
15
--- a/target/arm/neon-dp.decode
21
+++ b/include/hw/display/bcm2835_fb.h
16
+++ b/target/arm/neon-dp.decode
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
23
uint32_t pitch;
18
@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
24
} BCM2835FBState;
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
25
20
26
-void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
21
-# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
27
- uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
22
@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
28
- uint32_t *pixo, uint32_t *alpha);
23
- &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
29
+void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
24
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
30
25
@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \
31
#endif
26
&2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
32
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
27
28
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
33
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/display/bcm2835_fb.c
30
--- a/target/arm/translate-neon.c.inc
35
+++ b/hw/display/bcm2835_fb.c
31
+++ b/target/arm/translate-neon.c.inc
36
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
32
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
37
s->lock = false;
33
return false;
38
}
39
40
-void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
41
- uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
42
- uint32_t *pixo, uint32_t *alpha)
43
+void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
44
{
45
s->lock = true;
46
47
/* TODO: input validation! */
48
- if (xres) {
49
- s->config.xres = *xres;
50
- }
51
- if (yres) {
52
- s->config.yres = *yres;
53
- }
54
- if (xoffset) {
55
- s->config.xoffset = *xoffset;
56
- }
57
- if (yoffset) {
58
- s->config.yoffset = *yoffset;
59
- }
60
- if (bpp) {
61
- s->config.bpp = *bpp;
62
- }
63
- if (pixo) {
64
- s->config.pixo = *pixo;
65
- }
66
- if (alpha) {
67
- s->config.alpha = *alpha;
68
- }
69
+
70
+ s->config = *newconfig;
71
72
/* TODO - Manage properly virtual resolution */
73
74
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/hw/misc/bcm2835_property.c
77
+++ b/hw/misc/bcm2835_property.c
78
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
79
uint32_t tmp;
80
int n;
81
uint32_t offset, length, color;
82
- uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha;
83
- uint32_t tmp_xres, tmp_yres, tmp_xoffset, tmp_yoffset;
84
- uint32_t tmp_bpp, tmp_pixo, tmp_alpha;
85
- uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL,
86
- *newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL;
87
+
88
+ /*
89
+ * Copy the current state of the framebuffer config; we will update
90
+ * this copy as we process tags and then ask the framebuffer to use
91
+ * it at the end.
92
+ */
93
+ BCM2835FBConfig fbconfig = s->fbdev->config;
94
+ bool fbconfig_updated = false;
95
96
value &= ~0xf;
97
98
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
99
/* Frame buffer */
100
101
case 0x00040001: /* Allocate buffer */
102
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->config.base);
103
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
104
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
105
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
106
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
107
stl_le_phys(&s->dma_as, value + 16,
108
- tmp_xres * tmp_yres * tmp_bpp / 8);
109
+ fbconfig.xres * fbconfig.yres * fbconfig.bpp / 8);
110
resplen = 8;
111
break;
112
case 0x00048001: /* Release buffer */
113
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
114
break;
115
case 0x00040003: /* Get display width/height */
116
case 0x00040004:
117
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
118
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
119
- stl_le_phys(&s->dma_as, value + 12, tmp_xres);
120
- stl_le_phys(&s->dma_as, value + 16, tmp_yres);
121
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
122
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
123
resplen = 8;
124
break;
125
case 0x00044003: /* Test display width/height */
126
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
127
break;
128
case 0x00048003: /* Set display width/height */
129
case 0x00048004:
130
- xres = ldl_le_phys(&s->dma_as, value + 12);
131
- newxres = &xres;
132
- yres = ldl_le_phys(&s->dma_as, value + 16);
133
- newyres = &yres;
134
+ fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
135
+ fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
136
+ fbconfig_updated = true;
137
resplen = 8;
138
break;
139
case 0x00040005: /* Get depth */
140
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
141
- stl_le_phys(&s->dma_as, value + 12, tmp_bpp);
142
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
143
resplen = 4;
144
break;
145
case 0x00044005: /* Test depth */
146
resplen = 4;
147
break;
148
case 0x00048005: /* Set depth */
149
- bpp = ldl_le_phys(&s->dma_as, value + 12);
150
- newbpp = &bpp;
151
+ fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
152
+ fbconfig_updated = true;
153
resplen = 4;
154
break;
155
case 0x00040006: /* Get pixel order */
156
- tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->config.pixo;
157
- stl_le_phys(&s->dma_as, value + 12, tmp_pixo);
158
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
159
resplen = 4;
160
break;
161
case 0x00044006: /* Test pixel order */
162
resplen = 4;
163
break;
164
case 0x00048006: /* Set pixel order */
165
- pixo = ldl_le_phys(&s->dma_as, value + 12);
166
- newpixo = &pixo;
167
+ fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
168
+ fbconfig_updated = true;
169
resplen = 4;
170
break;
171
case 0x00040007: /* Get alpha */
172
- tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->config.alpha;
173
- stl_le_phys(&s->dma_as, value + 12, tmp_alpha);
174
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
175
resplen = 4;
176
break;
177
case 0x00044007: /* Test pixel alpha */
178
resplen = 4;
179
break;
180
case 0x00048007: /* Set alpha */
181
- alpha = ldl_le_phys(&s->dma_as, value + 12);
182
- newalpha = &alpha;
183
+ fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
184
+ fbconfig_updated = true;
185
resplen = 4;
186
break;
187
case 0x00040008: /* Get pitch */
188
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
189
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
190
- stl_le_phys(&s->dma_as, value + 12, tmp_xres * tmp_bpp / 8);
191
+ stl_le_phys(&s->dma_as, value + 12,
192
+ fbconfig.xres * fbconfig.bpp / 8);
193
resplen = 4;
194
break;
195
case 0x00040009: /* Get virtual offset */
196
- tmp_xoffset = newxoffset != NULL ?
197
- *newxoffset : s->fbdev->config.xoffset;
198
- tmp_yoffset = newyoffset != NULL ?
199
- *newyoffset : s->fbdev->config.yoffset;
200
- stl_le_phys(&s->dma_as, value + 12, tmp_xoffset);
201
- stl_le_phys(&s->dma_as, value + 16, tmp_yoffset);
202
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
203
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
204
resplen = 8;
205
break;
206
case 0x00044009: /* Test virtual offset */
207
resplen = 8;
208
break;
209
case 0x00048009: /* Set virtual offset */
210
- xoffset = ldl_le_phys(&s->dma_as, value + 12);
211
- newxoffset = &xoffset;
212
- yoffset = ldl_le_phys(&s->dma_as, value + 16);
213
- newyoffset = &yoffset;
214
+ fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
215
+ fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
216
+ fbconfig_updated = true;
217
resplen = 8;
218
break;
219
case 0x0004000a: /* Get/Test/Set overscan */
220
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
221
}
34
}
222
35
223
/* Reconfigure framebuffer if required */
36
- if (a->size != 0) {
224
- if (newxres || newyres || newxoffset || newyoffset || newbpp || newpixo
37
+ if (a->size == MO_16) {
225
- || newalpha) {
38
if (!dc_isar_feature(aa32_fp16_arith, s)) {
226
- bcm2835_fb_reconfigure(s->fbdev, newxres, newyres, newxoffset,
39
return false;
227
- newyoffset, newbpp, newpixo, newalpha);
40
}
228
+ if (fbconfig_updated) {
41
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
229
+ bcm2835_fb_reconfigure(s->fbdev, &fbconfig);
42
return true;
230
}
43
}
231
44
232
/* Buffer response code */
45
- fpst = fpstatus_ptr(a->size ? FPST_STD_F16 : FPST_STD);
46
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
47
tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
48
tcg_temp_free_ptr(fpst);
49
return true;
233
--
50
--
234
2.18.0
51
2.20.1
235
52
236
53
diff view generated by jsdifflib
1
The handling of framebuffer properties in the bcm2835_property code
1
The VCMLA and VCADD insns have a size field which is 0 for fp16
2
is a bit clumsy, because for each of the many fb related properties
2
and 1 for fp32 (note that this is the reverse of the Neon 3-same
3
we try to track the value we're about to set and whether we're going
3
encoding!). Convert it to MO_* values in decode for consistency.
4
to be setting a value, and then we hand all the new values off
5
to the framebuffer via a function which takes them all as separate
6
arguments. It would be simpler if the property code could easily
7
copy all the framebuffer's current settings, update them with
8
the new specified values and then ask the framebuffer to switch
9
to the new set.
10
11
As the first part of this refactoring, pull all the fb config
12
settings fields in BCM2835FBState out into their own struct.
13
4
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20180814144436.679-2-peter.maydell@linaro.org
7
Message-id: 20200903133209.5141-4-peter.maydell@linaro.org
17
---
8
---
18
include/hw/display/bcm2835_fb.h | 26 ++++++--
9
target/arm/neon-shared.decode | 18 ++++++++++++------
19
hw/display/bcm2835_fb.c | 114 +++++++++++++++++---------------
10
target/arm/translate-neon.c.inc | 22 ++++++++++++----------
20
hw/misc/bcm2835_property.c | 28 ++++----
11
2 files changed, 24 insertions(+), 16 deletions(-)
21
3 files changed, 94 insertions(+), 74 deletions(-)
22
12
23
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
13
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/display/bcm2835_fb.h
15
--- a/target/arm/neon-shared.decode
26
+++ b/include/hw/display/bcm2835_fb.h
16
+++ b/target/arm/neon-shared.decode
27
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
28
#define TYPE_BCM2835_FB "bcm2835-fb"
18
%vd_dp 22:1 12:4
29
#define BCM2835_FB(obj) OBJECT_CHECK(BCM2835FBState, (obj), TYPE_BCM2835_FB)
19
%vd_sp 12:4 22:1
30
20
31
+/*
21
-VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
32
+ * Configuration information about the fb which the guest can program
22
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
33
+ * via the mailbox property interface.
23
+# For VCMLA/VCADD insns, convert the single-bit size field
34
+ */
24
+# which is 0 for fp16 and 1 for fp32 into a MO_* constant.
35
+typedef struct {
25
+# (Note that this is the reverse of the sense of the 1-bit size
36
+ uint32_t xres, yres;
26
+# field in the 3same_fp Neon insns.)
37
+ uint32_t xres_virtual, yres_virtual;
27
+%vcadd_size 20:1 !function=plus1
38
+ uint32_t xoffset, yoffset;
28
39
+ uint32_t bpp;
29
-VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
40
+ uint32_t base;
30
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
41
+ uint32_t pixo;
31
+VCMLA 1111 110 rot:2 . 1 . .... .... 1000 . q:1 . 0 .... \
42
+ uint32_t alpha;
32
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
43
+} BCM2835FBConfig;
44
+
33
+
45
typedef struct {
34
+VCADD 1111 110 rot:1 1 . 0 . .... .... 1000 . q:1 . 0 .... \
46
/*< private >*/
35
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
47
SysBusDevice busdev;
36
48
@@ -XXX,XX +XXX,XX @@ typedef struct {
37
# VUDOT and VSDOT
49
qemu_irq mbox_irq;
38
VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \
50
39
@@ -XXX,XX +XXX,XX @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \
51
bool lock, invalidate, pending;
40
vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1
52
- uint32_t xres, yres;
41
53
- uint32_t xres_virtual, yres_virtual;
42
VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
54
- uint32_t xoffset, yoffset;
43
- vn=%vn_dp vd=%vd_dp size=0
55
- uint32_t bpp;
44
+ vn=%vn_dp vd=%vd_dp size=1
56
- uint32_t base, pitch, size;
45
VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
57
- uint32_t pixo, alpha;
46
- vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0
58
+
47
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=2 index=0
59
+ BCM2835FBConfig config;
48
60
+
49
VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \
61
+ /* These are just cached values calculated from the config settings */
50
vm=%vm_dp vn=%vn_dp vd=%vd_dp
62
+ uint32_t size;
51
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
63
+ uint32_t pitch;
64
} BCM2835FBState;
65
66
void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
67
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
68
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/display/bcm2835_fb.c
53
--- a/target/arm/translate-neon.c.inc
70
+++ b/hw/display/bcm2835_fb.c
54
+++ b/target/arm/translate-neon.c.inc
71
@@ -XXX,XX +XXX,XX @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
72
int bpp = surface_bits_per_pixel(surface);
56
gen_helper_gvec_3_ptr *fn_gvec_ptr;
73
57
74
while (width--) {
58
if (!dc_isar_feature(aa32_vcma, s)
75
- switch (s->bpp) {
59
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
76
+ switch (s->config.bpp) {
60
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
77
case 8:
61
return false;
78
/* lookup palette starting at video ram base
79
* TODO: cache translation, rather than doing this each time!
80
@@ -XXX,XX +XXX,XX @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
81
break;
82
}
83
84
- if (s->pixo == 0) {
85
+ if (s->config.pixo == 0) {
86
/* swap to BGR pixel format */
87
uint8_t tmp = r;
88
r = b;
89
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
90
int src_width = 0;
91
int dest_width = 0;
92
93
- if (s->lock || !s->xres) {
94
+ if (s->lock || !s->config.xres) {
95
return;
96
}
62
}
97
63
98
- src_width = s->xres * (s->bpp >> 3);
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
99
- dest_width = s->xres;
100
+ src_width = s->config.xres * (s->config.bpp >> 3);
101
+ dest_width = s->config.xres;
102
103
switch (surface_bits_per_pixel(surface)) {
104
case 0:
105
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
106
}
65
}
107
66
108
if (s->invalidate) {
67
opr_sz = (1 + a->q) * 8;
109
- framebuffer_update_memory_section(&s->fbsection, s->dma_mr, s->base,
68
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
110
- s->yres, src_width);
69
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
111
+ framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
70
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
112
+ s->config.base,
71
+ fn_gvec_ptr = (a->size == MO_16) ?
113
+ s->config.yres, src_width);
72
+ gen_helper_gvec_fcmlah : gen_helper_gvec_fcmlas;
73
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
74
vfp_reg_offset(1, a->vn),
75
vfp_reg_offset(1, a->vm),
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
77
gen_helper_gvec_3_ptr *fn_gvec_ptr;
78
79
if (!dc_isar_feature(aa32_vcma, s)
80
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
81
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
82
return false;
114
}
83
}
115
84
116
- framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
117
+ framebuffer_update_display(surface, &s->fbsection,
118
+ s->config.xres, s->config.yres,
119
src_width, dest_width, 0, s->invalidate,
120
draw_line_src16, s, &first, &last);
121
122
if (first >= 0) {
123
- dpy_gfx_update(s->con, 0, first, s->xres, last - first + 1);
124
+ dpy_gfx_update(s->con, 0, first, s->config.xres, last - first + 1);
125
}
86
}
126
87
127
s->invalidate = false;
88
opr_sz = (1 + a->q) * 8;
128
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
89
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
129
90
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
130
s->lock = true;
91
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
131
92
+ fn_gvec_ptr = (a->size == MO_16) ?
132
- s->xres = ldl_le_phys(&s->dma_as, value);
93
+ gen_helper_gvec_fcaddh : gen_helper_gvec_fcadds;
133
- s->yres = ldl_le_phys(&s->dma_as, value + 4);
94
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
134
- s->xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
95
vfp_reg_offset(1, a->vn),
135
- s->yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
96
vfp_reg_offset(1, a->vm),
136
- s->bpp = ldl_le_phys(&s->dma_as, value + 20);
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
137
- s->xoffset = ldl_le_phys(&s->dma_as, value + 24);
98
if (!dc_isar_feature(aa32_vcma, s)) {
138
- s->yoffset = ldl_le_phys(&s->dma_as, value + 28);
99
return false;
139
+ s->config.xres = ldl_le_phys(&s->dma_as, value);
140
+ s->config.yres = ldl_le_phys(&s->dma_as, value + 4);
141
+ s->config.xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
142
+ s->config.yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
143
+ s->config.bpp = ldl_le_phys(&s->dma_as, value + 20);
144
+ s->config.xoffset = ldl_le_phys(&s->dma_as, value + 24);
145
+ s->config.yoffset = ldl_le_phys(&s->dma_as, value + 28);
146
147
- s->base = s->vcram_base | (value & 0xc0000000);
148
- s->base += BCM2835_FB_OFFSET;
149
+ s->config.base = s->vcram_base | (value & 0xc0000000);
150
+ s->config.base += BCM2835_FB_OFFSET;
151
152
/* TODO - Manage properly virtual resolution */
153
154
- s->pitch = s->xres * (s->bpp >> 3);
155
- s->size = s->yres * s->pitch;
156
+ s->pitch = s->config.xres * (s->config.bpp >> 3);
157
+ s->size = s->config.yres * s->pitch;
158
159
stl_le_phys(&s->dma_as, value + 16, s->pitch);
160
- stl_le_phys(&s->dma_as, value + 32, s->base);
161
+ stl_le_phys(&s->dma_as, value + 32, s->config.base);
162
stl_le_phys(&s->dma_as, value + 36, s->size);
163
164
s->invalidate = true;
165
- qemu_console_resize(s->con, s->xres, s->yres);
166
+ qemu_console_resize(s->con, s->config.xres, s->config.yres);
167
s->lock = false;
168
}
169
170
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
171
172
/* TODO: input validation! */
173
if (xres) {
174
- s->xres = *xres;
175
+ s->config.xres = *xres;
176
}
100
}
177
if (yres) {
101
- if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) {
178
- s->yres = *yres;
102
+ if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) {
179
+ s->config.yres = *yres;
103
return false;
180
}
104
}
181
if (xoffset) {
105
182
- s->xoffset = *xoffset;
106
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
183
+ s->config.xoffset = *xoffset;
107
return true;
184
}
108
}
185
if (yoffset) {
109
186
- s->yoffset = *yoffset;
110
- fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
187
+ s->config.yoffset = *yoffset;
111
- : gen_helper_gvec_fcmlah_idx);
188
}
112
+ fn_gvec_ptr = (a->size == MO_16) ?
189
if (bpp) {
113
+ gen_helper_gvec_fcmlah_idx : gen_helper_gvec_fcmlas_idx;
190
- s->bpp = *bpp;
114
opr_sz = (1 + a->q) * 8;
191
+ s->config.bpp = *bpp;
115
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
192
}
116
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
193
if (pixo) {
117
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
194
- s->pixo = *pixo;
118
vfp_reg_offset(1, a->vn),
195
+ s->config.pixo = *pixo;
119
vfp_reg_offset(1, a->vm),
196
}
197
if (alpha) {
198
- s->alpha = *alpha;
199
+ s->config.alpha = *alpha;
200
}
201
202
/* TODO - Manage properly virtual resolution */
203
204
- s->pitch = s->xres * (s->bpp >> 3);
205
- s->size = s->yres * s->pitch;
206
+ s->pitch = s->config.xres * (s->config.bpp >> 3);
207
+ s->size = s->config.yres * s->pitch;
208
209
s->invalidate = true;
210
- qemu_console_resize(s->con, s->xres, s->yres);
211
+ qemu_console_resize(s->con, s->config.xres, s->config.yres);
212
s->lock = false;
213
}
214
215
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_bcm2835_fb = {
216
VMSTATE_BOOL(lock, BCM2835FBState),
217
VMSTATE_BOOL(invalidate, BCM2835FBState),
218
VMSTATE_BOOL(pending, BCM2835FBState),
219
- VMSTATE_UINT32(xres, BCM2835FBState),
220
- VMSTATE_UINT32(yres, BCM2835FBState),
221
- VMSTATE_UINT32(xres_virtual, BCM2835FBState),
222
- VMSTATE_UINT32(yres_virtual, BCM2835FBState),
223
- VMSTATE_UINT32(xoffset, BCM2835FBState),
224
- VMSTATE_UINT32(yoffset, BCM2835FBState),
225
- VMSTATE_UINT32(bpp, BCM2835FBState),
226
- VMSTATE_UINT32(base, BCM2835FBState),
227
+ VMSTATE_UINT32(config.xres, BCM2835FBState),
228
+ VMSTATE_UINT32(config.yres, BCM2835FBState),
229
+ VMSTATE_UINT32(config.xres_virtual, BCM2835FBState),
230
+ VMSTATE_UINT32(config.yres_virtual, BCM2835FBState),
231
+ VMSTATE_UINT32(config.xoffset, BCM2835FBState),
232
+ VMSTATE_UINT32(config.yoffset, BCM2835FBState),
233
+ VMSTATE_UINT32(config.bpp, BCM2835FBState),
234
+ VMSTATE_UINT32(config.base, BCM2835FBState),
235
VMSTATE_UINT32(pitch, BCM2835FBState),
236
VMSTATE_UINT32(size, BCM2835FBState),
237
- VMSTATE_UINT32(pixo, BCM2835FBState),
238
- VMSTATE_UINT32(alpha, BCM2835FBState),
239
+ VMSTATE_UINT32(config.pixo, BCM2835FBState),
240
+ VMSTATE_UINT32(config.alpha, BCM2835FBState),
241
VMSTATE_END_OF_LIST()
242
}
243
};
244
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_reset(DeviceState *dev)
245
246
s->pending = false;
247
248
- s->xres_virtual = s->xres;
249
- s->yres_virtual = s->yres;
250
- s->xoffset = 0;
251
- s->yoffset = 0;
252
- s->base = s->vcram_base + BCM2835_FB_OFFSET;
253
- s->pitch = s->xres * (s->bpp >> 3);
254
- s->size = s->yres * s->pitch;
255
+ s->config.xres_virtual = s->config.xres;
256
+ s->config.yres_virtual = s->config.yres;
257
+ s->config.xoffset = 0;
258
+ s->config.yoffset = 0;
259
+ s->config.base = s->vcram_base + BCM2835_FB_OFFSET;
260
+ s->pitch = s->config.xres * (s->config.bpp >> 3);
261
+ s->size = s->config.yres * s->pitch;
262
263
s->invalidate = true;
264
s->lock = false;
265
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_realize(DeviceState *dev, Error **errp)
266
bcm2835_fb_reset(dev);
267
268
s->con = graphic_console_init(dev, 0, &vgafb_ops, s);
269
- qemu_console_resize(s->con, s->xres, s->yres);
270
+ qemu_console_resize(s->con, s->config.xres, s->config.yres);
271
}
272
273
static Property bcm2835_fb_props[] = {
274
DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/
275
DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size,
276
DEFAULT_VCRAM_SIZE),
277
- DEFINE_PROP_UINT32("xres", BCM2835FBState, xres, 640),
278
- DEFINE_PROP_UINT32("yres", BCM2835FBState, yres, 480),
279
- DEFINE_PROP_UINT32("bpp", BCM2835FBState, bpp, 16),
280
- DEFINE_PROP_UINT32("pixo", BCM2835FBState, pixo, 1), /* 1=RGB, 0=BGR */
281
- DEFINE_PROP_UINT32("alpha", BCM2835FBState, alpha, 2), /* alpha ignored */
282
+ DEFINE_PROP_UINT32("xres", BCM2835FBState, config.xres, 640),
283
+ DEFINE_PROP_UINT32("yres", BCM2835FBState, config.yres, 480),
284
+ DEFINE_PROP_UINT32("bpp", BCM2835FBState, config.bpp, 16),
285
+ DEFINE_PROP_UINT32("pixo",
286
+ BCM2835FBState, config.pixo, 1), /* 1=RGB, 0=BGR */
287
+ DEFINE_PROP_UINT32("alpha",
288
+ BCM2835FBState, config.alpha, 2), /* alpha ignored */
289
DEFINE_PROP_END_OF_LIST()
290
};
291
292
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/hw/misc/bcm2835_property.c
295
+++ b/hw/misc/bcm2835_property.c
296
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
297
/* Frame buffer */
298
299
case 0x00040001: /* Allocate buffer */
300
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->base);
301
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
302
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
303
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
304
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->config.base);
305
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
306
+ tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
307
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
308
stl_le_phys(&s->dma_as, value + 16,
309
tmp_xres * tmp_yres * tmp_bpp / 8);
310
resplen = 8;
311
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
312
break;
313
case 0x00040003: /* Get display width/height */
314
case 0x00040004:
315
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
316
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
317
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
318
+ tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
319
stl_le_phys(&s->dma_as, value + 12, tmp_xres);
320
stl_le_phys(&s->dma_as, value + 16, tmp_yres);
321
resplen = 8;
322
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
323
resplen = 8;
324
break;
325
case 0x00040005: /* Get depth */
326
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
327
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
328
stl_le_phys(&s->dma_as, value + 12, tmp_bpp);
329
resplen = 4;
330
break;
331
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
332
resplen = 4;
333
break;
334
case 0x00040006: /* Get pixel order */
335
- tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->pixo;
336
+ tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->config.pixo;
337
stl_le_phys(&s->dma_as, value + 12, tmp_pixo);
338
resplen = 4;
339
break;
340
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
341
resplen = 4;
342
break;
343
case 0x00040007: /* Get alpha */
344
- tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->alpha;
345
+ tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->config.alpha;
346
stl_le_phys(&s->dma_as, value + 12, tmp_alpha);
347
resplen = 4;
348
break;
349
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
350
resplen = 4;
351
break;
352
case 0x00040008: /* Get pitch */
353
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
354
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
355
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
356
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
357
stl_le_phys(&s->dma_as, value + 12, tmp_xres * tmp_bpp / 8);
358
resplen = 4;
359
break;
360
case 0x00040009: /* Get virtual offset */
361
- tmp_xoffset = newxoffset != NULL ? *newxoffset : s->fbdev->xoffset;
362
- tmp_yoffset = newyoffset != NULL ? *newyoffset : s->fbdev->yoffset;
363
+ tmp_xoffset = newxoffset != NULL ?
364
+ *newxoffset : s->fbdev->config.xoffset;
365
+ tmp_yoffset = newyoffset != NULL ?
366
+ *newyoffset : s->fbdev->config.yoffset;
367
stl_le_phys(&s->dma_as, value + 12, tmp_xoffset);
368
stl_le_phys(&s->dma_as, value + 16, tmp_yoffset);
369
resplen = 8;
370
--
120
--
371
2.18.0
121
2.20.1
372
122
373
123
diff view generated by jsdifflib
1
Validate the config settings that the guest tries to set.
1
We deprecated the support for KVM on 32-bit Arm hosts in time
2
for release 5.0, which means that our deprecation policy allows
3
us to drop it in release 5.2. Remove the code.
2
4
3
The wiki page documentation is not really accurate here:
5
To repeat the rationale from the deprecation note: the Linux
4
generally rather than failing requests to set bad parameters,
6
kernel dropped support for 32-bit Arm KVM hosts in 5.7.
5
the hardware will just clip them to something sensible.
6
7
7
Validate the most important parameters: sizes and
8
Running 32-bit guests on a 64-bit Arm host remains supported.
8
the viewport offsets. This prevents the framebuffer
9
code from trying to read out-of-range memory.
10
11
In the property handling code, we validate the new parameters every
12
time we encounter a tag that sets them. This means we validate the
13
config multiple times if the request includes multiple config-setting
14
tags, but the code would require significant restructuring to do a
15
validation only once but still return the clipped settings for
16
get-parameter tags and the buffer allocation tag.
17
18
Validation of settings made via the older bcm2835_fb_mbox_push()
19
function will be done in the next commit.
20
9
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20180814144436.679-8-peter.maydell@linaro.org
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20200904154156.31943-2-peter.maydell@linaro.org
24
---
14
---
25
include/hw/display/bcm2835_fb.h | 8 +++++
15
docs/system/deprecated.rst | 16 +-
26
hw/display/bcm2835_fb.c | 48 +++++++++++++++++++++++++++--
16
configure | 2 +-
27
hw/misc/bcm2835_property.c | 54 ++++++++++++++++-----------------
17
target/arm/kvm32.c | 595 -------------------------------------
28
3 files changed, 81 insertions(+), 29 deletions(-)
18
target/arm/meson.build | 5 +-
19
4 files changed, 10 insertions(+), 608 deletions(-)
20
delete mode 100644 target/arm/kvm32.c
29
21
30
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
31
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/display/bcm2835_fb.h
24
--- a/docs/system/deprecated.rst
33
+++ b/include/hw/display/bcm2835_fb.h
25
+++ b/docs/system/deprecated.rst
34
@@ -XXX,XX +XXX,XX @@ static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
26
@@ -XXX,XX +XXX,XX @@ The ``compat`` property used to set backwards compatibility modes for
35
return yres * bcm2835_fb_get_pitch(config);
27
the processor has been deprecated. The ``max-cpu-compat`` property of
36
}
28
the ``pseries`` machine type should be used instead.
37
29
38
+/**
30
-KVM guest support on 32-bit Arm hosts (since 5.0)
39
+ * bcm2835_fb_validate_config: check provided config
31
-'''''''''''''''''''''''''''''''''''''''''''''''''
40
+ *
32
-
41
+ * Validates the configuration information provided by the guest and
33
-The Linux kernel has dropped support for allowing 32-bit Arm systems
42
+ * adjusts it if necessary.
34
-to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
43
+ */
35
-its support for this configuration and will remove it in a future version.
44
+void bcm2835_fb_validate_config(BCM2835FBConfig *config);
36
-Running 32-bit guests on a 64-bit Arm host remains supported.
37
-
38
System emulator devices
39
-----------------------
40
41
@@ -XXX,XX +XXX,XX @@ should be used instead of the 1.09.1 version.
42
System emulator CPUS
43
--------------------
44
45
+KVM guest support on 32-bit Arm hosts (removed in 5.2)
46
+''''''''''''''''''''''''''''''''''''''''''''''''''''''
45
+
47
+
46
#endif
48
+The Linux kernel has dropped support for allowing 32-bit Arm systems
47
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
49
+to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
50
+its support for this configuration and will remove it in a future version.
51
+Running 32-bit guests on a 64-bit Arm host remains supported.
52
+
53
RISC-V ISA Specific CPUs (removed in 5.1)
54
'''''''''''''''''''''''''''''''''''''''''
55
56
diff --git a/configure b/configure
57
index XXXXXXX..XXXXXXX 100755
58
--- a/configure
59
+++ b/configure
60
@@ -XXX,XX +XXX,XX @@ supported_kvm_target() {
61
test "$kvm" = "yes" || return 1
62
glob "$1" "*-softmmu" || return 1
63
case "${1%-softmmu}:$cpu" in
64
- arm:arm | aarch64:aarch64 | \
65
+ aarch64:aarch64 | \
66
i386:i386 | i386:x86_64 | i386:x32 | \
67
x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
68
mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
69
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
70
deleted file mode 100644
71
index XXXXXXX..XXXXXXX
72
--- a/target/arm/kvm32.c
73
+++ /dev/null
74
@@ -XXX,XX +XXX,XX @@
75
-/*
76
- * ARM implementation of KVM hooks, 32 bit specific code.
77
- *
78
- * Copyright Christoffer Dall 2009-2010
79
- *
80
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
81
- * See the COPYING file in the top-level directory.
82
- *
83
- */
84
-
85
-#include "qemu/osdep.h"
86
-#include <sys/ioctl.h>
87
-
88
-#include <linux/kvm.h>
89
-
90
-#include "qemu-common.h"
91
-#include "cpu.h"
92
-#include "qemu/timer.h"
93
-#include "sysemu/runstate.h"
94
-#include "sysemu/kvm.h"
95
-#include "kvm_arm.h"
96
-#include "internals.h"
97
-#include "qemu/log.h"
98
-
99
-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id)
100
-{
101
- struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret };
102
-
103
- assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32);
104
- return ioctl(fd, KVM_GET_ONE_REG, &idreg);
105
-}
106
-
107
-bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
108
-{
109
- /* Identify the feature bits corresponding to the host CPU, and
110
- * fill out the ARMHostCPUClass fields accordingly. To do this
111
- * we have to create a scratch VM, create a single CPU inside it,
112
- * and then query that CPU for the relevant ID registers.
113
- */
114
- int err = 0, fdarray[3];
115
- uint32_t midr, id_pfr0;
116
- uint64_t features = 0;
117
-
118
- /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
119
- * we know these will only support creating one kind of guest CPU,
120
- * which is its preferred CPU type.
121
- */
122
- static const uint32_t cpus_to_try[] = {
123
- QEMU_KVM_ARM_TARGET_CORTEX_A15,
124
- QEMU_KVM_ARM_TARGET_NONE
125
- };
126
- /*
127
- * target = -1 informs kvm_arm_create_scratch_host_vcpu()
128
- * to use the preferred target
129
- */
130
- struct kvm_vcpu_init init = { .target = -1, };
131
-
132
- if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
133
- return false;
134
- }
135
-
136
- ahcf->target = init.target;
137
-
138
- /* This is not strictly blessed by the device tree binding docs yet,
139
- * but in practice the kernel does not care about this string so
140
- * there is no point maintaining an KVM_ARM_TARGET_* -> string table.
141
- */
142
- ahcf->dtb_compatible = "arm,arm-v7";
143
-
144
- err |= read_sys_reg32(fdarray[2], &midr, ARM_CP15_REG32(0, 0, 0, 0));
145
- err |= read_sys_reg32(fdarray[2], &id_pfr0, ARM_CP15_REG32(0, 0, 1, 0));
146
-
147
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
148
- ARM_CP15_REG32(0, 0, 2, 0));
149
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
150
- ARM_CP15_REG32(0, 0, 2, 1));
151
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2,
152
- ARM_CP15_REG32(0, 0, 2, 2));
153
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3,
154
- ARM_CP15_REG32(0, 0, 2, 3));
155
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4,
156
- ARM_CP15_REG32(0, 0, 2, 4));
157
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
158
- ARM_CP15_REG32(0, 0, 2, 5));
159
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
160
- ARM_CP15_REG32(0, 0, 2, 7))) {
161
- /*
162
- * Older kernels don't support reading ID_ISAR6. This register was
163
- * only introduced in ARMv8, so we can assume that it is zero on a
164
- * CPU that a kernel this old is running on.
165
- */
166
- ahcf->isar.id_isar6 = 0;
167
- }
168
-
169
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
170
- ARM_CP15_REG32(0, 0, 1, 2));
171
-
172
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
173
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
174
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0);
175
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1,
176
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
177
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1);
178
- /*
179
- * FIXME: There is not yet a way to read MVFR2.
180
- * Fortunately there is not yet anything in there that affects migration.
181
- */
182
-
183
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
184
- ARM_CP15_REG32(0, 0, 1, 4));
185
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
186
- ARM_CP15_REG32(0, 0, 1, 5));
187
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
188
- ARM_CP15_REG32(0, 0, 1, 6));
189
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
190
- ARM_CP15_REG32(0, 0, 1, 7));
191
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
192
- ARM_CP15_REG32(0, 0, 2, 6))) {
193
- /*
194
- * Older kernels don't support reading ID_MMFR4 (a new in v8
195
- * register); assume it's zero.
196
- */
197
- ahcf->isar.id_mmfr4 = 0;
198
- }
199
-
200
- /*
201
- * There is no way to read DBGDIDR, because currently 32-bit KVM
202
- * doesn't implement debug at all. Leave it at zero.
203
- */
204
-
205
- kvm_arm_destroy_scratch_host_vcpu(fdarray);
206
-
207
- if (err < 0) {
208
- return false;
209
- }
210
-
211
- /* Now we've retrieved all the register information we can
212
- * set the feature bits based on the ID register fields.
213
- * We can assume any KVM supporting CPU is at least a v7
214
- * with VFPv3, virtualization extensions, and the generic
215
- * timers; this in turn implies most of the other feature
216
- * bits, but a few must be tested.
217
- */
218
- features |= 1ULL << ARM_FEATURE_V7VE;
219
- features |= 1ULL << ARM_FEATURE_GENERIC_TIMER;
220
-
221
- if (extract32(id_pfr0, 12, 4) == 1) {
222
- features |= 1ULL << ARM_FEATURE_THUMB2EE;
223
- }
224
- if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
225
- features |= 1ULL << ARM_FEATURE_NEON;
226
- }
227
-
228
- ahcf->features = features;
229
-
230
- return true;
231
-}
232
-
233
-bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
234
-{
235
- /* Return true if the regidx is a register we should synchronize
236
- * via the cpreg_tuples array (ie is not a core reg we sync by
237
- * hand in kvm_arch_get/put_registers())
238
- */
239
- switch (regidx & KVM_REG_ARM_COPROC_MASK) {
240
- case KVM_REG_ARM_CORE:
241
- case KVM_REG_ARM_VFP:
242
- return false;
243
- default:
244
- return true;
245
- }
246
-}
247
-
248
-typedef struct CPRegStateLevel {
249
- uint64_t regidx;
250
- int level;
251
-} CPRegStateLevel;
252
-
253
-/* All coprocessor registers not listed in the following table are assumed to
254
- * be of the level KVM_PUT_RUNTIME_STATE. If a register should be written less
255
- * often, you must add it to this table with a state of either
256
- * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE.
257
- */
258
-static const CPRegStateLevel non_runtime_cpregs[] = {
259
- { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
260
-};
261
-
262
-int kvm_arm_cpreg_level(uint64_t regidx)
263
-{
264
- int i;
265
-
266
- for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) {
267
- const CPRegStateLevel *l = &non_runtime_cpregs[i];
268
- if (l->regidx == regidx) {
269
- return l->level;
270
- }
271
- }
272
-
273
- return KVM_PUT_RUNTIME_STATE;
274
-}
275
-
276
-#define ARM_CPU_ID_MPIDR 0, 0, 0, 5
277
-
278
-int kvm_arch_init_vcpu(CPUState *cs)
279
-{
280
- int ret;
281
- uint64_t v;
282
- uint32_t mpidr;
283
- struct kvm_one_reg r;
284
- ARMCPU *cpu = ARM_CPU(cs);
285
-
286
- if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
287
- fprintf(stderr, "KVM is not supported for this guest CPU type\n");
288
- return -EINVAL;
289
- }
290
-
291
- qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
292
-
293
- /* Determine init features for this CPU */
294
- memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
295
- if (cs->start_powered_off) {
296
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
297
- }
298
- if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
299
- cpu->psci_version = 2;
300
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
301
- }
302
-
303
- /* Do KVM_ARM_VCPU_INIT ioctl */
304
- ret = kvm_arm_vcpu_init(cs);
305
- if (ret) {
306
- return ret;
307
- }
308
-
309
- /* Query the kernel to make sure it supports 32 VFP
310
- * registers: QEMU's "cortex-a15" CPU is always a
311
- * VFP-D32 core. The simplest way to do this is just
312
- * to attempt to read register d31.
313
- */
314
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
315
- r.addr = (uintptr_t)(&v);
316
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
317
- if (ret == -ENOENT) {
318
- return -EINVAL;
319
- }
320
-
321
- /*
322
- * When KVM is in use, PSCI is emulated in-kernel and not by qemu.
323
- * Currently KVM has its own idea about MPIDR assignment, so we
324
- * override our defaults with what we get from KVM.
325
- */
326
- ret = kvm_get_one_reg(cs, ARM_CP15_REG32(ARM_CPU_ID_MPIDR), &mpidr);
327
- if (ret) {
328
- return ret;
329
- }
330
- cpu->mp_affinity = mpidr & ARM32_AFFINITY_MASK;
331
-
332
- /* Check whether userspace can specify guest syndrome value */
333
- kvm_arm_init_serror_injection(cs);
334
-
335
- return kvm_arm_init_cpreg_list(cpu);
336
-}
337
-
338
-int kvm_arch_destroy_vcpu(CPUState *cs)
339
-{
340
-    return 0;
341
-}
342
-
343
-typedef struct Reg {
344
- uint64_t id;
345
- int offset;
346
-} Reg;
347
-
348
-#define COREREG(KERNELNAME, QEMUFIELD) \
349
- { \
350
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
351
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
352
- offsetof(CPUARMState, QEMUFIELD) \
353
- }
354
-
355
-#define VFPSYSREG(R) \
356
- { \
357
- KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
358
- KVM_REG_ARM_VFP_##R, \
359
- offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
360
- }
361
-
362
-/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
363
-#define COREREG64(KERNELNAME, QEMUFIELD) \
364
- { \
365
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
366
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
367
- offsetoflow32(CPUARMState, QEMUFIELD) \
368
- }
369
-
370
-static const Reg regs[] = {
371
- /* R0_usr .. R14_usr */
372
- COREREG(usr_regs.uregs[0], regs[0]),
373
- COREREG(usr_regs.uregs[1], regs[1]),
374
- COREREG(usr_regs.uregs[2], regs[2]),
375
- COREREG(usr_regs.uregs[3], regs[3]),
376
- COREREG(usr_regs.uregs[4], regs[4]),
377
- COREREG(usr_regs.uregs[5], regs[5]),
378
- COREREG(usr_regs.uregs[6], regs[6]),
379
- COREREG(usr_regs.uregs[7], regs[7]),
380
- COREREG(usr_regs.uregs[8], usr_regs[0]),
381
- COREREG(usr_regs.uregs[9], usr_regs[1]),
382
- COREREG(usr_regs.uregs[10], usr_regs[2]),
383
- COREREG(usr_regs.uregs[11], usr_regs[3]),
384
- COREREG(usr_regs.uregs[12], usr_regs[4]),
385
- COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]),
386
- COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]),
387
- /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
388
- COREREG(svc_regs[0], banked_r13[BANK_SVC]),
389
- COREREG(svc_regs[1], banked_r14[BANK_SVC]),
390
- COREREG64(svc_regs[2], banked_spsr[BANK_SVC]),
391
- COREREG(abt_regs[0], banked_r13[BANK_ABT]),
392
- COREREG(abt_regs[1], banked_r14[BANK_ABT]),
393
- COREREG64(abt_regs[2], banked_spsr[BANK_ABT]),
394
- COREREG(und_regs[0], banked_r13[BANK_UND]),
395
- COREREG(und_regs[1], banked_r14[BANK_UND]),
396
- COREREG64(und_regs[2], banked_spsr[BANK_UND]),
397
- COREREG(irq_regs[0], banked_r13[BANK_IRQ]),
398
- COREREG(irq_regs[1], banked_r14[BANK_IRQ]),
399
- COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]),
400
- /* R8_fiq .. R14_fiq and SPSR_fiq */
401
- COREREG(fiq_regs[0], fiq_regs[0]),
402
- COREREG(fiq_regs[1], fiq_regs[1]),
403
- COREREG(fiq_regs[2], fiq_regs[2]),
404
- COREREG(fiq_regs[3], fiq_regs[3]),
405
- COREREG(fiq_regs[4], fiq_regs[4]),
406
- COREREG(fiq_regs[5], banked_r13[BANK_FIQ]),
407
- COREREG(fiq_regs[6], banked_r14[BANK_FIQ]),
408
- COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]),
409
- /* R15 */
410
- COREREG(usr_regs.uregs[15], regs[15]),
411
- /* VFP system registers */
412
- VFPSYSREG(FPSID),
413
- VFPSYSREG(MVFR1),
414
- VFPSYSREG(MVFR0),
415
- VFPSYSREG(FPEXC),
416
- VFPSYSREG(FPINST),
417
- VFPSYSREG(FPINST2),
418
-};
419
-
420
-int kvm_arch_put_registers(CPUState *cs, int level)
421
-{
422
- ARMCPU *cpu = ARM_CPU(cs);
423
- CPUARMState *env = &cpu->env;
424
- struct kvm_one_reg r;
425
- int mode, bn;
426
- int ret, i;
427
- uint32_t cpsr, fpscr;
428
-
429
- /* Make sure the banked regs are properly set */
430
- mode = env->uncached_cpsr & CPSR_M;
431
- bn = bank_number(mode);
432
- if (mode == ARM_CPU_MODE_FIQ) {
433
- memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
434
- } else {
435
- memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
436
- }
437
- env->banked_r13[bn] = env->regs[13];
438
- env->banked_spsr[bn] = env->spsr;
439
- env->banked_r14[r14_bank_number(mode)] = env->regs[14];
440
-
441
- /* Now we can safely copy stuff down to the kernel */
442
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
443
- r.id = regs[i].id;
444
- r.addr = (uintptr_t)(env) + regs[i].offset;
445
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
446
- if (ret) {
447
- return ret;
448
- }
449
- }
450
-
451
- /* Special cases which aren't a single CPUARMState field */
452
- cpsr = cpsr_read(env);
453
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
454
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
455
- r.addr = (uintptr_t)(&cpsr);
456
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
457
- if (ret) {
458
- return ret;
459
- }
460
-
461
- /* VFP registers */
462
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
463
- for (i = 0; i < 32; i++) {
464
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
465
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
466
- if (ret) {
467
- return ret;
468
- }
469
- r.id++;
470
- }
471
-
472
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
473
- KVM_REG_ARM_VFP_FPSCR;
474
- fpscr = vfp_get_fpscr(env);
475
- r.addr = (uintptr_t)&fpscr;
476
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
477
- if (ret) {
478
- return ret;
479
- }
480
-
481
- write_cpustate_to_list(cpu, true);
482
-
483
- if (!write_list_to_kvmstate(cpu, level)) {
484
- return EINVAL;
485
- }
486
-
487
- /*
488
- * Setting VCPU events should be triggered after syncing the registers
489
- * to avoid overwriting potential changes made by KVM upon calling
490
- * KVM_SET_VCPU_EVENTS ioctl
491
- */
492
- ret = kvm_put_vcpu_events(cpu);
493
- if (ret) {
494
- return ret;
495
- }
496
-
497
- kvm_arm_sync_mpstate_to_kvm(cpu);
498
-
499
- return ret;
500
-}
501
-
502
-int kvm_arch_get_registers(CPUState *cs)
503
-{
504
- ARMCPU *cpu = ARM_CPU(cs);
505
- CPUARMState *env = &cpu->env;
506
- struct kvm_one_reg r;
507
- int mode, bn;
508
- int ret, i;
509
- uint32_t cpsr, fpscr;
510
-
511
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
512
- r.id = regs[i].id;
513
- r.addr = (uintptr_t)(env) + regs[i].offset;
514
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
515
- if (ret) {
516
- return ret;
517
- }
518
- }
519
-
520
- /* Special cases which aren't a single CPUARMState field */
521
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
522
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
523
- r.addr = (uintptr_t)(&cpsr);
524
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
525
- if (ret) {
526
- return ret;
527
- }
528
- cpsr_write(env, cpsr, 0xffffffff, CPSRWriteRaw);
529
-
530
- /* Make sure the current mode regs are properly set */
531
- mode = env->uncached_cpsr & CPSR_M;
532
- bn = bank_number(mode);
533
- if (mode == ARM_CPU_MODE_FIQ) {
534
- memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
535
- } else {
536
- memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
537
- }
538
- env->regs[13] = env->banked_r13[bn];
539
- env->spsr = env->banked_spsr[bn];
540
- env->regs[14] = env->banked_r14[r14_bank_number(mode)];
541
-
542
- /* VFP registers */
543
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
544
- for (i = 0; i < 32; i++) {
545
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
546
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
547
- if (ret) {
548
- return ret;
549
- }
550
- r.id++;
551
- }
552
-
553
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
554
- KVM_REG_ARM_VFP_FPSCR;
555
- r.addr = (uintptr_t)&fpscr;
556
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
557
- if (ret) {
558
- return ret;
559
- }
560
- vfp_set_fpscr(env, fpscr);
561
-
562
- ret = kvm_get_vcpu_events(cpu);
563
- if (ret) {
564
- return ret;
565
- }
566
-
567
- if (!write_kvmstate_to_list(cpu)) {
568
- return EINVAL;
569
- }
570
- /* Note that it's OK to have registers which aren't in CPUState,
571
- * so we can ignore a failure return here.
572
- */
573
- write_list_to_cpustate(cpu);
574
-
575
- kvm_arm_sync_mpstate_to_qemu(cpu);
576
-
577
- return 0;
578
-}
579
-
580
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
581
-{
582
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
583
- return -EINVAL;
584
-}
585
-
586
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
587
-{
588
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
589
- return -EINVAL;
590
-}
591
-
592
-bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
593
-{
594
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
595
- return false;
596
-}
597
-
598
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
599
- target_ulong len, int type)
600
-{
601
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
602
- return -EINVAL;
603
-}
604
-
605
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
606
- target_ulong len, int type)
607
-{
608
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
609
- return -EINVAL;
610
-}
611
-
612
-void kvm_arch_remove_all_hw_breakpoints(void)
613
-{
614
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
615
-}
616
-
617
-void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr)
618
-{
619
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
620
-}
621
-
622
-bool kvm_arm_hw_debug_active(CPUState *cs)
623
-{
624
- return false;
625
-}
626
-
627
-void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
628
-{
629
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
630
-}
631
-
632
-void kvm_arm_pmu_init(CPUState *cs)
633
-{
634
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
635
-}
636
-
637
-#define ARM_REG_DFSR ARM_CP15_REG32(0, 5, 0, 0)
638
-#define ARM_REG_TTBCR ARM_CP15_REG32(0, 2, 0, 2)
639
-/*
640
- *DFSR:
641
- * TTBCR.EAE == 0
642
- * FS[4] - DFSR[10]
643
- * FS[3:0] - DFSR[3:0]
644
- * TTBCR.EAE == 1
645
- * FS, bits [5:0]
646
- */
647
-#define DFSR_FSC(lpae, v) \
648
- ((lpae) ? ((v) & 0x3F) : (((v) >> 6) | ((v) & 0x1F)))
649
-
650
-#define DFSC_EXTABT(lpae) ((lpae) ? 0x10 : 0x08)
651
-
652
-bool kvm_arm_verify_ext_dabt_pending(CPUState *cs)
653
-{
654
- uint32_t dfsr_val;
655
-
656
- if (!kvm_get_one_reg(cs, ARM_REG_DFSR, &dfsr_val)) {
657
- ARMCPU *cpu = ARM_CPU(cs);
658
- CPUARMState *env = &cpu->env;
659
- uint32_t ttbcr;
660
- int lpae = 0;
661
-
662
- if (!kvm_get_one_reg(cs, ARM_REG_TTBCR, &ttbcr)) {
663
- lpae = arm_feature(env, ARM_FEATURE_LPAE) && (ttbcr & TTBCR_EAE);
664
- }
665
- /* The verification is based on FS filed of the DFSR reg only*/
666
- return (DFSR_FSC(lpae, dfsr_val) == DFSC_EXTABT(lpae));
667
- }
668
- return false;
669
-}
670
diff --git a/target/arm/meson.build b/target/arm/meson.build
48
index XXXXXXX..XXXXXXX 100644
671
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/display/bcm2835_fb.c
672
--- a/target/arm/meson.build
50
+++ b/hw/display/bcm2835_fb.c
673
+++ b/target/arm/meson.build
51
@@ -XXX,XX +XXX,XX @@
674
@@ -XXX,XX +XXX,XX @@ arm_ss.add(zlib)
52
#define DEFAULT_VCRAM_SIZE 0x4000000
675
53
#define BCM2835_FB_OFFSET 0x00100000
676
arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
54
677
55
+/* Maximum permitted framebuffer size; experimentally determined on an rpi2 */
678
-kvm_ss = ss.source_set()
56
+#define XRES_MAX 3840
679
-kvm_ss.add(when: 'TARGET_AARCH64', if_true: files('kvm64.c'), if_false: files('kvm32.c'))
57
+#define YRES_MAX 2560
680
-arm_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
58
+/* Framebuffer size used if guest requests zero size */
681
-arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
59
+#define XRES_SMALL 592
682
+arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
60
+#define YRES_SMALL 488
683
61
+
684
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
62
static void fb_invalidate_display(void *opaque)
685
'cpu64.c',
63
{
64
BCM2835FBState *s = BCM2835_FB(opaque);
65
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
66
s->invalidate = false;
67
}
68
69
+void bcm2835_fb_validate_config(BCM2835FBConfig *config)
70
+{
71
+ /*
72
+ * Validate the config, and clip any bogus values into range,
73
+ * as the hardware does. Note that fb_update_display() relies on
74
+ * this happening to prevent it from performing out-of-range
75
+ * accesses on redraw.
76
+ */
77
+ config->xres = MIN(config->xres, XRES_MAX);
78
+ config->xres_virtual = MIN(config->xres_virtual, XRES_MAX);
79
+ config->yres = MIN(config->yres, YRES_MAX);
80
+ config->yres_virtual = MIN(config->yres_virtual, YRES_MAX);
81
+
82
+ /*
83
+ * These are not minima: a 40x40 framebuffer will be accepted.
84
+ * They're only used as defaults if the guest asks for zero size.
85
+ */
86
+ if (config->xres == 0) {
87
+ config->xres = XRES_SMALL;
88
+ }
89
+ if (config->yres == 0) {
90
+ config->yres = YRES_SMALL;
91
+ }
92
+ if (config->xres_virtual == 0) {
93
+ config->xres_virtual = config->xres;
94
+ }
95
+ if (config->yres_virtual == 0) {
96
+ config->yres_virtual = config->yres;
97
+ }
98
+
99
+ if (fb_use_offsets(config)) {
100
+ /* Clip the offsets so the viewport is within the physical screen */
101
+ config->xoffset = MIN(config->xoffset,
102
+ config->xres_virtual - config->xres);
103
+ config->yoffset = MIN(config->yoffset,
104
+ config->yres_virtual - config->yres);
105
+ }
106
+}
107
+
108
static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
109
{
110
uint32_t pitch;
111
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
112
{
113
s->lock = true;
114
115
- /* TODO: input validation! */
116
-
117
s->config = *newconfig;
118
119
s->invalidate = true;
120
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/misc/bcm2835_property.c
123
+++ b/hw/misc/bcm2835_property.c
124
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
125
case 0x00040002: /* Blank screen */
126
resplen = 4;
127
break;
128
- case 0x00040003: /* Get physical display width/height */
129
- stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
130
- stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
131
- resplen = 8;
132
- break;
133
- case 0x00040004: /* Get virtual display width/height */
134
- stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
135
- stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
136
- resplen = 8;
137
- break;
138
case 0x00044003: /* Test physical display width/height */
139
case 0x00044004: /* Test virtual display width/height */
140
resplen = 8;
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
142
case 0x00048003: /* Set physical display width/height */
143
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
144
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
145
+ bcm2835_fb_validate_config(&fbconfig);
146
fbconfig_updated = true;
147
+ /* fall through */
148
+ case 0x00040003: /* Get physical display width/height */
149
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
150
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
151
resplen = 8;
152
break;
153
case 0x00048004: /* Set virtual display width/height */
154
fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
155
fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
156
+ bcm2835_fb_validate_config(&fbconfig);
157
fbconfig_updated = true;
158
+ /* fall through */
159
+ case 0x00040004: /* Get virtual display width/height */
160
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
161
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
162
resplen = 8;
163
break;
164
- case 0x00040005: /* Get depth */
165
- stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
166
- resplen = 4;
167
- break;
168
case 0x00044005: /* Test depth */
169
resplen = 4;
170
break;
171
case 0x00048005: /* Set depth */
172
fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
173
+ bcm2835_fb_validate_config(&fbconfig);
174
fbconfig_updated = true;
175
- resplen = 4;
176
- break;
177
- case 0x00040006: /* Get pixel order */
178
- stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
179
+ /* fall through */
180
+ case 0x00040005: /* Get depth */
181
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
182
resplen = 4;
183
break;
184
case 0x00044006: /* Test pixel order */
185
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
186
break;
187
case 0x00048006: /* Set pixel order */
188
fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
189
+ bcm2835_fb_validate_config(&fbconfig);
190
fbconfig_updated = true;
191
- resplen = 4;
192
- break;
193
- case 0x00040007: /* Get alpha */
194
- stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
195
+ /* fall through */
196
+ case 0x00040006: /* Get pixel order */
197
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
198
resplen = 4;
199
break;
200
case 0x00044007: /* Test pixel alpha */
201
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
202
break;
203
case 0x00048007: /* Set alpha */
204
fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
205
+ bcm2835_fb_validate_config(&fbconfig);
206
fbconfig_updated = true;
207
+ /* fall through */
208
+ case 0x00040007: /* Get alpha */
209
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
210
resplen = 4;
211
break;
212
case 0x00040008: /* Get pitch */
213
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
214
bcm2835_fb_get_pitch(&fbconfig));
215
resplen = 4;
216
break;
217
- case 0x00040009: /* Get virtual offset */
218
- stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
219
- stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
220
- resplen = 8;
221
- break;
222
case 0x00044009: /* Test virtual offset */
223
resplen = 8;
224
break;
225
case 0x00048009: /* Set virtual offset */
226
fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
227
fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
228
+ bcm2835_fb_validate_config(&fbconfig);
229
fbconfig_updated = true;
230
+ /* fall through */
231
+ case 0x00040009: /* Get virtual offset */
232
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
233
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
234
resplen = 8;
235
break;
236
case 0x0004000a: /* Get/Test/Set overscan */
237
--
686
--
238
2.18.0
687
2.20.1
239
688
240
689
diff view generated by jsdifflib
1
Use the DeviceState vmsd pointer rather than calling vmstate_register()
1
Now that 32-bit KVM host support is gone, KVM can never
2
directly.
2
be enabled unless CONFIG_AARCH64 is true, and some code
3
paths are no longer reachable and can be deleted.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180820141116.9118-18-peter.maydell@linaro.org
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20200904154156.31943-3-peter.maydell@linaro.org
7
---
9
---
8
hw/ssi/pl022.c | 2 +-
10
target/arm/kvm-consts.h | 7 ---
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
target/arm/kvm_arm.h | 6 ---
10
12
target/arm/cpu.c | 101 +++++++++++++++++++---------------------
11
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
13
target/arm/kvm.c | 7 ---
12
index XXXXXXX..XXXXXXX 100644
14
4 files changed, 47 insertions(+), 74 deletions(-)
13
--- a/hw/ssi/pl022.c
15
14
+++ b/hw/ssi/pl022.c
16
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
15
@@ -XXX,XX +XXX,XX @@ static int pl022_init(SysBusDevice *sbd)
17
index XXXXXXX..XXXXXXX 100644
16
sysbus_init_mmio(sbd, &s->iomem);
18
--- a/target/arm/kvm-consts.h
17
sysbus_init_irq(sbd, &s->irq);
19
+++ b/target/arm/kvm-consts.h
18
s->ssi = ssi_create_bus(dev, "ssi");
20
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
19
- vmstate_register(dev, -1, &vmstate_pl022, s);
21
*/
22
#define QEMU_KVM_ARM_TARGET_NONE UINT_MAX
23
24
-#ifdef TARGET_AARCH64
25
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_AEM_V8);
26
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8);
27
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57);
28
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA);
29
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53);
30
-#else
31
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15);
32
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
33
-#endif
34
35
#define CP_REG_ARM64 0x6000000000000000ULL
36
#define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000
37
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
38
/* No kernel define but it's useful to QEMU */
39
#define CP_REG_ARM64_SYSREG_CP (CP_REG_ARM64_SYSREG >> CP_REG_ARM_COPROC_SHIFT)
40
41
-#ifdef TARGET_AARCH64
42
MISMATCH_CHECK(CP_REG_ARM64, KVM_REG_ARM64);
43
MISMATCH_CHECK(CP_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_MASK);
44
MISMATCH_CHECK(CP_REG_ARM_COPROC_SHIFT, KVM_REG_ARM_COPROC_SHIFT);
45
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_MASK);
46
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRM_SHIFT);
47
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK);
48
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM64_SYSREG_OP2_SHIFT);
49
-#endif
50
51
#undef MISMATCH_CHECK
52
53
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/kvm_arm.h
56
+++ b/target/arm/kvm_arm.h
57
@@ -XXX,XX +XXX,XX @@ static inline const char *gic_class_name(void)
58
static inline const char *gicv3_class_name(void)
59
{
60
if (kvm_irqchip_in_kernel()) {
61
-#ifdef TARGET_AARCH64
62
return "kvm-arm-gicv3";
63
-#else
64
- error_report("KVM GICv3 acceleration is not supported on this "
65
- "platform");
66
- exit(1);
67
-#endif
68
} else {
69
if (kvm_enabled()) {
70
error_report("Userspace GICv3 is not supported with KVM");
71
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/cpu.c
74
+++ b/target/arm/cpu.c
75
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
76
}
77
78
#ifndef TARGET_AARCH64
79
-/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
80
- * otherwise, a CPU with as many features enabled as our emulation supports.
81
+/*
82
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
83
* The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
84
- * this only needs to handle 32 bits.
85
+ * this only needs to handle 32 bits, and need not care about KVM.
86
*/
87
static void arm_max_initfn(Object *obj)
88
{
89
ARMCPU *cpu = ARM_CPU(obj);
90
91
- if (kvm_enabled()) {
92
- kvm_arm_set_cpu_features_from_host(cpu);
93
- } else {
94
- cortex_a15_initfn(obj);
95
+ cortex_a15_initfn(obj);
96
97
- /* old-style VFP short-vector support */
98
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
99
+ /* old-style VFP short-vector support */
100
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
101
102
#ifdef CONFIG_USER_ONLY
103
- /* We don't set these in system emulation mode for the moment,
104
- * since we don't correctly set (all of) the ID registers to
105
- * advertise them.
106
- */
107
- set_feature(&cpu->env, ARM_FEATURE_V8);
108
- {
109
- uint32_t t;
110
+ /*
111
+ * We don't set these in system emulation mode for the moment,
112
+ * since we don't correctly set (all of) the ID registers to
113
+ * advertise them.
114
+ */
115
+ set_feature(&cpu->env, ARM_FEATURE_V8);
116
+ {
117
+ uint32_t t;
118
119
- t = cpu->isar.id_isar5;
120
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
121
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
122
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
123
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
124
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
125
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
126
- cpu->isar.id_isar5 = t;
127
+ t = cpu->isar.id_isar5;
128
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
129
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
130
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
131
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
132
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
133
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
134
+ cpu->isar.id_isar5 = t;
135
136
- t = cpu->isar.id_isar6;
137
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
138
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
139
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
140
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
141
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
142
- cpu->isar.id_isar6 = t;
143
+ t = cpu->isar.id_isar6;
144
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
145
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
146
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
147
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
148
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
149
+ cpu->isar.id_isar6 = t;
150
151
- t = cpu->isar.mvfr1;
152
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
153
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
154
- cpu->isar.mvfr1 = t;
155
+ t = cpu->isar.mvfr1;
156
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
157
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
158
+ cpu->isar.mvfr1 = t;
159
160
- t = cpu->isar.mvfr2;
161
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
162
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
163
- cpu->isar.mvfr2 = t;
164
+ t = cpu->isar.mvfr2;
165
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
166
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
167
+ cpu->isar.mvfr2 = t;
168
169
- t = cpu->isar.id_mmfr3;
170
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
171
- cpu->isar.id_mmfr3 = t;
172
+ t = cpu->isar.id_mmfr3;
173
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
174
+ cpu->isar.id_mmfr3 = t;
175
176
- t = cpu->isar.id_mmfr4;
177
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
178
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
179
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
180
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
181
- cpu->isar.id_mmfr4 = t;
182
- }
183
-#endif
184
+ t = cpu->isar.id_mmfr4;
185
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
186
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
187
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
188
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
189
+ cpu->isar.id_mmfr4 = t;
190
}
191
+#endif
192
}
193
#endif
194
195
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
196
197
static const TypeInfo host_arm_cpu_type_info = {
198
.name = TYPE_ARM_HOST_CPU,
199
-#ifdef TARGET_AARCH64
200
.parent = TYPE_AARCH64_CPU,
201
-#else
202
- .parent = TYPE_ARM_CPU,
203
-#endif
204
.instance_init = arm_host_initfn,
205
};
206
207
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
208
index XXXXXXX..XXXXXXX 100644
209
--- a/target/arm/kvm.c
210
+++ b/target/arm/kvm.c
211
@@ -XXX,XX +XXX,XX @@ int kvm_arch_process_async_events(CPUState *cs)
20
return 0;
212
return 0;
21
}
213
}
22
214
23
@@ -XXX,XX +XXX,XX @@ static void pl022_class_init(ObjectClass *klass, void *data)
215
-/* The #ifdef protections are until 32bit headers are imported and can
24
216
- * be removed once both 32 and 64 bit reach feature parity.
25
sdc->init = pl022_init;
217
- */
26
dc->reset = pl022_reset;
218
void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg)
27
+ dc->vmsd = &vmstate_pl022;
219
{
28
}
220
-#ifdef KVM_GUESTDBG_USE_SW_BP
29
221
if (kvm_sw_breakpoints_active(cs)) {
30
static const TypeInfo pl022_info = {
222
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
223
}
224
-#endif
225
-#ifdef KVM_GUESTDBG_USE_HW
226
if (kvm_arm_hw_debug_active(cs)) {
227
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW;
228
kvm_arm_copy_hw_debug_data(&dbg->arch);
229
}
230
-#endif
231
}
232
233
void kvm_arch_init_irq_routing(KVMState *s)
31
--
234
--
32
2.18.0
235
2.20.1
33
236
34
237
diff view generated by jsdifflib
1
The MPS2 FPGA images for the Cortex-M3 (mps2-an385 and mps2-511)
1
Implement a model of the MPS2 with the AN386 firmware. This is
2
both include a CMSDK dual-timer module. Wire this up.
2
essentially identical to the AN385 firmware, but it has a
3
Cortex-M4 rather than a Cortex-M3.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200903202048.15370-2-peter.maydell@linaro.org
7
Message-id: 20180820141116.9118-6-peter.maydell@linaro.org
8
---
9
---
9
hw/arm/mps2.c | 11 +++++++++++
10
docs/system/arm/mps2.rst | 8 +++++---
10
1 file changed, 11 insertions(+)
11
hw/arm/mps2.c | 34 +++++++++++++++++++++++++++++-----
12
2 files changed, 34 insertions(+), 8 deletions(-)
11
13
14
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
15
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/mps2.rst
17
+++ b/docs/system/arm/mps2.rst
18
@@ -XXX,XX +XXX,XX @@
19
-Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
20
-================================================================================
21
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
22
+================================================================================================
23
24
These board models all use Arm M-profile CPUs.
25
26
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
27
28
``mps2-an385``
29
Cortex-M3 as documented in ARM Application Note AN385
30
+``mps2-an386``
31
+ Cortex-M4 as documented in ARM Application Note AN386
32
``mps2-an511``
33
Cortex-M3 'DesignStart' as documented in AN511
34
``mps2-an505``
35
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
36
37
Differences between QEMU and real hardware:
38
39
-- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to
40
+- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
41
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
42
if zbt_boot_ctrl is always zero)
43
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
12
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
44
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
13
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2.c
46
--- a/hw/arm/mps2.c
15
+++ b/hw/arm/mps2.c
47
+++ b/hw/arm/mps2.c
16
@@ -XXX,XX +XXX,XX @@
48
@@ -XXX,XX +XXX,XX @@
17
#include "hw/misc/unimp.h"
49
* as seen by the guest depend significantly on the FPGA image.
18
#include "hw/char/cmsdk-apb-uart.h"
50
* We model the following FPGA images:
19
#include "hw/timer/cmsdk-apb-timer.h"
51
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
20
+#include "hw/timer/cmsdk-apb-dualtimer.h"
52
+ * "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
21
#include "hw/misc/mps2-scc.h"
53
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
22
#include "hw/devices.h"
54
*
23
#include "net/net.h"
55
* Links to the TRM for the board itself and to the various Application
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
56
@@ -XXX,XX +XXX,XX @@
25
MemoryRegion blockram_m3;
57
26
MemoryRegion sram;
58
typedef enum MPS2FPGAType {
27
MPS2SCC scc;
59
FPGA_AN385,
28
+ CMSDKAPBDualTimer dualtimer;
60
+ FPGA_AN386,
29
} MPS2MachineState;
61
FPGA_AN511,
62
} MPS2FPGAType;
63
64
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
30
65
31
#define TYPE_MPS2_MACHINE "mps2"
66
#define TYPE_MPS2_MACHINE "mps2"
67
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
68
+#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
69
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
70
71
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
32
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
72
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
33
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
73
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
34
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
74
* call the 16MB our "system memory", as it's the largest lump.
35
75
*
36
+ sysbus_init_child_obj(OBJECT(mms), "dualtimer", &mms->dualtimer,
76
- * Common to both boards:
37
+ sizeof(mms->dualtimer), TYPE_CMSDK_APB_DUALTIMER);
77
- * 0x21000000..0x21ffffff : PSRAM (16MB)
38
+ qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
78
- * AN385 only:
39
+ object_property_set_bool(OBJECT(&mms->dualtimer), true, "realized",
79
+ * AN385/AN386/AN511:
40
+ &error_fatal);
80
+ * 0x21000000 .. 0x21ffffff : PSRAM (16MB)
41
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
81
+ * AN385/AN386 only:
42
+ qdev_get_gpio_in(armv7m, 10));
82
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
43
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
83
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
84
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
85
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
86
* 0x20000000 .. 0x2001ffff : SRAM
87
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
88
*
89
- * The AN385 has a feature where the lowest 16K can be mapped
90
+ * The AN385/AN386 has a feature where the lowest 16K can be mapped
91
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
92
* This is of no use for QEMU so we don't implement it (as if
93
* zbt_boot_ctrl is always zero).
94
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
95
96
switch (mmc->fpga_type) {
97
case FPGA_AN385:
98
+ case FPGA_AN386:
99
make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
100
make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
101
make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
102
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
103
armv7m = DEVICE(&mms->armv7m);
104
switch (mmc->fpga_type) {
105
case FPGA_AN385:
106
+ case FPGA_AN386:
107
qdev_prop_set_uint32(armv7m, "num-irq", 32);
108
break;
109
case FPGA_AN511:
110
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
111
112
switch (mmc->fpga_type) {
113
case FPGA_AN385:
114
+ case FPGA_AN386:
115
{
116
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
117
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
*/
120
lan9118_init(&nd_table[0], 0x40200000,
121
qdev_get_gpio_in(armv7m,
122
- mmc->fpga_type == FPGA_AN385 ? 13 : 47));
123
+ mmc->fpga_type == FPGA_AN511 ? 47 : 13));
124
125
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
126
127
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
128
mmc->scc_id = 0x41043850;
129
}
130
131
+static void mps2_an386_class_init(ObjectClass *oc, void *data)
132
+{
133
+ MachineClass *mc = MACHINE_CLASS(oc);
134
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
44
+
135
+
45
object_initialize(&mms->scc, sizeof(mms->scc), TYPE_MPS2_SCC);
136
+ mc->desc = "ARM MPS2 with AN386 FPGA image for Cortex-M4";
46
sccdev = DEVICE(&mms->scc);
137
+ mmc->fpga_type = FPGA_AN386;
47
qdev_set_parent_bus(sccdev, sysbus_get_default());
138
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
139
+ mmc->scc_id = 0x41043860;
140
+}
141
+
142
static void mps2_an511_class_init(ObjectClass *oc, void *data)
143
{
144
MachineClass *mc = MACHINE_CLASS(oc);
145
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an385_info = {
146
.class_init = mps2_an385_class_init,
147
};
148
149
+static const TypeInfo mps2_an386_info = {
150
+ .name = TYPE_MPS2_AN386_MACHINE,
151
+ .parent = TYPE_MPS2_MACHINE,
152
+ .class_init = mps2_an386_class_init,
153
+};
154
+
155
static const TypeInfo mps2_an511_info = {
156
.name = TYPE_MPS2_AN511_MACHINE,
157
.parent = TYPE_MPS2_MACHINE,
158
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
159
{
160
type_register_static(&mps2_info);
161
type_register_static(&mps2_an385_info);
162
+ type_register_static(&mps2_an386_info);
163
type_register_static(&mps2_an511_info);
164
}
165
48
--
166
--
49
2.18.0
167
2.20.1
50
168
51
169
diff view generated by jsdifflib
1
Fix MPS2 SCC config register values for the mps2-an511
1
Implement a model of the MPS2 with the AN500 firmware. This is
2
and mps2-an385 boards:
2
similar to the AN385, with the following differences:
3
* the SCC_AID bits [23:20] specify the FPGA build target board revision,
3
* Cortex-M7 CPU
4
and the SCC_CFG4 register specifies the actual board revision, so
4
* PSRAM is at 0x6000_0000
5
these should have matching values. Claim to be board revision C,
5
* Ethernet is at 0xa000_0000
6
consistently -- we had the revision in the wrong part of SCC_AID.
6
* No zbt_boot_ctrl remapping of the low 16K
7
* SCC_ID bits [15:4] should be the board number in hex, not decimal
7
(but QEMU doesn't implement this anyway)
8
* no "block RAM" at 0x01000000
8
9
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20180823175225.22612-1-peter.maydell@linaro.org
12
Message-id: 20200903202048.15370-3-peter.maydell@linaro.org
12
---
13
---
13
hw/arm/mps2.c | 6 +++---
14
docs/system/arm/mps2.rst | 6 ++--
14
1 file changed, 3 insertions(+), 3 deletions(-)
15
hw/arm/mps2.c | 67 +++++++++++++++++++++++++++++++++-------
15
16
2 files changed, 60 insertions(+), 13 deletions(-)
17
18
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
19
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/mps2.rst
21
+++ b/docs/system/arm/mps2.rst
22
@@ -XXX,XX +XXX,XX @@
23
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
24
-================================================================================================
25
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
26
+================================================================================================================
27
28
These board models all use Arm M-profile CPUs.
29
30
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
31
Cortex-M3 as documented in ARM Application Note AN385
32
``mps2-an386``
33
Cortex-M4 as documented in ARM Application Note AN386
34
+``mps2-an500``
35
+ Cortex-M7 as documented in ARM Application Note AN500
36
``mps2-an511``
37
Cortex-M3 'DesignStart' as documented in AN511
38
``mps2-an505``
16
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
39
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
17
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/mps2.c
41
--- a/hw/arm/mps2.c
19
+++ b/hw/arm/mps2.c
42
+++ b/hw/arm/mps2.c
20
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
43
@@ -XXX,XX +XXX,XX @@
21
sccdev = DEVICE(&mms->scc);
44
* We model the following FPGA images:
22
qdev_set_parent_bus(sccdev, sysbus_get_default());
45
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
23
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
46
* "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
24
- qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
47
+ * "mps2-an500" -- Cortex-M7 as documented in ARM Application Note AN500
25
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
48
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
26
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
49
*
27
object_property_set_bool(OBJECT(&mms->scc), true, "realized",
50
* Links to the TRM for the board itself and to the various Application
28
&error_fatal);
51
@@ -XXX,XX +XXX,XX @@
52
typedef enum MPS2FPGAType {
53
FPGA_AN385,
54
FPGA_AN386,
55
+ FPGA_AN500,
56
FPGA_AN511,
57
} MPS2FPGAType;
58
59
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineClass {
60
MachineClass parent;
61
MPS2FPGAType fpga_type;
62
uint32_t scc_id;
63
+ bool has_block_ram;
64
+ hwaddr ethernet_base;
65
+ hwaddr psram_base;
66
};
67
typedef struct MPS2MachineClass MPS2MachineClass;
68
69
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
70
#define TYPE_MPS2_MACHINE "mps2"
71
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
72
#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
73
+#define TYPE_MPS2_AN500_MACHINE MACHINE_TYPE_NAME("mps2-an500")
74
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
75
76
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
77
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
78
*
79
* AN385/AN386/AN511:
80
* 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
- * AN385/AN386 only:
82
+ * AN385/AN386/AN500:
83
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
84
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
85
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
86
* 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3
87
+ * AN385/AN386 only:
88
* 0x01000000 .. 0x01003fff : block RAM (16K)
89
* 0x01004000 .. 0x01007fff : mirror of above
90
* 0x01008000 .. 0x0100bfff : mirror of above
91
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
92
* 0x00400000 .. 0x007fffff : ZBT SSRAM1
93
* 0x20000000 .. 0x2001ffff : SRAM
94
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
95
+ * AN500 only:
96
+ * 0x60000000 .. 0x60ffffff : PSRAM (16MB)
97
*
98
* The AN385/AN386 has a feature where the lowest 16K can be mapped
99
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
100
* This is of no use for QEMU so we don't implement it (as if
101
* zbt_boot_ctrl is always zero).
102
*/
103
- memory_region_add_subregion(system_memory, 0x21000000, machine->ram);
104
+ memory_region_add_subregion(system_memory, mmc->psram_base, machine->ram);
105
106
- switch (mmc->fpga_type) {
107
- case FPGA_AN385:
108
- case FPGA_AN386:
109
- make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
110
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
111
- make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
112
- make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
113
- &mms->ssram23, 0x20400000);
114
+ if (mmc->has_block_ram) {
115
make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000);
116
make_ram_alias(&mms->blockram_m1, "mps.blockram_m1",
117
&mms->blockram, 0x01004000);
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
&mms->blockram, 0x01008000);
120
make_ram_alias(&mms->blockram_m3, "mps.blockram_m3",
121
&mms->blockram, 0x0100c000);
122
+ }
123
+
124
+ switch (mmc->fpga_type) {
125
+ case FPGA_AN385:
126
+ case FPGA_AN386:
127
+ case FPGA_AN500:
128
+ make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
129
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
130
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
131
+ make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
132
+ &mms->ssram23, 0x20400000);
133
break;
134
case FPGA_AN511:
135
make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000);
136
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
137
switch (mmc->fpga_type) {
138
case FPGA_AN385:
139
case FPGA_AN386:
140
+ case FPGA_AN500:
141
qdev_prop_set_uint32(armv7m, "num-irq", 32);
142
break;
143
case FPGA_AN511:
144
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
145
switch (mmc->fpga_type) {
146
case FPGA_AN385:
147
case FPGA_AN386:
148
+ case FPGA_AN500:
149
{
150
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
151
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
152
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
153
/* In hardware this is a LAN9220; the LAN9118 is software compatible
154
* except that it doesn't support the checksum-offload feature.
155
*/
156
- lan9118_init(&nd_table[0], 0x40200000,
157
+ lan9118_init(&nd_table[0], mmc->ethernet_base,
158
qdev_get_gpio_in(armv7m,
159
mmc->fpga_type == FPGA_AN511 ? 47 : 13));
160
29
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
161
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
30
mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3";
31
mmc->fpga_type = FPGA_AN385;
162
mmc->fpga_type = FPGA_AN385;
32
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
163
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
33
- mmc->scc_id = 0x41040000 | (385 << 4);
164
mmc->scc_id = 0x41043850;
34
+ mmc->scc_id = 0x41043850;
165
+ mmc->psram_base = 0x21000000;
35
}
166
+ mmc->ethernet_base = 0x40200000;
167
+ mmc->has_block_ram = true;
168
}
169
170
static void mps2_an386_class_init(ObjectClass *oc, void *data)
171
@@ -XXX,XX +XXX,XX @@ static void mps2_an386_class_init(ObjectClass *oc, void *data)
172
mmc->fpga_type = FPGA_AN386;
173
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
174
mmc->scc_id = 0x41043860;
175
+ mmc->psram_base = 0x21000000;
176
+ mmc->ethernet_base = 0x40200000;
177
+ mmc->has_block_ram = true;
178
+}
179
+
180
+static void mps2_an500_class_init(ObjectClass *oc, void *data)
181
+{
182
+ MachineClass *mc = MACHINE_CLASS(oc);
183
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
184
+
185
+ mc->desc = "ARM MPS2 with AN500 FPGA image for Cortex-M7";
186
+ mmc->fpga_type = FPGA_AN500;
187
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m7");
188
+ mmc->scc_id = 0x41045000;
189
+ mmc->psram_base = 0x60000000;
190
+ mmc->ethernet_base = 0xa0000000;
191
+ mmc->has_block_ram = false;
192
}
36
193
37
static void mps2_an511_class_init(ObjectClass *oc, void *data)
194
static void mps2_an511_class_init(ObjectClass *oc, void *data)
38
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
195
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
39
mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3";
40
mmc->fpga_type = FPGA_AN511;
196
mmc->fpga_type = FPGA_AN511;
41
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
197
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
42
- mmc->scc_id = 0x4104000 | (511 << 4);
198
mmc->scc_id = 0x41045110;
43
+ mmc->scc_id = 0x41045110;
199
+ mmc->psram_base = 0x21000000;
44
}
200
+ mmc->ethernet_base = 0x40200000;
201
+ mmc->has_block_ram = false;
202
}
45
203
46
static const TypeInfo mps2_info = {
204
static const TypeInfo mps2_info = {
205
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an386_info = {
206
.class_init = mps2_an386_class_init,
207
};
208
209
+static const TypeInfo mps2_an500_info = {
210
+ .name = TYPE_MPS2_AN500_MACHINE,
211
+ .parent = TYPE_MPS2_MACHINE,
212
+ .class_init = mps2_an500_class_init,
213
+};
214
+
215
static const TypeInfo mps2_an511_info = {
216
.name = TYPE_MPS2_AN511_MACHINE,
217
.parent = TYPE_MPS2_MACHINE,
218
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
219
type_register_static(&mps2_info);
220
type_register_static(&mps2_an385_info);
221
type_register_static(&mps2_an386_info);
222
+ type_register_static(&mps2_an500_info);
223
type_register_static(&mps2_an511_info);
224
}
225
47
--
226
--
48
2.18.0
227
2.20.1
49
228
50
229
diff view generated by jsdifflib
1
The IoTKit doesn't have any MSCs itself but it does need
1
Make the list of MPS2 boards consistent in the phrasing of each
2
some wiring to connect the external signals from MSCs
2
entry, use the correct casing of "Arm", and move the mps2-an511
3
in the outer board model up to the registers and the
3
entry so the list is in numeric order.
4
NVIC IRQ line.
5
6
We also need to expose a MemoryRegion corresponding to
7
the AHB bus, so that MSCs in the outer board model can
8
use that as their downstream port. (In the FPGA this is
9
the "AHB Slave Expansion" ports shown in the block
10
diagram in the AN505 documentation.)
11
4
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20180820141116.9118-14-peter.maydell@linaro.org
7
Message-id: 20200903202048.15370-4-peter.maydell@linaro.org
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
8
---
17
include/hw/arm/iotkit.h | 8 ++++++++
9
docs/system/arm/mps2.rst | 14 +++++++-------
18
hw/arm/iotkit.c | 15 +++++++++++++++
10
1 file changed, 7 insertions(+), 7 deletions(-)
19
2 files changed, 23 insertions(+)
20
11
21
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
12
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/iotkit.h
14
--- a/docs/system/arm/mps2.rst
24
+++ b/include/hw/arm/iotkit.h
15
+++ b/docs/system/arm/mps2.rst
25
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ as seen by the guest depend significantly on the FPGA image.
26
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
17
QEMU models the following FPGA images:
27
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
18
28
* are wired to the NVIC lines 32 .. n+32
19
``mps2-an385``
29
+ * + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
20
- Cortex-M3 as documented in ARM Application Note AN385
30
+ * bus master devices in the board model to make transactions into
21
+ Cortex-M3 as documented in Arm Application Note AN385
31
+ * all the devices and memory areas in the IoTKit
22
``mps2-an386``
32
* Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
23
- Cortex-M4 as documented in ARM Application Note AN386
33
* might provide:
24
+ Cortex-M4 as documented in Arm Application Note AN386
34
* + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
25
``mps2-an500``
35
@@ -XXX,XX +XXX,XX @@
26
- Cortex-M7 as documented in ARM Application Note AN500
36
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
27
-``mps2-an511``
37
* might provide:
28
- Cortex-M3 'DesignStart' as documented in AN511
38
* + named GPIO inputs mpcexp_status[0..15]
29
+ Cortex-M7 as documented in Arm Application Note AN500
39
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
30
``mps2-an505``
40
+ * might provide:
31
- Cortex-M33 as documented in ARM Application Note AN505
41
+ * + named GPIO inputs mscexp_status[0..15]
32
+ Cortex-M33 as documented in Arm Application Note AN505
42
+ * + named GPIO outputs mscexp_clear[0..15]
33
+``mps2-an511``
43
+ * + named GPIO outputs mscexp_ns[0..15]
34
+ Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
44
*/
35
``mps2-an521``
45
36
- Dual Cortex-M33 as documented in Application Note AN521
46
#ifndef IOTKIT_H
37
+ Dual Cortex-M33 as documented in Arm Application Note AN521
47
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
38
48
index XXXXXXX..XXXXXXX 100644
39
Differences between QEMU and real hardware:
49
--- a/hw/arm/iotkit.c
50
+++ b/hw/arm/iotkit.c
51
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
52
53
iotkit_forward_sec_resp_cfg(s);
54
55
+ /* Forward the MSC related signals */
56
+ qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
57
+ qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
58
+ qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
59
+ qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
60
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 11));
61
+
62
+ /*
63
+ * Expose our container region to the board model; this corresponds
64
+ * to the AHB Slave Expansion ports which allow bus master devices
65
+ * (eg DMA controllers) in the board model to make transactions into
66
+ * devices in the IoTKit.
67
+ */
68
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
69
+
70
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
71
}
72
40
73
--
41
--
74
2.18.0
42
2.20.1
75
43
76
44
diff view generated by jsdifflib
1
The PL022 interrupt registers have bits allocated as:
1
Deprecate our Unicore32 target support:
2
0: ROR (receive overrun)
2
* the Linux kernel dropped support for unicore32 in commit
3
1: RT (receive timeout)
3
05119217a9bd199c for its 5.9 release (with rationale in the
4
2: RX (receive FIFO half full or less)
4
cover letter: https://lkml.org/lkml/2020/8/3/232 )
5
3: TX (transmit FIFO half full or less)
5
* there is apparently no upstream toolchain that can create unicore32
6
6
binaries
7
A cut and paste error meant we had the wrong value for
7
* the maintainer doesn't seem to have made any contributions to
8
the PL022_INT_RT constant. This bug doesn't affect device
8
QEMU since the port first landed in 2012
9
behaviour, because we don't implement the receive timeout
9
* nobody else seems to have made changes to the unicore code except
10
feature and so never set that interrupt bit.
10
for generic cleanups either
11
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20180820141116.9118-20-peter.maydell@linaro.org
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200825172719.19422-1-peter.maydell@linaro.org
15
---
15
---
16
hw/ssi/pl022.c | 2 +-
16
docs/system/deprecated.rst | 8 ++++++++
17
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 8 insertions(+)
18
18
19
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
19
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/ssi/pl022.c
21
--- a/docs/system/deprecated.rst
22
+++ b/hw/ssi/pl022.c
22
+++ b/docs/system/deprecated.rst
23
@@ -XXX,XX +XXX,XX @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
23
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
24
#define PL022_SR_BSY 0x10
24
linux-user mode CPUs
25
25
--------------------
26
#define PL022_INT_ROR 0x01
26
27
-#define PL022_INT_RT 0x04
27
+``unicore32`` CPUs (since 5.2.0)
28
+#define PL022_INT_RT 0x02
28
+''''''''''''''''''''''''''''''''
29
#define PL022_INT_RX 0x04
29
+
30
#define PL022_INT_TX 0x08
30
+The ``unicore32`` guest CPU support is deprecated and will be removed in
31
+a future version of QEMU. Support for this CPU was removed from the
32
+upstream Linux kernel, and there is no available upstream toolchain
33
+to build binaries for it.
34
+
35
``tilegx`` CPUs (since 5.1.0)
36
'''''''''''''''''''''''''''''
31
37
32
--
38
--
33
2.18.0
39
2.20.1
34
40
35
41
diff view generated by jsdifflib
1
The kernel booting specification for an AArch32 kernel requires that
1
Deprecate our lm32 target support. Michael Walle (former lm32 maintainer)
2
it is booted in Hyp mode if available; otherwise the kernel can't
2
suggested that we do this in 2019:
3
enable KVM. We were incorrectly leaving the kernel in SVC mode.
3
https://www.mail-archive.com/qemu-devel@nongnu.org/msg605024.html
4
If we're booting an AArch32 kernel in the Nonsecure state and Hyp
4
because the only public user of the architecture is the many-years-dead
5
mode is available, start in it.
5
milkymist project. (The Linux port to lm32 was never merged upstream.)
6
7
In commit 4b4d96c776f552e (March 2020) we marked it as 'orphan' in
8
the MAINTAINERS file, but didn't officially deprecate it. Mark it
9
deprecated now, with the intention of removing it from QEMU in
10
mid-2021 before the 6.1 release.
6
11
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
15
Reviewed-by: Thomas Huth <thuth@redhat.com>
11
Message-id: 20180820153020.21478-7-peter.maydell@linaro.org
16
Acked-by: Michael Walle <michael@walle.cc>
17
Message-id: 20200827113259.25064-1-peter.maydell@linaro.org
12
---
18
---
13
hw/arm/boot.c | 11 +++++++++++
19
docs/system/deprecated.rst | 8 ++++++++
14
1 file changed, 11 insertions(+)
20
1 file changed, 8 insertions(+)
15
21
16
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/boot.c
24
--- a/docs/system/deprecated.rst
19
+++ b/hw/arm/boot.c
25
+++ b/docs/system/deprecated.rst
20
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
26
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
21
}
27
linux-user mode CPUs
22
}
28
--------------------
23
29
24
+ if (!env->aarch64 && !info->secure_boot &&
30
+``lm32`` CPUs (since 5.2.0)
25
+ arm_feature(env, ARM_FEATURE_EL2)) {
31
+'''''''''''''''''''''''''''
26
+ /*
27
+ * This is an AArch32 boot not to Secure state, and
28
+ * we have Hyp mode available, so boot the kernel into
29
+ * Hyp mode. This is not how the CPU comes out of reset,
30
+ * so we need to manually put it there.
31
+ */
32
+ cpsr_write(env, ARM_CPU_MODE_HYP, CPSR_M, CPSRWriteRaw);
33
+ }
34
+
32
+
35
if (cs == first_cpu) {
33
+The ``lm32`` guest CPU support is deprecated and will be removed in
36
AddressSpace *as = arm_boot_address_space(cpu, info);
34
+a future version of QEMU. The only public user of this architecture
35
+was the milkymist project, which has been dead for years; there was
36
+never an upstream Linux port.
37
+
38
``unicore32`` CPUs (since 5.2.0)
39
''''''''''''''''''''''''''''''''
37
40
38
--
41
--
39
2.18.0
42
2.20.1
40
43
41
44
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
This check was backwards when introduced in commit
4
Message-id: 20180814002653.12828-5-richard.henderson@linaro.org
4
033614c47de78409ad3fb39bb7bd1483b71c6789:
5
6
target/arm: Filter cycle counter based on PMCCFILTR_EL0
7
8
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/helper.c | 101 ++++++++++++++++++++++----------------------
13
target/arm/helper.c | 2 +-
9
1 file changed, 51 insertions(+), 50 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
15
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
18
--- a/target/arm/helper.c
14
+++ b/target/arm/helper.c
19
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
20
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
16
void *fpstp) \
21
}
17
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
22
} else {
18
23
prohibited = arm_feature(env, ARM_FEATURE_EL3) &&
19
-/* Notice that we want only input-denormal exception flags from the
24
- (env->cp15.mdcr_el3 & MDCR_SPME);
20
- * scalbn operation: the other possible flags (overflow+inexact if
25
+ !(env->cp15.mdcr_el3 & MDCR_SPME);
21
- * we overflow to infinity, output-denormal) aren't correct for the
26
}
22
- * complete scale-and-convert operation.
27
23
- */
28
if (prohibited && counter == 31) {
24
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, round) \
25
-uint##isz##_t HELPER(vfp_to##name##p##round)(float##fsz x, \
26
- uint32_t shift, \
27
- void *fpstp) \
28
-{ \
29
- float_status *fpst = fpstp; \
30
- int old_exc_flags = get_float_exception_flags(fpst); \
31
- float##fsz tmp; \
32
- if (float##fsz##_is_any_nan(x)) { \
33
- float_raise(float_flag_invalid, fpst); \
34
- return 0; \
35
- } \
36
- tmp = float##fsz##_scalbn(x, shift, fpst); \
37
- old_exc_flags |= get_float_exception_flags(fpst) \
38
- & float_flag_input_denormal; \
39
- set_float_exception_flags(old_exc_flags, fpst); \
40
- return float##fsz##_to_##itype##round(tmp, fpst); \
41
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
42
+uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
43
+ void *fpst) \
44
+{ \
45
+ if (unlikely(float##fsz##_is_any_nan(x))) { \
46
+ float_raise(float_flag_invalid, fpst); \
47
+ return 0; \
48
+ } \
49
+ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
50
}
51
52
#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
53
VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
54
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, _round_to_zero) \
55
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
56
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
57
+ float_round_to_zero, _round_to_zero) \
58
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
59
+ get_float_rounding_mode(fpst), )
60
61
#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
62
VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
63
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
64
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
65
+ get_float_rounding_mode(fpst), )
66
67
VFP_CONV_FIX(sh, d, 64, 64, int16)
68
VFP_CONV_FIX(sl, d, 64, 64, int32)
69
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
70
return uint64_to_float16_scalbn(x, -shift, fpst);
71
}
72
73
-static float64 do_prescale_fp16(float16 f, int shift, float_status *fpst)
74
-{
75
- if (unlikely(float16_is_any_nan(f))) {
76
- float_raise(float_flag_invalid, fpst);
77
- return 0;
78
- } else {
79
- int old_exc_flags = get_float_exception_flags(fpst);
80
- float64 ret;
81
-
82
- ret = float16_to_float64(f, true, fpst);
83
- ret = float64_scalbn(ret, shift, fpst);
84
- old_exc_flags |= get_float_exception_flags(fpst)
85
- & float_flag_input_denormal;
86
- set_float_exception_flags(old_exc_flags, fpst);
87
-
88
- return ret;
89
- }
90
-}
91
-
92
uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
93
{
94
- return float64_to_int16(do_prescale_fp16(x, shift, fpst), fpst);
95
+ if (unlikely(float16_is_any_nan(x))) {
96
+ float_raise(float_flag_invalid, fpst);
97
+ return 0;
98
+ }
99
+ return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
100
+ shift, fpst);
101
}
102
103
uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
104
{
105
- return float64_to_uint16(do_prescale_fp16(x, shift, fpst), fpst);
106
+ if (unlikely(float16_is_any_nan(x))) {
107
+ float_raise(float_flag_invalid, fpst);
108
+ return 0;
109
+ }
110
+ return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
111
+ shift, fpst);
112
}
113
114
uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
115
{
116
- return float64_to_int32(do_prescale_fp16(x, shift, fpst), fpst);
117
+ if (unlikely(float16_is_any_nan(x))) {
118
+ float_raise(float_flag_invalid, fpst);
119
+ return 0;
120
+ }
121
+ return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
122
+ shift, fpst);
123
}
124
125
uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
126
{
127
- return float64_to_uint32(do_prescale_fp16(x, shift, fpst), fpst);
128
+ if (unlikely(float16_is_any_nan(x))) {
129
+ float_raise(float_flag_invalid, fpst);
130
+ return 0;
131
+ }
132
+ return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
133
+ shift, fpst);
134
}
135
136
uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
137
{
138
- return float64_to_int64(do_prescale_fp16(x, shift, fpst), fpst);
139
+ if (unlikely(float16_is_any_nan(x))) {
140
+ float_raise(float_flag_invalid, fpst);
141
+ return 0;
142
+ }
143
+ return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
144
+ shift, fpst);
145
}
146
147
uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
148
{
149
- return float64_to_uint64(do_prescale_fp16(x, shift, fpst), fpst);
150
+ if (unlikely(float16_is_any_nan(x))) {
151
+ float_raise(float_flag_invalid, fpst);
152
+ return 0;
153
+ }
154
+ return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
155
+ shift, fpst);
156
}
157
158
/* Set the current fp rounding mode and return the old one.
159
--
29
--
160
2.18.0
30
2.20.1
161
31
162
32
diff view generated by jsdifflib
1
Reduce the size of the per-cpu GICH memory regions from 0x1000
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
to 0x200. The registers only cover 0x200 bytes, and the Cortex-A15
3
wants to map them at a spacing of 0x200 bytes apart. Having the
4
region be too large interferes with mapping them like that, so
5
reduce it.
6
2
3
Correct the GEMs tx/rx clocks to use the 125Mhz fixed-clock.
4
This matches the setup with the fixed-link 100Mbit PHY.
5
It also avoids the following warnings from the Linux kernel
6
driver:
7
8
eth0: unable to generate target frequency: 125000000 Hz
9
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
13
Message-id: 20200909174647.662864-2-edgar.iglesias@gmail.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20180821132811.17675-3-peter.maydell@linaro.org
10
---
15
---
11
hw/intc/arm_gic.c | 2 +-
16
hw/arm/xlnx-versal-virt.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 1 insertion(+), 1 deletion(-)
13
18
14
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
19
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gic.c
21
--- a/hw/arm/xlnx-versal-virt.c
17
+++ b/hw/intc/arm_gic.c
22
+++ b/hw/arm/xlnx-versal-virt.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
23
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gem_nodes(VersalVirt *s)
19
for (i = 0; i < s->num_cpu; i++) {
24
s->phandle.ethernet_phy[i]);
20
memory_region_init_io(&s->vifaceiomem[i + 1], OBJECT(s),
25
qemu_fdt_setprop_cells(s->fdt, name, "clocks",
21
&gic_viface_ops, &s->backref[i],
26
s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
22
- "gic_viface", 0x1000);
27
- s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
23
+ "gic_viface", 0x200);
28
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
24
sysbus_init_mmio(sbd, &s->vifaceiomem[i + 1]);
29
qemu_fdt_setprop(s->fdt, name, "clock-names",
25
}
30
clocknames, sizeof(clocknames));
26
}
31
qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
27
--
32
--
28
2.18.0
33
2.20.1
29
34
30
35
diff view generated by jsdifflib
1
Implement a model of the TrustZone Master Securtiy Controller,
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
as documented in the Arm CoreLink SIE-200 System IP for
2
3
Embedded TRM (DDI0571G):
3
Implement a device model for the System Global Control Registers in the
4
https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
4
NPCM730 and NPCM750 BMC SoCs.
5
5
6
The MSC is intended to sit in front of a device which can
6
This is primarily used to enable SMP boot (the boot ROM spins reading
7
be a bus master (eg a DMA controller) and programmably gate
7
the SCRPAD register) and DDR memory initialization; other registers are
8
its transactions. This allows a bus-mastering device to be
8
best effort for now.
9
controlled by non-secure code but still restricted from
9
10
making accesses to addresses which are secure-only.
10
The reset values of the MDLR and PWRON registers are determined by the
11
11
SoC variant (730 vs 750) and board straps respectively.
12
13
Reviewed-by: Joel Stanley <joel@jms.id.au>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Alexander Bulekov <alxndr@bu.edu>
18
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Message-id: 20200911052101.2602693-2-hskinnemoen@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20180820141116.9118-12-peter.maydell@linaro.org
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
---
21
---
16
hw/misc/Makefile.objs | 1 +
22
include/hw/misc/npcm7xx_gcr.h | 43 ++++++
17
include/hw/misc/tz-msc.h | 79 ++++++++
23
hw/misc/npcm7xx_gcr.c | 269 ++++++++++++++++++++++++++++++++++
18
hw/misc/tz-msc.c | 308 ++++++++++++++++++++++++++++++++
24
MAINTAINERS | 8 +
19
MAINTAINERS | 2 +
25
hw/arm/Kconfig | 3 +
20
default-configs/arm-softmmu.mak | 1 +
26
hw/misc/meson.build | 3 +
21
hw/misc/trace-events | 9 +
27
hw/misc/trace-events | 4 +
22
6 files changed, 400 insertions(+)
28
6 files changed, 330 insertions(+)
23
create mode 100644 include/hw/misc/tz-msc.h
29
create mode 100644 include/hw/misc/npcm7xx_gcr.h
24
create mode 100644 hw/misc/tz-msc.c
30
create mode 100644 hw/misc/npcm7xx_gcr.c
25
31
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
32
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/Makefile.objs
29
+++ b/hw/misc/Makefile.objs
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
31
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
32
33
obj-$(CONFIG_TZ_MPC) += tz-mpc.o
34
+obj-$(CONFIG_TZ_MSC) += tz-msc.o
35
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
36
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
37
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
38
diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h
39
new file mode 100644
33
new file mode 100644
40
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
41
--- /dev/null
35
--- /dev/null
42
+++ b/include/hw/misc/tz-msc.h
36
+++ b/include/hw/misc/npcm7xx_gcr.h
43
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
44
+/*
38
+/*
45
+ * ARM TrustZone master security controller emulation
39
+ * Nuvoton NPCM7xx System Global Control Registers.
46
+ *
40
+ *
47
+ * Copyright (c) 2018 Linaro Limited
41
+ * Copyright 2020 Google LLC
48
+ * Written by Peter Maydell
42
+ *
49
+ *
43
+ * This program is free software; you can redistribute it and/or modify it
50
+ * This program is free software; you can redistribute it and/or modify
44
+ * under the terms of the GNU General Public License as published by the
51
+ * it under the terms of the GNU General Public License version 2 or
45
+ * Free Software Foundation; either version 2 of the License, or
52
+ * (at your option) any later version.
46
+ * (at your option) any later version.
47
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * for more details.
53
+ */
52
+ */
53
+#ifndef NPCM7XX_GCR_H
54
+#define NPCM7XX_GCR_H
55
+
56
+#include "exec/memory.h"
57
+#include "hw/sysbus.h"
54
+
58
+
55
+/*
59
+/*
56
+ * This is a model of the TrustZone master security controller (MSC).
60
+ * Number of registers in our device state structure. Don't change this without
57
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
61
+ * incrementing the version_id in the vmstate.
58
+ * (DDI 0571G):
59
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
60
+ *
61
+ * The MSC sits in front of a device which can be a bus master (such as
62
+ * a DMA controller) and allows secure software to configure it to either
63
+ * pass through or reject transactions made by that bus master.
64
+ * Rejected transactions may be configured to either be aborted, or to
65
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
66
+ *
67
+ * The MSC has no register interface -- it is configured purely by a
68
+ * collection of input signals from other hardware in the system. Typically
69
+ * they are either hardwired or exposed in an ad-hoc register interface by
70
+ * the SoC that uses the MSC.
71
+ *
72
+ * We don't currently implement the irq_enable GPIO input, because on
73
+ * the MPS2 FPGA images it is always tied high, which is awkward to
74
+ * implement in QEMU.
75
+ *
76
+ * QEMU interface:
77
+ * + Named GPIO input "cfg_nonsec": set to 1 if the bus master should be
78
+ * treated as nonsecure, or 0 for secure
79
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
80
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
81
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
82
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
83
+ * + Property "downstream": MemoryRegion defining where bus master transactions
84
+ * are made if they are not blocked
85
+ * + Property "idau": an object implementing IDAUInterface, which defines which
86
+ * addresses should be treated as secure and which as non-secure.
87
+ * This need not be the same IDAU as the one used by the CPU.
88
+ * + sysbus MMIO region 0: MemoryRegion defining the upstream end of the MSC;
89
+ * this should be passed to the bus master device as the region it should
90
+ * make memory transactions to
91
+ */
62
+ */
92
+
63
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
93
+#ifndef TZ_MSC_H
64
+
94
+#define TZ_MSC_H
65
+typedef struct NPCM7xxGCRState {
95
+
66
+ SysBusDevice parent;
96
+#include "hw/sysbus.h"
67
+
97
+#include "target/arm/idau.h"
68
+ MemoryRegion iomem;
98
+
69
+
99
+#define TYPE_TZ_MSC "tz-msc"
70
+ uint32_t regs[NPCM7XX_GCR_NR_REGS];
100
+#define TZ_MSC(obj) OBJECT_CHECK(TZMSC, (obj), TYPE_TZ_MSC)
71
+
101
+
72
+ uint32_t reset_pwron;
102
+typedef struct TZMSC {
73
+ uint32_t reset_mdlr;
103
+ /*< private >*/
74
+ uint32_t reset_intcr3;
104
+ SysBusDevice parent_obj;
75
+} NPCM7xxGCRState;
105
+
76
+
106
+ /*< public >*/
77
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
107
+
78
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
108
+ /* State: these just track the values of our input signals */
79
+
109
+ bool cfg_nonsec;
80
+#endif /* NPCM7XX_GCR_H */
110
+ bool cfg_sec_resp;
81
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
111
+ bool irq_clear;
112
+ /* State: are we asserting irq ? */
113
+ bool irq_status;
114
+
115
+ qemu_irq irq;
116
+ MemoryRegion *downstream;
117
+ AddressSpace downstream_as;
118
+ MemoryRegion upstream;
119
+ IDAUInterface *idau;
120
+} TZMSC;
121
+
122
+#endif
123
diff --git a/hw/misc/tz-msc.c b/hw/misc/tz-msc.c
124
new file mode 100644
82
new file mode 100644
125
index XXXXXXX..XXXXXXX
83
index XXXXXXX..XXXXXXX
126
--- /dev/null
84
--- /dev/null
127
+++ b/hw/misc/tz-msc.c
85
+++ b/hw/misc/npcm7xx_gcr.c
128
@@ -XXX,XX +XXX,XX @@
86
@@ -XXX,XX +XXX,XX @@
129
+/*
87
+/*
130
+ * ARM TrustZone master security controller emulation
88
+ * Nuvoton NPCM7xx System Global Control Registers.
131
+ *
89
+ *
132
+ * Copyright (c) 2018 Linaro Limited
90
+ * Copyright 2020 Google LLC
133
+ * Written by Peter Maydell
91
+ *
134
+ *
92
+ * This program is free software; you can redistribute it and/or modify it
135
+ * This program is free software; you can redistribute it and/or modify
93
+ * under the terms of the GNU General Public License as published by the
136
+ * it under the terms of the GNU General Public License version 2 or
94
+ * Free Software Foundation; either version 2 of the License, or
137
+ * (at your option) any later version.
95
+ * (at your option) any later version.
96
+ *
97
+ * This program is distributed in the hope that it will be useful, but WITHOUT
98
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
99
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
100
+ * for more details.
138
+ */
101
+ */
139
+
102
+
140
+#include "qemu/osdep.h"
103
+#include "qemu/osdep.h"
104
+
105
+#include "hw/misc/npcm7xx_gcr.h"
106
+#include "hw/qdev-properties.h"
107
+#include "migration/vmstate.h"
108
+#include "qapi/error.h"
109
+#include "qemu/cutils.h"
141
+#include "qemu/log.h"
110
+#include "qemu/log.h"
142
+#include "qapi/error.h"
111
+#include "qemu/module.h"
112
+#include "qemu/units.h"
113
+
143
+#include "trace.h"
114
+#include "trace.h"
144
+#include "hw/sysbus.h"
115
+
145
+#include "hw/registerfields.h"
116
+#define NPCM7XX_GCR_MIN_DRAM_SIZE (128 * MiB)
146
+#include "hw/misc/tz-msc.h"
117
+#define NPCM7XX_GCR_MAX_DRAM_SIZE (2 * GiB)
147
+
118
+
148
+static void tz_msc_update_irq(TZMSC *s)
119
+enum NPCM7xxGCRRegisters {
149
+{
120
+ NPCM7XX_GCR_PDID,
150
+ bool level = s->irq_status;
121
+ NPCM7XX_GCR_PWRON,
151
+
122
+ NPCM7XX_GCR_MFSEL1 = 0x0c / sizeof(uint32_t),
152
+ trace_tz_msc_update_irq(level);
123
+ NPCM7XX_GCR_MFSEL2,
153
+ qemu_set_irq(s->irq, level);
124
+ NPCM7XX_GCR_MISCPE,
154
+}
125
+ NPCM7XX_GCR_SPSWC = 0x038 / sizeof(uint32_t),
155
+
126
+ NPCM7XX_GCR_INTCR,
156
+static void tz_msc_cfg_nonsec(void *opaque, int n, int level)
127
+ NPCM7XX_GCR_INTSR,
157
+{
128
+ NPCM7XX_GCR_HIFCR = 0x050 / sizeof(uint32_t),
158
+ TZMSC *s = TZ_MSC(opaque);
129
+ NPCM7XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t),
159
+
130
+ NPCM7XX_GCR_MFSEL3,
160
+ trace_tz_msc_cfg_nonsec(level);
131
+ NPCM7XX_GCR_SRCNT,
161
+ s->cfg_nonsec = level;
132
+ NPCM7XX_GCR_RESSR,
162
+}
133
+ NPCM7XX_GCR_RLOCKR1,
163
+
134
+ NPCM7XX_GCR_FLOCKR1,
164
+static void tz_msc_cfg_sec_resp(void *opaque, int n, int level)
135
+ NPCM7XX_GCR_DSCNT,
165
+{
136
+ NPCM7XX_GCR_MDLR,
166
+ TZMSC *s = TZ_MSC(opaque);
137
+ NPCM7XX_GCR_SCRPAD3,
167
+
138
+ NPCM7XX_GCR_SCRPAD2,
168
+ trace_tz_msc_cfg_sec_resp(level);
139
+ NPCM7XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t),
169
+ s->cfg_sec_resp = level;
140
+ NPCM7XX_GCR_INTCR3,
170
+}
141
+ NPCM7XX_GCR_VSINTR = 0x0ac / sizeof(uint32_t),
171
+
142
+ NPCM7XX_GCR_MFSEL4,
172
+static void tz_msc_irq_clear(void *opaque, int n, int level)
143
+ NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
173
+{
144
+ NPCM7XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t),
174
+ TZMSC *s = TZ_MSC(opaque);
145
+ NPCM7XX_GCR_CP2BST,
175
+
146
+ NPCM7XX_GCR_B2CPNT,
176
+ trace_tz_msc_irq_clear(level);
147
+ NPCM7XX_GCR_CPPCTL,
177
+
148
+ NPCM7XX_GCR_I2CSEGSEL,
178
+ s->irq_clear = level;
149
+ NPCM7XX_GCR_I2CSEGCTL,
179
+ if (level) {
150
+ NPCM7XX_GCR_VSRCR,
180
+ s->irq_status = false;
151
+ NPCM7XX_GCR_MLOCKR,
181
+ tz_msc_update_irq(s);
152
+ NPCM7XX_GCR_SCRPAD = 0x013c / sizeof(uint32_t),
153
+ NPCM7XX_GCR_USB1PHYCTL,
154
+ NPCM7XX_GCR_USB2PHYCTL,
155
+ NPCM7XX_GCR_REGS_END,
156
+};
157
+
158
+static const uint32_t cold_reset_values[NPCM7XX_GCR_NR_REGS] = {
159
+ [NPCM7XX_GCR_PDID] = 0x04a92750, /* Poleg A1 */
160
+ [NPCM7XX_GCR_MISCPE] = 0x0000ffff,
161
+ [NPCM7XX_GCR_SPSWC] = 0x00000003,
162
+ [NPCM7XX_GCR_INTCR] = 0x0000035e,
163
+ [NPCM7XX_GCR_HIFCR] = 0x0000004e,
164
+ [NPCM7XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */
165
+ [NPCM7XX_GCR_RESSR] = 0x80000000,
166
+ [NPCM7XX_GCR_DSCNT] = 0x000000c0,
167
+ [NPCM7XX_GCR_DAVCLVLR] = 0x5a00f3cf,
168
+ [NPCM7XX_GCR_SCRPAD] = 0x00000008,
169
+ [NPCM7XX_GCR_USB1PHYCTL] = 0x034730e4,
170
+ [NPCM7XX_GCR_USB2PHYCTL] = 0x034730e4,
171
+};
172
+
173
+static uint64_t npcm7xx_gcr_read(void *opaque, hwaddr offset, unsigned size)
174
+{
175
+ uint32_t reg = offset / sizeof(uint32_t);
176
+ NPCM7xxGCRState *s = opaque;
177
+
178
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
179
+ qemu_log_mask(LOG_GUEST_ERROR,
180
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
181
+ __func__, offset);
182
+ return 0;
182
+ }
183
+ }
183
+}
184
+
184
+
185
+ trace_npcm7xx_gcr_read(offset, s->regs[reg]);
185
+/* The MSC may either block a transaction by aborting it, block a
186
+
186
+ * transaction by making it RAZ/WI, allow it through with
187
+ return s->regs[reg];
187
+ * MemTxAttrs indicating a secure transaction, or allow it with
188
+}
188
+ * MemTxAttrs indicating a non-secure transaction.
189
+
189
+ */
190
+static void npcm7xx_gcr_write(void *opaque, hwaddr offset,
190
+typedef enum MSCAction {
191
+ uint64_t v, unsigned size)
191
+ MSCBlockAbort,
192
+{
192
+ MSCBlockRAZWI,
193
+ uint32_t reg = offset / sizeof(uint32_t);
193
+ MSCAllowSecure,
194
+ NPCM7xxGCRState *s = opaque;
194
+ MSCAllowNonSecure,
195
+ uint32_t value = v;
195
+} MSCAction;
196
+
196
+
197
+ trace_npcm7xx_gcr_write(offset, value);
197
+static MSCAction tz_msc_check(TZMSC *s, hwaddr addr)
198
+
198
+{
199
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
199
+ /*
200
+ qemu_log_mask(LOG_GUEST_ERROR,
200
+ * Check whether to allow an access from the bus master, returning
201
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
201
+ * an MSCAction indicating the required behaviour. If the transaction
202
+ __func__, offset);
202
+ * is blocked, the caller must check cfg_sec_resp to determine
203
+ return;
203
+ * whether to abort or RAZ/WI the transaction.
204
+ */
205
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(s->idau);
206
+ IDAUInterface *ii = IDAU_INTERFACE(s->idau);
207
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
208
+ int idau_region = IREGION_NOTVALID;
209
+
210
+ iic->check(ii, addr, &idau_region, &idau_exempt, &idau_ns, &idau_nsc);
211
+
212
+ if (idau_exempt) {
213
+ /*
214
+ * Uncheck region -- OK, transaction type depends on
215
+ * whether bus master is configured as Secure or NonSecure
216
+ */
217
+ return s->cfg_nonsec ? MSCAllowNonSecure : MSCAllowSecure;
218
+ }
204
+ }
219
+
205
+
220
+ if (idau_ns) {
206
+ switch (reg) {
221
+ /* NonSecure region -- always forward as NS transaction */
207
+ case NPCM7XX_GCR_PDID:
222
+ return MSCAllowNonSecure;
208
+ case NPCM7XX_GCR_PWRON:
223
+ }
209
+ case NPCM7XX_GCR_INTSR:
224
+
210
+ qemu_log_mask(LOG_GUEST_ERROR,
225
+ if (!s->cfg_nonsec) {
211
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
226
+ /* Access to Secure region by Secure bus master: OK */
212
+ __func__, offset);
227
+ return MSCAllowSecure;
213
+ return;
228
+ }
214
+
229
+
215
+ case NPCM7XX_GCR_RESSR:
230
+ /* Attempted access to Secure region by NS bus master: block */
216
+ case NPCM7XX_GCR_CP2BST:
231
+ trace_tz_msc_access_blocked(addr);
217
+ /* Write 1 to clear */
232
+ if (!s->cfg_sec_resp) {
218
+ value = s->regs[reg] & ~value;
233
+ return MSCBlockRAZWI;
234
+ }
235
+
236
+ /*
237
+ * The TRM isn't clear on behaviour if irq_clear is high when a
238
+ * transaction is blocked. We assume that the MSC behaves like the
239
+ * PPC, where holding irq_clear high suppresses the interrupt.
240
+ */
241
+ if (!s->irq_clear) {
242
+ s->irq_status = true;
243
+ tz_msc_update_irq(s);
244
+ }
245
+ return MSCBlockAbort;
246
+}
247
+
248
+static MemTxResult tz_msc_read(void *opaque, hwaddr addr, uint64_t *pdata,
249
+ unsigned size, MemTxAttrs attrs)
250
+{
251
+ TZMSC *s = opaque;
252
+ AddressSpace *as = &s->downstream_as;
253
+ uint64_t data;
254
+ MemTxResult res;
255
+
256
+ switch (tz_msc_check(s, addr)) {
257
+ case MSCBlockAbort:
258
+ return MEMTX_ERROR;
259
+ case MSCBlockRAZWI:
260
+ *pdata = 0;
261
+ return MEMTX_OK;
262
+ case MSCAllowSecure:
263
+ attrs.secure = 1;
264
+ attrs.unspecified = 0;
265
+ break;
219
+ break;
266
+ case MSCAllowNonSecure:
220
+
267
+ attrs.secure = 0;
221
+ case NPCM7XX_GCR_RLOCKR1:
268
+ attrs.unspecified = 0;
222
+ case NPCM7XX_GCR_MDLR:
223
+ /* Write 1 to set */
224
+ value |= s->regs[reg];
225
+ break;
226
+ };
227
+
228
+ s->regs[reg] = value;
229
+}
230
+
231
+static const struct MemoryRegionOps npcm7xx_gcr_ops = {
232
+ .read = npcm7xx_gcr_read,
233
+ .write = npcm7xx_gcr_write,
234
+ .endianness = DEVICE_LITTLE_ENDIAN,
235
+ .valid = {
236
+ .min_access_size = 4,
237
+ .max_access_size = 4,
238
+ .unaligned = false,
239
+ },
240
+};
241
+
242
+static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type)
243
+{
244
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
245
+
246
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
247
+
248
+ switch (type) {
249
+ case RESET_TYPE_COLD:
250
+ memcpy(s->regs, cold_reset_values, sizeof(s->regs));
251
+ s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
252
+ s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
253
+ s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
269
+ break;
254
+ break;
270
+ }
255
+ }
271
+
256
+}
272
+ switch (size) {
257
+
273
+ case 1:
258
+static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp)
274
+ data = address_space_ldub(as, addr, attrs, &res);
259
+{
275
+ break;
260
+ ERRP_GUARD();
276
+ case 2:
261
+ NPCM7xxGCRState *s = NPCM7XX_GCR(dev);
277
+ data = address_space_lduw_le(as, addr, attrs, &res);
262
+ uint64_t dram_size;
278
+ break;
263
+ Object *obj;
279
+ case 4:
264
+
280
+ data = address_space_ldl_le(as, addr, attrs, &res);
265
+ obj = object_property_get_link(OBJECT(dev), "dram-mr", errp);
281
+ break;
266
+ if (!obj) {
282
+ case 8:
267
+ error_prepend(errp, "%s: required dram-mr link not found: ", __func__);
283
+ data = address_space_ldq_le(as, addr, attrs, &res);
284
+ break;
285
+ default:
286
+ g_assert_not_reached();
287
+ }
288
+ *pdata = data;
289
+ return res;
290
+}
291
+
292
+static MemTxResult tz_msc_write(void *opaque, hwaddr addr, uint64_t val,
293
+ unsigned size, MemTxAttrs attrs)
294
+{
295
+ TZMSC *s = opaque;
296
+ AddressSpace *as = &s->downstream_as;
297
+ MemTxResult res;
298
+
299
+ switch (tz_msc_check(s, addr)) {
300
+ case MSCBlockAbort:
301
+ return MEMTX_ERROR;
302
+ case MSCBlockRAZWI:
303
+ return MEMTX_OK;
304
+ case MSCAllowSecure:
305
+ attrs.secure = 1;
306
+ attrs.unspecified = 0;
307
+ break;
308
+ case MSCAllowNonSecure:
309
+ attrs.secure = 0;
310
+ attrs.unspecified = 0;
311
+ break;
312
+ }
313
+
314
+ switch (size) {
315
+ case 1:
316
+ address_space_stb(as, addr, val, attrs, &res);
317
+ break;
318
+ case 2:
319
+ address_space_stw_le(as, addr, val, attrs, &res);
320
+ break;
321
+ case 4:
322
+ address_space_stl_le(as, addr, val, attrs, &res);
323
+ break;
324
+ case 8:
325
+ address_space_stq_le(as, addr, val, attrs, &res);
326
+ break;
327
+ default:
328
+ g_assert_not_reached();
329
+ }
330
+ return res;
331
+}
332
+
333
+static const MemoryRegionOps tz_msc_ops = {
334
+ .read_with_attrs = tz_msc_read,
335
+ .write_with_attrs = tz_msc_write,
336
+ .endianness = DEVICE_LITTLE_ENDIAN,
337
+};
338
+
339
+static void tz_msc_reset(DeviceState *dev)
340
+{
341
+ TZMSC *s = TZ_MSC(dev);
342
+
343
+ trace_tz_msc_reset();
344
+ s->cfg_sec_resp = false;
345
+ s->cfg_nonsec = false;
346
+ s->irq_clear = 0;
347
+ s->irq_status = 0;
348
+}
349
+
350
+static void tz_msc_init(Object *obj)
351
+{
352
+ DeviceState *dev = DEVICE(obj);
353
+ TZMSC *s = TZ_MSC(obj);
354
+
355
+ qdev_init_gpio_in_named(dev, tz_msc_cfg_nonsec, "cfg_nonsec", 1);
356
+ qdev_init_gpio_in_named(dev, tz_msc_cfg_sec_resp, "cfg_sec_resp", 1);
357
+ qdev_init_gpio_in_named(dev, tz_msc_irq_clear, "irq_clear", 1);
358
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
359
+}
360
+
361
+static void tz_msc_realize(DeviceState *dev, Error **errp)
362
+{
363
+ Object *obj = OBJECT(dev);
364
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
365
+ TZMSC *s = TZ_MSC(dev);
366
+ const char *name = "tz-msc-downstream";
367
+ uint64_t size;
368
+
369
+ /*
370
+ * We can't create the upstream end of the port until realize,
371
+ * as we don't know the size of the MR used as the downstream until then.
372
+ * We insist on having a downstream, to avoid complicating the
373
+ * code with handling the "don't know how big this is" case. It's easy
374
+ * enough for the user to create an unimplemented_device as downstream
375
+ * if they have nothing else to plug into this.
376
+ */
377
+ if (!s->downstream) {
378
+ error_setg(errp, "MSC 'downstream' link not set");
379
+ return;
268
+ return;
380
+ }
269
+ }
381
+ if (!s->idau) {
270
+ dram_size = memory_region_size(MEMORY_REGION(obj));
382
+ error_setg(errp, "MSC 'idau' link not set");
271
+ if (!is_power_of_2(dram_size) ||
272
+ dram_size < NPCM7XX_GCR_MIN_DRAM_SIZE ||
273
+ dram_size > NPCM7XX_GCR_MAX_DRAM_SIZE) {
274
+ g_autofree char *sz = size_to_str(dram_size);
275
+ g_autofree char *min_sz = size_to_str(NPCM7XX_GCR_MIN_DRAM_SIZE);
276
+ g_autofree char *max_sz = size_to_str(NPCM7XX_GCR_MAX_DRAM_SIZE);
277
+ error_setg(errp, "%s: unsupported DRAM size %s", __func__, sz);
278
+ error_append_hint(errp,
279
+ "DRAM size must be a power of two between %s and %s,"
280
+ " inclusive.\n", min_sz, max_sz);
383
+ return;
281
+ return;
384
+ }
282
+ }
385
+
283
+
386
+ size = memory_region_size(s->downstream);
284
+ /* Power-on reset value */
387
+ address_space_init(&s->downstream_as, s->downstream, name);
285
+ s->reset_intcr3 = 0x00001002;
388
+ memory_region_init_io(&s->upstream, obj, &tz_msc_ops, s, name, size);
286
+
389
+ sysbus_init_mmio(sbd, &s->upstream);
287
+ /*
390
+}
288
+ * The GMMAP (Graphics Memory Map) field is used by u-boot to detect the
391
+
289
+ * DRAM size, and is normally initialized by the boot block as part of DRAM
392
+static const VMStateDescription tz_msc_vmstate = {
290
+ * training. However, since we don't have a complete emulation of the
393
+ .name = "tz-msc",
291
+ * memory controller and try to make it look like it has already been
394
+ .version_id = 1,
292
+ * initialized, the boot block will skip this initialization, and we need
395
+ .minimum_version_id = 1,
293
+ * to make sure this field is set correctly up front.
294
+ *
295
+ * WARNING: some versions of u-boot only looks at bits 8 and 9, so 2 GiB of
296
+ * DRAM will be interpreted as 128 MiB.
297
+ *
298
+ * https://github.com/Nuvoton-Israel/u-boot/blob/2aef993bd2aafeb5408dbaad0f3ce099ee40c4aa/board/nuvoton/poleg/poleg.c#L244
299
+ */
300
+ s->reset_intcr3 |= ctz64(dram_size / NPCM7XX_GCR_MIN_DRAM_SIZE) << 8;
301
+}
302
+
303
+static void npcm7xx_gcr_init(Object *obj)
304
+{
305
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
306
+
307
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
308
+ TYPE_NPCM7XX_GCR, 4 * KiB);
309
+ sysbus_init_mmio(&s->parent, &s->iomem);
310
+}
311
+
312
+static const VMStateDescription vmstate_npcm7xx_gcr = {
313
+ .name = "npcm7xx-gcr",
314
+ .version_id = 0,
315
+ .minimum_version_id = 0,
396
+ .fields = (VMStateField[]) {
316
+ .fields = (VMStateField[]) {
397
+ VMSTATE_BOOL(cfg_nonsec, TZMSC),
317
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxGCRState, NPCM7XX_GCR_NR_REGS),
398
+ VMSTATE_BOOL(cfg_sec_resp, TZMSC),
318
+ VMSTATE_END_OF_LIST(),
399
+ VMSTATE_BOOL(irq_clear, TZMSC),
319
+ },
400
+ VMSTATE_BOOL(irq_status, TZMSC),
320
+};
401
+ VMSTATE_END_OF_LIST()
321
+
402
+ }
322
+static Property npcm7xx_gcr_properties[] = {
403
+};
323
+ DEFINE_PROP_UINT32("disabled-modules", NPCM7xxGCRState, reset_mdlr, 0),
404
+
324
+ DEFINE_PROP_UINT32("power-on-straps", NPCM7xxGCRState, reset_pwron, 0),
405
+static Property tz_msc_properties[] = {
406
+ DEFINE_PROP_LINK("downstream", TZMSC, downstream,
407
+ TYPE_MEMORY_REGION, MemoryRegion *),
408
+ DEFINE_PROP_LINK("idau", TZMSC, idau,
409
+ TYPE_IDAU_INTERFACE, IDAUInterface *),
410
+ DEFINE_PROP_END_OF_LIST(),
325
+ DEFINE_PROP_END_OF_LIST(),
411
+};
326
+};
412
+
327
+
413
+static void tz_msc_class_init(ObjectClass *klass, void *data)
328
+static void npcm7xx_gcr_class_init(ObjectClass *klass, void *data)
414
+{
329
+{
330
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
415
+ DeviceClass *dc = DEVICE_CLASS(klass);
331
+ DeviceClass *dc = DEVICE_CLASS(klass);
416
+
332
+
417
+ dc->realize = tz_msc_realize;
333
+ QEMU_BUILD_BUG_ON(NPCM7XX_GCR_REGS_END > NPCM7XX_GCR_NR_REGS);
418
+ dc->vmsd = &tz_msc_vmstate;
334
+
419
+ dc->reset = tz_msc_reset;
335
+ dc->desc = "NPCM7xx System Global Control Registers";
420
+ dc->props = tz_msc_properties;
336
+ dc->realize = npcm7xx_gcr_realize;
421
+}
337
+ dc->vmsd = &vmstate_npcm7xx_gcr;
422
+
338
+ rc->phases.enter = npcm7xx_gcr_enter_reset;
423
+static const TypeInfo tz_msc_info = {
339
+
424
+ .name = TYPE_TZ_MSC,
340
+ device_class_set_props(dc, npcm7xx_gcr_properties);
425
+ .parent = TYPE_SYS_BUS_DEVICE,
341
+}
426
+ .instance_size = sizeof(TZMSC),
342
+
427
+ .instance_init = tz_msc_init,
343
+static const TypeInfo npcm7xx_gcr_info = {
428
+ .class_init = tz_msc_class_init,
344
+ .name = TYPE_NPCM7XX_GCR,
429
+};
345
+ .parent = TYPE_SYS_BUS_DEVICE,
430
+
346
+ .instance_size = sizeof(NPCM7xxGCRState),
431
+static void tz_msc_register_types(void)
347
+ .instance_init = npcm7xx_gcr_init,
432
+{
348
+ .class_init = npcm7xx_gcr_class_init,
433
+ type_register_static(&tz_msc_info);
349
+};
434
+}
350
+
435
+
351
+static void npcm7xx_gcr_register_type(void)
436
+type_init(tz_msc_register_types);
352
+{
353
+ type_register_static(&npcm7xx_gcr_info);
354
+}
355
+type_init(npcm7xx_gcr_register_type);
437
diff --git a/MAINTAINERS b/MAINTAINERS
356
diff --git a/MAINTAINERS b/MAINTAINERS
438
index XXXXXXX..XXXXXXX 100644
357
index XXXXXXX..XXXXXXX 100644
439
--- a/MAINTAINERS
358
--- a/MAINTAINERS
440
+++ b/MAINTAINERS
359
+++ b/MAINTAINERS
441
@@ -XXX,XX +XXX,XX @@ F: hw/misc/tz-ppc.c
360
@@ -XXX,XX +XXX,XX @@ S: Odd Fixes
442
F: include/hw/misc/tz-ppc.h
361
F: hw/arm/musicpal.c
443
F: hw/misc/tz-mpc.c
362
F: docs/system/arm/musicpal.rst
444
F: include/hw/misc/tz-mpc.h
363
445
+F: hw/misc/tz-msc.c
364
+Nuvoton NPCM7xx
446
+F: include/hw/misc/tz-msc.h
365
+M: Havard Skinnemoen <hskinnemoen@google.com>
447
366
+M: Tyrone Ting <kfting@nuvoton.com>
448
ARM cores
367
+L: qemu-arm@nongnu.org
368
+S: Supported
369
+F: hw/*/npcm7xx*
370
+F: include/hw/*/npcm7xx*
371
+
372
nSeries
373
M: Andrzej Zaborowski <balrogg@gmail.com>
449
M: Peter Maydell <peter.maydell@linaro.org>
374
M: Peter Maydell <peter.maydell@linaro.org>
450
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
375
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
451
index XXXXXXX..XXXXXXX 100644
376
index XXXXXXX..XXXXXXX 100644
452
--- a/default-configs/arm-softmmu.mak
377
--- a/hw/arm/Kconfig
453
+++ b/default-configs/arm-softmmu.mak
378
+++ b/hw/arm/Kconfig
454
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
379
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
455
CONFIG_MPS2_SCC=y
380
select VIRTIO_MMIO
456
381
select UNIMP
457
CONFIG_TZ_MPC=y
382
458
+CONFIG_TZ_MSC=y
383
+config NPCM7XX
459
CONFIG_TZ_PPC=y
384
+ bool
460
CONFIG_IOTKIT=y
385
+
461
CONFIG_IOTKIT_SECCTL=y
386
config FSL_IMX25
387
bool
388
select IMX
389
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
390
index XXXXXXX..XXXXXXX 100644
391
--- a/hw/misc/meson.build
392
+++ b/hw/misc/meson.build
393
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
394
))
395
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
396
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
397
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
398
+ 'npcm7xx_gcr.c',
399
+))
400
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
401
'omap_clk.c',
402
'omap_gpmc.c',
462
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
403
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
463
index XXXXXXX..XXXXXXX 100644
404
index XXXXXXX..XXXXXXX 100644
464
--- a/hw/misc/trace-events
405
--- a/hw/misc/trace-events
465
+++ b/hw/misc/trace-events
406
+++ b/hw/misc/trace-events
466
@@ -XXX,XX +XXX,XX @@ tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool secur
407
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
467
tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *res) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s"
408
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
468
tz_mpc_iommu_notify(uint64_t addr) "TZ MPC iommu: notifying UNMAP/MAP for 0x%" PRIx64
409
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
469
410
470
+# hw/misc/tz-msc.c
411
+# npcm7xx_gcr.c
471
+tz_msc_reset(void) "TZ MSC: reset"
412
+npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
472
+tz_msc_cfg_nonsec(int level) "TZ MSC: cfg_nonsec = %d"
413
+npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
473
+tz_msc_cfg_sec_resp(int level) "TZ MSC: cfg_sec_resp = %d"
414
+
474
+tz_msc_irq_enable(int level) "TZ MSC: int_enable = %d"
415
# stm32f4xx_syscfg.c
475
+tz_msc_irq_clear(int level) "TZ MSC: int_clear = %d"
416
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
476
+tz_msc_update_irq(int level) "TZ MSC: setting irq line to %d"
417
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
477
+tz_msc_access_blocked(uint64_t offset) "TZ MSC: offset 0x%" PRIx64 " access blocked"
478
+
479
# hw/misc/tz-ppc.c
480
tz_ppc_reset(void) "TZ PPC: reset"
481
tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
482
--
418
--
483
2.18.0
419
2.20.1
484
420
485
421
diff view generated by jsdifflib
1
The Arm IoTKit includes a system control element which
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
provides a block of read-only ID registers and a block
2
3
of read-write control registers. Implement a minimal
3
Enough functionality to boot the Linux kernel has been implemented. This
4
version of this.
4
includes:
5
5
6
- Correct power-on reset values so the various clock rates can be
7
accurately calculated.
8
- Clock enables stick around when written.
9
10
In addition, a best effort attempt to implement SECCNT and CNTR25M was
11
made even though I don't think the kernel needs them.
12
13
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
14
Reviewed-by: Joel Stanley <joel@jms.id.au>
15
Reviewed-by: Cédric Le Goater <clg@kaod.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
20
Message-id: 20200911052101.2602693-3-hskinnemoen@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180820141116.9118-9-peter.maydell@linaro.org
9
---
22
---
10
hw/misc/Makefile.objs | 1 +
23
include/hw/misc/npcm7xx_clk.h | 48 ++++++
11
include/hw/misc/iotkit-sysctl.h | 49 ++++++
24
hw/misc/npcm7xx_clk.c | 266 ++++++++++++++++++++++++++++++++++
12
hw/misc/iotkit-sysctl.c | 261 ++++++++++++++++++++++++++++++++
25
hw/misc/meson.build | 1 +
13
MAINTAINERS | 2 +
26
hw/misc/trace-events | 4 +
14
default-configs/arm-softmmu.mak | 1 +
27
4 files changed, 319 insertions(+)
15
hw/misc/trace-events | 7 +
28
create mode 100644 include/hw/misc/npcm7xx_clk.h
16
6 files changed, 321 insertions(+)
29
create mode 100644 hw/misc/npcm7xx_clk.c
17
create mode 100644 include/hw/misc/iotkit-sysctl.h
30
18
create mode 100644 hw/misc/iotkit-sysctl.c
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
19
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
23
+++ b/hw/misc/Makefile.objs
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
25
obj-$(CONFIG_TZ_MPC) += tz-mpc.o
26
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
27
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
28
+obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
29
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
32
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
33
new file mode 100644
32
new file mode 100644
34
index XXXXXXX..XXXXXXX
33
index XXXXXXX..XXXXXXX
35
--- /dev/null
34
--- /dev/null
36
+++ b/include/hw/misc/iotkit-sysctl.h
35
+++ b/include/hw/misc/npcm7xx_clk.h
37
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
38
+/*
37
+/*
39
+ * ARM IoTKit system control element
38
+ * Nuvoton NPCM7xx Clock Control Registers.
40
+ *
39
+ *
41
+ * Copyright (c) 2018 Linaro Limited
40
+ * Copyright 2020 Google LLC
42
+ * Written by Peter Maydell
41
+ *
43
+ *
42
+ * This program is free software; you can redistribute it and/or modify it
44
+ * This program is free software; you can redistribute it and/or modify
43
+ * under the terms of the GNU General Public License as published by the
45
+ * it under the terms of the GNU General Public License version 2 or
44
+ * Free Software Foundation; either version 2 of the License, or
46
+ * (at your option) any later version.
45
+ * (at your option) any later version.
47
+ */
46
+ *
48
+
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+/*
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+ * This is a model of the "system control element" which is part of the
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * Arm IoTKit and documented in
50
+ * for more details.
52
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
51
+ */
53
+ * Specifically, it implements the "system information block" and
52
+#ifndef NPCM7XX_CLK_H
54
+ * "system control register" blocks.
53
+#define NPCM7XX_CLK_H
55
+ *
54
+
56
+ * QEMU interface:
55
+#include "exec/memory.h"
57
+ * + sysbus MMIO region 0: the system information register bank
58
+ * + sysbus MMIO region 1: the system control register bank
59
+ */
60
+
61
+#ifndef HW_MISC_IOTKIT_SYSCTL_H
62
+#define HW_MISC_IOTKIT_SYSCTL_H
63
+
64
+#include "hw/sysbus.h"
56
+#include "hw/sysbus.h"
65
+
57
+
66
+#define TYPE_IOTKIT_SYSCTL "iotkit-sysctl"
58
+/*
67
+#define IOTKIT_SYSCTL(obj) OBJECT_CHECK(IoTKitSysCtl, (obj), \
59
+ * The reference clock frequency for the timer modules, and the SECCNT and
68
+ TYPE_IOTKIT_SYSCTL)
60
+ * CNTR25M registers in this module, is always 25 MHz.
69
+
61
+ */
70
+typedef struct IoTKitSysCtl {
62
+#define NPCM7XX_TIMER_REF_HZ (25000000)
71
+ /*< private >*/
63
+
72
+ SysBusDevice parent_obj;
64
+/*
73
+
65
+ * Number of registers in our device state structure. Don't change this without
74
+ /*< public >*/
66
+ * incrementing the version_id in the vmstate.
67
+ */
68
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
69
+
70
+typedef struct NPCM7xxCLKState {
71
+ SysBusDevice parent;
72
+
75
+ MemoryRegion iomem;
73
+ MemoryRegion iomem;
76
+
74
+
77
+ uint32_t secure_debug;
75
+ uint32_t regs[NPCM7XX_CLK_NR_REGS];
78
+ uint32_t reset_syndrome;
76
+
79
+ uint32_t reset_mask;
77
+ /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
80
+ uint32_t gretreg;
78
+ int64_t ref_ns;
81
+ uint32_t initsvrtor0;
79
+} NPCM7xxCLKState;
82
+ uint32_t cpuwait;
80
+
83
+ uint32_t wicctrl;
81
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
84
+} IoTKitSysCtl;
82
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
85
+
83
+
86
+#endif
84
+#endif /* NPCM7XX_CLK_H */
87
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
85
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
88
new file mode 100644
86
new file mode 100644
89
index XXXXXXX..XXXXXXX
87
index XXXXXXX..XXXXXXX
90
--- /dev/null
88
--- /dev/null
91
+++ b/hw/misc/iotkit-sysctl.c
89
+++ b/hw/misc/npcm7xx_clk.c
92
@@ -XXX,XX +XXX,XX @@
90
@@ -XXX,XX +XXX,XX @@
93
+/*
91
+/*
94
+ * ARM IoTKit system control element
92
+ * Nuvoton NPCM7xx Clock Control Registers.
95
+ *
93
+ *
96
+ * Copyright (c) 2018 Linaro Limited
94
+ * Copyright 2020 Google LLC
97
+ * Written by Peter Maydell
95
+ *
98
+ *
96
+ * This program is free software; you can redistribute it and/or modify it
99
+ * This program is free software; you can redistribute it and/or modify
97
+ * under the terms of the GNU General Public License as published by the
100
+ * it under the terms of the GNU General Public License version 2 or
98
+ * Free Software Foundation; either version 2 of the License, or
101
+ * (at your option) any later version.
99
+ * (at your option) any later version.
102
+ */
100
+ *
103
+
101
+ * This program is distributed in the hope that it will be useful, but WITHOUT
104
+/*
102
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
105
+ * This is a model of the "system control element" which is part of the
103
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
106
+ * Arm IoTKit and documented in
104
+ * for more details.
107
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
108
+ * Specifically, it implements the "system control register" blocks.
109
+ */
105
+ */
110
+
106
+
111
+#include "qemu/osdep.h"
107
+#include "qemu/osdep.h"
108
+
109
+#include "hw/misc/npcm7xx_clk.h"
110
+#include "migration/vmstate.h"
111
+#include "qemu/error-report.h"
112
+#include "qemu/log.h"
112
+#include "qemu/log.h"
113
+#include "qemu/module.h"
114
+#include "qemu/timer.h"
115
+#include "qemu/units.h"
113
+#include "trace.h"
116
+#include "trace.h"
114
+#include "qapi/error.h"
117
+
115
+#include "sysemu/sysemu.h"
118
+#define PLLCON_LOKI BIT(31)
116
+#include "hw/sysbus.h"
119
+#define PLLCON_LOKS BIT(30)
117
+#include "hw/registerfields.h"
120
+#define PLLCON_PWDEN BIT(12)
118
+#include "hw/misc/iotkit-sysctl.h"
121
+
119
+
122
+enum NPCM7xxCLKRegisters {
120
+REG32(SECDBGSTAT, 0x0)
123
+ NPCM7XX_CLK_CLKEN1,
121
+REG32(SECDBGSET, 0x4)
124
+ NPCM7XX_CLK_CLKSEL,
122
+REG32(SECDBGCLR, 0x8)
125
+ NPCM7XX_CLK_CLKDIV1,
123
+REG32(RESET_SYNDROME, 0x100)
126
+ NPCM7XX_CLK_PLLCON0,
124
+REG32(RESET_MASK, 0x104)
127
+ NPCM7XX_CLK_PLLCON1,
125
+REG32(SWRESET, 0x108)
128
+ NPCM7XX_CLK_SWRSTR,
126
+ FIELD(SWRESET, SWRESETREQ, 9, 1)
129
+ NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t),
127
+REG32(GRETREG, 0x10c)
130
+ NPCM7XX_CLK_IPSRST2,
128
+REG32(INITSVRTOR0, 0x110)
131
+ NPCM7XX_CLK_CLKEN2,
129
+REG32(CPUWAIT, 0x118)
132
+ NPCM7XX_CLK_CLKDIV2,
130
+REG32(BUSWAIT, 0x11c)
133
+ NPCM7XX_CLK_CLKEN3,
131
+REG32(WICCTRL, 0x120)
134
+ NPCM7XX_CLK_IPSRST3,
132
+REG32(PID4, 0xfd0)
135
+ NPCM7XX_CLK_WD0RCR,
133
+REG32(PID5, 0xfd4)
136
+ NPCM7XX_CLK_WD1RCR,
134
+REG32(PID6, 0xfd8)
137
+ NPCM7XX_CLK_WD2RCR,
135
+REG32(PID7, 0xfdc)
138
+ NPCM7XX_CLK_SWRSTC1,
136
+REG32(PID0, 0xfe0)
139
+ NPCM7XX_CLK_SWRSTC2,
137
+REG32(PID1, 0xfe4)
140
+ NPCM7XX_CLK_SWRSTC3,
138
+REG32(PID2, 0xfe8)
141
+ NPCM7XX_CLK_SWRSTC4,
139
+REG32(PID3, 0xfec)
142
+ NPCM7XX_CLK_PLLCON2,
140
+REG32(CID0, 0xff0)
143
+ NPCM7XX_CLK_CLKDIV3,
141
+REG32(CID1, 0xff4)
144
+ NPCM7XX_CLK_CORSTC,
142
+REG32(CID2, 0xff8)
145
+ NPCM7XX_CLK_PLLCONG,
143
+REG32(CID3, 0xffc)
146
+ NPCM7XX_CLK_AHBCKFI,
144
+
147
+ NPCM7XX_CLK_SECCNT,
145
+/* PID/CID values */
148
+ NPCM7XX_CLK_CNTR25M,
146
+static const int sysctl_id[] = {
149
+ NPCM7XX_CLK_REGS_END,
147
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
150
+};
148
+ 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
151
+
149
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
152
+/*
150
+};
153
+ * These reset values were taken from version 0.91 of the NPCM750R data sheet.
151
+
154
+ *
152
+static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
155
+ * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
153
+ unsigned size)
156
+ * core domain reset, but this reset type is not yet supported by QEMU.
154
+{
157
+ */
155
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
158
+static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
156
+ uint64_t r;
159
+ [NPCM7XX_CLK_CLKEN1] = 0xffffffff,
157
+
160
+ [NPCM7XX_CLK_CLKSEL] = 0x004aaaaa,
158
+ switch (offset) {
161
+ [NPCM7XX_CLK_CLKDIV1] = 0x5413f855,
159
+ case A_SECDBGSTAT:
162
+ [NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI,
160
+ r = s->secure_debug;
163
+ [NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI,
161
+ break;
164
+ [NPCM7XX_CLK_IPSRST1] = 0x00001000,
162
+ case A_RESET_SYNDROME:
165
+ [NPCM7XX_CLK_IPSRST2] = 0x80000000,
163
+ r = s->reset_syndrome;
166
+ [NPCM7XX_CLK_CLKEN2] = 0xffffffff,
164
+ break;
167
+ [NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f,
165
+ case A_RESET_MASK:
168
+ [NPCM7XX_CLK_CLKEN3] = 0xffffffff,
166
+ r = s->reset_mask;
169
+ [NPCM7XX_CLK_IPSRST3] = 0x03000000,
167
+ break;
170
+ [NPCM7XX_CLK_WD0RCR] = 0xffffffff,
168
+ case A_GRETREG:
171
+ [NPCM7XX_CLK_WD1RCR] = 0xffffffff,
169
+ r = s->gretreg;
172
+ [NPCM7XX_CLK_WD2RCR] = 0xffffffff,
170
+ break;
173
+ [NPCM7XX_CLK_SWRSTC1] = 0x00000003,
171
+ case A_INITSVRTOR0:
174
+ [NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI,
172
+ r = s->initsvrtor0;
175
+ [NPCM7XX_CLK_CORSTC] = 0x04000003,
173
+ break;
176
+ [NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI,
174
+ case A_CPUWAIT:
177
+ [NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
175
+ r = s->cpuwait;
178
+};
176
+ break;
179
+
177
+ case A_BUSWAIT:
180
+static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
178
+ /* In IoTKit BUSWAIT is reserved, R/O, zero */
181
+{
179
+ r = 0;
182
+ uint32_t reg = offset / sizeof(uint32_t);
180
+ break;
183
+ NPCM7xxCLKState *s = opaque;
181
+ case A_WICCTRL:
184
+ int64_t now_ns;
182
+ r = s->wicctrl;
185
+ uint32_t value = 0;
183
+ break;
186
+
184
+ case A_PID4 ... A_CID3:
187
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
185
+ r = sysctl_id[(offset - A_PID4) / 4];
186
+ break;
187
+ case A_SECDBGSET:
188
+ case A_SECDBGCLR:
189
+ case A_SWRESET:
190
+ qemu_log_mask(LOG_GUEST_ERROR,
188
+ qemu_log_mask(LOG_GUEST_ERROR,
191
+ "IoTKit SysCtl read: read of WO offset %x\n",
189
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
192
+ (int)offset);
190
+ __func__, offset);
193
+ r = 0;
191
+ return 0;
194
+ break;
192
+ }
193
+
194
+ switch (reg) {
195
+ case NPCM7XX_CLK_SWRSTR:
196
+ qemu_log_mask(LOG_GUEST_ERROR,
197
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
198
+ __func__, offset);
199
+ break;
200
+
201
+ case NPCM7XX_CLK_SECCNT:
202
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
203
+ value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND;
204
+ break;
205
+
206
+ case NPCM7XX_CLK_CNTR25M:
207
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
208
+ /*
209
+ * This register counts 25 MHz cycles, updating every 640 ns. It rolls
210
+ * over to zero every second.
211
+ *
212
+ * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
213
+ */
214
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
215
+ break;
216
+
195
+ default:
217
+ default:
218
+ value = s->regs[reg];
219
+ break;
220
+ };
221
+
222
+ trace_npcm7xx_clk_read(offset, value);
223
+
224
+ return value;
225
+}
226
+
227
+static void npcm7xx_clk_write(void *opaque, hwaddr offset,
228
+ uint64_t v, unsigned size)
229
+{
230
+ uint32_t reg = offset / sizeof(uint32_t);
231
+ NPCM7xxCLKState *s = opaque;
232
+ uint32_t value = v;
233
+
234
+ trace_npcm7xx_clk_write(offset, value);
235
+
236
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
196
+ qemu_log_mask(LOG_GUEST_ERROR,
237
+ qemu_log_mask(LOG_GUEST_ERROR,
197
+ "IoTKit SysCtl read: bad offset %x\n", (int)offset);
238
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
198
+ r = 0;
239
+ __func__, offset);
199
+ break;
240
+ return;
200
+ }
241
+ }
201
+ trace_iotkit_sysctl_read(offset, r, size);
242
+
202
+ return r;
243
+ switch (reg) {
203
+}
244
+ case NPCM7XX_CLK_SWRSTR:
204
+
245
+ qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n",
205
+static void iotkit_sysctl_write(void *opaque, hwaddr offset,
246
+ __func__, value);
206
+ uint64_t value, unsigned size)
247
+ value = 0;
207
+{
248
+ break;
208
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
249
+
209
+
250
+ case NPCM7XX_CLK_PLLCON0:
210
+ trace_iotkit_sysctl_write(offset, value, size);
251
+ case NPCM7XX_CLK_PLLCON1:
252
+ case NPCM7XX_CLK_PLLCON2:
253
+ case NPCM7XX_CLK_PLLCONG:
254
+ if (value & PLLCON_PWDEN) {
255
+ /* Power down -- clear lock and indicate loss of lock */
256
+ value &= ~PLLCON_LOKI;
257
+ value |= PLLCON_LOKS;
258
+ } else {
259
+ /* Normal mode -- assume always locked */
260
+ value |= PLLCON_LOKI;
261
+ /* Keep LOKS unchanged unless cleared by writing 1 */
262
+ if (value & PLLCON_LOKS) {
263
+ value &= ~PLLCON_LOKS;
264
+ } else {
265
+ value |= (value & PLLCON_LOKS);
266
+ }
267
+ }
268
+ break;
269
+
270
+ case NPCM7XX_CLK_CNTR25M:
271
+ qemu_log_mask(LOG_GUEST_ERROR,
272
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
273
+ __func__, offset);
274
+ return;
275
+ }
276
+
277
+ s->regs[reg] = value;
278
+}
279
+
280
+static const struct MemoryRegionOps npcm7xx_clk_ops = {
281
+ .read = npcm7xx_clk_read,
282
+ .write = npcm7xx_clk_write,
283
+ .endianness = DEVICE_LITTLE_ENDIAN,
284
+ .valid = {
285
+ .min_access_size = 4,
286
+ .max_access_size = 4,
287
+ .unaligned = false,
288
+ },
289
+};
290
+
291
+static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
292
+{
293
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
294
+
295
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
296
+
297
+ switch (type) {
298
+ case RESET_TYPE_COLD:
299
+ memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
300
+ s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
301
+ return;
302
+ }
211
+
303
+
212
+ /*
304
+ /*
213
+ * Most of the state here has to do with control of reset and
305
+ * A small number of registers need to be reset on a core domain reset,
214
+ * similar kinds of power up -- for instance the guest can ask
306
+ * but no such reset type exists yet.
215
+ * what the reason for the last reset was, or forbid reset for
216
+ * some causes (like the non-secure watchdog). Most of this is
217
+ * not relevant to QEMU, which doesn't really model anything other
218
+ * than a full power-on reset.
219
+ * We just model the registers as reads-as-written.
220
+ */
307
+ */
221
+
308
+ qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
222
+ switch (offset) {
309
+ __func__, type);
223
+ case A_RESET_SYNDROME:
310
+}
224
+ qemu_log_mask(LOG_UNIMP,
311
+
225
+ "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
312
+static void npcm7xx_clk_init(Object *obj)
226
+ s->reset_syndrome = value;
313
+{
227
+ break;
314
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
228
+ case A_RESET_MASK:
315
+
229
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
316
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
230
+ s->reset_mask = value;
317
+ TYPE_NPCM7XX_CLK, 4 * KiB);
231
+ break;
318
+ sysbus_init_mmio(&s->parent, &s->iomem);
232
+ case A_GRETREG:
319
+}
233
+ /*
320
+
234
+ * General retention register, which is only reset by a power-on
321
+static const VMStateDescription vmstate_npcm7xx_clk = {
235
+ * reset. Technically this implementation is complete, since
322
+ .name = "npcm7xx-clk",
236
+ * QEMU only supports power-on resets...
323
+ .version_id = 0,
237
+ */
324
+ .minimum_version_id = 0,
238
+ s->gretreg = value;
239
+ break;
240
+ case A_INITSVRTOR0:
241
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVRTOR0 unimplemented\n");
242
+ s->initsvrtor0 = value;
243
+ break;
244
+ case A_CPUWAIT:
245
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n");
246
+ s->cpuwait = value;
247
+ break;
248
+ case A_WICCTRL:
249
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
250
+ s->wicctrl = value;
251
+ break;
252
+ case A_SECDBGSET:
253
+ /* write-1-to-set */
254
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
255
+ s->secure_debug |= value;
256
+ break;
257
+ case A_SECDBGCLR:
258
+ /* write-1-to-clear */
259
+ s->secure_debug &= ~value;
260
+ break;
261
+ case A_SWRESET:
262
+ /* One w/o bit to request a reset; all other bits reserved */
263
+ if (value & R_SWRESET_SWRESETREQ_MASK) {
264
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
265
+ }
266
+ break;
267
+ case A_BUSWAIT: /* In IoTKit BUSWAIT is reserved, R/O, zero */
268
+ case A_SECDBGSTAT:
269
+ case A_PID4 ... A_CID3:
270
+ qemu_log_mask(LOG_GUEST_ERROR,
271
+ "IoTKit SysCtl write: write of RO offset %x\n",
272
+ (int)offset);
273
+ break;
274
+ default:
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "IoTKit SysCtl write: bad offset %x\n", (int)offset);
277
+ break;
278
+ }
279
+}
280
+
281
+static const MemoryRegionOps iotkit_sysctl_ops = {
282
+ .read = iotkit_sysctl_read,
283
+ .write = iotkit_sysctl_write,
284
+ .endianness = DEVICE_LITTLE_ENDIAN,
285
+ /* byte/halfword accesses are just zero-padded on reads and writes */
286
+ .impl.min_access_size = 4,
287
+ .impl.max_access_size = 4,
288
+ .valid.min_access_size = 1,
289
+ .valid.max_access_size = 4,
290
+};
291
+
292
+static void iotkit_sysctl_reset(DeviceState *dev)
293
+{
294
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
295
+
296
+ trace_iotkit_sysctl_reset();
297
+ s->secure_debug = 0;
298
+ s->reset_syndrome = 1;
299
+ s->reset_mask = 0;
300
+ s->gretreg = 0;
301
+ s->initsvrtor0 = 0x10000000;
302
+ s->cpuwait = 0;
303
+ s->wicctrl = 0;
304
+}
305
+
306
+static void iotkit_sysctl_init(Object *obj)
307
+{
308
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
309
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
310
+
311
+ memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
312
+ s, "iotkit-sysctl", 0x1000);
313
+ sysbus_init_mmio(sbd, &s->iomem);
314
+}
315
+
316
+static const VMStateDescription iotkit_sysctl_vmstate = {
317
+ .name = "iotkit-sysctl",
318
+ .version_id = 1,
319
+ .minimum_version_id = 1,
320
+ .fields = (VMStateField[]) {
325
+ .fields = (VMStateField[]) {
321
+ VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
326
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
322
+ VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
327
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
323
+ VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
328
+ VMSTATE_END_OF_LIST(),
324
+ VMSTATE_UINT32(gretreg, IoTKitSysCtl),
329
+ },
325
+ VMSTATE_UINT32(initsvrtor0, IoTKitSysCtl),
330
+};
326
+ VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
331
+
327
+ VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
332
+static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
328
+ VMSTATE_END_OF_LIST()
333
+{
329
+ }
334
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
330
+};
331
+
332
+static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
333
+{
334
+ DeviceClass *dc = DEVICE_CLASS(klass);
335
+ DeviceClass *dc = DEVICE_CLASS(klass);
335
+
336
+
336
+ dc->vmsd = &iotkit_sysctl_vmstate;
337
+ QEMU_BUILD_BUG_ON(NPCM7XX_CLK_REGS_END > NPCM7XX_CLK_NR_REGS);
337
+ dc->reset = iotkit_sysctl_reset;
338
+
338
+}
339
+ dc->desc = "NPCM7xx Clock Control Registers";
339
+
340
+ dc->vmsd = &vmstate_npcm7xx_clk;
340
+static const TypeInfo iotkit_sysctl_info = {
341
+ rc->phases.enter = npcm7xx_clk_enter_reset;
341
+ .name = TYPE_IOTKIT_SYSCTL,
342
+}
342
+ .parent = TYPE_SYS_BUS_DEVICE,
343
+
343
+ .instance_size = sizeof(IoTKitSysCtl),
344
+static const TypeInfo npcm7xx_clk_info = {
344
+ .instance_init = iotkit_sysctl_init,
345
+ .name = TYPE_NPCM7XX_CLK,
345
+ .class_init = iotkit_sysctl_class_init,
346
+ .parent = TYPE_SYS_BUS_DEVICE,
346
+};
347
+ .instance_size = sizeof(NPCM7xxCLKState),
347
+
348
+ .instance_init = npcm7xx_clk_init,
348
+static void iotkit_sysctl_register_types(void)
349
+ .class_init = npcm7xx_clk_class_init,
349
+{
350
+};
350
+ type_register_static(&iotkit_sysctl_info);
351
+
351
+}
352
+static void npcm7xx_clk_register_type(void)
352
+
353
+{
353
+type_init(iotkit_sysctl_register_types);
354
+ type_register_static(&npcm7xx_clk_info);
354
diff --git a/MAINTAINERS b/MAINTAINERS
355
+}
356
+type_init(npcm7xx_clk_register_type);
357
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
355
index XXXXXXX..XXXXXXX 100644
358
index XXXXXXX..XXXXXXX 100644
356
--- a/MAINTAINERS
359
--- a/hw/misc/meson.build
357
+++ b/MAINTAINERS
360
+++ b/hw/misc/meson.build
358
@@ -XXX,XX +XXX,XX @@ F: hw/misc/mps2-*.c
361
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
359
F: include/hw/misc/mps2-*.h
362
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
360
F: hw/arm/iotkit.c
363
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
361
F: include/hw/arm/iotkit.h
364
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
362
+F: hw/misc/iotkit-sysctl.c
365
+ 'npcm7xx_clk.c',
363
+F: include/hw/misc/iotkit-sysctl.h
366
'npcm7xx_gcr.c',
364
367
))
365
Musicpal
368
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
366
M: Jan Kiszka <jan.kiszka@web.de>
367
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
368
index XXXXXXX..XXXXXXX 100644
369
--- a/default-configs/arm-softmmu.mak
370
+++ b/default-configs/arm-softmmu.mak
371
@@ -XXX,XX +XXX,XX @@ CONFIG_TZ_MPC=y
372
CONFIG_TZ_PPC=y
373
CONFIG_IOTKIT=y
374
CONFIG_IOTKIT_SECCTL=y
375
+CONFIG_IOTKIT_SYSCTL=y
376
377
CONFIG_VERSATILE=y
378
CONFIG_VERSATILE_PCI=y
379
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
369
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
380
index XXXXXXX..XXXXXXX 100644
370
index XXXXXXX..XXXXXXX 100644
381
--- a/hw/misc/trace-events
371
--- a/hw/misc/trace-events
382
+++ b/hw/misc/trace-events
372
+++ b/hw/misc/trace-events
383
@@ -XXX,XX +XXX,XX @@ ccm_freq(uint32_t freq) "freq = %d\n"
373
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
384
ccm_clock_freq(uint32_t clock, uint32_t freq) "(Clock = %d) = %d\n"
374
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
385
ccm_read_reg(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32 "\n"
375
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
386
ccm_write_reg(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32 "\n"
376
387
+
377
+# npcm7xx_clk.c
388
+# hw/misc/iotkit-sysctl.c
378
+npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
389
+iotkit_sysinfo_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
379
+npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
390
+iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
380
+
391
+iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
381
# npcm7xx_gcr.c
392
+iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
382
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
393
+iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
383
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
394
--
384
--
395
2.18.0
385
2.20.1
396
386
397
387
diff view generated by jsdifflib
1
Implement the IoTKit system control element's system information
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
block; this is just a pair of read-only version/config registers,
3
plus the usual PID/CID ID registers.
4
2
3
The NPCM730 and NPCM750 SoCs have three timer modules each holding five
4
timers and some shared registers (e.g. interrupt status).
5
6
Each timer runs at 25 MHz divided by a prescaler, and counts down from a
7
configurable initial value to zero. When zero is reached, the interrupt
8
flag for the timer is set, and the timer is disabled (one-shot mode) or
9
reloaded from its initial value (periodic mode).
10
11
This implementation is sufficient to boot a Linux kernel configured for
12
NPCM750. Note that the kernel does not seem to actually turn on the
13
interrupts.
14
15
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
16
Reviewed-by: Joel Stanley <joel@jms.id.au>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-4-hskinnemoen@google.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180820141116.9118-10-peter.maydell@linaro.org
9
---
23
---
10
hw/misc/Makefile.objs | 1 +
24
include/hw/timer/npcm7xx_timer.h | 78 +++++
11
include/hw/misc/iotkit-sysinfo.h | 37 +++++++++
25
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++++++++++++++++++
12
hw/misc/iotkit-sysinfo.c | 128 +++++++++++++++++++++++++++++++
26
hw/timer/meson.build | 1 +
13
MAINTAINERS | 2 +
27
hw/timer/trace-events | 5 +
14
default-configs/arm-softmmu.mak | 1 +
28
4 files changed, 627 insertions(+)
15
5 files changed, 169 insertions(+)
29
create mode 100644 include/hw/timer/npcm7xx_timer.h
16
create mode 100644 include/hw/misc/iotkit-sysinfo.h
30
create mode 100644 hw/timer/npcm7xx_timer.c
17
create mode 100644 hw/misc/iotkit-sysinfo.c
18
31
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
32
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
22
+++ b/hw/misc/Makefile.objs
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_TZ_MPC) += tz-mpc.o
24
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
25
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
26
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
27
+obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
28
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
31
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
32
new file mode 100644
33
new file mode 100644
33
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
34
--- /dev/null
35
--- /dev/null
35
+++ b/include/hw/misc/iotkit-sysinfo.h
36
+++ b/include/hw/timer/npcm7xx_timer.h
36
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
37
+/*
38
+/*
38
+ * ARM IoTKit system information block
39
+ * Nuvoton NPCM7xx Timer Controller
39
+ *
40
+ *
40
+ * Copyright (c) 2018 Linaro Limited
41
+ * Copyright 2020 Google LLC
41
+ * Written by Peter Maydell
42
+ *
42
+ *
43
+ * This program is free software; you can redistribute it and/or modify
43
+ * This program is free software; you can redistribute it and/or modify it
44
+ * it under the terms of the GNU General Public License version 2 or
44
+ * under the terms of the GNU General Public License as published by the
45
+ * (at your option) any later version.
45
+ * Free Software Foundation; either version 2 of the License, or
46
+ */
46
+ * (at your option) any later version.
47
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * for more details.
52
+ */
53
+#ifndef NPCM7XX_TIMER_H
54
+#define NPCM7XX_TIMER_H
55
+
56
+#include "exec/memory.h"
57
+#include "hw/sysbus.h"
58
+#include "qemu/timer.h"
59
+
60
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
61
+#define NPCM7XX_TIMERS_PER_CTRL (5)
47
+
62
+
48
+/*
63
+/*
49
+ * This is a model of the "system information block" which is part of the
64
+ * Number of registers in our device state structure. Don't change this without
50
+ * Arm IoTKit and documented in
65
+ * incrementing the version_id in the vmstate.
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
66
+ */
52
+ * QEMU interface:
67
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
53
+ * + sysbus MMIO region 0: the system information register bank
68
+
54
+ */
69
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
55
+
70
+
56
+#ifndef HW_MISC_IOTKIT_SYSINFO_H
71
+/**
57
+#define HW_MISC_IOTKIT_SYSINFO_H
72
+ * struct NPCM7xxTimer - Individual timer state.
58
+
73
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
59
+#include "hw/sysbus.h"
74
+ * @qtimer: QEMU timer that notifies us on expiration.
60
+
75
+ * @expires_ns: Absolute virtual expiration time.
61
+#define TYPE_IOTKIT_SYSINFO "iotkit-sysinfo"
76
+ * @remaining_ns: Remaining time until expiration if timer is paused.
62
+#define IOTKIT_SYSINFO(obj) OBJECT_CHECK(IoTKitSysInfo, (obj), \
77
+ * @tcsr: The Timer Control and Status Register.
63
+ TYPE_IOTKIT_SYSINFO)
78
+ * @ticr: The Timer Initial Count Register.
64
+
79
+ */
65
+typedef struct IoTKitSysInfo {
80
+typedef struct NPCM7xxTimer {
66
+ /*< private >*/
81
+ NPCM7xxTimerCtrlState *ctrl;
67
+ SysBusDevice parent_obj;
82
+
68
+
83
+ qemu_irq irq;
69
+ /*< public >*/
84
+ QEMUTimer qtimer;
85
+ int64_t expires_ns;
86
+ int64_t remaining_ns;
87
+
88
+ uint32_t tcsr;
89
+ uint32_t ticr;
90
+} NPCM7xxTimer;
91
+
92
+/**
93
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
94
+ * @parent: System bus device.
95
+ * @iomem: Memory region through which registers are accessed.
96
+ * @tisr: The Timer Interrupt Status Register.
97
+ * @wtcr: The Watchdog Timer Control Register.
98
+ * @timer: The five individual timers managed by this module.
99
+ */
100
+struct NPCM7xxTimerCtrlState {
101
+ SysBusDevice parent;
102
+
70
+ MemoryRegion iomem;
103
+ MemoryRegion iomem;
71
+} IoTKitSysInfo;
104
+
72
+
105
+ uint32_t tisr;
73
+#endif
106
+ uint32_t wtcr;
74
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
107
+
108
+ NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
109
+};
110
+
111
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
112
+#define NPCM7XX_TIMER(obj) \
113
+ OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
114
+
115
+#endif /* NPCM7XX_TIMER_H */
116
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
75
new file mode 100644
117
new file mode 100644
76
index XXXXXXX..XXXXXXX
118
index XXXXXXX..XXXXXXX
77
--- /dev/null
119
--- /dev/null
78
+++ b/hw/misc/iotkit-sysinfo.c
120
+++ b/hw/timer/npcm7xx_timer.c
79
@@ -XXX,XX +XXX,XX @@
121
@@ -XXX,XX +XXX,XX @@
80
+/*
122
+/*
81
+ * ARM IoTKit system information block
123
+ * Nuvoton NPCM7xx Timer Controller
82
+ *
124
+ *
83
+ * Copyright (c) 2018 Linaro Limited
125
+ * Copyright 2020 Google LLC
84
+ * Written by Peter Maydell
85
+ *
126
+ *
86
+ * This program is free software; you can redistribute it and/or modify
127
+ * This program is free software; you can redistribute it and/or modify it
87
+ * it under the terms of the GNU General Public License version 2 or
128
+ * under the terms of the GNU General Public License as published by the
88
+ * (at your option) any later version.
129
+ * Free Software Foundation; either version 2 of the License, or
89
+ */
130
+ * (at your option) any later version.
131
+ *
132
+ * This program is distributed in the hope that it will be useful, but WITHOUT
133
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
135
+ * for more details.
136
+ */
137
+
138
+#include "qemu/osdep.h"
139
+
140
+#include "hw/irq.h"
141
+#include "hw/misc/npcm7xx_clk.h"
142
+#include "hw/timer/npcm7xx_timer.h"
143
+#include "migration/vmstate.h"
144
+#include "qemu/bitops.h"
145
+#include "qemu/error-report.h"
146
+#include "qemu/log.h"
147
+#include "qemu/module.h"
148
+#include "qemu/timer.h"
149
+#include "qemu/units.h"
150
+#include "trace.h"
151
+
152
+/* 32-bit register indices. */
153
+enum NPCM7xxTimerRegisters {
154
+ NPCM7XX_TIMER_TCSR0,
155
+ NPCM7XX_TIMER_TCSR1,
156
+ NPCM7XX_TIMER_TICR0,
157
+ NPCM7XX_TIMER_TICR1,
158
+ NPCM7XX_TIMER_TDR0,
159
+ NPCM7XX_TIMER_TDR1,
160
+ NPCM7XX_TIMER_TISR,
161
+ NPCM7XX_TIMER_WTCR,
162
+ NPCM7XX_TIMER_TCSR2,
163
+ NPCM7XX_TIMER_TCSR3,
164
+ NPCM7XX_TIMER_TICR2,
165
+ NPCM7XX_TIMER_TICR3,
166
+ NPCM7XX_TIMER_TDR2,
167
+ NPCM7XX_TIMER_TDR3,
168
+ NPCM7XX_TIMER_TCSR4 = 0x0040 / sizeof(uint32_t),
169
+ NPCM7XX_TIMER_TICR4 = 0x0048 / sizeof(uint32_t),
170
+ NPCM7XX_TIMER_TDR4 = 0x0050 / sizeof(uint32_t),
171
+ NPCM7XX_TIMER_REGS_END,
172
+};
173
+
174
+/* Register field definitions. */
175
+#define NPCM7XX_TCSR_CEN BIT(30)
176
+#define NPCM7XX_TCSR_IE BIT(29)
177
+#define NPCM7XX_TCSR_PERIODIC BIT(27)
178
+#define NPCM7XX_TCSR_CRST BIT(26)
179
+#define NPCM7XX_TCSR_CACT BIT(25)
180
+#define NPCM7XX_TCSR_RSVD 0x01ffff00
181
+#define NPCM7XX_TCSR_PRESCALE_START 0
182
+#define NPCM7XX_TCSR_PRESCALE_LEN 8
90
+
183
+
91
+/*
184
+/*
92
+ * This is a model of the "system information block" which is part of the
185
+ * Returns the index of timer in the tc->timer array. This can be used to
93
+ * Arm IoTKit and documented in
186
+ * locate the registers that belong to this timer.
94
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
187
+ */
95
+ * It consists of 2 read-only version/config registers, plus the
188
+static int npcm7xx_timer_index(NPCM7xxTimerCtrlState *tc, NPCM7xxTimer *timer)
96
+ * usual ID registers.
189
+{
97
+ */
190
+ int index = timer - tc->timer;
98
+
191
+
99
+#include "qemu/osdep.h"
192
+ g_assert(index >= 0 && index < NPCM7XX_TIMERS_PER_CTRL);
100
+#include "qemu/log.h"
193
+
101
+#include "trace.h"
194
+ return index;
102
+#include "qapi/error.h"
195
+}
103
+#include "sysemu/sysemu.h"
196
+
104
+#include "hw/sysbus.h"
197
+/* Return the value by which to divide the reference clock rate. */
105
+#include "hw/registerfields.h"
198
+static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
106
+#include "hw/misc/iotkit-sysinfo.h"
199
+{
107
+
200
+ return extract32(tcsr, NPCM7XX_TCSR_PRESCALE_START,
108
+REG32(SYS_VERSION, 0x0)
201
+ NPCM7XX_TCSR_PRESCALE_LEN) + 1;
109
+REG32(SYS_CONFIG, 0x4)
202
+}
110
+REG32(PID4, 0xfd0)
203
+
111
+REG32(PID5, 0xfd4)
204
+/* Convert a timer cycle count to a time interval in nanoseconds. */
112
+REG32(PID6, 0xfd8)
205
+static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
113
+REG32(PID7, 0xfdc)
206
+{
114
+REG32(PID0, 0xfe0)
207
+ int64_t ns = count;
115
+REG32(PID1, 0xfe4)
208
+
116
+REG32(PID2, 0xfe8)
209
+ ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
117
+REG32(PID3, 0xfec)
210
+ ns *= npcm7xx_tcsr_prescaler(t->tcsr);
118
+REG32(CID0, 0xff0)
211
+
119
+REG32(CID1, 0xff4)
212
+ return ns;
120
+REG32(CID2, 0xff8)
213
+}
121
+REG32(CID3, 0xffc)
214
+
122
+
215
+/* Convert a time interval in nanoseconds to a timer cycle count. */
123
+/* PID/CID values */
216
+static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
124
+static const int sysinfo_id[] = {
217
+{
125
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
218
+ int64_t count;
126
+ 0x58, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
219
+
127
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
220
+ count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
128
+};
221
+ count /= npcm7xx_tcsr_prescaler(t->tcsr);
129
+
222
+
130
+static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
223
+ return count;
131
+ unsigned size)
224
+}
132
+{
225
+
133
+ uint64_t r;
226
+/*
134
+
227
+ * Raise the interrupt line if there's a pending interrupt and interrupts are
135
+ switch (offset) {
228
+ * enabled for this timer. If not, lower it.
136
+ case A_SYS_VERSION:
229
+ */
137
+ r = 0x41743;
230
+static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t)
231
+{
232
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
233
+ int index = npcm7xx_timer_index(tc, t);
234
+ bool pending = (t->tcsr & NPCM7XX_TCSR_IE) && (tc->tisr & BIT(index));
235
+
236
+ qemu_set_irq(t->irq, pending);
237
+ trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending);
238
+}
239
+
240
+/* Start or resume the timer. */
241
+static void npcm7xx_timer_start(NPCM7xxTimer *t)
242
+{
243
+ int64_t now;
244
+
245
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
246
+ t->expires_ns = now + t->remaining_ns;
247
+ timer_mod(&t->qtimer, t->expires_ns);
248
+}
249
+
250
+/*
251
+ * Called when the counter reaches zero. Sets the interrupt flag, and either
252
+ * restarts or disables the timer.
253
+ */
254
+static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
255
+{
256
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
257
+ int index = npcm7xx_timer_index(tc, t);
258
+
259
+ tc->tisr |= BIT(index);
260
+
261
+ if (t->tcsr & NPCM7XX_TCSR_PERIODIC) {
262
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
263
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
264
+ npcm7xx_timer_start(t);
265
+ }
266
+ } else {
267
+ t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT);
268
+ }
269
+
270
+ npcm7xx_timer_check_interrupt(t);
271
+}
272
+
273
+/* Stop counting. Record the time remaining so we can continue later. */
274
+static void npcm7xx_timer_pause(NPCM7xxTimer *t)
275
+{
276
+ int64_t now;
277
+
278
+ timer_del(&t->qtimer);
279
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
280
+ t->remaining_ns = t->expires_ns - now;
281
+ if (t->remaining_ns <= 0) {
282
+ npcm7xx_timer_reached_zero(t);
283
+ }
284
+}
285
+
286
+/*
287
+ * Restart the timer from its initial value. If the timer was enabled and stays
288
+ * enabled, adjust the QEMU timer according to the new count. If the timer is
289
+ * transitioning from disabled to enabled, the caller is expected to start the
290
+ * timer later.
291
+ */
292
+static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr)
293
+{
294
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
295
+
296
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
297
+ npcm7xx_timer_start(t);
298
+ }
299
+}
300
+
301
+/* Register read and write handlers */
302
+
303
+static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t)
304
+{
305
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
306
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
307
+
308
+ return npcm7xx_timer_ns_to_count(t, t->expires_ns - now);
309
+ }
310
+
311
+ return npcm7xx_timer_ns_to_count(t, t->remaining_ns);
312
+}
313
+
314
+static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
315
+{
316
+ uint32_t old_tcsr = t->tcsr;
317
+ uint32_t tdr;
318
+
319
+ if (new_tcsr & NPCM7XX_TCSR_RSVD) {
320
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: reserved bits in 0x%08x ignored\n",
321
+ __func__, new_tcsr);
322
+ new_tcsr &= ~NPCM7XX_TCSR_RSVD;
323
+ }
324
+ if (new_tcsr & NPCM7XX_TCSR_CACT) {
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only bits in 0x%08x ignored\n",
326
+ __func__, new_tcsr);
327
+ new_tcsr &= ~NPCM7XX_TCSR_CACT;
328
+ }
329
+ if ((new_tcsr & NPCM7XX_TCSR_CRST) && (new_tcsr & NPCM7XX_TCSR_CEN)) {
330
+ qemu_log_mask(LOG_GUEST_ERROR,
331
+ "%s: both CRST and CEN set; ignoring CEN.\n",
332
+ __func__);
333
+ new_tcsr &= ~NPCM7XX_TCSR_CEN;
334
+ }
335
+
336
+ /* Calculate the value of TDR before potentially changing the prescaler. */
337
+ tdr = npcm7xx_timer_read_tdr(t);
338
+
339
+ t->tcsr = (t->tcsr & NPCM7XX_TCSR_CACT) | new_tcsr;
340
+
341
+ if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) {
342
+ /* Recalculate time remaining based on the current TDR value. */
343
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
344
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
345
+ npcm7xx_timer_start(t);
346
+ }
347
+ }
348
+
349
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_IE) {
350
+ npcm7xx_timer_check_interrupt(t);
351
+ }
352
+ if (new_tcsr & NPCM7XX_TCSR_CRST) {
353
+ npcm7xx_timer_restart(t, old_tcsr);
354
+ t->tcsr &= ~NPCM7XX_TCSR_CRST;
355
+ }
356
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) {
357
+ if (new_tcsr & NPCM7XX_TCSR_CEN) {
358
+ t->tcsr |= NPCM7XX_TCSR_CACT;
359
+ npcm7xx_timer_start(t);
360
+ } else {
361
+ t->tcsr &= ~NPCM7XX_TCSR_CACT;
362
+ npcm7xx_timer_pause(t);
363
+ }
364
+ }
365
+}
366
+
367
+static void npcm7xx_timer_write_ticr(NPCM7xxTimer *t, uint32_t new_ticr)
368
+{
369
+ t->ticr = new_ticr;
370
+
371
+ npcm7xx_timer_restart(t, t->tcsr);
372
+}
373
+
374
+static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value)
375
+{
376
+ int i;
377
+
378
+ s->tisr &= ~value;
379
+ for (i = 0; i < ARRAY_SIZE(s->timer); i++) {
380
+ if (value & (1U << i)) {
381
+ npcm7xx_timer_check_interrupt(&s->timer[i]);
382
+ }
383
+ }
384
+}
385
+
386
+static hwaddr npcm7xx_tcsr_index(hwaddr reg)
387
+{
388
+ switch (reg) {
389
+ case NPCM7XX_TIMER_TCSR0:
390
+ return 0;
391
+ case NPCM7XX_TIMER_TCSR1:
392
+ return 1;
393
+ case NPCM7XX_TIMER_TCSR2:
394
+ return 2;
395
+ case NPCM7XX_TIMER_TCSR3:
396
+ return 3;
397
+ case NPCM7XX_TIMER_TCSR4:
398
+ return 4;
399
+ default:
400
+ g_assert_not_reached();
401
+ }
402
+}
403
+
404
+static hwaddr npcm7xx_ticr_index(hwaddr reg)
405
+{
406
+ switch (reg) {
407
+ case NPCM7XX_TIMER_TICR0:
408
+ return 0;
409
+ case NPCM7XX_TIMER_TICR1:
410
+ return 1;
411
+ case NPCM7XX_TIMER_TICR2:
412
+ return 2;
413
+ case NPCM7XX_TIMER_TICR3:
414
+ return 3;
415
+ case NPCM7XX_TIMER_TICR4:
416
+ return 4;
417
+ default:
418
+ g_assert_not_reached();
419
+ }
420
+}
421
+
422
+static hwaddr npcm7xx_tdr_index(hwaddr reg)
423
+{
424
+ switch (reg) {
425
+ case NPCM7XX_TIMER_TDR0:
426
+ return 0;
427
+ case NPCM7XX_TIMER_TDR1:
428
+ return 1;
429
+ case NPCM7XX_TIMER_TDR2:
430
+ return 2;
431
+ case NPCM7XX_TIMER_TDR3:
432
+ return 3;
433
+ case NPCM7XX_TIMER_TDR4:
434
+ return 4;
435
+ default:
436
+ g_assert_not_reached();
437
+ }
438
+}
439
+
440
+static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size)
441
+{
442
+ NPCM7xxTimerCtrlState *s = opaque;
443
+ uint64_t value = 0;
444
+ hwaddr reg;
445
+
446
+ reg = offset / sizeof(uint32_t);
447
+ switch (reg) {
448
+ case NPCM7XX_TIMER_TCSR0:
449
+ case NPCM7XX_TIMER_TCSR1:
450
+ case NPCM7XX_TIMER_TCSR2:
451
+ case NPCM7XX_TIMER_TCSR3:
452
+ case NPCM7XX_TIMER_TCSR4:
453
+ value = s->timer[npcm7xx_tcsr_index(reg)].tcsr;
138
+ break;
454
+ break;
139
+
455
+
140
+ case A_SYS_CONFIG:
456
+ case NPCM7XX_TIMER_TICR0:
141
+ r = 0x31;
457
+ case NPCM7XX_TIMER_TICR1:
458
+ case NPCM7XX_TIMER_TICR2:
459
+ case NPCM7XX_TIMER_TICR3:
460
+ case NPCM7XX_TIMER_TICR4:
461
+ value = s->timer[npcm7xx_ticr_index(reg)].ticr;
142
+ break;
462
+ break;
143
+ case A_PID4 ... A_CID3:
463
+
144
+ r = sysinfo_id[(offset - A_PID4) / 4];
464
+ case NPCM7XX_TIMER_TDR0:
465
+ case NPCM7XX_TIMER_TDR1:
466
+ case NPCM7XX_TIMER_TDR2:
467
+ case NPCM7XX_TIMER_TDR3:
468
+ case NPCM7XX_TIMER_TDR4:
469
+ value = npcm7xx_timer_read_tdr(&s->timer[npcm7xx_tdr_index(reg)]);
145
+ break;
470
+ break;
471
+
472
+ case NPCM7XX_TIMER_TISR:
473
+ value = s->tisr;
474
+ break;
475
+
476
+ case NPCM7XX_TIMER_WTCR:
477
+ value = s->wtcr;
478
+ break;
479
+
146
+ default:
480
+ default:
147
+ qemu_log_mask(LOG_GUEST_ERROR,
481
+ qemu_log_mask(LOG_GUEST_ERROR,
148
+ "IoTKit SysInfo read: bad offset %x\n", (int)offset);
482
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
149
+ r = 0;
483
+ __func__, offset);
150
+ break;
484
+ break;
151
+ }
485
+ }
152
+ trace_iotkit_sysinfo_read(offset, r, size);
486
+
153
+ return r;
487
+ trace_npcm7xx_timer_read(DEVICE(s)->canonical_path, offset, value);
154
+}
488
+
155
+
489
+ return value;
156
+static void iotkit_sysinfo_write(void *opaque, hwaddr offset,
490
+}
157
+ uint64_t value, unsigned size)
491
+
158
+{
492
+static void npcm7xx_timer_write(void *opaque, hwaddr offset,
159
+ trace_iotkit_sysinfo_write(offset, value, size);
493
+ uint64_t v, unsigned size)
494
+{
495
+ uint32_t reg = offset / sizeof(uint32_t);
496
+ NPCM7xxTimerCtrlState *s = opaque;
497
+ uint32_t value = v;
498
+
499
+ trace_npcm7xx_timer_write(DEVICE(s)->canonical_path, offset, value);
500
+
501
+ switch (reg) {
502
+ case NPCM7XX_TIMER_TCSR0:
503
+ case NPCM7XX_TIMER_TCSR1:
504
+ case NPCM7XX_TIMER_TCSR2:
505
+ case NPCM7XX_TIMER_TCSR3:
506
+ case NPCM7XX_TIMER_TCSR4:
507
+ npcm7xx_timer_write_tcsr(&s->timer[npcm7xx_tcsr_index(reg)], value);
508
+ return;
509
+
510
+ case NPCM7XX_TIMER_TICR0:
511
+ case NPCM7XX_TIMER_TICR1:
512
+ case NPCM7XX_TIMER_TICR2:
513
+ case NPCM7XX_TIMER_TICR3:
514
+ case NPCM7XX_TIMER_TICR4:
515
+ npcm7xx_timer_write_ticr(&s->timer[npcm7xx_ticr_index(reg)], value);
516
+ return;
517
+
518
+ case NPCM7XX_TIMER_TDR0:
519
+ case NPCM7XX_TIMER_TDR1:
520
+ case NPCM7XX_TIMER_TDR2:
521
+ case NPCM7XX_TIMER_TDR3:
522
+ case NPCM7XX_TIMER_TDR4:
523
+ qemu_log_mask(LOG_GUEST_ERROR,
524
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
525
+ __func__, offset);
526
+ return;
527
+
528
+ case NPCM7XX_TIMER_TISR:
529
+ npcm7xx_timer_write_tisr(s, value);
530
+ return;
531
+
532
+ case NPCM7XX_TIMER_WTCR:
533
+ qemu_log_mask(LOG_UNIMP, "%s: WTCR write not implemented: 0x%08x\n",
534
+ __func__, value);
535
+ return;
536
+ }
160
+
537
+
161
+ qemu_log_mask(LOG_GUEST_ERROR,
538
+ qemu_log_mask(LOG_GUEST_ERROR,
162
+ "IoTKit SysInfo: write to RO offset 0x%x\n", (int)offset);
539
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
163
+}
540
+ __func__, offset);
164
+
541
+}
165
+static const MemoryRegionOps iotkit_sysinfo_ops = {
542
+
166
+ .read = iotkit_sysinfo_read,
543
+static const struct MemoryRegionOps npcm7xx_timer_ops = {
167
+ .write = iotkit_sysinfo_write,
544
+ .read = npcm7xx_timer_read,
545
+ .write = npcm7xx_timer_write,
168
+ .endianness = DEVICE_LITTLE_ENDIAN,
546
+ .endianness = DEVICE_LITTLE_ENDIAN,
169
+ /* byte/halfword accesses are just zero-padded on reads and writes */
547
+ .valid = {
170
+ .impl.min_access_size = 4,
548
+ .min_access_size = 4,
171
+ .impl.max_access_size = 4,
549
+ .max_access_size = 4,
172
+ .valid.min_access_size = 1,
550
+ .unaligned = false,
173
+ .valid.max_access_size = 4,
551
+ },
174
+};
552
+};
175
+
553
+
176
+static void iotkit_sysinfo_init(Object *obj)
554
+/* Called when the QEMU timer expires. */
177
+{
555
+static void npcm7xx_timer_expired(void *opaque)
178
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
556
+{
179
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(obj);
557
+ NPCM7xxTimer *t = opaque;
180
+
558
+
181
+ memory_region_init_io(&s->iomem, obj, &iotkit_sysinfo_ops,
559
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
182
+ s, "iotkit-sysinfo", 0x1000);
560
+ npcm7xx_timer_reached_zero(t);
561
+ }
562
+}
563
+
564
+static void npcm7xx_timer_enter_reset(Object *obj, ResetType type)
565
+{
566
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
567
+ int i;
568
+
569
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
570
+ NPCM7xxTimer *t = &s->timer[i];
571
+
572
+ timer_del(&t->qtimer);
573
+ t->expires_ns = 0;
574
+ t->remaining_ns = 0;
575
+ t->tcsr = 0x00000005;
576
+ t->ticr = 0x00000000;
577
+ }
578
+
579
+ s->tisr = 0x00000000;
580
+ s->wtcr = 0x00000400;
581
+}
582
+
583
+static void npcm7xx_timer_hold_reset(Object *obj)
584
+{
585
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
586
+ int i;
587
+
588
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
589
+ qemu_irq_lower(s->timer[i].irq);
590
+ }
591
+}
592
+
593
+static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
594
+{
595
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
596
+ SysBusDevice *sbd = &s->parent;
597
+ int i;
598
+
599
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
600
+ NPCM7xxTimer *t = &s->timer[i];
601
+ t->ctrl = s;
602
+ timer_init_ns(&t->qtimer, QEMU_CLOCK_VIRTUAL, npcm7xx_timer_expired, t);
603
+ sysbus_init_irq(sbd, &t->irq);
604
+ }
605
+
606
+ memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
607
+ TYPE_NPCM7XX_TIMER, 4 * KiB);
183
+ sysbus_init_mmio(sbd, &s->iomem);
608
+ sysbus_init_mmio(sbd, &s->iomem);
184
+}
609
+}
185
+
610
+
186
+static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
611
+static const VMStateDescription vmstate_npcm7xx_timer = {
187
+{
612
+ .name = "npcm7xx-timer",
188
+ /*
613
+ .version_id = 0,
189
+ * This device has no guest-modifiable state and so it
614
+ .minimum_version_id = 0,
190
+ * does not need a reset function or VMState.
615
+ .fields = (VMStateField[]) {
191
+ */
616
+ VMSTATE_TIMER(qtimer, NPCM7xxTimer),
192
+}
617
+ VMSTATE_INT64(expires_ns, NPCM7xxTimer),
193
+
618
+ VMSTATE_INT64(remaining_ns, NPCM7xxTimer),
194
+static const TypeInfo iotkit_sysinfo_info = {
619
+ VMSTATE_UINT32(tcsr, NPCM7xxTimer),
195
+ .name = TYPE_IOTKIT_SYSINFO,
620
+ VMSTATE_UINT32(ticr, NPCM7xxTimer),
196
+ .parent = TYPE_SYS_BUS_DEVICE,
621
+ VMSTATE_END_OF_LIST(),
197
+ .instance_size = sizeof(IoTKitSysInfo),
622
+ },
198
+ .instance_init = iotkit_sysinfo_init,
199
+ .class_init = iotkit_sysinfo_class_init,
200
+};
623
+};
201
+
624
+
202
+static void iotkit_sysinfo_register_types(void)
625
+static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
203
+{
626
+ .name = "npcm7xx-timer-ctrl",
204
+ type_register_static(&iotkit_sysinfo_info);
627
+ .version_id = 0,
205
+}
628
+ .minimum_version_id = 0,
206
+
629
+ .fields = (VMStateField[]) {
207
+type_init(iotkit_sysinfo_register_types);
630
+ VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
208
diff --git a/MAINTAINERS b/MAINTAINERS
631
+ VMSTATE_UINT32(wtcr, NPCM7xxTimerCtrlState),
632
+ VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
633
+ NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
634
+ NPCM7xxTimer),
635
+ VMSTATE_END_OF_LIST(),
636
+ },
637
+};
638
+
639
+static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
640
+{
641
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
642
+ DeviceClass *dc = DEVICE_CLASS(klass);
643
+
644
+ QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
645
+
646
+ dc->desc = "NPCM7xx Timer Controller";
647
+ dc->realize = npcm7xx_timer_realize;
648
+ dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
649
+ rc->phases.enter = npcm7xx_timer_enter_reset;
650
+ rc->phases.hold = npcm7xx_timer_hold_reset;
651
+}
652
+
653
+static const TypeInfo npcm7xx_timer_info = {
654
+ .name = TYPE_NPCM7XX_TIMER,
655
+ .parent = TYPE_SYS_BUS_DEVICE,
656
+ .instance_size = sizeof(NPCM7xxTimerCtrlState),
657
+ .class_init = npcm7xx_timer_class_init,
658
+};
659
+
660
+static void npcm7xx_timer_register_type(void)
661
+{
662
+ type_register_static(&npcm7xx_timer_info);
663
+}
664
+type_init(npcm7xx_timer_register_type);
665
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
209
index XXXXXXX..XXXXXXX 100644
666
index XXXXXXX..XXXXXXX 100644
210
--- a/MAINTAINERS
667
--- a/hw/timer/meson.build
211
+++ b/MAINTAINERS
668
+++ b/hw/timer/meson.build
212
@@ -XXX,XX +XXX,XX @@ F: hw/arm/iotkit.c
669
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_timer.c'))
213
F: include/hw/arm/iotkit.h
670
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-sysctl.c'))
214
F: hw/misc/iotkit-sysctl.c
671
softmmu_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gictimer.c'))
215
F: include/hw/misc/iotkit-sysctl.h
672
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-timer.c'))
216
+F: hw/misc/iotkit-sysinfo.c
673
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_timer.c'))
217
+F: include/hw/misc/iotkit-sysinfo.h
674
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_timer.c'))
218
675
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gptimer.c'))
219
Musicpal
676
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_synctimer.c'))
220
M: Jan Kiszka <jan.kiszka@web.de>
677
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
221
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
222
index XXXXXXX..XXXXXXX 100644
678
index XXXXXXX..XXXXXXX 100644
223
--- a/default-configs/arm-softmmu.mak
679
--- a/hw/timer/trace-events
224
+++ b/default-configs/arm-softmmu.mak
680
+++ b/hw/timer/trace-events
225
@@ -XXX,XX +XXX,XX @@ CONFIG_TZ_PPC=y
681
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A
226
CONFIG_IOTKIT=y
682
cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
227
CONFIG_IOTKIT_SECCTL=y
683
cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
228
CONFIG_IOTKIT_SYSCTL=y
684
229
+CONFIG_IOTKIT_SYSINFO=y
685
+# npcm7xx_timer.c
230
686
+npcm7xx_timer_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
231
CONFIG_VERSATILE=y
687
+npcm7xx_timer_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
232
CONFIG_VERSATILE_PCI=y
688
+npcm7xx_timer_irq(const char *id, int timer, int state) "%s timer %d state %d"
689
+
690
# nrf51_timer.c
691
nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
692
nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
233
--
693
--
234
2.18.0
694
2.20.1
235
695
236
696
diff view generated by jsdifflib
1
Abstract out the calculation of the pitch and size of the
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
framebuffer into functions that operate on the BCM2835FBConfig
2
3
struct -- these are about to get a little more complicated
3
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
4
when we add support for virtual and physical sizes differing.
4
Management Controllers in servers. While the family includes four SoCs,
5
5
this patch implements limited support for two of them: NPCM730 (targeted
6
for Data Center applications) and NPCM750 (targeted for Enterprise
7
applications).
8
9
This patch includes little more than the bare minimum needed to boot a
10
Linux kernel built with NPCM7xx support in direct-kernel mode:
11
12
- Two Cortex-A9 CPU cores with built-in periperhals.
13
- Global Configuration Registers.
14
- Clock Management.
15
- 3 Timer Modules with 5 timers each.
16
- 4 serial ports.
17
18
The chips themselves have a lot more features, some of which will be
19
added to the model at a later stage.
20
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Reviewed-by: Joel Stanley <joel@jms.id.au>
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Tested-by: Alexander Bulekov <alxndr@bu.edu>
26
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
27
Message-id: 20200911052101.2602693-5-hskinnemoen@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180814144436.679-6-peter.maydell@linaro.org
9
---
29
---
10
include/hw/display/bcm2835_fb.h | 22 ++++++++++++++++++++++
30
include/hw/arm/npcm7xx.h | 85 ++++++++
11
hw/display/bcm2835_fb.c | 6 +++---
31
hw/arm/npcm7xx.c | 407 +++++++++++++++++++++++++++++++++++++++
12
hw/misc/bcm2835_property.c | 4 ++--
32
hw/arm/Kconfig | 5 +
13
3 files changed, 27 insertions(+), 5 deletions(-)
33
hw/arm/meson.build | 1 +
14
34
4 files changed, 498 insertions(+)
15
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
35
create mode 100644 include/hw/arm/npcm7xx.h
36
create mode 100644 hw/arm/npcm7xx.c
37
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/include/hw/arm/npcm7xx.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * Nuvoton NPCM7xx SoC family.
46
+ *
47
+ * Copyright 2020 Google LLC
48
+ *
49
+ * This program is free software; you can redistribute it and/or modify it
50
+ * under the terms of the GNU General Public License as published by the
51
+ * Free Software Foundation; either version 2 of the License, or
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful, but WITHOUT
55
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
57
+ * for more details.
58
+ */
59
+#ifndef NPCM7XX_H
60
+#define NPCM7XX_H
61
+
62
+#include "hw/boards.h"
63
+#include "hw/cpu/a9mpcore.h"
64
+#include "hw/misc/npcm7xx_clk.h"
65
+#include "hw/misc/npcm7xx_gcr.h"
66
+#include "hw/timer/npcm7xx_timer.h"
67
+#include "target/arm/cpu.h"
68
+
69
+#define NPCM7XX_MAX_NUM_CPUS (2)
70
+
71
+/* The first half of the address space is reserved for DDR4 DRAM. */
72
+#define NPCM7XX_DRAM_BA (0x00000000)
73
+#define NPCM7XX_DRAM_SZ (2 * GiB)
74
+
75
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
76
+#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */
77
+#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
78
+#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
79
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
80
+
81
+typedef struct NPCM7xxState {
82
+ DeviceState parent;
83
+
84
+ ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
85
+ A9MPPrivState a9mpcore;
86
+
87
+ MemoryRegion sram;
88
+ MemoryRegion irom;
89
+ MemoryRegion ram3;
90
+ MemoryRegion *dram;
91
+
92
+ NPCM7xxGCRState gcr;
93
+ NPCM7xxCLKState clk;
94
+ NPCM7xxTimerCtrlState tim[3];
95
+} NPCM7xxState;
96
+
97
+#define TYPE_NPCM7XX "npcm7xx"
98
+#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
99
+
100
+#define TYPE_NPCM730 "npcm730"
101
+#define TYPE_NPCM750 "npcm750"
102
+
103
+typedef struct NPCM7xxClass {
104
+ DeviceClass parent;
105
+
106
+ /* Bitmask of modules that are permanently disabled on this chip. */
107
+ uint32_t disabled_modules;
108
+ /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
109
+ uint32_t num_cpus;
110
+} NPCM7xxClass;
111
+
112
+#define NPCM7XX_CLASS(klass) \
113
+ OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
114
+#define NPCM7XX_GET_CLASS(obj) \
115
+ OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
116
+
117
+/**
118
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
119
+ * @machine - The machine containing the SoC to be booted.
120
+ * @soc - The SoC containing the CPU to be booted.
121
+ *
122
+ * This will set up the ARM boot info structure for the specific NPCM7xx
123
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
124
+ * into memory, if requested by the user.
125
+ */
126
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
127
+
128
+#endif /* NPCM7XX_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
new file mode 100644
131
index XXXXXXX..XXXXXXX
132
--- /dev/null
133
+++ b/hw/arm/npcm7xx.c
134
@@ -XXX,XX +XXX,XX @@
135
+/*
136
+ * Nuvoton NPCM7xx SoC family.
137
+ *
138
+ * Copyright 2020 Google LLC
139
+ *
140
+ * This program is free software; you can redistribute it and/or modify it
141
+ * under the terms of the GNU General Public License as published by the
142
+ * Free Software Foundation; either version 2 of the License, or
143
+ * (at your option) any later version.
144
+ *
145
+ * This program is distributed in the hope that it will be useful, but WITHOUT
146
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
147
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
148
+ * for more details.
149
+ */
150
+
151
+#include "qemu/osdep.h"
152
+
153
+#include "exec/address-spaces.h"
154
+#include "hw/arm/boot.h"
155
+#include "hw/arm/npcm7xx.h"
156
+#include "hw/char/serial.h"
157
+#include "hw/loader.h"
158
+#include "hw/misc/unimp.h"
159
+#include "hw/qdev-properties.h"
160
+#include "qapi/error.h"
161
+#include "qemu/units.h"
162
+#include "sysemu/sysemu.h"
163
+
164
+/*
165
+ * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
166
+ * that aren't handled by any device.
167
+ */
168
+#define NPCM7XX_MMIO_BA (0x80000000)
169
+#define NPCM7XX_MMIO_SZ (0x7ffd0000)
170
+
171
+/* Core system modules. */
172
+#define NPCM7XX_L2C_BA (0xf03fc000)
173
+#define NPCM7XX_CPUP_BA (0xf03fe000)
174
+#define NPCM7XX_GCR_BA (0xf0800000)
175
+#define NPCM7XX_CLK_BA (0xf0801000)
176
+
177
+/* Internal AHB SRAM */
178
+#define NPCM7XX_RAM3_BA (0xc0008000)
179
+#define NPCM7XX_RAM3_SZ (4 * KiB)
180
+
181
+/* Memory blocks at the end of the address space */
182
+#define NPCM7XX_RAM2_BA (0xfffd0000)
183
+#define NPCM7XX_RAM2_SZ (128 * KiB)
184
+#define NPCM7XX_ROM_BA (0xffff0000)
185
+#define NPCM7XX_ROM_SZ (64 * KiB)
186
+
187
+/*
188
+ * Interrupt lines going into the GIC. This does not include internal Cortex-A9
189
+ * interrupts.
190
+ */
191
+enum NPCM7xxInterrupt {
192
+ NPCM7XX_UART0_IRQ = 2,
193
+ NPCM7XX_UART1_IRQ,
194
+ NPCM7XX_UART2_IRQ,
195
+ NPCM7XX_UART3_IRQ,
196
+ NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
197
+ NPCM7XX_TIMER1_IRQ,
198
+ NPCM7XX_TIMER2_IRQ,
199
+ NPCM7XX_TIMER3_IRQ,
200
+ NPCM7XX_TIMER4_IRQ,
201
+ NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */
202
+ NPCM7XX_TIMER6_IRQ,
203
+ NPCM7XX_TIMER7_IRQ,
204
+ NPCM7XX_TIMER8_IRQ,
205
+ NPCM7XX_TIMER9_IRQ,
206
+ NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */
207
+ NPCM7XX_TIMER11_IRQ,
208
+ NPCM7XX_TIMER12_IRQ,
209
+ NPCM7XX_TIMER13_IRQ,
210
+ NPCM7XX_TIMER14_IRQ,
211
+};
212
+
213
+/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
214
+#define NPCM7XX_NUM_IRQ (160)
215
+
216
+/* Register base address for each Timer Module */
217
+static const hwaddr npcm7xx_tim_addr[] = {
218
+ 0xf0008000,
219
+ 0xf0009000,
220
+ 0xf000a000,
221
+};
222
+
223
+/* Register base address for each 16550 UART */
224
+static const hwaddr npcm7xx_uart_addr[] = {
225
+ 0xf0001000,
226
+ 0xf0002000,
227
+ 0xf0003000,
228
+ 0xf0004000,
229
+};
230
+
231
+static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
232
+ const struct arm_boot_info *info)
233
+{
234
+ /*
235
+ * The default smpboot stub halts the secondary CPU with a 'wfi'
236
+ * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel
237
+ * does not send an IPI to wake it up, so the second CPU fails to boot. So
238
+ * we need to provide our own smpboot stub that can not use 'wfi', it has
239
+ * to spin the secondary CPU until the first CPU writes to the SCRPAD reg.
240
+ */
241
+ uint32_t smpboot[] = {
242
+ 0xe59f2018, /* ldr r2, bootreg_addr */
243
+ 0xe3a00000, /* mov r0, #0 */
244
+ 0xe5820000, /* str r0, [r2] */
245
+ 0xe320f002, /* wfe */
246
+ 0xe5921000, /* ldr r1, [r2] */
247
+ 0xe1110001, /* tst r1, r1 */
248
+ 0x0afffffb, /* beq <wfe> */
249
+ 0xe12fff11, /* bx r1 */
250
+ NPCM7XX_SMP_BOOTREG_ADDR,
251
+ };
252
+ int i;
253
+
254
+ for (i = 0; i < ARRAY_SIZE(smpboot); i++) {
255
+ smpboot[i] = tswap32(smpboot[i]);
256
+ }
257
+
258
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
259
+ NPCM7XX_SMP_LOADER_START);
260
+}
261
+
262
+static struct arm_boot_info npcm7xx_binfo = {
263
+ .loader_start = NPCM7XX_LOADER_START,
264
+ .smp_loader_start = NPCM7XX_SMP_LOADER_START,
265
+ .smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR,
266
+ .gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
267
+ .write_secondary_boot = npcm7xx_write_secondary_boot,
268
+ .board_id = -1,
269
+};
270
+
271
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
272
+{
273
+ NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
274
+
275
+ npcm7xx_binfo.ram_size = machine->ram_size;
276
+ npcm7xx_binfo.nb_cpus = sc->num_cpus;
277
+
278
+ arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
279
+}
280
+
281
+static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
282
+{
283
+ return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
284
+}
285
+
286
+static void npcm7xx_init(Object *obj)
287
+{
288
+ NPCM7xxState *s = NPCM7XX(obj);
289
+ int i;
290
+
291
+ for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
292
+ object_initialize_child(obj, "cpu[*]", &s->cpu[i],
293
+ ARM_CPU_TYPE_NAME("cortex-a9"));
294
+ }
295
+
296
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
297
+ object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR);
298
+ object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
299
+ "power-on-straps");
300
+ object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
301
+
302
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
303
+ object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
304
+ }
305
+}
306
+
307
+static void npcm7xx_realize(DeviceState *dev, Error **errp)
308
+{
309
+ NPCM7xxState *s = NPCM7XX(dev);
310
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
311
+ int i;
312
+
313
+ if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) {
314
+ error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64
315
+ " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB);
316
+ return;
317
+ }
318
+
319
+ /* CPUs */
320
+ for (i = 0; i < nc->num_cpus; i++) {
321
+ object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity",
322
+ arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
323
+ &error_abort);
324
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
325
+ NPCM7XX_GIC_CPU_IF_ADDR, &error_abort);
326
+ object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true,
327
+ &error_abort);
328
+
329
+ /* Disable security extensions. */
330
+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false,
331
+ &error_abort);
332
+
333
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
334
+ return;
335
+ }
336
+ }
337
+
338
+ /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
339
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus,
340
+ &error_abort);
341
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
342
+ &error_abort);
343
+ sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort);
344
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA);
345
+
346
+ for (i = 0; i < nc->num_cpus; i++) {
347
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
348
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
349
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus,
350
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
351
+ }
352
+
353
+ /* L2 cache controller */
354
+ sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
355
+
356
+ /* System Global Control Registers (GCR). Can fail due to user input. */
357
+ object_property_set_int(OBJECT(&s->gcr), "disabled-modules",
358
+ nc->disabled_modules, &error_abort);
359
+ object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram));
360
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) {
361
+ return;
362
+ }
363
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA);
364
+
365
+ /* Clock Control Registers (CLK). Cannot fail. */
366
+ sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
368
+
369
+ /* Timer Modules (TIM). Cannot fail. */
370
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
371
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
372
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]);
373
+ int first_irq;
374
+ int j;
375
+
376
+ sysbus_realize(sbd, &error_abort);
377
+ sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
378
+
379
+ first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL;
380
+ for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) {
381
+ qemu_irq irq = npcm7xx_irq(s, first_irq + j);
382
+ sysbus_connect_irq(sbd, j, irq);
383
+ }
384
+ }
385
+
386
+ /* UART0..3 (16550 compatible) */
387
+ for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) {
388
+ serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2,
389
+ npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200,
390
+ serial_hd(i), DEVICE_LITTLE_ENDIAN);
391
+ }
392
+
393
+ /* RAM2 (SRAM) */
394
+ memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
395
+ NPCM7XX_RAM2_SZ, &error_abort);
396
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram);
397
+
398
+ /* RAM3 (SRAM) */
399
+ memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3",
400
+ NPCM7XX_RAM3_SZ, &error_abort);
401
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3);
402
+
403
+ /* Internal ROM */
404
+ memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ,
405
+ &error_abort);
406
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
407
+
408
+ create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
409
+ create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
410
+ create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
411
+ create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
412
+ create_unimplemented_device("npcm7xx.rng", 0xf000b000, 4 * KiB);
413
+ create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
414
+ create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
415
+ create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
416
+ create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
417
+ create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * KiB);
418
+ create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * KiB);
419
+ create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * KiB);
420
+ create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * KiB);
421
+ create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * KiB);
422
+ create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * KiB);
423
+ create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB);
424
+ create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB);
425
+ create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB);
426
+ create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * KiB);
427
+ create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * KiB);
428
+ create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * KiB);
429
+ create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * KiB);
430
+ create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * KiB);
431
+ create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * KiB);
432
+ create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * KiB);
433
+ create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * KiB);
434
+ create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * KiB);
435
+ create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * KiB);
436
+ create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * KiB);
437
+ create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * KiB);
438
+ create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * KiB);
439
+ create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB);
440
+ create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
441
+ create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
442
+ create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
443
+ create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
444
+ create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
445
+ create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
446
+ create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
447
+ create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
448
+ create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
449
+ create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
450
+ create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
451
+ create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
452
+ create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
453
+ create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
454
+ create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
455
+ create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
456
+ create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
457
+ create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
458
+ create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
459
+ create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
460
+ create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
461
+ create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
462
+ create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
463
+ create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
464
+ create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
465
+ create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
466
+ create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
467
+ create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
468
+ create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
469
+ create_unimplemented_device("npcm7xx.usbd[3]", 0xf0833000, 4 * KiB);
470
+ create_unimplemented_device("npcm7xx.usbd[4]", 0xf0834000, 4 * KiB);
471
+ create_unimplemented_device("npcm7xx.usbd[5]", 0xf0835000, 4 * KiB);
472
+ create_unimplemented_device("npcm7xx.usbd[6]", 0xf0836000, 4 * KiB);
473
+ create_unimplemented_device("npcm7xx.usbd[7]", 0xf0837000, 4 * KiB);
474
+ create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
475
+ create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
476
+ create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
477
+ create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
478
+ create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
479
+ create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
480
+ create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
481
+ create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB);
482
+ create_unimplemented_device("npcm7xx.secacc", 0xf085b000, 4 * KiB);
483
+ create_unimplemented_device("npcm7xx.spixcs0", 0xf8000000, 16 * MiB);
484
+ create_unimplemented_device("npcm7xx.spixcs1", 0xf9000000, 16 * MiB);
485
+ create_unimplemented_device("npcm7xx.spix", 0xfb001000, 4 * KiB);
486
+}
487
+
488
+static Property npcm7xx_properties[] = {
489
+ DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION,
490
+ MemoryRegion *),
491
+ DEFINE_PROP_END_OF_LIST(),
492
+};
493
+
494
+static void npcm7xx_class_init(ObjectClass *oc, void *data)
495
+{
496
+ DeviceClass *dc = DEVICE_CLASS(oc);
497
+
498
+ dc->realize = npcm7xx_realize;
499
+ dc->user_creatable = false;
500
+ device_class_set_props(dc, npcm7xx_properties);
501
+}
502
+
503
+static void npcm730_class_init(ObjectClass *oc, void *data)
504
+{
505
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
506
+
507
+ /* NPCM730 is optimized for data center use, so no graphics, etc. */
508
+ nc->disabled_modules = 0x00300395;
509
+ nc->num_cpus = 2;
510
+}
511
+
512
+static void npcm750_class_init(ObjectClass *oc, void *data)
513
+{
514
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
515
+
516
+ /* NPCM750 has 2 cores and a full set of peripherals */
517
+ nc->disabled_modules = 0x00000000;
518
+ nc->num_cpus = 2;
519
+}
520
+
521
+static const TypeInfo npcm7xx_soc_types[] = {
522
+ {
523
+ .name = TYPE_NPCM7XX,
524
+ .parent = TYPE_DEVICE,
525
+ .instance_size = sizeof(NPCM7xxState),
526
+ .instance_init = npcm7xx_init,
527
+ .class_size = sizeof(NPCM7xxClass),
528
+ .class_init = npcm7xx_class_init,
529
+ .abstract = true,
530
+ }, {
531
+ .name = TYPE_NPCM730,
532
+ .parent = TYPE_NPCM7XX,
533
+ .class_init = npcm730_class_init,
534
+ }, {
535
+ .name = TYPE_NPCM750,
536
+ .parent = TYPE_NPCM7XX,
537
+ .class_init = npcm750_class_init,
538
+ },
539
+};
540
+
541
+DEFINE_TYPES(npcm7xx_soc_types);
542
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
16
index XXXXXXX..XXXXXXX 100644
543
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/display/bcm2835_fb.h
544
--- a/hw/arm/Kconfig
18
+++ b/include/hw/display/bcm2835_fb.h
545
+++ b/hw/arm/Kconfig
19
@@ -XXX,XX +XXX,XX @@ typedef struct {
546
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
20
547
21
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
548
config NPCM7XX
22
549
bool
23
+/**
550
+ select A9MPCORE
24
+ * bcm2835_fb_get_pitch: return number of bytes per line of the framebuffer
551
+ select ARM_GIC
25
+ * @config: configuration info for the framebuffer
552
+ select PL310 # cache controller
26
+ *
553
+ select SERIAL
27
+ * Return the number of bytes per line of the framebuffer, ie the number
554
+ select UNIMP
28
+ * that must be added to a pixel address to get the address of the pixel
555
29
+ * directly below it on screen.
556
config FSL_IMX25
30
+ */
557
bool
31
+static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
558
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
32
+{
33
+ return config->xres * (config->bpp >> 3);
34
+}
35
+
36
+/**
37
+ * bcm2835_fb_get_size: return total size of framebuffer in bytes
38
+ * @config: configuration info for the framebuffer
39
+ */
40
+static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
41
+{
42
+ return config->yres * bcm2835_fb_get_pitch(config);
43
+}
44
+
45
#endif
46
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
47
index XXXXXXX..XXXXXXX 100644
559
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/display/bcm2835_fb.c
560
--- a/hw/arm/meson.build
49
+++ b/hw/display/bcm2835_fb.c
561
+++ b/hw/arm/meson.build
50
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
562
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
51
return;
563
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
52
}
564
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
53
565
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
54
- src_width = s->config.xres * (s->config.bpp >> 3);
566
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
55
+ src_width = bcm2835_fb_get_pitch(&s->config);
567
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
56
dest_width = s->config.xres;
568
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
57
569
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
58
switch (surface_bits_per_pixel(surface)) {
59
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
60
61
/* TODO - Manage properly virtual resolution */
62
63
- pitch = s->config.xres * (s->config.bpp >> 3);
64
- size = s->config.yres * pitch;
65
+ pitch = bcm2835_fb_get_pitch(&s->config);
66
+ size = bcm2835_fb_get_size(&s->config);
67
68
stl_le_phys(&s->dma_as, value + 16, pitch);
69
stl_le_phys(&s->dma_as, value + 32, s->config.base);
70
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/misc/bcm2835_property.c
73
+++ b/hw/misc/bcm2835_property.c
74
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
75
case 0x00040001: /* Allocate buffer */
76
stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
77
stl_le_phys(&s->dma_as, value + 16,
78
- fbconfig.xres * fbconfig.yres * fbconfig.bpp / 8);
79
+ bcm2835_fb_get_size(&fbconfig));
80
resplen = 8;
81
break;
82
case 0x00048001: /* Release buffer */
83
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
84
break;
85
case 0x00040008: /* Get pitch */
86
stl_le_phys(&s->dma_as, value + 12,
87
- fbconfig.xres * fbconfig.bpp / 8);
88
+ bcm2835_fb_get_pitch(&fbconfig));
89
resplen = 4;
90
break;
91
case 0x00040009: /* Get virtual offset */
92
--
570
--
93
2.18.0
571
2.20.1
94
572
95
573
diff view generated by jsdifflib
1
The AArch32 HCR and HCR2 registers alias HCR_EL2
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
bits [31:0] and [63:32]; implement them.
2
3
3
This adds two new machines, both supported by OpenBMC:
4
Since HCR2 exists in ARMv8 but not ARMv7, we need new
4
5
regdef arrays for "we have EL3, not EL2, we're ARMv8"
5
- npcm750-evb: Nuvoton NPCM750 Evaluation Board.
6
and "we have EL2, we're ARMv8" to hold the definitions.
6
- quanta-gsj: A board with a NPCM730 chip.
7
7
8
They rely on the NPCM7xx SoC device to do the heavy lifting. They are
9
almost completely identical at the moment, apart from the SoC type,
10
which currently only changes the reset contents of one register
11
(GCR.MDLR), but they might grow apart a bit more as more functionality
12
is added.
13
14
Both machines can boot the Linux kernel into /bin/sh.
15
16
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
17
Reviewed-by: Joel Stanley <joel@jms.id.au>
18
Reviewed-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Tested-by: Alexander Bulekov <alxndr@bu.edu>
22
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
23
Message-id: 20200911052101.2602693-6-hskinnemoen@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
Message-id: 20180820153020.21478-3-peter.maydell@linaro.org
13
---
25
---
14
target/arm/helper.c | 54 +++++++++++++++++++++++++++++++++++++++++----
26
default-configs/arm-softmmu.mak | 1 +
15
1 file changed, 50 insertions(+), 4 deletions(-)
27
include/hw/arm/npcm7xx.h | 19 +++++
16
28
hw/arm/npcm7xx_boards.c | 145 ++++++++++++++++++++++++++++++++
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
hw/arm/meson.build | 2 +-
30
4 files changed, 166 insertions(+), 1 deletion(-)
31
create mode 100644 hw/arm/npcm7xx_boards.c
32
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
18
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
35
--- a/default-configs/arm-softmmu.mak
20
+++ b/target/arm/helper.c
36
+++ b/default-configs/arm-softmmu.mak
21
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
37
@@ -XXX,XX +XXX,XX @@ CONFIG_GUMSTIX=y
22
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
38
CONFIG_SPITZ=y
23
.access = PL2_RW,
39
CONFIG_TOSA=y
24
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
40
CONFIG_Z2=y
25
- { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
41
+CONFIG_NPCM7XX=y
26
+ { .name = "HCR_EL2", .state = ARM_CP_STATE_BOTH,
42
CONFIG_COLLIE=y
27
.type = ARM_CP_NO_RAW,
43
CONFIG_ASPEED_SOC=y
28
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
44
CONFIG_NETDUINO2=y
29
.access = PL2_RW,
45
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
30
- .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
46
index XXXXXXX..XXXXXXX 100644
31
+ .type = ARM_CP_CONST, .resetvalue = 0 },
47
--- a/include/hw/arm/npcm7xx.h
32
{ .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
48
+++ b/include/hw/arm/npcm7xx.h
33
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
49
@@ -XXX,XX +XXX,XX @@
34
.access = PL2_RW,
50
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
35
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
51
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
36
REGINFO_SENTINEL
52
37
};
53
+typedef struct NPCM7xxMachine {
38
54
+ MachineState parent;
39
+/* Ditto, but for registers which exist in ARMv8 but not v7 */
55
+} NPCM7xxMachine;
40
+static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
56
+
41
+ { .name = "HCR2", .state = ARM_CP_STATE_AA32,
57
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
42
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
58
+#define NPCM7XX_MACHINE(obj) \
43
+ .access = PL2_RW,
59
+ OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
44
+ .type = ARM_CP_CONST, .resetvalue = 0 },
60
+
45
+ REGINFO_SENTINEL
61
+typedef struct NPCM7xxMachineClass {
62
+ MachineClass parent;
63
+
64
+ const char *soc_type;
65
+} NPCM7xxMachineClass;
66
+
67
+#define NPCM7XX_MACHINE_CLASS(klass) \
68
+ OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
69
+#define NPCM7XX_MACHINE_GET_CLASS(obj) \
70
+ OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
71
+
72
typedef struct NPCM7xxState {
73
DeviceState parent;
74
75
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/arm/npcm7xx_boards.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
82
+ * Machine definitions for boards featuring an NPCM7xx SoC.
83
+ *
84
+ * Copyright 2020 Google LLC
85
+ *
86
+ * This program is free software; you can redistribute it and/or modify it
87
+ * under the terms of the GNU General Public License as published by the
88
+ * Free Software Foundation; either version 2 of the License, or
89
+ * (at your option) any later version.
90
+ *
91
+ * This program is distributed in the hope that it will be useful, but WITHOUT
92
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
93
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
94
+ * for more details.
95
+ */
96
+
97
+#include "qemu/osdep.h"
98
+
99
+#include "exec/address-spaces.h"
100
+#include "hw/arm/npcm7xx.h"
101
+#include "hw/core/cpu.h"
102
+#include "qapi/error.h"
103
+#include "qemu/units.h"
104
+
105
+#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
106
+#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
107
+
108
+static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
109
+{
110
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
111
+
112
+ object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
113
+ &error_abort);
114
+}
115
+
116
+static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
117
+ uint32_t hw_straps)
118
+{
119
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
120
+ MachineClass *mc = &nmc->parent;
121
+ Object *obj;
122
+
123
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
124
+ error_report("This board can only be used with %s",
125
+ mc->default_cpu_type);
126
+ exit(1);
127
+ }
128
+
129
+ obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
130
+ &error_abort, NULL);
131
+ object_property_set_uint(obj, "power-on-straps", hw_straps, &error_abort);
132
+
133
+ return NPCM7XX(obj);
134
+}
135
+
136
+static void npcm750_evb_init(MachineState *machine)
137
+{
138
+ NPCM7xxState *soc;
139
+
140
+ soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
141
+ npcm7xx_connect_dram(soc, machine->ram);
142
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
143
+
144
+ npcm7xx_load_kernel(machine, soc);
145
+}
146
+
147
+static void quanta_gsj_init(MachineState *machine)
148
+{
149
+ NPCM7xxState *soc;
150
+
151
+ soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS);
152
+ npcm7xx_connect_dram(soc, machine->ram);
153
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
154
+
155
+ npcm7xx_load_kernel(machine, soc);
156
+}
157
+
158
+static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
159
+{
160
+ NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
161
+ MachineClass *mc = MACHINE_CLASS(nmc);
162
+
163
+ nmc->soc_type = type;
164
+ mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus;
165
+}
166
+
167
+static void npcm7xx_machine_class_init(ObjectClass *oc, void *data)
168
+{
169
+ MachineClass *mc = MACHINE_CLASS(oc);
170
+
171
+ mc->no_floppy = 1;
172
+ mc->no_cdrom = 1;
173
+ mc->no_parallel = 1;
174
+ mc->default_ram_id = "ram";
175
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
176
+}
177
+
178
+/*
179
+ * Schematics:
180
+ * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf
181
+ */
182
+static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data)
183
+{
184
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
185
+ MachineClass *mc = MACHINE_CLASS(oc);
186
+
187
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM750);
188
+
189
+ mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex A9)";
190
+ mc->init = npcm750_evb_init;
191
+ mc->default_ram_size = 512 * MiB;
46
+};
192
+};
47
+
193
+
48
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
194
+static void gsj_machine_class_init(ObjectClass *oc, void *data)
49
{
195
+{
50
ARMCPU *cpu = arm_env_get_cpu(env);
196
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
51
@@ -XXX,XX +XXX,XX @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
197
+ MachineClass *mc = MACHINE_CLASS(oc);
52
* HCR_PTW forbids certain page-table setups
198
+
53
* HCR_DC Disables stage1 and enables stage2 translation
199
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
54
*/
200
+
55
- if ((raw_read(env, ri) ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
201
+ mc->desc = "Quanta GSJ (Cortex A9)";
56
+ if ((env->cp15.hcr_el2 ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
202
+ mc->init = quanta_gsj_init;
57
tlb_flush(CPU(cpu));
203
+ mc->default_ram_size = 512 * MiB;
58
}
59
- raw_write(env, ri, value);
60
+ env->cp15.hcr_el2 = value;
61
+}
62
+
63
+static void hcr_writehigh(CPUARMState *env, const ARMCPRegInfo *ri,
64
+ uint64_t value)
65
+{
66
+ /* Handle HCR2 write, i.e. write to high half of HCR_EL2 */
67
+ value = deposit64(env->cp15.hcr_el2, 32, 32, value);
68
+ hcr_write(env, NULL, value);
69
+}
70
+
71
+static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
72
+ uint64_t value)
73
+{
74
+ /* Handle HCR write, i.e. write to low half of HCR_EL2 */
75
+ value = deposit64(env->cp15.hcr_el2, 0, 32, value);
76
+ hcr_write(env, NULL, value);
77
}
78
79
static const ARMCPRegInfo el2_cp_reginfo[] = {
80
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
81
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
82
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
83
.writefn = hcr_write },
84
+ { .name = "HCR", .state = ARM_CP_STATE_AA32,
85
+ .type = ARM_CP_ALIAS,
86
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
87
+ .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
88
+ .writefn = hcr_writelow },
89
{ .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
90
.type = ARM_CP_ALIAS,
91
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
92
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
93
REGINFO_SENTINEL
94
};
95
96
+static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
97
+ { .name = "HCR2", .state = ARM_CP_STATE_AA32,
98
+ .type = ARM_CP_ALIAS,
99
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
100
+ .access = PL2_RW,
101
+ .fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
102
+ .writefn = hcr_writehigh },
103
+ REGINFO_SENTINEL
104
+};
204
+};
105
+
205
+
106
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
206
+static const TypeInfo npcm7xx_machine_types[] = {
107
bool isread)
207
+ {
108
{
208
+ .name = TYPE_NPCM7XX_MACHINE,
109
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
209
+ .parent = TYPE_MACHINE,
110
};
210
+ .instance_size = sizeof(NPCM7xxMachine),
111
define_arm_cp_regs(cpu, vpidr_regs);
211
+ .class_size = sizeof(NPCM7xxMachineClass),
112
define_arm_cp_regs(cpu, el2_cp_reginfo);
212
+ .class_init = npcm7xx_machine_class_init,
113
+ if (arm_feature(env, ARM_FEATURE_V8)) {
213
+ .abstract = true,
114
+ define_arm_cp_regs(cpu, el2_v8_cp_reginfo);
214
+ }, {
115
+ }
215
+ .name = MACHINE_TYPE_NAME("npcm750-evb"),
116
/* RVBAR_EL2 is only implemented if EL2 is the highest EL */
216
+ .parent = TYPE_NPCM7XX_MACHINE,
117
if (!arm_feature(env, ARM_FEATURE_EL3)) {
217
+ .class_init = npcm750_evb_machine_class_init,
118
ARMCPRegInfo rvbar = {
218
+ }, {
119
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
219
+ .name = MACHINE_TYPE_NAME("quanta-gsj"),
120
};
220
+ .parent = TYPE_NPCM7XX_MACHINE,
121
define_arm_cp_regs(cpu, vpidr_regs);
221
+ .class_init = gsj_machine_class_init,
122
define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
222
+ },
123
+ if (arm_feature(env, ARM_FEATURE_V8)) {
223
+};
124
+ define_arm_cp_regs(cpu, el3_no_el2_v8_cp_reginfo);
224
+
125
+ }
225
+DEFINE_TYPES(npcm7xx_machine_types)
126
}
226
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
127
}
227
index XXXXXXX..XXXXXXX 100644
128
if (arm_feature(env, ARM_FEATURE_EL3)) {
228
--- a/hw/arm/meson.build
229
+++ b/hw/arm/meson.build
230
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
231
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
232
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
233
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
234
-arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
235
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
236
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
237
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
238
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
129
--
239
--
130
2.18.0
240
2.20.1
131
241
132
242
diff view generated by jsdifflib
1
The BCM2835FBState struct has a 'pitch' field which is a
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
cached copy of xres * (bpp >> 3), and a 'size' field which is
3
a cached copy of pitch * yres. However we don't actually do
4
anything with these fields; delete them. We retain the
5
now-unused slots in the VMState struct for migration
6
compatibility.
7
2
3
This is a minimalistic boot ROM written specifically for use with QEMU.
4
It supports loading the second-stage loader from SPI flash into RAM, SMP
5
boot, and not much else.
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Message-id: 20200911052101.2602693-7-hskinnemoen@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180814144436.679-4-peter.maydell@linaro.org
11
---
12
---
12
include/hw/display/bcm2835_fb.h | 4 ----
13
.gitmodules | 3 +++
13
hw/display/bcm2835_fb.c | 19 ++++++++-----------
14
MAINTAINERS | 2 ++
14
2 files changed, 8 insertions(+), 15 deletions(-)
15
pc-bios/README | 6 ++++++
16
pc-bios/meson.build | 1 +
17
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
18
roms/Makefile | 7 +++++++
19
roms/vbootrom | 1 +
20
7 files changed, 20 insertions(+)
21
create mode 100644 pc-bios/npcm7xx_bootrom.bin
22
create mode 160000 roms/vbootrom
15
23
16
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
24
diff --git a/.gitmodules b/.gitmodules
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/display/bcm2835_fb.h
26
--- a/.gitmodules
19
+++ b/include/hw/display/bcm2835_fb.h
27
+++ b/.gitmodules
20
@@ -XXX,XX +XXX,XX @@ typedef struct {
28
@@ -XXX,XX +XXX,XX @@
21
bool lock, invalidate, pending;
29
[submodule "meson"]
22
30
    path = meson
23
BCM2835FBConfig config;
31
    url = https://github.com/mesonbuild/meson/
24
-
32
+[submodule "roms/vbootrom"]
25
- /* These are just cached values calculated from the config settings */
33
+    path = roms/vbootrom
26
- uint32_t size;
34
+    url = https://github.com/google/vbootrom.git
27
- uint32_t pitch;
35
diff --git a/MAINTAINERS b/MAINTAINERS
28
} BCM2835FBState;
29
30
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
31
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
32
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/display/bcm2835_fb.c
37
--- a/MAINTAINERS
34
+++ b/hw/display/bcm2835_fb.c
38
+++ b/MAINTAINERS
35
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
39
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
36
40
S: Supported
37
static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
41
F: hw/*/npcm7xx*
38
{
42
F: include/hw/*/npcm7xx*
39
+ uint32_t pitch;
43
+F: pc-bios/npcm7xx_bootrom.bin
40
+ uint32_t size;
44
+F: roms/vbootrom
45
46
nSeries
47
M: Andrzej Zaborowski <balrogg@gmail.com>
48
diff --git a/pc-bios/README b/pc-bios/README
49
index XXXXXXX..XXXXXXX 100644
50
--- a/pc-bios/README
51
+++ b/pc-bios/README
52
@@ -XXX,XX +XXX,XX @@
53
("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
54
source code also contains code reused from other projects desribed here:
55
https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
41
+
56
+
42
value &= ~0xf;
57
+- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton
43
58
+ NPCM7xx BMC devices. It currently implements the bare minimum to load, parse,
44
s->lock = true;
59
+ initialize and run boot images stored in SPI flash, but may grow more
45
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
60
+ features over time as needed. The source code is available at:
46
61
+ https://github.com/google/vbootrom
47
/* TODO - Manage properly virtual resolution */
62
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
48
63
index XXXXXXX..XXXXXXX 100644
49
- s->pitch = s->config.xres * (s->config.bpp >> 3);
64
--- a/pc-bios/meson.build
50
- s->size = s->config.yres * s->pitch;
65
+++ b/pc-bios/meson.build
51
+ pitch = s->config.xres * (s->config.bpp >> 3);
66
@@ -XXX,XX +XXX,XX @@ blobs = files(
52
+ size = s->config.yres * pitch;
67
'opensbi-riscv64-generic-fw_dynamic.bin',
53
68
'opensbi-riscv32-generic-fw_dynamic.elf',
54
- stl_le_phys(&s->dma_as, value + 16, s->pitch);
69
'opensbi-riscv64-generic-fw_dynamic.elf',
55
+ stl_le_phys(&s->dma_as, value + 16, pitch);
70
+ 'npcm7xx_bootrom.bin',
56
stl_le_phys(&s->dma_as, value + 32, s->config.base);
71
)
57
- stl_le_phys(&s->dma_as, value + 36, s->size);
72
58
+ stl_le_phys(&s->dma_as, value + 36, size);
73
if install_blobs
59
74
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
60
s->invalidate = true;
75
new file mode 100644
61
qemu_console_resize(s->con, s->config.xres, s->config.yres);
76
index XXXXXXX..XXXXXXX
62
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
77
GIT binary patch
63
78
literal 768
64
/* TODO - Manage properly virtual resolution */
79
zcmd5)JxClu6n-<aczPbVhZYusb8wKx;7TklHfmuZdYT9pDRLwd1p_t-DFpWpyA+8(
65
80
zwKtZg3J4a0aCM3_X(ZL&4g;46VVk5e$K;z;L99|b@aE%v^S$rQ8)h(Vm@cB9IYc+2
66
- s->pitch = s->config.xres * (s->config.bpp >> 3);
81
z2SHd4^NwTIGE%w>9S05p1#kf90Sj5Z(jG8}+)IZIp~iXK=T&)dL`%d-q*8aR#mq{7
67
- s->size = s->config.yres * s->pitch;
82
z9`=6;Dr(H0ACe72R5x?!)^86Qj-X%{+!K9iZNA@*wkBAV&iZ(l^I9?!Gz=S2I_*1d
68
-
83
zr+tTQDHjvyzKnw(hu00yX`u!Fv<!~XVcX?@kr#<B0(gGU?$W{gSsQa}CF^8Cfzp2X
69
s->invalidate = true;
84
z@P}yDV-bci(K9XL$FU!som2C`c)?Uc&294s^}Wzumap{hg1X^jN|V25M5tQZ=<9lN
70
qemu_console_resize(s->con, s->config.xres, s->config.yres);
85
z%(zKz#t-qCwHKb;HygOCpvCNL_4@1tXV1YGf^XUE_$zr{g8zWh-6gz-teI(eibtxo
71
s->lock = false;
86
z?0OZI4%rU0741PgUD`2xq@H|*4=+Rs?%N)Ox5G+q>C;DilBe_YlkeSUVHA-crNk+k
72
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_bcm2835_fb = {
87
jtiF_MudA<CB(}8|fqYwCf3re&=&@_s761P#-ID$TwgmBa
73
VMSTATE_UINT32(config.yoffset, BCM2835FBState),
88
74
VMSTATE_UINT32(config.bpp, BCM2835FBState),
89
literal 0
75
VMSTATE_UINT32(config.base, BCM2835FBState),
90
HcmV?d00001
76
- VMSTATE_UINT32(pitch, BCM2835FBState),
91
77
- VMSTATE_UINT32(size, BCM2835FBState),
92
diff --git a/roms/Makefile b/roms/Makefile
78
+ VMSTATE_UNUSED(8), /* Was pitch and size */
93
index XXXXXXX..XXXXXXX 100644
79
VMSTATE_UINT32(config.pixo, BCM2835FBState),
94
--- a/roms/Makefile
80
VMSTATE_UINT32(config.alpha, BCM2835FBState),
95
+++ b/roms/Makefile
81
VMSTATE_END_OF_LIST()
96
@@ -XXX,XX +XXX,XX @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld
82
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_reset(DeviceState *dev)
97
# finally strip off path + toolname so we get the prefix
83
s->config.xoffset = 0;
98
find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1))))
84
s->config.yoffset = 0;
99
85
s->config.base = s->vcram_base + BCM2835_FB_OFFSET;
100
+arm_cross_prefix := $(call find-cross-prefix,arm)
86
- s->pitch = s->config.xres * (s->config.bpp >> 3);
101
powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
87
- s->size = s->config.yres * s->pitch;
102
powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
88
103
x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
89
s->invalidate = true;
104
@@ -XXX,XX +XXX,XX @@ default help:
90
s->lock = false;
105
    @echo " skiboot -- update skiboot.lid"
106
    @echo " u-boot.e500 -- update u-boot.e500"
107
    @echo " u-boot.sam460 -- update u-boot.sam460"
108
+    @echo " npcm7xx_bootrom -- update vbootrom for npcm7xx"
109
    @echo " efi -- update UEFI (edk2) platform firmware"
110
    @echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine"
111
    @echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine"
112
@@ -XXX,XX +XXX,XX @@ bios-microvm:
113
    $(MAKE) -C qboot
114
    cp qboot/bios.bin ../pc-bios/bios-microvm.bin
115
116
+npcm7xx_bootrom:
117
+    $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix)
118
+    cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin
119
+
120
clean:
121
    rm -rf seabios/.config seabios/out seabios/builds
122
    $(MAKE) -C sgabios clean
123
@@ -XXX,XX +XXX,XX @@ clean:
124
    $(MAKE) -f Makefile.edk2 clean
125
    $(MAKE) -C opensbi clean
126
    $(MAKE) -C qboot clean
127
+    $(MAKE) -C vbootrom clean
128
diff --git a/roms/vbootrom b/roms/vbootrom
129
new file mode 160000
130
index XXXXXXX..XXXXXXX
131
--- /dev/null
132
+++ b/roms/vbootrom
133
@@ -0,0 +1 @@
134
+Subproject commit 0c37a43527f0ee2b9584e7fb2fdc805e902635ac
91
--
135
--
92
2.18.0
136
2.20.1
93
137
94
138
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
If a -bios option is specified on the command line, load the image into
4
Message-id: 20180814002653.12828-2-richard.henderson@linaro.org
4
the internal ROM memory region, which contains the first instructions
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
run by the CPU after reset.
6
7
If -bios is not specified, the vbootrom included with qemu is loaded by
8
default.
9
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Message-id: 20200911052101.2602693-8-hskinnemoen@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
17
---
8
include/fpu/softfloat.h | 56 ++++++++----
18
hw/arm/npcm7xx_boards.c | 32 ++++++++++++++++++++++++++++++++
9
fpu/softfloat.c | 188 +++++++++++++++++++++++++++++-----------
19
1 file changed, 32 insertions(+)
10
2 files changed, 179 insertions(+), 65 deletions(-)
11
20
12
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/include/fpu/softfloat.h
23
--- a/hw/arm/npcm7xx_boards.c
15
+++ b/include/fpu/softfloat.h
24
+++ b/hw/arm/npcm7xx_boards.c
16
@@ -XXX,XX +XXX,XX @@ enum {
25
@@ -XXX,XX +XXX,XX @@
17
/*----------------------------------------------------------------------------
26
#include "exec/address-spaces.h"
18
| Software IEC/IEEE integer-to-floating-point conversion routines.
27
#include "hw/arm/npcm7xx.h"
19
*----------------------------------------------------------------------------*/
28
#include "hw/core/cpu.h"
29
+#include "hw/loader.h"
30
#include "qapi/error.h"
31
+#include "qemu-common.h"
32
#include "qemu/units.h"
33
+#include "sysemu/sysemu.h"
34
35
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
36
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
37
38
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
20
+
39
+
21
+float16 int16_to_float16_scalbn(int16_t a, int, float_status *status);
40
+static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
22
+float16 int32_to_float16_scalbn(int32_t a, int, float_status *status);
41
+{
23
+float16 int64_to_float16_scalbn(int64_t a, int, float_status *status);
42
+ g_autofree char *filename = NULL;
24
+float16 uint16_to_float16_scalbn(uint16_t a, int, float_status *status);
43
+ int ret;
25
+float16 uint32_to_float16_scalbn(uint32_t a, int, float_status *status);
26
+float16 uint64_to_float16_scalbn(uint64_t a, int, float_status *status);
27
+
44
+
28
+float16 int16_to_float16(int16_t a, float_status *status);
45
+ if (!bios_name) {
29
+float16 int32_to_float16(int32_t a, float_status *status);
46
+ bios_name = npcm7xx_default_bootrom;
30
+float16 int64_to_float16(int64_t a, float_status *status);
47
+ }
31
+float16 uint16_to_float16(uint16_t a, float_status *status);
32
+float16 uint32_to_float16(uint32_t a, float_status *status);
33
+float16 uint64_to_float16(uint64_t a, float_status *status);
34
+
48
+
35
+float32 int16_to_float32_scalbn(int16_t, int, float_status *status);
49
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
36
+float32 int32_to_float32_scalbn(int32_t, int, float_status *status);
50
+ if (!filename) {
37
+float32 int64_to_float32_scalbn(int64_t, int, float_status *status);
51
+ error_report("Could not find ROM image '%s'", bios_name);
38
+float32 uint16_to_float32_scalbn(uint16_t, int, float_status *status);
52
+ if (!machine->kernel_filename) {
39
+float32 uint32_to_float32_scalbn(uint32_t, int, float_status *status);
53
+ /* We can't boot without a bootrom or a kernel image. */
40
+float32 uint64_to_float32_scalbn(uint64_t, int, float_status *status);
54
+ exit(1);
41
+
42
float32 int16_to_float32(int16_t, float_status *status);
43
float32 int32_to_float32(int32_t, float_status *status);
44
-float64 int16_to_float64(int16_t, float_status *status);
45
-float64 int32_to_float64(int32_t, float_status *status);
46
+float32 int64_to_float32(int64_t, float_status *status);
47
float32 uint16_to_float32(uint16_t, float_status *status);
48
float32 uint32_to_float32(uint32_t, float_status *status);
49
+float32 uint64_to_float32(uint64_t, float_status *status);
50
+
51
+float64 int16_to_float64_scalbn(int16_t, int, float_status *status);
52
+float64 int32_to_float64_scalbn(int32_t, int, float_status *status);
53
+float64 int64_to_float64_scalbn(int64_t, int, float_status *status);
54
+float64 uint16_to_float64_scalbn(uint16_t, int, float_status *status);
55
+float64 uint32_to_float64_scalbn(uint32_t, int, float_status *status);
56
+float64 uint64_to_float64_scalbn(uint64_t, int, float_status *status);
57
+
58
+float64 int16_to_float64(int16_t, float_status *status);
59
+float64 int32_to_float64(int32_t, float_status *status);
60
+float64 int64_to_float64(int64_t, float_status *status);
61
float64 uint16_to_float64(uint16_t, float_status *status);
62
float64 uint32_to_float64(uint32_t, float_status *status);
63
-floatx80 int32_to_floatx80(int32_t, float_status *status);
64
-float128 int32_to_float128(int32_t, float_status *status);
65
-float32 int64_to_float32(int64_t, float_status *status);
66
-float64 int64_to_float64(int64_t, float_status *status);
67
-floatx80 int64_to_floatx80(int64_t, float_status *status);
68
-float128 int64_to_float128(int64_t, float_status *status);
69
-float32 uint64_to_float32(uint64_t, float_status *status);
70
float64 uint64_to_float64(uint64_t, float_status *status);
71
+
72
+floatx80 int32_to_floatx80(int32_t, float_status *status);
73
+floatx80 int64_to_floatx80(int64_t, float_status *status);
74
+
75
+float128 int32_to_float128(int32_t, float_status *status);
76
+float128 int64_to_float128(int64_t, float_status *status);
77
float128 uint64_to_float128(uint64_t, float_status *status);
78
79
/*----------------------------------------------------------------------------
80
@@ -XXX,XX +XXX,XX @@ int64_t float16_to_int64(float16, float_status *status);
81
uint64_t float16_to_uint64(float16 a, float_status *status);
82
int64_t float16_to_int64_round_to_zero(float16, float_status *status);
83
uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *status);
84
-float16 int16_to_float16(int16_t a, float_status *status);
85
-float16 int32_to_float16(int32_t a, float_status *status);
86
-float16 int64_to_float16(int64_t a, float_status *status);
87
-float16 uint16_to_float16(uint16_t a, float_status *status);
88
-float16 uint32_to_float16(uint32_t a, float_status *status);
89
-float16 uint64_to_float16(uint64_t a, float_status *status);
90
91
/*----------------------------------------------------------------------------
92
| Software half-precision operations.
93
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/fpu/softfloat.c
96
+++ b/fpu/softfloat.c
97
@@ -XXX,XX +XXX,XX @@ FLOAT_TO_UINT(64, 64)
98
* to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
99
*/
100
101
-static FloatParts int_to_float(int64_t a, float_status *status)
102
+static FloatParts int_to_float(int64_t a, int scale, float_status *status)
103
{
104
- FloatParts r = {};
105
+ FloatParts r = { .sign = false };
106
+
107
if (a == 0) {
108
r.cls = float_class_zero;
109
- r.sign = false;
110
- } else if (a == (1ULL << 63)) {
111
- r.cls = float_class_normal;
112
- r.sign = true;
113
- r.frac = DECOMPOSED_IMPLICIT_BIT;
114
- r.exp = 63;
115
} else {
116
- uint64_t f;
117
- if (a < 0) {
118
- f = -a;
119
- r.sign = true;
120
- } else {
121
- f = a;
122
- r.sign = false;
123
- }
124
- int shift = clz64(f) - 1;
125
+ uint64_t f = a;
126
+ int shift;
127
+
128
r.cls = float_class_normal;
129
- r.exp = (DECOMPOSED_BINARY_POINT - shift);
130
- r.frac = f << shift;
131
+ if (a < 0) {
132
+ f = -f;
133
+ r.sign = true;
134
+ }
55
+ }
135
+ shift = clz64(f) - 1;
56
+ return;
136
+ scale = MIN(MAX(scale, -0x10000), 0x10000);
57
+ }
137
+
58
+ ret = load_image_mr(filename, &soc->irom);
138
+ r.exp = DECOMPOSED_BINARY_POINT - shift + scale;
59
+ if (ret < 0) {
139
+ r.frac = (shift < 0 ? DECOMPOSED_IMPLICIT_BIT : f << shift);
60
+ error_report("Failed to load ROM image '%s'", filename);
140
}
61
+ exit(1);
141
62
+ }
142
return r;
143
}
144
145
+float16 int64_to_float16_scalbn(int64_t a, int scale, float_status *status)
146
+{
147
+ FloatParts pa = int_to_float(a, scale, status);
148
+ return float16_round_pack_canonical(pa, status);
149
+}
63
+}
150
+
64
+
151
+float16 int32_to_float16_scalbn(int32_t a, int scale, float_status *status)
65
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
152
+{
153
+ return int64_to_float16_scalbn(a, scale, status);
154
+}
155
+
156
+float16 int16_to_float16_scalbn(int16_t a, int scale, float_status *status)
157
+{
158
+ return int64_to_float16_scalbn(a, scale, status);
159
+}
160
+
161
float16 int64_to_float16(int64_t a, float_status *status)
162
{
66
{
163
- FloatParts pa = int_to_float(a, status);
67
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
164
- return float16_round_pack_canonical(pa, status);
68
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
165
+ return int64_to_float16_scalbn(a, 0, status);
69
npcm7xx_connect_dram(soc, machine->ram);
70
qdev_realize(DEVICE(soc), NULL, &error_fatal);
71
72
+ npcm7xx_load_bootrom(machine, soc);
73
npcm7xx_load_kernel(machine, soc);
166
}
74
}
167
75
168
float16 int32_to_float16(int32_t a, float_status *status)
76
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
169
{
77
npcm7xx_connect_dram(soc, machine->ram);
170
- return int64_to_float16(a, status);
78
qdev_realize(DEVICE(soc), NULL, &error_fatal);
171
+ return int64_to_float16_scalbn(a, 0, status);
79
80
+ npcm7xx_load_bootrom(machine, soc);
81
npcm7xx_load_kernel(machine, soc);
172
}
82
}
173
83
174
float16 int16_to_float16(int16_t a, float_status *status)
175
{
176
- return int64_to_float16(a, status);
177
+ return int64_to_float16_scalbn(a, 0, status);
178
+}
179
+
180
+float32 int64_to_float32_scalbn(int64_t a, int scale, float_status *status)
181
+{
182
+ FloatParts pa = int_to_float(a, scale, status);
183
+ return float32_round_pack_canonical(pa, status);
184
+}
185
+
186
+float32 int32_to_float32_scalbn(int32_t a, int scale, float_status *status)
187
+{
188
+ return int64_to_float32_scalbn(a, scale, status);
189
+}
190
+
191
+float32 int16_to_float32_scalbn(int16_t a, int scale, float_status *status)
192
+{
193
+ return int64_to_float32_scalbn(a, scale, status);
194
}
195
196
float32 int64_to_float32(int64_t a, float_status *status)
197
{
198
- FloatParts pa = int_to_float(a, status);
199
- return float32_round_pack_canonical(pa, status);
200
+ return int64_to_float32_scalbn(a, 0, status);
201
}
202
203
float32 int32_to_float32(int32_t a, float_status *status)
204
{
205
- return int64_to_float32(a, status);
206
+ return int64_to_float32_scalbn(a, 0, status);
207
}
208
209
float32 int16_to_float32(int16_t a, float_status *status)
210
{
211
- return int64_to_float32(a, status);
212
+ return int64_to_float32_scalbn(a, 0, status);
213
+}
214
+
215
+float64 int64_to_float64_scalbn(int64_t a, int scale, float_status *status)
216
+{
217
+ FloatParts pa = int_to_float(a, scale, status);
218
+ return float64_round_pack_canonical(pa, status);
219
+}
220
+
221
+float64 int32_to_float64_scalbn(int32_t a, int scale, float_status *status)
222
+{
223
+ return int64_to_float64_scalbn(a, scale, status);
224
+}
225
+
226
+float64 int16_to_float64_scalbn(int16_t a, int scale, float_status *status)
227
+{
228
+ return int64_to_float64_scalbn(a, scale, status);
229
}
230
231
float64 int64_to_float64(int64_t a, float_status *status)
232
{
233
- FloatParts pa = int_to_float(a, status);
234
- return float64_round_pack_canonical(pa, status);
235
+ return int64_to_float64_scalbn(a, 0, status);
236
}
237
238
float64 int32_to_float64(int32_t a, float_status *status)
239
{
240
- return int64_to_float64(a, status);
241
+ return int64_to_float64_scalbn(a, 0, status);
242
}
243
244
float64 int16_to_float64(int16_t a, float_status *status)
245
{
246
- return int64_to_float64(a, status);
247
+ return int64_to_float64_scalbn(a, 0, status);
248
}
249
250
251
@@ -XXX,XX +XXX,XX @@ float64 int16_to_float64(int16_t a, float_status *status)
252
* IEC/IEEE Standard for Binary Floating-Point Arithmetic.
253
*/
254
255
-static FloatParts uint_to_float(uint64_t a, float_status *status)
256
+static FloatParts uint_to_float(uint64_t a, int scale, float_status *status)
257
{
258
- FloatParts r = { .sign = false};
259
+ FloatParts r = { .sign = false };
260
261
if (a == 0) {
262
r.cls = float_class_zero;
263
} else {
264
- int spare_bits = clz64(a) - 1;
265
+ scale = MIN(MAX(scale, -0x10000), 0x10000);
266
r.cls = float_class_normal;
267
- r.exp = DECOMPOSED_BINARY_POINT - spare_bits;
268
- if (spare_bits < 0) {
269
- shift64RightJamming(a, -spare_bits, &a);
270
+ if ((int64_t)a < 0) {
271
+ r.exp = DECOMPOSED_BINARY_POINT + 1 + scale;
272
+ shift64RightJamming(a, 1, &a);
273
r.frac = a;
274
} else {
275
- r.frac = a << spare_bits;
276
+ int shift = clz64(a) - 1;
277
+ r.exp = DECOMPOSED_BINARY_POINT - shift + scale;
278
+ r.frac = a << shift;
279
}
280
}
281
282
return r;
283
}
284
285
+float16 uint64_to_float16_scalbn(uint64_t a, int scale, float_status *status)
286
+{
287
+ FloatParts pa = uint_to_float(a, scale, status);
288
+ return float16_round_pack_canonical(pa, status);
289
+}
290
+
291
+float16 uint32_to_float16_scalbn(uint32_t a, int scale, float_status *status)
292
+{
293
+ return uint64_to_float16_scalbn(a, scale, status);
294
+}
295
+
296
+float16 uint16_to_float16_scalbn(uint16_t a, int scale, float_status *status)
297
+{
298
+ return uint64_to_float16_scalbn(a, scale, status);
299
+}
300
+
301
float16 uint64_to_float16(uint64_t a, float_status *status)
302
{
303
- FloatParts pa = uint_to_float(a, status);
304
- return float16_round_pack_canonical(pa, status);
305
+ return uint64_to_float16_scalbn(a, 0, status);
306
}
307
308
float16 uint32_to_float16(uint32_t a, float_status *status)
309
{
310
- return uint64_to_float16(a, status);
311
+ return uint64_to_float16_scalbn(a, 0, status);
312
}
313
314
float16 uint16_to_float16(uint16_t a, float_status *status)
315
{
316
- return uint64_to_float16(a, status);
317
+ return uint64_to_float16_scalbn(a, 0, status);
318
+}
319
+
320
+float32 uint64_to_float32_scalbn(uint64_t a, int scale, float_status *status)
321
+{
322
+ FloatParts pa = uint_to_float(a, scale, status);
323
+ return float32_round_pack_canonical(pa, status);
324
+}
325
+
326
+float32 uint32_to_float32_scalbn(uint32_t a, int scale, float_status *status)
327
+{
328
+ return uint64_to_float32_scalbn(a, scale, status);
329
+}
330
+
331
+float32 uint16_to_float32_scalbn(uint16_t a, int scale, float_status *status)
332
+{
333
+ return uint64_to_float32_scalbn(a, scale, status);
334
}
335
336
float32 uint64_to_float32(uint64_t a, float_status *status)
337
{
338
- FloatParts pa = uint_to_float(a, status);
339
- return float32_round_pack_canonical(pa, status);
340
+ return uint64_to_float32_scalbn(a, 0, status);
341
}
342
343
float32 uint32_to_float32(uint32_t a, float_status *status)
344
{
345
- return uint64_to_float32(a, status);
346
+ return uint64_to_float32_scalbn(a, 0, status);
347
}
348
349
float32 uint16_to_float32(uint16_t a, float_status *status)
350
{
351
- return uint64_to_float32(a, status);
352
+ return uint64_to_float32_scalbn(a, 0, status);
353
+}
354
+
355
+float64 uint64_to_float64_scalbn(uint64_t a, int scale, float_status *status)
356
+{
357
+ FloatParts pa = uint_to_float(a, scale, status);
358
+ return float64_round_pack_canonical(pa, status);
359
+}
360
+
361
+float64 uint32_to_float64_scalbn(uint32_t a, int scale, float_status *status)
362
+{
363
+ return uint64_to_float64_scalbn(a, scale, status);
364
+}
365
+
366
+float64 uint16_to_float64_scalbn(uint16_t a, int scale, float_status *status)
367
+{
368
+ return uint64_to_float64_scalbn(a, scale, status);
369
}
370
371
float64 uint64_to_float64(uint64_t a, float_status *status)
372
{
373
- FloatParts pa = uint_to_float(a, status);
374
- return float64_round_pack_canonical(pa, status);
375
+ return uint64_to_float64_scalbn(a, 0, status);
376
}
377
378
float64 uint32_to_float64(uint32_t a, float_status *status)
379
{
380
- return uint64_to_float64(a, status);
381
+ return uint64_to_float64_scalbn(a, 0, status);
382
}
383
384
float64 uint16_to_float64(uint16_t a, float_status *status)
385
{
386
- return uint64_to_float64(a, status);
387
+ return uint64_to_float64_scalbn(a, 0, status);
388
}
389
390
/* Float Min/Max */
391
--
84
--
392
2.18.0
85
2.20.1
393
86
394
87
diff view generated by jsdifflib
1
In the MPS2 FPGAIO, PSCNTR is a free-running downcounter with
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
a reload value configured via the PRESCALE register, and
3
COUNTER counts up by 1 every time PSCNTR reaches zero.
4
Implement these counters.
5
2
6
We can just increment the counters migration subsection's
3
This supports reading and writing OTP fuses and keys. Only fuse reading
7
version ID because we only added it in the previous commit,
4
has been tested. Protection is not implemented.
8
so no released QEMU versions will be using it.
9
5
6
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Tested-by: Alexander Bulekov <alxndr@bu.edu>
10
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
11
Message-id: 20200911052101.2602693-9-hskinnemoen@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20180820141116.9118-3-peter.maydell@linaro.org
14
---
13
---
15
include/hw/misc/mps2-fpgaio.h | 6 +++
14
include/hw/arm/npcm7xx.h | 3 +
16
hw/misc/mps2-fpgaio.c | 97 +++++++++++++++++++++++++++++++++--
15
include/hw/nvram/npcm7xx_otp.h | 79 ++++++
17
2 files changed, 99 insertions(+), 4 deletions(-)
16
hw/arm/npcm7xx.c | 29 +++
17
hw/nvram/npcm7xx_otp.c | 440 +++++++++++++++++++++++++++++++++
18
hw/nvram/meson.build | 1 +
19
5 files changed, 552 insertions(+)
20
create mode 100644 include/hw/nvram/npcm7xx_otp.h
21
create mode 100644 hw/nvram/npcm7xx_otp.c
18
22
19
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
23
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/mps2-fpgaio.h
25
--- a/include/hw/arm/npcm7xx.h
22
+++ b/include/hw/misc/mps2-fpgaio.h
26
+++ b/include/hw/arm/npcm7xx.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
@@ -XXX,XX +XXX,XX @@
24
uint32_t prescale;
28
#include "hw/cpu/a9mpcore.h"
25
uint32_t misc;
29
#include "hw/misc/npcm7xx_clk.h"
26
30
#include "hw/misc/npcm7xx_gcr.h"
27
+ /* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
31
+#include "hw/nvram/npcm7xx_otp.h"
28
+ int64_t pscntr_sync_ticks;
32
#include "hw/timer/npcm7xx_timer.h"
29
+ /* Values of COUNTER and PSCNTR at time pscntr_sync_ticks */
33
#include "target/arm/cpu.h"
30
+ uint32_t counter;
34
31
+ uint32_t pscntr;
35
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
32
+
36
NPCM7xxGCRState gcr;
33
uint32_t prescale_clk;
37
NPCM7xxCLKState clk;
34
38
NPCM7xxTimerCtrlState tim[3];
35
/* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
39
+ NPCM7xxOTPState key_storage;
36
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
40
+ NPCM7xxOTPState fuse_array;
41
} NPCM7xxState;
42
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/nvram/npcm7xx_otp.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_OTP_H
66
+#define NPCM7XX_OTP_H
67
+
68
+#include "exec/memory.h"
69
+#include "hw/sysbus.h"
70
+
71
+/* Each OTP module holds 8192 bits of one-time programmable storage */
72
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
73
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
74
+
75
+/* Fuse array offsets */
76
+#define NPCM7XX_FUSE_FUSTRAP (0)
77
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
78
+#define NPCM7XX_FUSE_DAC_CALIB (16)
79
+#define NPCM7XX_FUSE_ADC_CALIB (24)
80
+#define NPCM7XX_FUSE_DERIVATIVE (64)
81
+#define NPCM7XX_FUSE_TEST_SIG (72)
82
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
83
+#define NPCM7XX_FUSE_GP1 (80)
84
+#define NPCM7XX_FUSE_GP2 (128)
85
+
86
+/*
87
+ * Number of registers in our device state structure. Don't change this without
88
+ * incrementing the version_id in the vmstate.
89
+ */
90
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
91
+
92
+/**
93
+ * struct NPCM7xxOTPState - Device state for one OTP module.
94
+ * @parent: System bus device.
95
+ * @mmio: Memory region through which registers are accessed.
96
+ * @regs: Register contents.
97
+ * @array: OTP storage array.
98
+ */
99
+typedef struct NPCM7xxOTPState {
100
+ SysBusDevice parent;
101
+
102
+ MemoryRegion mmio;
103
+ uint32_t regs[NPCM7XX_OTP_NR_REGS];
104
+ uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
105
+} NPCM7xxOTPState;
106
+
107
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
108
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
109
+
110
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
111
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
112
+
113
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
114
+
115
+/**
116
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
117
+ * @s: OTP module.
118
+ * @data: Data to be encoded and written.
119
+ * @offset: Offset of first byte to be written in the OTP array.
120
+ * @len: Number of bytes before ECC encoding.
121
+ *
122
+ * Each nibble of data is encoded into a byte, so the number of bytes written
123
+ * to the array will be @len * 2.
124
+ */
125
+extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
126
+ unsigned int offset, unsigned int len);
127
+
128
+#endif /* NPCM7XX_OTP_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
37
index XXXXXXX..XXXXXXX 100644
130
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/misc/mps2-fpgaio.c
131
--- a/hw/arm/npcm7xx.c
39
+++ b/hw/misc/mps2-fpgaio.c
132
+++ b/hw/arm/npcm7xx.c
40
@@ -XXX,XX +XXX,XX @@ static int64_t tickoff_from_counter(int64_t now, uint32_t count, int frq)
133
@@ -XXX,XX +XXX,XX @@
41
return now - muldiv64(count, NANOSECONDS_PER_SECOND, frq);
134
#define NPCM7XX_MMIO_BA (0x80000000)
135
#define NPCM7XX_MMIO_SZ (0x7ffd0000)
136
137
+/* OTP key storage and fuse strap array */
138
+#define NPCM7XX_OTP1_BA (0xf0189000)
139
+#define NPCM7XX_OTP2_BA (0xf018a000)
140
+
141
/* Core system modules. */
142
#define NPCM7XX_L2C_BA (0xf03fc000)
143
#define NPCM7XX_CPUP_BA (0xf03fe000)
144
@@ -XXX,XX +XXX,XX @@ void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
145
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
42
}
146
}
43
147
44
+static void resync_counter(MPS2FPGAIO *s)
148
+static void npcm7xx_init_fuses(NPCM7xxState *s)
45
+{
149
+{
150
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
151
+ uint32_t value;
152
+
46
+ /*
153
+ /*
47
+ * Update s->counter and s->pscntr to their true current values
154
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
48
+ * by calculating how many times PSCNTR has ticked since the
155
+ * NPCM750 or NPCM730).
49
+ * last time we did a resync.
50
+ */
156
+ */
51
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
157
+ value = tswap32(nc->disabled_modules);
52
+ int64_t elapsed = now - s->pscntr_sync_ticks;
158
+ npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
159
+ sizeof(value));
160
+}
161
+
162
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
163
{
164
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
165
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
166
object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
167
"power-on-straps");
168
object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
169
+ object_initialize_child(obj, "otp1", &s->key_storage,
170
+ TYPE_NPCM7XX_KEY_STORAGE);
171
+ object_initialize_child(obj, "otp2", &s->fuse_array,
172
+ TYPE_NPCM7XX_FUSE_ARRAY);
173
174
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
175
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
177
sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
178
sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
179
180
+ /* OTP key storage and fuse strap array. Cannot fail. */
181
+ sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
182
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
183
+ sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
184
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
185
+ npcm7xx_init_fuses(s);
186
+
187
/* Timer Modules (TIM). Cannot fail. */
188
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
189
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
190
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
191
new file mode 100644
192
index XXXXXXX..XXXXXXX
193
--- /dev/null
194
+++ b/hw/nvram/npcm7xx_otp.c
195
@@ -XXX,XX +XXX,XX @@
196
+/*
197
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
198
+ *
199
+ * Copyright 2020 Google LLC
200
+ *
201
+ * This program is free software; you can redistribute it and/or modify it
202
+ * under the terms of the GNU General Public License as published by the
203
+ * Free Software Foundation; either version 2 of the License, or
204
+ * (at your option) any later version.
205
+ *
206
+ * This program is distributed in the hope that it will be useful, but WITHOUT
207
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
208
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
209
+ * for more details.
210
+ */
211
+
212
+#include "qemu/osdep.h"
213
+
214
+#include "hw/nvram/npcm7xx_otp.h"
215
+#include "migration/vmstate.h"
216
+#include "qapi/error.h"
217
+#include "qemu/bitops.h"
218
+#include "qemu/log.h"
219
+#include "qemu/module.h"
220
+#include "qemu/units.h"
221
+
222
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
223
+#define NPCM7XX_OTP_REGS_SIZE (4 * KiB)
224
+
225
+/* 32-bit register indices. */
226
+typedef enum NPCM7xxOTPRegister {
227
+ NPCM7XX_OTP_FST,
228
+ NPCM7XX_OTP_FADDR,
229
+ NPCM7XX_OTP_FDATA,
230
+ NPCM7XX_OTP_FCFG,
231
+ /* Offset 0x10 is FKEYIND in OTP1, FUSTRAP in OTP2 */
232
+ NPCM7XX_OTP_FKEYIND = 0x0010 / sizeof(uint32_t),
233
+ NPCM7XX_OTP_FUSTRAP = 0x0010 / sizeof(uint32_t),
234
+ NPCM7XX_OTP_FCTL,
235
+ NPCM7XX_OTP_REGS_END,
236
+} NPCM7xxOTPRegister;
237
+
238
+/* Register field definitions. */
239
+#define FST_RIEN BIT(2)
240
+#define FST_RDST BIT(1)
241
+#define FST_RDY BIT(0)
242
+#define FST_RO_MASK (FST_RDST | FST_RDY)
243
+
244
+#define FADDR_BYTEADDR(rv) extract32((rv), 0, 10)
245
+#define FADDR_BITPOS(rv) extract32((rv), 10, 3)
246
+
247
+#define FDATA_CLEAR 0x00000001
248
+
249
+#define FCFG_FDIS BIT(31)
250
+#define FCFG_FCFGLK_MASK 0x00ff0000
251
+
252
+#define FCTL_PROG_CMD1 0x00000001
253
+#define FCTL_PROG_CMD2 0xbf79e5d0
254
+#define FCTL_READ_CMD 0x00000002
255
+
256
+/**
257
+ * struct NPCM7xxOTPClass - OTP module class.
258
+ * @parent: System bus device class.
259
+ * @mmio_ops: MMIO register operations for this type of module.
260
+ *
261
+ * The two OTP modules (key-storage and fuse-array) have slightly different
262
+ * behavior, so we give them different MMIO register operations.
263
+ */
264
+struct NPCM7xxOTPClass {
265
+ SysBusDeviceClass parent;
266
+
267
+ const MemoryRegionOps *mmio_ops;
268
+};
269
+
270
+#define NPCM7XX_OTP_CLASS(klass) \
271
+ OBJECT_CLASS_CHECK(NPCM7xxOTPClass, (klass), TYPE_NPCM7XX_OTP)
272
+#define NPCM7XX_OTP_GET_CLASS(obj) \
273
+ OBJECT_GET_CLASS(NPCM7xxOTPClass, (obj), TYPE_NPCM7XX_OTP)
274
+
275
+static uint8_t ecc_encode_nibble(uint8_t n)
276
+{
277
+ uint8_t result = n;
278
+
279
+ result |= (((n >> 0) & 1) ^ ((n >> 1) & 1)) << 4;
280
+ result |= (((n >> 2) & 1) ^ ((n >> 3) & 1)) << 5;
281
+ result |= (((n >> 0) & 1) ^ ((n >> 2) & 1)) << 6;
282
+ result |= (((n >> 1) & 1) ^ ((n >> 3) & 1)) << 7;
283
+
284
+ return result;
285
+}
286
+
287
+void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
288
+ unsigned int offset, unsigned int len)
289
+{
290
+ const uint8_t *src = data;
291
+ uint8_t *dst = &s->array[offset];
292
+
293
+ while (len-- > 0) {
294
+ uint8_t c = *src++;
295
+
296
+ *dst++ = ecc_encode_nibble(extract8(c, 0, 4));
297
+ *dst++ = ecc_encode_nibble(extract8(c, 4, 4));
298
+ }
299
+}
300
+
301
+/* Common register read handler for both OTP classes. */
302
+static uint64_t npcm7xx_otp_read(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg)
303
+{
304
+ uint32_t value = 0;
305
+
306
+ switch (reg) {
307
+ case NPCM7XX_OTP_FST:
308
+ case NPCM7XX_OTP_FADDR:
309
+ case NPCM7XX_OTP_FDATA:
310
+ case NPCM7XX_OTP_FCFG:
311
+ value = s->regs[reg];
312
+ break;
313
+
314
+ case NPCM7XX_OTP_FCTL:
315
+ qemu_log_mask(LOG_GUEST_ERROR,
316
+ "%s: read from write-only FCTL register\n",
317
+ DEVICE(s)->canonical_path);
318
+ break;
319
+
320
+ default:
321
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read from invalid offset 0x%zx\n",
322
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
323
+ break;
324
+ }
325
+
326
+ return value;
327
+}
328
+
329
+/* Read a byte from the OTP array into the data register. */
330
+static void npcm7xx_otp_read_array(NPCM7xxOTPState *s)
331
+{
332
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
333
+
334
+ s->regs[NPCM7XX_OTP_FDATA] = s->array[FADDR_BYTEADDR(faddr)];
335
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
336
+}
337
+
338
+/* Program a byte from the data register into the OTP array. */
339
+static void npcm7xx_otp_program_array(NPCM7xxOTPState *s)
340
+{
341
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
342
+
343
+ /* Bits can only go 0->1, never 1->0. */
344
+ s->array[FADDR_BYTEADDR(faddr)] |= (1U << FADDR_BITPOS(faddr));
345
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
346
+}
347
+
348
+/* Compute the next value of the FCFG register. */
349
+static uint32_t npcm7xx_otp_compute_fcfg(uint32_t cur_value, uint32_t new_value)
350
+{
351
+ uint32_t lock_mask;
352
+ uint32_t value;
53
+
353
+
54
+ /*
354
+ /*
55
+ * Round elapsed down to a whole number of PSCNTR ticks, so we don't
355
+ * FCFGLK holds sticky bits 16..23, indicating which bits in FPRGLK (8..15)
56
+ * lose time if we do multiple resyncs in a single tick.
356
+ * and FRDLK (0..7) that are read-only.
57
+ */
357
+ */
58
+ uint64_t ticks = muldiv64(elapsed, s->prescale_clk, NANOSECONDS_PER_SECOND);
358
+ lock_mask = (cur_value & FCFG_FCFGLK_MASK) >> 8;
359
+ lock_mask |= lock_mask >> 8;
360
+ /* FDIS and FCFGLK bits are sticky (write 1 to set; can't clear). */
361
+ value = cur_value & (FCFG_FDIS | FCFG_FCFGLK_MASK);
362
+ /* Preserve read-only bits in FPRGLK and FRDLK */
363
+ value |= cur_value & lock_mask;
364
+ /* Set all bits that aren't read-only. */
365
+ value |= new_value & ~lock_mask;
366
+
367
+ return value;
368
+}
369
+
370
+/* Common register write handler for both OTP classes. */
371
+static void npcm7xx_otp_write(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg,
372
+ uint32_t value)
373
+{
374
+ switch (reg) {
375
+ case NPCM7XX_OTP_FST:
376
+ /* RDST is cleared by writing 1 to it. */
377
+ if (value & FST_RDST) {
378
+ s->regs[NPCM7XX_OTP_FST] &= ~FST_RDST;
379
+ }
380
+ /* Preserve read-only and write-one-to-clear bits */
381
+ value &= ~FST_RO_MASK;
382
+ value |= s->regs[NPCM7XX_OTP_FST] & FST_RO_MASK;
383
+ break;
384
+
385
+ case NPCM7XX_OTP_FADDR:
386
+ break;
387
+
388
+ case NPCM7XX_OTP_FDATA:
389
+ /*
390
+ * This register is cleared by writing a magic value to it; no other
391
+ * values can be written.
392
+ */
393
+ if (value == FDATA_CLEAR) {
394
+ value = 0;
395
+ } else {
396
+ value = s->regs[NPCM7XX_OTP_FDATA];
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_OTP_FCFG:
401
+ value = npcm7xx_otp_compute_fcfg(s->regs[NPCM7XX_OTP_FCFG], value);
402
+ break;
403
+
404
+ case NPCM7XX_OTP_FCTL:
405
+ switch (value) {
406
+ case FCTL_READ_CMD:
407
+ npcm7xx_otp_read_array(s);
408
+ break;
409
+
410
+ case FCTL_PROG_CMD1:
411
+ /*
412
+ * Programming requires writing two separate magic values to this
413
+ * register; this is the first one. Just store it so it can be
414
+ * verified later when the second magic value is received.
415
+ */
416
+ break;
417
+
418
+ case FCTL_PROG_CMD2:
419
+ /*
420
+ * Only initiate programming if we received the first half of the
421
+ * command immediately before this one.
422
+ */
423
+ if (s->regs[NPCM7XX_OTP_FCTL] == FCTL_PROG_CMD1) {
424
+ npcm7xx_otp_program_array(s);
425
+ }
426
+ break;
427
+
428
+ default:
429
+ qemu_log_mask(LOG_GUEST_ERROR,
430
+ "%s: unrecognized FCNTL value 0x%" PRIx32 "\n",
431
+ DEVICE(s)->canonical_path, value);
432
+ break;
433
+ }
434
+ if (value != FCTL_PROG_CMD1) {
435
+ value = 0;
436
+ }
437
+ break;
438
+
439
+ default:
440
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to invalid offset 0x%zx\n",
441
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
442
+ return;
443
+ }
444
+
445
+ s->regs[reg] = value;
446
+}
447
+
448
+/* Register read handler specific to the fuse array OTP module. */
449
+static uint64_t npcm7xx_fuse_array_read(void *opaque, hwaddr addr,
450
+ unsigned int size)
451
+{
452
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
453
+ NPCM7xxOTPState *s = opaque;
454
+ uint32_t value;
59
+
455
+
60
+ /*
456
+ /*
61
+ * Work out what PSCNTR and COUNTER have moved to. We assume that
457
+ * Only the Fuse Strap register needs special handling; all other registers
62
+ * PSCNTR reloads from PRESCALE one tick-period after it hits zero,
458
+ * work the same way for both kinds of OTP modules.
63
+ * and that COUNTER increments at the same moment.
64
+ */
459
+ */
65
+ if (ticks == 0) {
460
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
66
+ /* We haven't ticked since the last time we were asked */
461
+ value = npcm7xx_otp_read(s, reg);
462
+ } else {
463
+ /* FUSTRAP is stored as three copies in the OTP array. */
464
+ uint32_t fustrap[3];
465
+
466
+ memcpy(fustrap, &s->array[0], sizeof(fustrap));
467
+
468
+ /* Determine value by a majority vote on each bit. */
469
+ value = (fustrap[0] & fustrap[1]) | (fustrap[0] & fustrap[2]) |
470
+ (fustrap[1] & fustrap[2]);
471
+ }
472
+
473
+ return value;
474
+}
475
+
476
+/* Register write handler specific to the fuse array OTP module. */
477
+static void npcm7xx_fuse_array_write(void *opaque, hwaddr addr, uint64_t v,
478
+ unsigned int size)
479
+{
480
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
481
+ NPCM7xxOTPState *s = opaque;
482
+
483
+ /*
484
+ * The Fuse Strap register is read-only. Other registers are handled by
485
+ * common code.
486
+ */
487
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
488
+ npcm7xx_otp_write(s, reg, v);
489
+ }
490
+}
491
+
492
+static const MemoryRegionOps npcm7xx_fuse_array_ops = {
493
+ .read = npcm7xx_fuse_array_read,
494
+ .write = npcm7xx_fuse_array_write,
495
+ .endianness = DEVICE_LITTLE_ENDIAN,
496
+ .valid = {
497
+ .min_access_size = 4,
498
+ .max_access_size = 4,
499
+ .unaligned = false,
500
+ },
501
+};
502
+
503
+/* Register read handler specific to the key storage OTP module. */
504
+static uint64_t npcm7xx_key_storage_read(void *opaque, hwaddr addr,
505
+ unsigned int size)
506
+{
507
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
508
+ NPCM7xxOTPState *s = opaque;
509
+
510
+ /*
511
+ * Only the Fuse Key Index register needs special handling; all other
512
+ * registers work the same way for both kinds of OTP modules.
513
+ */
514
+ if (reg != NPCM7XX_OTP_FKEYIND) {
515
+ return npcm7xx_otp_read(s, reg);
516
+ }
517
+
518
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
519
+
520
+ return s->regs[NPCM7XX_OTP_FKEYIND];
521
+}
522
+
523
+/* Register write handler specific to the key storage OTP module. */
524
+static void npcm7xx_key_storage_write(void *opaque, hwaddr addr, uint64_t v,
525
+ unsigned int size)
526
+{
527
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
528
+ NPCM7xxOTPState *s = opaque;
529
+
530
+ /*
531
+ * Only the Fuse Key Index register needs special handling; all other
532
+ * registers work the same way for both kinds of OTP modules.
533
+ */
534
+ if (reg != NPCM7XX_OTP_FKEYIND) {
535
+ npcm7xx_otp_write(s, reg, v);
67
+ return;
536
+ return;
68
+ } else if (ticks < s->pscntr) {
69
+ /* We haven't yet reached zero, just reduce the PSCNTR */
70
+ s->pscntr -= ticks;
71
+ } else {
72
+ if (s->prescale == 0) {
73
+ /*
74
+ * If the reload value is zero then the PSCNTR will stick
75
+ * at zero once it reaches it, and so we will increment
76
+ * COUNTER every tick after that.
77
+ */
78
+ s->counter += ticks - s->pscntr;
79
+ s->pscntr = 0;
80
+ } else {
81
+ /*
82
+ * This is the complicated bit. This ASCII art diagram gives an
83
+ * example with PRESCALE==5 PSCNTR==7:
84
+ *
85
+ * ticks 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
86
+ * PSCNTR 7 6 5 4 3 2 1 0 5 4 3 2 1 0 5
87
+ * cinc 1 2
88
+ * y 0 1 2 3 4 5 6 7 8 9 10 11 12
89
+ * x 0 1 2 3 4 5 0 1 2 3 4 5 0
90
+ *
91
+ * where x = y % (s->prescale + 1)
92
+ * and so PSCNTR = s->prescale - x
93
+ * and COUNTER is incremented by y / (s->prescale + 1)
94
+ *
95
+ * The case where PSCNTR < PRESCALE works out the same,
96
+ * though we must be careful to calculate y as 64-bit unsigned
97
+ * for all parts of the expression.
98
+ * y < 0 is not possible because that implies ticks < s->pscntr.
99
+ */
100
+ uint64_t y = ticks - s->pscntr + s->prescale;
101
+ s->pscntr = s->prescale - (y % (s->prescale + 1));
102
+ s->counter += y / (s->prescale + 1);
103
+ }
104
+ }
537
+ }
105
+
538
+
106
+ /*
539
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
107
+ * Only advance the sync time to the timestamp of the last PSCNTR tick,
540
+
108
+ * not all the way to 'now', so we don't lose time if we do multiple
541
+ s->regs[NPCM7XX_OTP_FKEYIND] = v;
109
+ * resyncs in a single tick.
542
+}
110
+ */
543
+
111
+ s->pscntr_sync_ticks += muldiv64(ticks, NANOSECONDS_PER_SECOND,
544
+static const MemoryRegionOps npcm7xx_key_storage_ops = {
112
+ s->prescale_clk);
545
+ .read = npcm7xx_key_storage_read,
113
+}
546
+ .write = npcm7xx_key_storage_write,
114
+
547
+ .endianness = DEVICE_LITTLE_ENDIAN,
115
static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
548
+ .valid = {
116
{
549
+ .min_access_size = 4,
117
MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
550
+ .max_access_size = 4,
118
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
551
+ .unaligned = false,
119
r = counter_from_tickoff(now, s->clk100hz_tick_offset, 100);
552
+ },
120
break;
553
+};
121
case A_COUNTER:
554
+
122
+ resync_counter(s);
555
+static void npcm7xx_otp_enter_reset(Object *obj, ResetType type)
123
+ r = s->counter;
556
+{
124
+ break;
557
+ NPCM7xxOTPState *s = NPCM7XX_OTP(obj);
125
case A_PSCNTR:
558
+
126
- qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
559
+ memset(s->regs, 0, sizeof(s->regs));
127
- r = 0;
560
+
128
+ resync_counter(s);
561
+ s->regs[NPCM7XX_OTP_FST] = 0x00000001;
129
+ r = s->pscntr;
562
+ s->regs[NPCM7XX_OTP_FCFG] = 0x20000000;
130
break;
563
+}
131
default:
564
+
132
qemu_log_mask(LOG_GUEST_ERROR,
565
+static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
133
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
566
+{
134
s->led0 = value & 0x3;
567
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
135
break;
568
+ NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
136
case A_PRESCALE:
569
+ SysBusDevice *sbd = &s->parent;
137
+ resync_counter(s);
570
+
138
s->prescale = value;
571
+ memset(s->array, 0, sizeof(s->array));
139
break;
572
+
140
case A_MISC:
573
+ memory_region_init_io(&s->mmio, OBJECT(s), oc->mmio_ops, s, "regs",
141
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
574
+ NPCM7XX_OTP_REGS_SIZE);
142
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
575
+ sysbus_init_mmio(sbd, &s->mmio);
143
s->clk100hz_tick_offset = tickoff_from_counter(now, value, 100);
576
+}
144
break;
577
+
145
+ case A_COUNTER:
578
+static const VMStateDescription vmstate_npcm7xx_otp = {
146
+ resync_counter(s);
579
+ .name = "npcm7xx-otp",
147
+ s->counter = value;
580
+ .version_id = 0,
148
+ break;
581
+ .minimum_version_id = 0,
149
+ case A_PSCNTR:
582
+ .fields = (VMStateField[]) {
150
+ resync_counter(s);
583
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxOTPState, NPCM7XX_OTP_NR_REGS),
151
+ s->pscntr = value;
584
+ VMSTATE_UINT8_ARRAY(array, NPCM7xxOTPState, NPCM7XX_OTP_ARRAY_BYTES),
152
+ break;
585
+ VMSTATE_END_OF_LIST(),
153
default:
586
+ },
154
qemu_log_mask(LOG_GUEST_ERROR,
587
+};
155
"MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
588
+
156
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_reset(DeviceState *dev)
589
+static void npcm7xx_otp_class_init(ObjectClass *klass, void *data)
157
s->misc = 0;
590
+{
158
s->clk1hz_tick_offset = tickoff_from_counter(now, 0, 1);
591
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
159
s->clk100hz_tick_offset = tickoff_from_counter(now, 0, 100);
592
+ DeviceClass *dc = DEVICE_CLASS(klass);
160
+ s->counter = 0;
593
+
161
+ s->pscntr = 0;
594
+ QEMU_BUILD_BUG_ON(NPCM7XX_OTP_REGS_END > NPCM7XX_OTP_NR_REGS);
162
+ s->pscntr_sync_ticks = now;
595
+
163
}
596
+ dc->realize = npcm7xx_otp_realize;
164
597
+ dc->vmsd = &vmstate_npcm7xx_otp;
165
static void mps2_fpgaio_init(Object *obj)
598
+ rc->phases.enter = npcm7xx_otp_enter_reset;
166
@@ -XXX,XX +XXX,XX @@ static bool mps2_fpgaio_counters_needed(void *opaque)
599
+}
167
600
+
168
static const VMStateDescription mps2_fpgaio_counters_vmstate = {
601
+static void npcm7xx_key_storage_class_init(ObjectClass *klass, void *data)
169
.name = "mps2-fpgaio/counters",
602
+{
170
- .version_id = 1,
603
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
171
- .minimum_version_id = 1,
604
+
172
+ .version_id = 2,
605
+ oc->mmio_ops = &npcm7xx_key_storage_ops;
173
+ .minimum_version_id = 2,
606
+}
174
.needed = mps2_fpgaio_counters_needed,
607
+
175
.fields = (VMStateField[]) {
608
+static void npcm7xx_fuse_array_class_init(ObjectClass *klass, void *data)
176
VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
609
+{
177
VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
610
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
178
+ VMSTATE_UINT32(counter, MPS2FPGAIO),
611
+
179
+ VMSTATE_UINT32(pscntr, MPS2FPGAIO),
612
+ oc->mmio_ops = &npcm7xx_fuse_array_ops;
180
+ VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
613
+}
181
VMSTATE_END_OF_LIST()
614
+
182
}
615
+static const TypeInfo npcm7xx_otp_types[] = {
183
};
616
+ {
617
+ .name = TYPE_NPCM7XX_OTP,
618
+ .parent = TYPE_SYS_BUS_DEVICE,
619
+ .instance_size = sizeof(NPCM7xxOTPState),
620
+ .class_size = sizeof(NPCM7xxOTPClass),
621
+ .class_init = npcm7xx_otp_class_init,
622
+ .abstract = true,
623
+ },
624
+ {
625
+ .name = TYPE_NPCM7XX_KEY_STORAGE,
626
+ .parent = TYPE_NPCM7XX_OTP,
627
+ .class_init = npcm7xx_key_storage_class_init,
628
+ },
629
+ {
630
+ .name = TYPE_NPCM7XX_FUSE_ARRAY,
631
+ .parent = TYPE_NPCM7XX_OTP,
632
+ .class_init = npcm7xx_fuse_array_class_init,
633
+ },
634
+};
635
+DEFINE_TYPES(npcm7xx_otp_types);
636
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
637
index XXXXXXX..XXXXXXX 100644
638
--- a/hw/nvram/meson.build
639
+++ b/hw/nvram/meson.build
640
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_DS1225Y', if_true: files('ds1225y.c'))
641
softmmu_ss.add(when: 'CONFIG_NMC93XX_EEPROM', if_true: files('eeprom93xx.c'))
642
softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c'))
643
softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c'))
644
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
645
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
646
647
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
184
--
648
--
185
2.18.0
649
2.20.1
186
650
187
651
diff view generated by jsdifflib
1
Implement the necessary support code for taking exceptions
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
to Hyp mode in AArch32.
2
3
3
This just implements the bare minimum to cause the boot block to skip
4
memory initialization.
5
6
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Tested-by: Alexander Bulekov <alxndr@bu.edu>
11
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
Message-id: 20200911052101.2602693-10-hskinnemoen@google.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180820153020.21478-5-peter.maydell@linaro.org
9
---
14
---
10
target/arm/helper.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
15
include/hw/arm/npcm7xx.h | 2 +
11
1 file changed, 82 insertions(+)
16
include/hw/mem/npcm7xx_mc.h | 36 ++++++++++++++++
12
17
hw/arm/npcm7xx.c | 6 +++
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
hw/mem/npcm7xx_mc.c | 84 +++++++++++++++++++++++++++++++++++++
19
hw/mem/meson.build | 1 +
20
5 files changed, 129 insertions(+)
21
create mode 100644 include/hw/mem/npcm7xx_mc.h
22
create mode 100644 hw/mem/npcm7xx_mc.c
23
24
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
14
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
26
--- a/include/hw/arm/npcm7xx.h
16
+++ b/target/arm/helper.c
27
+++ b/include/hw/arm/npcm7xx.h
17
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
28
@@ -XXX,XX +XXX,XX @@
18
env->regs[15] = newpc;
29
19
}
30
#include "hw/boards.h"
20
31
#include "hw/cpu/a9mpcore.h"
21
+static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
32
+#include "hw/mem/npcm7xx_mc.h"
33
#include "hw/misc/npcm7xx_clk.h"
34
#include "hw/misc/npcm7xx_gcr.h"
35
#include "hw/nvram/npcm7xx_otp.h"
36
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
37
NPCM7xxTimerCtrlState tim[3];
38
NPCM7xxOTPState key_storage;
39
NPCM7xxOTPState fuse_array;
40
+ NPCM7xxMCState mc;
41
} NPCM7xxState;
42
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/mem/npcm7xx_mc.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx Memory Controller stub
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_MC_H
66
+#define NPCM7XX_MC_H
67
+
68
+#include "exec/memory.h"
69
+#include "hw/sysbus.h"
70
+
71
+/**
72
+ * struct NPCM7xxMCState - Device state for the memory controller.
73
+ * @parent: System bus device.
74
+ * @mmio: Memory region through which registers are accessed.
75
+ */
76
+typedef struct NPCM7xxMCState {
77
+ SysBusDevice parent;
78
+
79
+ MemoryRegion mmio;
80
+} NPCM7xxMCState;
81
+
82
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
83
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
84
+
85
+#endif /* NPCM7XX_MC_H */
86
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/npcm7xx.c
89
+++ b/hw/arm/npcm7xx.c
90
@@ -XXX,XX +XXX,XX @@
91
#define NPCM7XX_CPUP_BA (0xf03fe000)
92
#define NPCM7XX_GCR_BA (0xf0800000)
93
#define NPCM7XX_CLK_BA (0xf0801000)
94
+#define NPCM7XX_MC_BA (0xf0824000)
95
96
/* Internal AHB SRAM */
97
#define NPCM7XX_RAM3_BA (0xc0008000)
98
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
99
TYPE_NPCM7XX_KEY_STORAGE);
100
object_initialize_child(obj, "otp2", &s->fuse_array,
101
TYPE_NPCM7XX_FUSE_ARRAY);
102
+ object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
103
104
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
105
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
107
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
108
npcm7xx_init_fuses(s);
109
110
+ /* Fake Memory Controller (MC). Cannot fail. */
111
+ sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
112
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
113
+
114
/* Timer Modules (TIM). Cannot fail. */
115
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
116
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
117
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
118
new file mode 100644
119
index XXXXXXX..XXXXXXX
120
--- /dev/null
121
+++ b/hw/mem/npcm7xx_mc.c
122
@@ -XXX,XX +XXX,XX @@
123
+/*
124
+ * Nuvoton NPCM7xx Memory Controller stub
125
+ *
126
+ * Copyright 2020 Google LLC
127
+ *
128
+ * This program is free software; you can redistribute it and/or modify it
129
+ * under the terms of the GNU General Public License as published by the
130
+ * Free Software Foundation; either version 2 of the License, or
131
+ * (at your option) any later version.
132
+ *
133
+ * This program is distributed in the hope that it will be useful, but WITHOUT
134
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
135
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
136
+ * for more details.
137
+ */
138
+
139
+#include "qemu/osdep.h"
140
+
141
+#include "hw/mem/npcm7xx_mc.h"
142
+#include "qapi/error.h"
143
+#include "qemu/log.h"
144
+#include "qemu/module.h"
145
+#include "qemu/units.h"
146
+
147
+#define NPCM7XX_MC_REGS_SIZE (4 * KiB)
148
+
149
+static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size)
22
+{
150
+{
23
+ /*
151
+ /*
24
+ * Handle exception entry to Hyp mode; this is sufficiently
152
+ * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory
25
+ * different to entry to other AArch32 modes that we handle it
153
+ * controller has already been initialized and will skip DDR training.
26
+ * separately here.
27
+ *
28
+ * The vector table entry used is always the 0x14 Hyp mode entry point,
29
+ * unless this is an UNDEF/HVC/abort taken from Hyp to Hyp.
30
+ * The offset applied to the preferred return address is always zero
31
+ * (see DDI0487C.a section G1.12.3).
32
+ * PSTATE A/I/F masks are set based only on the SCR.EA/IRQ/FIQ values.
33
+ */
154
+ */
34
+ uint32_t addr, mask;
155
+ if (addr == 0) {
35
+ ARMCPU *cpu = ARM_CPU(cs);
156
+ return 0x100;
36
+ CPUARMState *env = &cpu->env;
37
+
38
+ switch (cs->exception_index) {
39
+ case EXCP_UDEF:
40
+ addr = 0x04;
41
+ break;
42
+ case EXCP_SWI:
43
+ addr = 0x14;
44
+ break;
45
+ case EXCP_BKPT:
46
+ /* Fall through to prefetch abort. */
47
+ case EXCP_PREFETCH_ABORT:
48
+ env->cp15.ifar_s = env->exception.vaddress;
49
+ qemu_log_mask(CPU_LOG_INT, "...with HIFAR 0x%x\n",
50
+ (uint32_t)env->exception.vaddress);
51
+ addr = 0x0c;
52
+ break;
53
+ case EXCP_DATA_ABORT:
54
+ env->cp15.dfar_s = env->exception.vaddress;
55
+ qemu_log_mask(CPU_LOG_INT, "...with HDFAR 0x%x\n",
56
+ (uint32_t)env->exception.vaddress);
57
+ addr = 0x10;
58
+ break;
59
+ case EXCP_IRQ:
60
+ addr = 0x18;
61
+ break;
62
+ case EXCP_FIQ:
63
+ addr = 0x1c;
64
+ break;
65
+ case EXCP_HVC:
66
+ addr = 0x08;
67
+ break;
68
+ case EXCP_HYP_TRAP:
69
+ addr = 0x14;
70
+ default:
71
+ cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
72
+ }
157
+ }
73
+
158
+
74
+ if (cs->exception_index != EXCP_IRQ && cs->exception_index != EXCP_FIQ) {
159
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
75
+ env->cp15.esr_el[2] = env->exception.syndrome;
160
+
76
+ }
161
+ return 0;
77
+
162
+}
78
+ if (arm_current_el(env) != 2 && addr < 0x14) {
163
+
79
+ addr = 0x14;
164
+static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v,
80
+ }
165
+ unsigned int size)
81
+
166
+{
82
+ mask = 0;
167
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
83
+ if (!(env->cp15.scr_el3 & SCR_EA)) {
168
+}
84
+ mask |= CPSR_A;
169
+
85
+ }
170
+static const MemoryRegionOps npcm7xx_mc_ops = {
86
+ if (!(env->cp15.scr_el3 & SCR_IRQ)) {
171
+ .read = npcm7xx_mc_read,
87
+ mask |= CPSR_I;
172
+ .write = npcm7xx_mc_write,
88
+ }
173
+ .endianness = DEVICE_LITTLE_ENDIAN,
89
+ if (!(env->cp15.scr_el3 & SCR_FIQ)) {
174
+ .valid = {
90
+ mask |= CPSR_F;
175
+ .min_access_size = 4,
91
+ }
176
+ .max_access_size = 4,
92
+
177
+ .unaligned = false,
93
+ addr += env->cp15.hvbar;
178
+ },
94
+
179
+};
95
+ take_aarch32_exception(env, ARM_CPU_MODE_HYP, mask, 0, addr);
180
+
96
+}
181
+static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
97
+
182
+{
98
static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
183
+ NPCM7xxMCState *s = NPCM7XX_MC(dev);
99
{
184
+
100
ARMCPU *cpu = ARM_CPU(cs);
185
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
101
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
186
+ NPCM7XX_MC_REGS_SIZE);
102
env->cp15.mdscr_el1 = deposit64(env->cp15.mdscr_el1, 2, 4, moe);
187
+ sysbus_init_mmio(&s->parent, &s->mmio);
103
}
188
+}
104
189
+
105
+ if (env->exception.target_el == 2) {
190
+static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
106
+ arm_cpu_do_interrupt_aarch32_hyp(cs);
191
+{
107
+ return;
192
+ DeviceClass *dc = DEVICE_CLASS(klass);
108
+ }
193
+
109
+
194
+ dc->desc = "NPCM7xx Memory Controller stub";
110
/* TODO: Vectored interrupt controller. */
195
+ dc->realize = npcm7xx_mc_realize;
111
switch (cs->exception_index) {
196
+}
112
case EXCP_UDEF:
197
+
198
+static const TypeInfo npcm7xx_mc_types[] = {
199
+ {
200
+ .name = TYPE_NPCM7XX_MC,
201
+ .parent = TYPE_SYS_BUS_DEVICE,
202
+ .instance_size = sizeof(NPCM7xxMCState),
203
+ .class_init = npcm7xx_mc_class_init,
204
+ },
205
+};
206
+DEFINE_TYPES(npcm7xx_mc_types);
207
diff --git a/hw/mem/meson.build b/hw/mem/meson.build
208
index XXXXXXX..XXXXXXX 100644
209
--- a/hw/mem/meson.build
210
+++ b/hw/mem/meson.build
211
@@ -XXX,XX +XXX,XX @@
212
mem_ss = ss.source_set()
213
mem_ss.add(files('memory-device.c'))
214
mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c'))
215
+mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c'))
216
mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c'))
217
218
softmmu_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss)
113
--
219
--
114
2.18.0
220
2.20.1
115
221
116
222
diff view generated by jsdifflib
1
The IoTKit includes three different instances of the
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
CMSDK APB watchdog; create and wire them up.
3
2
3
This implements a device model for the NPCM7xx SPI flash controller.
4
5
Direct reads and writes, and user-mode transactions have been tested in
6
various modes. Protection features are not implemented yet.
7
8
All the FIU instances are available in the SoC's address space,
9
regardless of whether or not they're connected to actual flash chips.
10
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Reviewed-by: Cédric Le Goater <clg@kaod.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Tested-by: Alexander Bulekov <alxndr@bu.edu>
16
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Message-id: 20200911052101.2602693-11-hskinnemoen@google.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-7-peter.maydell@linaro.org
8
---
19
---
9
include/hw/arm/iotkit.h | 6 +++++
20
include/hw/arm/npcm7xx.h | 2 +
10
hw/arm/iotkit.c | 58 ++++++++++++++++++++++++++++++++++++++---
21
include/hw/ssi/npcm7xx_fiu.h | 73 +++++
11
2 files changed, 61 insertions(+), 3 deletions(-)
22
hw/arm/npcm7xx.c | 58 ++++
23
hw/ssi/npcm7xx_fiu.c | 572 +++++++++++++++++++++++++++++++++++
24
hw/arm/Kconfig | 1 +
25
hw/ssi/meson.build | 1 +
26
hw/ssi/trace-events | 11 +
27
7 files changed, 718 insertions(+)
28
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
29
create mode 100644 hw/ssi/npcm7xx_fiu.c
12
30
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
31
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
14
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/iotkit.h
33
--- a/include/hw/arm/npcm7xx.h
16
+++ b/include/hw/arm/iotkit.h
34
+++ b/include/hw/arm/npcm7xx.h
17
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
18
#include "hw/misc/tz-mpc.h"
36
#include "hw/misc/npcm7xx_gcr.h"
19
#include "hw/timer/cmsdk-apb-timer.h"
37
#include "hw/nvram/npcm7xx_otp.h"
20
#include "hw/timer/cmsdk-apb-dualtimer.h"
38
#include "hw/timer/npcm7xx_timer.h"
21
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
39
+#include "hw/ssi/npcm7xx_fiu.h"
22
#include "hw/misc/unimp.h"
40
#include "target/arm/cpu.h"
23
#include "hw/or-irq.h"
41
24
#include "hw/core/split-irq.h"
42
#define NPCM7XX_MAX_NUM_CPUS (2)
25
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
43
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
26
SplitIRQ ppc_irq_splitter[NUM_PPCS];
44
NPCM7xxOTPState key_storage;
27
SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
45
NPCM7xxOTPState fuse_array;
28
qemu_or_irq mpc_irq_orgate;
46
NPCM7xxMCState mc;
29
+ qemu_or_irq nmi_orgate;
47
+ NPCM7xxFIUState fiu[2];
30
48
} NPCM7xxState;
31
CMSDKAPBDualTimer dualtimer;
49
32
UnimplementedDeviceState s32ktimer;
50
#define TYPE_NPCM7XX "npcm7xx"
33
51
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
34
+ CMSDKAPBWatchdog s32kwatchdog;
52
new file mode 100644
35
+ CMSDKAPBWatchdog nswatchdog;
53
index XXXXXXX..XXXXXXX
36
+ CMSDKAPBWatchdog swatchdog;
54
--- /dev/null
37
+
55
+++ b/include/hw/ssi/npcm7xx_fiu.h
38
MemoryRegion container;
56
@@ -XXX,XX +XXX,XX @@
39
MemoryRegion alias1;
57
+/*
40
MemoryRegion alias2;
58
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
41
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
59
+ *
60
+ * Copyright 2020 Google LLC
61
+ *
62
+ * This program is free software; you can redistribute it and/or modify it
63
+ * under the terms of the GNU General Public License as published by the
64
+ * Free Software Foundation; either version 2 of the License, or
65
+ * (at your option) any later version.
66
+ *
67
+ * This program is distributed in the hope that it will be useful, but WITHOUT
68
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
69
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
70
+ * for more details.
71
+ */
72
+#ifndef NPCM7XX_FIU_H
73
+#define NPCM7XX_FIU_H
74
+
75
+#include "hw/ssi/ssi.h"
76
+#include "hw/sysbus.h"
77
+
78
+/*
79
+ * Number of registers in our device state structure. Don't change this without
80
+ * incrementing the version_id in the vmstate.
81
+ */
82
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
83
+
84
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
85
+
86
+/**
87
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
88
+ * @direct_access: Memory region for direct flash access.
89
+ * @fiu: Pointer to flash controller shared state.
90
+ */
91
+typedef struct NPCM7xxFIUFlash {
92
+ MemoryRegion direct_access;
93
+ NPCM7xxFIUState *fiu;
94
+} NPCM7xxFIUFlash;
95
+
96
+/**
97
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
98
+ * @parent: System bus device.
99
+ * @mmio: Memory region for register access.
100
+ * @cs_count: Number of flash chips that may be connected to this module.
101
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
102
+ * @cs_lines: GPIO lines that may be wired to flash chips.
103
+ * @flash: Array of @cs_count per-flash-chip state objects.
104
+ * @spi: The SPI bus mastered by this controller.
105
+ * @regs: Register contents.
106
+ *
107
+ * Each FIU has a shared bank of registers, and controls up to four chip
108
+ * selects. Each chip select has a dedicated memory region which may be used to
109
+ * read and write the flash connected to that chip select as if it were memory.
110
+ */
111
+struct NPCM7xxFIUState {
112
+ SysBusDevice parent;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ int32_t cs_count;
117
+ int32_t active_cs;
118
+ qemu_irq *cs_lines;
119
+ NPCM7xxFIUFlash *flash;
120
+
121
+ SSIBus *spi;
122
+
123
+ uint32_t regs[NPCM7XX_FIU_NR_REGS];
124
+};
125
+
126
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
127
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
128
+
129
+#endif /* NPCM7XX_FIU_H */
130
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
42
index XXXXXXX..XXXXXXX 100644
131
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/iotkit.c
132
--- a/hw/arm/npcm7xx.c
44
+++ b/hw/arm/iotkit.c
133
+++ b/hw/arm/npcm7xx.c
134
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_uart_addr[] = {
135
0xf0004000,
136
};
137
138
+/* Direct memory-mapped access to SPI0 CS0-1. */
139
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
140
+ 0x80000000, /* CS0 */
141
+ 0x88000000, /* CS1 */
142
+};
143
+
144
+/* Direct memory-mapped access to SPI3 CS0-3. */
145
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
146
+ 0xa0000000, /* CS0 */
147
+ 0xa8000000, /* CS1 */
148
+ 0xb0000000, /* CS2 */
149
+ 0xb8000000, /* CS3 */
150
+};
151
+
152
+static const struct {
153
+ const char *name;
154
+ hwaddr regs_addr;
155
+ int cs_count;
156
+ const hwaddr *flash_addr;
157
+} npcm7xx_fiu[] = {
158
+ {
159
+ .name = "fiu0",
160
+ .regs_addr = 0xfb000000,
161
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
162
+ .flash_addr = npcm7xx_fiu0_flash_addr,
163
+ }, {
164
+ .name = "fiu3",
165
+ .regs_addr = 0xc0000000,
166
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
167
+ .flash_addr = npcm7xx_fiu3_flash_addr,
168
+ },
169
+};
170
+
171
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
172
const struct arm_boot_info *info)
173
{
174
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
175
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
176
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
177
}
178
+
179
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
180
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
181
+ object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
182
+ TYPE_NPCM7XX_FIU);
183
+ }
184
}
185
186
static void npcm7xx_realize(DeviceState *dev, Error **errp)
187
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
188
serial_hd(i), DEVICE_LITTLE_ENDIAN);
189
}
190
191
+ /*
192
+ * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
193
+ * specified, but this is a programming error.
194
+ */
195
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
196
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
197
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
198
+ int j;
199
+
200
+ object_property_set_int(OBJECT(sbd), "cs-count",
201
+ npcm7xx_fiu[i].cs_count, &error_abort);
202
+ sysbus_realize(sbd, &error_abort);
203
+
204
+ sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
205
+ for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
206
+ sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
207
+ }
208
+ }
209
+
210
/* RAM2 (SRAM) */
211
memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
212
NPCM7XX_RAM2_SZ, &error_abort);
213
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
214
new file mode 100644
215
index XXXXXXX..XXXXXXX
216
--- /dev/null
217
+++ b/hw/ssi/npcm7xx_fiu.c
45
@@ -XXX,XX +XXX,XX @@
218
@@ -XXX,XX +XXX,XX @@
46
#include "hw/misc/unimp.h"
219
+/*
47
#include "hw/arm/arm.h"
220
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
48
221
+ *
49
+/* Clock frequency in HZ of the 32KHz "slow clock" */
222
+ * Copyright 2020 Google LLC
50
+#define S32KCLK (32 * 1000)
223
+ *
51
+
224
+ * This program is free software; you can redistribute it and/or modify it
52
/* Create an alias region of @size bytes starting at @base
225
+ * under the terms of the GNU General Public License as published by the
53
* which mirrors the memory starting at @orig.
226
+ * Free Software Foundation; either version 2 of the License, or
54
*/
227
+ * (at your option) any later version.
55
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
228
+ *
56
TYPE_CMSDK_APB_TIMER);
229
+ * This program is distributed in the hope that it will be useful, but WITHOUT
57
sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
230
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
58
TYPE_CMSDK_APB_DUALTIMER);
231
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
59
+ sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog,
232
+ * for more details.
60
+ sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG);
233
+ */
61
+ sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog,
234
+
62
+ sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
235
+#include "qemu/osdep.h"
63
+ sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
236
+
64
+ sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
237
+#include "hw/irq.h"
65
+ object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
238
+#include "hw/qdev-properties.h"
66
+ sizeof(s->nmi_orgate), TYPE_OR_IRQ,
239
+#include "hw/ssi/npcm7xx_fiu.h"
67
+ &error_abort, NULL);
240
+#include "migration/vmstate.h"
68
object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
241
+#include "qapi/error.h"
69
sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
242
+#include "qemu/error-report.h"
70
&error_abort, NULL);
243
+#include "qemu/log.h"
71
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
244
+#include "qemu/module.h"
72
create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
245
+#include "qemu/units.h"
73
246
+
74
create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
247
+#include "trace.h"
75
- create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
248
+
76
+
249
+/* Up to 128 MiB of flash may be accessed directly as memory. */
77
+ /* This OR gate wires together outputs from the secure watchdogs to NMI */
250
+#define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB)
78
+ object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
251
+
79
+ if (err) {
252
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
80
+ error_propagate(errp, err);
253
+#define NPCM7XX_FIU_CTRL_REGS_SIZE (4 * KiB)
254
+
255
+/* 32-bit FIU register indices. */
256
+enum NPCM7xxFIURegister {
257
+ NPCM7XX_FIU_DRD_CFG,
258
+ NPCM7XX_FIU_DWR_CFG,
259
+ NPCM7XX_FIU_UMA_CFG,
260
+ NPCM7XX_FIU_UMA_CTS,
261
+ NPCM7XX_FIU_UMA_CMD,
262
+ NPCM7XX_FIU_UMA_ADDR,
263
+ NPCM7XX_FIU_PRT_CFG,
264
+ NPCM7XX_FIU_UMA_DW0 = 0x0020 / sizeof(uint32_t),
265
+ NPCM7XX_FIU_UMA_DW1,
266
+ NPCM7XX_FIU_UMA_DW2,
267
+ NPCM7XX_FIU_UMA_DW3,
268
+ NPCM7XX_FIU_UMA_DR0,
269
+ NPCM7XX_FIU_UMA_DR1,
270
+ NPCM7XX_FIU_UMA_DR2,
271
+ NPCM7XX_FIU_UMA_DR3,
272
+ NPCM7XX_FIU_PRT_CMD0,
273
+ NPCM7XX_FIU_PRT_CMD1,
274
+ NPCM7XX_FIU_PRT_CMD2,
275
+ NPCM7XX_FIU_PRT_CMD3,
276
+ NPCM7XX_FIU_PRT_CMD4,
277
+ NPCM7XX_FIU_PRT_CMD5,
278
+ NPCM7XX_FIU_PRT_CMD6,
279
+ NPCM7XX_FIU_PRT_CMD7,
280
+ NPCM7XX_FIU_PRT_CMD8,
281
+ NPCM7XX_FIU_PRT_CMD9,
282
+ NPCM7XX_FIU_CFG = 0x78 / sizeof(uint32_t),
283
+ NPCM7XX_FIU_REGS_END,
284
+};
285
+
286
+/* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */
287
+#define NPCM7XX_FIU_CFG_LCK BIT(31)
288
+
289
+/* Direct Read configuration register fields. */
290
+#define FIU_DRD_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
291
+#define FIU_ADDSIZ_3BYTES 0
292
+#define FIU_ADDSIZ_4BYTES 1
293
+#define FIU_DRD_CFG_DBW(rv) extract32(rv, 12, 2)
294
+#define FIU_DRD_CFG_ACCTYPE(rv) extract32(rv, 8, 2)
295
+#define FIU_DRD_CFG_RDCMD(rv) extract32(rv, 0, 8)
296
+
297
+/* Direct Write configuration register fields. */
298
+#define FIU_DWR_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
299
+#define FIU_DWR_CFG_WRCMD(rv) extract32(rv, 0, 8)
300
+
301
+/* User-Mode Access register fields. */
302
+
303
+/* Command Mode Lock and the bits protected by it. */
304
+#define FIU_UMA_CFG_CMMLCK BIT(30)
305
+#define FIU_UMA_CFG_CMMLCK_MASK 0x00000403
306
+
307
+#define FIU_UMA_CFG_RDATSIZ(rv) extract32(rv, 24, 5)
308
+#define FIU_UMA_CFG_DBSIZ(rv) extract32(rv, 21, 3)
309
+#define FIU_UMA_CFG_WDATSIZ(rv) extract32(rv, 16, 5)
310
+#define FIU_UMA_CFG_ADDSIZ(rv) extract32(rv, 11, 3)
311
+#define FIU_UMA_CFG_CMDSIZ(rv) extract32(rv, 10, 1)
312
+#define FIU_UMA_CFG_DBPCK(rv) extract32(rv, 6, 2)
313
+
314
+#define FIU_UMA_CTS_RDYIE BIT(25)
315
+#define FIU_UMA_CTS_RDYST BIT(24)
316
+#define FIU_UMA_CTS_SW_CS BIT(16)
317
+#define FIU_UMA_CTS_DEV_NUM(rv) extract32(rv, 8, 2)
318
+#define FIU_UMA_CTS_EXEC_DONE BIT(0)
319
+
320
+/*
321
+ * Returns the index of flash in the fiu->flash array. This corresponds to the
322
+ * chip select ID of the flash.
323
+ */
324
+static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash)
325
+{
326
+ int index = flash - fiu->flash;
327
+
328
+ g_assert(index >= 0 && index < fiu->cs_count);
329
+
330
+ return index;
331
+}
332
+
333
+/* Assert the chip select specified in the UMA Control/Status Register. */
334
+static void npcm7xx_fiu_select(NPCM7xxFIUState *s, int cs_id)
335
+{
336
+ trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id);
337
+
338
+ if (cs_id < s->cs_count) {
339
+ qemu_irq_lower(s->cs_lines[cs_id]);
340
+ } else {
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: UMA to CS%d; this module has only %d chip selects",
343
+ DEVICE(s)->canonical_path, cs_id, s->cs_count);
344
+ cs_id = -1;
345
+ }
346
+
347
+ s->active_cs = cs_id;
348
+}
349
+
350
+/* Deassert the currently active chip select. */
351
+static void npcm7xx_fiu_deselect(NPCM7xxFIUState *s)
352
+{
353
+ if (s->active_cs < 0) {
81
+ return;
354
+ return;
82
+ }
355
+ }
83
+ object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err);
356
+
84
+ if (err) {
357
+ trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs);
85
+ error_propagate(errp, err);
358
+
359
+ qemu_irq_raise(s->cs_lines[s->active_cs]);
360
+ s->active_cs = -1;
361
+}
362
+
363
+/* Direct flash memory read handler. */
364
+static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr,
365
+ unsigned int size)
366
+{
367
+ NPCM7xxFIUFlash *f = opaque;
368
+ NPCM7xxFIUState *fiu = f->fiu;
369
+ uint64_t value = 0;
370
+ uint32_t drd_cfg;
371
+ int dummy_cycles;
372
+ int i;
373
+
374
+ if (fiu->active_cs != -1) {
375
+ qemu_log_mask(LOG_GUEST_ERROR,
376
+ "%s: direct flash read with CS%d already active",
377
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
378
+ }
379
+
380
+ npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f));
381
+
382
+ drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG];
383
+ ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg));
384
+
385
+ switch (FIU_DRD_CFG_ADDSIZ(drd_cfg)) {
386
+ case FIU_ADDSIZ_4BYTES:
387
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
388
+ /* fall through */
389
+ case FIU_ADDSIZ_3BYTES:
390
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
391
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
392
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
393
+ break;
394
+
395
+ default:
396
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
397
+ DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg));
398
+ break;
399
+ }
400
+
401
+ /* Flash chip model expects one transfer per dummy bit, not byte */
402
+ dummy_cycles =
403
+ (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
404
+ for (i = 0; i < dummy_cycles; i++) {
405
+ ssi_transfer(fiu->spi, 0);
406
+ }
407
+
408
+ for (i = 0; i < size; i++) {
409
+ value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0));
410
+ }
411
+
412
+ trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs,
413
+ addr, size, value);
414
+
415
+ npcm7xx_fiu_deselect(fiu);
416
+
417
+ return value;
418
+}
419
+
420
+/* Direct flash memory write handler. */
421
+static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v,
422
+ unsigned int size)
423
+{
424
+ NPCM7xxFIUFlash *f = opaque;
425
+ NPCM7xxFIUState *fiu = f->fiu;
426
+ uint32_t dwr_cfg;
427
+ int cs_id;
428
+ int i;
429
+
430
+ if (fiu->active_cs != -1) {
431
+ qemu_log_mask(LOG_GUEST_ERROR,
432
+ "%s: direct flash write with CS%d already active",
433
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
434
+ }
435
+
436
+ cs_id = npcm7xx_fiu_cs_index(fiu, f);
437
+ trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr,
438
+ size, v);
439
+ npcm7xx_fiu_select(fiu, cs_id);
440
+
441
+ dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG];
442
+ ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg));
443
+
444
+ switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg)) {
445
+ case FIU_ADDSIZ_4BYTES:
446
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
447
+ /* fall through */
448
+ case FIU_ADDSIZ_3BYTES:
449
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
450
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
451
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
452
+ break;
453
+
454
+ default:
455
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
456
+ DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg));
457
+ break;
458
+ }
459
+
460
+ for (i = 0; i < size; i++) {
461
+ ssi_transfer(fiu->spi, extract64(v, i * 8, 8));
462
+ }
463
+
464
+ npcm7xx_fiu_deselect(fiu);
465
+}
466
+
467
+static const MemoryRegionOps npcm7xx_fiu_flash_ops = {
468
+ .read = npcm7xx_fiu_flash_read,
469
+ .write = npcm7xx_fiu_flash_write,
470
+ .endianness = DEVICE_LITTLE_ENDIAN,
471
+ .valid = {
472
+ .min_access_size = 1,
473
+ .max_access_size = 8,
474
+ .unaligned = true,
475
+ },
476
+};
477
+
478
+/* Control register read handler. */
479
+static uint64_t npcm7xx_fiu_ctrl_read(void *opaque, hwaddr addr,
480
+ unsigned int size)
481
+{
482
+ hwaddr reg = addr / sizeof(uint32_t);
483
+ NPCM7xxFIUState *s = opaque;
484
+ uint32_t value;
485
+
486
+ if (reg < NPCM7XX_FIU_NR_REGS) {
487
+ value = s->regs[reg];
488
+ } else {
489
+ qemu_log_mask(LOG_GUEST_ERROR,
490
+ "%s: read from invalid offset 0x%" PRIx64 "\n",
491
+ DEVICE(s)->canonical_path, addr);
492
+ value = 0;
493
+ }
494
+
495
+ trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value);
496
+
497
+ return value;
498
+}
499
+
500
+/* Send the specified number of address bytes from the UMA address register. */
501
+static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr)
502
+{
503
+ switch (addsiz) {
504
+ case 4:
505
+ ssi_transfer(spi, extract32(addr, 24, 8));
506
+ /* fall through */
507
+ case 3:
508
+ ssi_transfer(spi, extract32(addr, 16, 8));
509
+ /* fall through */
510
+ case 2:
511
+ ssi_transfer(spi, extract32(addr, 8, 8));
512
+ /* fall through */
513
+ case 1:
514
+ ssi_transfer(spi, extract32(addr, 0, 8));
515
+ /* fall through */
516
+ case 0:
517
+ break;
518
+ }
519
+}
520
+
521
+/* Send the number of dummy bits specified in the UMA config register. */
522
+static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd)
523
+{
524
+ unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg);
525
+ unsigned int i;
526
+
527
+ for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) {
528
+ /* Use bytes 0 and 1 first, then keep repeating byte 2 */
529
+ unsigned int field = (i < 2) ? ((i + 1) * 8) : 24;
530
+ unsigned int j;
531
+
532
+ for (j = 0; j < 8; j += bits_per_clock) {
533
+ ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock));
534
+ }
535
+ }
536
+}
537
+
538
+/* Perform a User-Mode Access transaction. */
539
+static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s)
540
+{
541
+ uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS];
542
+ uint32_t uma_cfg;
543
+ unsigned int i;
544
+
545
+ /* SW_CS means the CS is already forced low, so don't touch it. */
546
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
547
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
548
+ npcm7xx_fiu_select(s, cs_id);
549
+ }
550
+
551
+ /* Send command, if present. */
552
+ uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG];
553
+ if (FIU_UMA_CFG_CMDSIZ(uma_cfg) > 0) {
554
+ ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8));
555
+ }
556
+
557
+ /* Send address, if present. */
558
+ send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg),
559
+ s->regs[NPCM7XX_FIU_UMA_ADDR]);
560
+
561
+ /* Write data, if present. */
562
+ for (i = 0; i < FIU_UMA_CFG_WDATSIZ(uma_cfg); i++) {
563
+ unsigned int reg =
564
+ (i < 16) ? (NPCM7XX_FIU_UMA_DW0 + i / 4) : NPCM7XX_FIU_UMA_DW3;
565
+ unsigned int field = (i % 4) * 8;
566
+
567
+ ssi_transfer(s->spi, extract32(s->regs[reg], field, 8));
568
+ }
569
+
570
+ /* Send dummy bits, if present. */
571
+ send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]);
572
+
573
+ /* Read data, if present. */
574
+ for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) {
575
+ unsigned int reg = NPCM7XX_FIU_UMA_DR0 + i / 4;
576
+ unsigned int field = (i % 4) * 8;
577
+ uint8_t c;
578
+
579
+ c = ssi_transfer(s->spi, 0);
580
+ if (reg <= NPCM7XX_FIU_UMA_DR3) {
581
+ s->regs[reg] = deposit32(s->regs[reg], field, 8, c);
582
+ }
583
+ }
584
+
585
+ /* Again, don't touch CS if the user is forcing it low. */
586
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
587
+ npcm7xx_fiu_deselect(s);
588
+ }
589
+
590
+ /* RDYST means a command has completed since it was cleared. */
591
+ s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST;
592
+ /* EXEC_DONE means Execute Command / Not Done, so clear it here. */
593
+ s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE;
594
+}
595
+
596
+/* Control register write handler. */
597
+static void npcm7xx_fiu_ctrl_write(void *opaque, hwaddr addr, uint64_t v,
598
+ unsigned int size)
599
+{
600
+ hwaddr reg = addr / sizeof(uint32_t);
601
+ NPCM7xxFIUState *s = opaque;
602
+ uint32_t value = v;
603
+
604
+ trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value);
605
+
606
+ switch (reg) {
607
+ case NPCM7XX_FIU_UMA_CFG:
608
+ if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) {
609
+ value &= ~FIU_UMA_CFG_CMMLCK_MASK;
610
+ value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK);
611
+ }
612
+ /* fall through */
613
+ case NPCM7XX_FIU_DRD_CFG:
614
+ case NPCM7XX_FIU_DWR_CFG:
615
+ if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) {
616
+ qemu_log_mask(LOG_GUEST_ERROR,
617
+ "%s: write to locked register @ 0x%" PRIx64 "\n",
618
+ DEVICE(s)->canonical_path, addr);
619
+ return;
620
+ }
621
+ s->regs[reg] = value;
622
+ break;
623
+
624
+ case NPCM7XX_FIU_UMA_CTS:
625
+ if (value & FIU_UMA_CTS_RDYST) {
626
+ value &= ~FIU_UMA_CTS_RDYST;
627
+ } else {
628
+ value |= s->regs[reg] & FIU_UMA_CTS_RDYST;
629
+ }
630
+ if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) {
631
+ if (value & FIU_UMA_CTS_SW_CS) {
632
+ /*
633
+ * Don't drop CS if there's a transfer in progress, or we're
634
+ * about to start one.
635
+ */
636
+ if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) {
637
+ npcm7xx_fiu_deselect(s);
638
+ }
639
+ } else {
640
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
641
+ npcm7xx_fiu_select(s, cs_id);
642
+ }
643
+ }
644
+ s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE);
645
+ if (value & FIU_UMA_CTS_EXEC_DONE) {
646
+ npcm7xx_fiu_uma_transaction(s);
647
+ }
648
+ break;
649
+
650
+ case NPCM7XX_FIU_UMA_DR0 ... NPCM7XX_FIU_UMA_DR3:
651
+ qemu_log_mask(LOG_GUEST_ERROR,
652
+ "%s: write to read-only register @ 0x%" PRIx64 "\n",
653
+ DEVICE(s)->canonical_path, addr);
86
+ return;
654
+ return;
87
+ }
655
+
88
+ qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
656
+ case NPCM7XX_FIU_PRT_CFG:
89
+ qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
657
+ case NPCM7XX_FIU_PRT_CMD0 ... NPCM7XX_FIU_PRT_CMD9:
90
+
658
+ qemu_log_mask(LOG_UNIMP, "%s: PRT is not implemented\n", __func__);
91
+ qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
659
+ break;
92
+ object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err);
660
+
93
+ if (err) {
661
+ case NPCM7XX_FIU_UMA_CMD:
94
+ error_propagate(errp, err);
662
+ case NPCM7XX_FIU_UMA_ADDR:
663
+ case NPCM7XX_FIU_UMA_DW0 ... NPCM7XX_FIU_UMA_DW3:
664
+ case NPCM7XX_FIU_CFG:
665
+ s->regs[reg] = value;
666
+ break;
667
+
668
+ default:
669
+ qemu_log_mask(LOG_GUEST_ERROR,
670
+ "%s: write to invalid offset 0x%" PRIx64 "\n",
671
+ DEVICE(s)->canonical_path, addr);
95
+ return;
672
+ return;
96
+ }
673
+ }
97
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
674
+}
98
+ qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
675
+
99
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
676
+static const MemoryRegionOps npcm7xx_fiu_ctrl_ops = {
100
677
+ .read = npcm7xx_fiu_ctrl_read,
101
/* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
678
+ .write = npcm7xx_fiu_ctrl_write,
102
679
+ .endianness = DEVICE_LITTLE_ENDIAN,
103
- create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
680
+ .valid = {
104
- create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
681
+ .min_access_size = 4,
105
+ qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
682
+ .max_access_size = 4,
106
+ object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
683
+ .unaligned = false,
107
+ if (err) {
684
+ },
108
+ error_propagate(errp, err);
685
+};
686
+
687
+static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type)
688
+{
689
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
690
+
691
+ trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type);
692
+
693
+ memset(s->regs, 0, sizeof(s->regs));
694
+
695
+ s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b;
696
+ s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002;
697
+ s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400;
698
+ s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000;
699
+ s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b;
700
+ s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400;
701
+ s->regs[NPCM7XX_FIU_CFG] = 0x0000000b;
702
+}
703
+
704
+static void npcm7xx_fiu_hold_reset(Object *obj)
705
+{
706
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
707
+ int i;
708
+
709
+ trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path);
710
+
711
+ for (i = 0; i < s->cs_count; i++) {
712
+ qemu_irq_raise(s->cs_lines[i]);
713
+ }
714
+}
715
+
716
+static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
717
+{
718
+ NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
719
+ SysBusDevice *sbd = &s->parent;
720
+ int i;
721
+
722
+ if (s->cs_count <= 0) {
723
+ error_setg(errp, "%s: %d chip selects specified, need at least one",
724
+ dev->canonical_path, s->cs_count);
109
+ return;
725
+ return;
110
+ }
726
+ }
111
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
727
+
112
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 1));
728
+ s->spi = ssi_create_bus(dev, "spi");
113
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
729
+ s->cs_lines = g_new0(qemu_irq, s->cs_count);
114
+
730
+ qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count);
115
+ qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
731
+ s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count);
116
+ object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err);
732
+
117
+ if (err) {
733
+ /*
118
+ error_propagate(errp, err);
734
+ * Register the control registers region first. It may be followed by one
119
+ return;
735
+ * or more direct flash access regions.
120
+ }
736
+ */
121
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
737
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl",
122
+ qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
738
+ NPCM7XX_FIU_CTRL_REGS_SIZE);
123
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
739
+ sysbus_init_mmio(sbd, &s->mmio);
124
740
+
125
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
741
+ for (i = 0; i < s->cs_count; i++) {
126
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
742
+ NPCM7xxFIUFlash *flash = &s->flash[i];
743
+ flash->fiu = s;
744
+ memory_region_init_io(&flash->direct_access, OBJECT(s),
745
+ &npcm7xx_fiu_flash_ops, &s->flash[i], "flash",
746
+ NPCM7XX_FIU_FLASH_WINDOW_SIZE);
747
+ sysbus_init_mmio(sbd, &flash->direct_access);
748
+ }
749
+}
750
+
751
+static const VMStateDescription vmstate_npcm7xx_fiu = {
752
+ .name = "npcm7xx-fiu",
753
+ .version_id = 0,
754
+ .minimum_version_id = 0,
755
+ .fields = (VMStateField[]) {
756
+ VMSTATE_INT32(active_cs, NPCM7xxFIUState),
757
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxFIUState, NPCM7XX_FIU_NR_REGS),
758
+ VMSTATE_END_OF_LIST(),
759
+ },
760
+};
761
+
762
+static Property npcm7xx_fiu_properties[] = {
763
+ DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0),
764
+ DEFINE_PROP_END_OF_LIST(),
765
+};
766
+
767
+static void npcm7xx_fiu_class_init(ObjectClass *klass, void *data)
768
+{
769
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
770
+ DeviceClass *dc = DEVICE_CLASS(klass);
771
+
772
+ QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END > NPCM7XX_FIU_NR_REGS);
773
+
774
+ dc->desc = "NPCM7xx Flash Interface Unit";
775
+ dc->realize = npcm7xx_fiu_realize;
776
+ dc->vmsd = &vmstate_npcm7xx_fiu;
777
+ rc->phases.enter = npcm7xx_fiu_enter_reset;
778
+ rc->phases.hold = npcm7xx_fiu_hold_reset;
779
+ device_class_set_props(dc, npcm7xx_fiu_properties);
780
+}
781
+
782
+static const TypeInfo npcm7xx_fiu_types[] = {
783
+ {
784
+ .name = TYPE_NPCM7XX_FIU,
785
+ .parent = TYPE_SYS_BUS_DEVICE,
786
+ .instance_size = sizeof(NPCM7xxFIUState),
787
+ .class_init = npcm7xx_fiu_class_init,
788
+ },
789
+};
790
+DEFINE_TYPES(npcm7xx_fiu_types);
791
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
792
index XXXXXXX..XXXXXXX 100644
793
--- a/hw/arm/Kconfig
794
+++ b/hw/arm/Kconfig
795
@@ -XXX,XX +XXX,XX @@ config NPCM7XX
796
select ARM_GIC
797
select PL310 # cache controller
798
select SERIAL
799
+ select SSI
800
select UNIMP
801
802
config FSL_IMX25
803
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
804
index XXXXXXX..XXXXXXX 100644
805
--- a/hw/ssi/meson.build
806
+++ b/hw/ssi/meson.build
807
@@ -XXX,XX +XXX,XX @@
808
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c'))
809
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c'))
810
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c'))
811
softmmu_ss.add(when: 'CONFIG_PL022', if_true: files('pl022.c'))
812
softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c'))
813
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c'))
814
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
815
index XXXXXXX..XXXXXXX 100644
816
--- a/hw/ssi/trace-events
817
+++ b/hw/ssi/trace-events
818
@@ -XXX,XX +XXX,XX @@ aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
819
aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
820
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
821
aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
822
+
823
+# npcm7xx_fiu.c
824
+
825
+npcm7xx_fiu_enter_reset(const char *id, int reset_type) "%s reset type: %d"
826
+npcm7xx_fiu_hold_reset(const char *id) "%s"
827
+npcm7xx_fiu_select(const char *id, int cs) "%s select CS%d"
828
+npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect CS%d"
829
+npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
830
+npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
831
+npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
832
+npcm7xx_fiu_flash_write(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
127
--
833
--
128
2.18.0
834
2.20.1
129
835
130
836
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
This allows these NPCM7xx-based boards to boot from a flash image, e.g.
4
Message-id: 20180814002653.12828-3-richard.henderson@linaro.org
4
one built with OpenBMC. For example like this:
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
6
IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
7
qemu-system-arm -machine quanta-gsj -nographic \
8
    -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
9
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Tested-by: Cédric Le Goater <clg@kaod.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200911052101.2602693-12-hskinnemoen@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
18
---
8
include/fpu/softfloat.h | 85 ++++++---
19
hw/arm/npcm7xx_boards.c | 20 ++++++++++++++++++++
9
fpu/softfloat.c | 391 ++++++++++++++++++++++++++++++++--------
20
1 file changed, 20 insertions(+)
10
2 files changed, 379 insertions(+), 97 deletions(-)
11
21
12
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
22
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/include/fpu/softfloat.h
24
--- a/hw/arm/npcm7xx_boards.c
15
+++ b/include/fpu/softfloat.h
25
+++ b/hw/arm/npcm7xx_boards.c
16
@@ -XXX,XX +XXX,XX @@ float128 uint64_to_float128(uint64_t, float_status *status);
26
@@ -XXX,XX +XXX,XX @@
17
/*----------------------------------------------------------------------------
27
#include "hw/arm/npcm7xx.h"
18
| Software half-precision conversion routines.
28
#include "hw/core/cpu.h"
19
*----------------------------------------------------------------------------*/
29
#include "hw/loader.h"
20
+
30
+#include "hw/qdev-properties.h"
21
float16 float32_to_float16(float32, bool ieee, float_status *status);
31
#include "qapi/error.h"
22
float32 float16_to_float32(float16, bool ieee, float_status *status);
32
#include "qemu-common.h"
23
float16 float64_to_float16(float64 a, bool ieee, float_status *status);
33
#include "qemu/units.h"
24
float64 float16_to_float64(float16 a, bool ieee, float_status *status);
34
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
25
+
26
+int16_t float16_to_int16_scalbn(float16, int, int, float_status *status);
27
+int32_t float16_to_int32_scalbn(float16, int, int, float_status *status);
28
+int64_t float16_to_int64_scalbn(float16, int, int, float_status *status);
29
+
30
int16_t float16_to_int16(float16, float_status *status);
31
-uint16_t float16_to_uint16(float16 a, float_status *status);
32
-int16_t float16_to_int16_round_to_zero(float16, float_status *status);
33
-uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *status);
34
int32_t float16_to_int32(float16, float_status *status);
35
-uint32_t float16_to_uint32(float16 a, float_status *status);
36
-int32_t float16_to_int32_round_to_zero(float16, float_status *status);
37
-uint32_t float16_to_uint32_round_to_zero(float16 a, float_status *status);
38
int64_t float16_to_int64(float16, float_status *status);
39
-uint64_t float16_to_uint64(float16 a, float_status *status);
40
+
41
+int16_t float16_to_int16_round_to_zero(float16, float_status *status);
42
+int32_t float16_to_int32_round_to_zero(float16, float_status *status);
43
int64_t float16_to_int64_round_to_zero(float16, float_status *status);
44
+
45
+uint16_t float16_to_uint16_scalbn(float16 a, int, int, float_status *status);
46
+uint32_t float16_to_uint32_scalbn(float16 a, int, int, float_status *status);
47
+uint64_t float16_to_uint64_scalbn(float16 a, int, int, float_status *status);
48
+
49
+uint16_t float16_to_uint16(float16 a, float_status *status);
50
+uint32_t float16_to_uint32(float16 a, float_status *status);
51
+uint64_t float16_to_uint64(float16 a, float_status *status);
52
+
53
+uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *status);
54
+uint32_t float16_to_uint32_round_to_zero(float16 a, float_status *status);
55
uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *status);
56
57
/*----------------------------------------------------------------------------
58
@@ -XXX,XX +XXX,XX @@ float16 float16_default_nan(float_status *status);
59
/*----------------------------------------------------------------------------
60
| Software IEC/IEEE single-precision conversion routines.
61
*----------------------------------------------------------------------------*/
62
+
63
+int16_t float32_to_int16_scalbn(float32, int, int, float_status *status);
64
+int32_t float32_to_int32_scalbn(float32, int, int, float_status *status);
65
+int64_t float32_to_int64_scalbn(float32, int, int, float_status *status);
66
+
67
int16_t float32_to_int16(float32, float_status *status);
68
-uint16_t float32_to_uint16(float32, float_status *status);
69
-int16_t float32_to_int16_round_to_zero(float32, float_status *status);
70
-uint16_t float32_to_uint16_round_to_zero(float32, float_status *status);
71
int32_t float32_to_int32(float32, float_status *status);
72
-int32_t float32_to_int32_round_to_zero(float32, float_status *status);
73
-uint32_t float32_to_uint32(float32, float_status *status);
74
-uint32_t float32_to_uint32_round_to_zero(float32, float_status *status);
75
int64_t float32_to_int64(float32, float_status *status);
76
-uint64_t float32_to_uint64(float32, float_status *status);
77
-uint64_t float32_to_uint64_round_to_zero(float32, float_status *status);
78
+
79
+int16_t float32_to_int16_round_to_zero(float32, float_status *status);
80
+int32_t float32_to_int32_round_to_zero(float32, float_status *status);
81
int64_t float32_to_int64_round_to_zero(float32, float_status *status);
82
+
83
+uint16_t float32_to_uint16_scalbn(float32, int, int, float_status *status);
84
+uint32_t float32_to_uint32_scalbn(float32, int, int, float_status *status);
85
+uint64_t float32_to_uint64_scalbn(float32, int, int, float_status *status);
86
+
87
+uint16_t float32_to_uint16(float32, float_status *status);
88
+uint32_t float32_to_uint32(float32, float_status *status);
89
+uint64_t float32_to_uint64(float32, float_status *status);
90
+
91
+uint16_t float32_to_uint16_round_to_zero(float32, float_status *status);
92
+uint32_t float32_to_uint32_round_to_zero(float32, float_status *status);
93
+uint64_t float32_to_uint64_round_to_zero(float32, float_status *status);
94
+
95
float64 float32_to_float64(float32, float_status *status);
96
floatx80 float32_to_floatx80(float32, float_status *status);
97
float128 float32_to_float128(float32, float_status *status);
98
@@ -XXX,XX +XXX,XX @@ float32 float32_default_nan(float_status *status);
99
/*----------------------------------------------------------------------------
100
| Software IEC/IEEE double-precision conversion routines.
101
*----------------------------------------------------------------------------*/
102
+
103
+int16_t float64_to_int16_scalbn(float64, int, int, float_status *status);
104
+int32_t float64_to_int32_scalbn(float64, int, int, float_status *status);
105
+int64_t float64_to_int64_scalbn(float64, int, int, float_status *status);
106
+
107
int16_t float64_to_int16(float64, float_status *status);
108
-uint16_t float64_to_uint16(float64, float_status *status);
109
-int16_t float64_to_int16_round_to_zero(float64, float_status *status);
110
-uint16_t float64_to_uint16_round_to_zero(float64, float_status *status);
111
int32_t float64_to_int32(float64, float_status *status);
112
-int32_t float64_to_int32_round_to_zero(float64, float_status *status);
113
-uint32_t float64_to_uint32(float64, float_status *status);
114
-uint32_t float64_to_uint32_round_to_zero(float64, float_status *status);
115
int64_t float64_to_int64(float64, float_status *status);
116
+
117
+int16_t float64_to_int16_round_to_zero(float64, float_status *status);
118
+int32_t float64_to_int32_round_to_zero(float64, float_status *status);
119
int64_t float64_to_int64_round_to_zero(float64, float_status *status);
120
-uint64_t float64_to_uint64(float64 a, float_status *status);
121
-uint64_t float64_to_uint64_round_to_zero(float64 a, float_status *status);
122
+
123
+uint16_t float64_to_uint16_scalbn(float64, int, int, float_status *status);
124
+uint32_t float64_to_uint32_scalbn(float64, int, int, float_status *status);
125
+uint64_t float64_to_uint64_scalbn(float64, int, int, float_status *status);
126
+
127
+uint16_t float64_to_uint16(float64, float_status *status);
128
+uint32_t float64_to_uint32(float64, float_status *status);
129
+uint64_t float64_to_uint64(float64, float_status *status);
130
+
131
+uint16_t float64_to_uint16_round_to_zero(float64, float_status *status);
132
+uint32_t float64_to_uint32_round_to_zero(float64, float_status *status);
133
+uint64_t float64_to_uint64_round_to_zero(float64, float_status *status);
134
+
135
float32 float64_to_float32(float64, float_status *status);
136
floatx80 float64_to_floatx80(float64, float_status *status);
137
float128 float64_to_float128(float64, float_status *status);
138
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/fpu/softfloat.c
141
+++ b/fpu/softfloat.c
142
@@ -XXX,XX +XXX,XX @@ float32 float64_to_float32(float64 a, float_status *s)
143
* Arithmetic.
144
*/
145
146
-static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
147
+static FloatParts round_to_int(FloatParts a, int rmode,
148
+ int scale, float_status *s)
149
{
150
- if (is_nan(a.cls)) {
151
- return return_nan(a, s);
152
- }
153
-
154
switch (a.cls) {
155
+ case float_class_qnan:
156
+ case float_class_snan:
157
+ return return_nan(a, s);
158
+
159
case float_class_zero:
160
case float_class_inf:
161
- case float_class_qnan:
162
/* already "integral" */
163
break;
164
+
165
case float_class_normal:
166
+ scale = MIN(MAX(scale, -0x10000), 0x10000);
167
+ a.exp += scale;
168
+
169
if (a.exp >= DECOMPOSED_BINARY_POINT) {
170
/* already integral */
171
break;
172
@@ -XXX,XX +XXX,XX @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
173
bool one;
174
/* all fractional */
175
s->float_exception_flags |= float_flag_inexact;
176
- switch (rounding_mode) {
177
+ switch (rmode) {
178
case float_round_nearest_even:
179
one = a.exp == -1 && a.frac > DECOMPOSED_IMPLICIT_BIT;
180
break;
181
@@ -XXX,XX +XXX,XX @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
182
uint64_t rnd_mask = rnd_even_mask >> 1;
183
uint64_t inc;
184
185
- switch (rounding_mode) {
186
+ switch (rmode) {
187
case float_round_nearest_even:
188
inc = ((a.frac & rnd_even_mask) != frac_lsbm1 ? frac_lsbm1 : 0);
189
break;
190
@@ -XXX,XX +XXX,XX @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
191
float16 float16_round_to_int(float16 a, float_status *s)
192
{
193
FloatParts pa = float16_unpack_canonical(a, s);
194
- FloatParts pr = round_to_int(pa, s->float_rounding_mode, s);
195
+ FloatParts pr = round_to_int(pa, s->float_rounding_mode, 0, s);
196
return float16_round_pack_canonical(pr, s);
197
}
198
199
float32 float32_round_to_int(float32 a, float_status *s)
200
{
201
FloatParts pa = float32_unpack_canonical(a, s);
202
- FloatParts pr = round_to_int(pa, s->float_rounding_mode, s);
203
+ FloatParts pr = round_to_int(pa, s->float_rounding_mode, 0, s);
204
return float32_round_pack_canonical(pr, s);
205
}
206
207
float64 float64_round_to_int(float64 a, float_status *s)
208
{
209
FloatParts pa = float64_unpack_canonical(a, s);
210
- FloatParts pr = round_to_int(pa, s->float_rounding_mode, s);
211
+ FloatParts pr = round_to_int(pa, s->float_rounding_mode, 0, s);
212
return float64_round_pack_canonical(pr, s);
213
}
214
215
float64 float64_trunc_to_int(float64 a, float_status *s)
216
{
217
FloatParts pa = float64_unpack_canonical(a, s);
218
- FloatParts pr = round_to_int(pa, float_round_to_zero, s);
219
+ FloatParts pr = round_to_int(pa, float_round_to_zero, 0, s);
220
return float64_round_pack_canonical(pr, s);
221
}
222
223
@@ -XXX,XX +XXX,XX @@ float64 float64_trunc_to_int(float64 a, float_status *s)
224
* is returned.
225
*/
226
227
-static int64_t round_to_int_and_pack(FloatParts in, int rmode,
228
+static int64_t round_to_int_and_pack(FloatParts in, int rmode, int scale,
229
int64_t min, int64_t max,
230
float_status *s)
231
{
232
uint64_t r;
233
int orig_flags = get_float_exception_flags(s);
234
- FloatParts p = round_to_int(in, rmode, s);
235
+ FloatParts p = round_to_int(in, rmode, scale, s);
236
237
switch (p.cls) {
238
case float_class_snan:
239
@@ -XXX,XX +XXX,XX @@ static int64_t round_to_int_and_pack(FloatParts in, int rmode,
240
}
35
}
241
}
36
}
242
37
243
-#define FLOAT_TO_INT(fsz, isz) \
38
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
244
-int ## isz ## _t float ## fsz ## _to_int ## isz(float ## fsz a, \
39
+ const char *flash_type, DriveInfo *dinfo)
245
- float_status *s) \
246
-{ \
247
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
248
- return round_to_int_and_pack(p, s->float_rounding_mode, \
249
- INT ## isz ## _MIN, INT ## isz ## _MAX,\
250
- s); \
251
-} \
252
- \
253
-int ## isz ## _t float ## fsz ## _to_int ## isz ## _round_to_zero \
254
- (float ## fsz a, float_status *s) \
255
-{ \
256
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
257
- return round_to_int_and_pack(p, float_round_to_zero, \
258
- INT ## isz ## _MIN, INT ## isz ## _MAX,\
259
- s); \
260
+int16_t float16_to_int16_scalbn(float16 a, int rmode, int scale,
261
+ float_status *s)
262
+{
40
+{
263
+ return round_to_int_and_pack(float16_unpack_canonical(a, s),
41
+ DeviceState *flash;
264
+ rmode, scale, INT16_MIN, INT16_MAX, s);
42
+ qemu_irq flash_cs;
265
}
43
+
266
44
+ flash = qdev_new(flash_type);
267
-FLOAT_TO_INT(16, 16)
45
+ if (dinfo) {
268
-FLOAT_TO_INT(16, 32)
46
+ qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
269
-FLOAT_TO_INT(16, 64)
47
+ }
270
+int32_t float16_to_int32_scalbn(float16 a, int rmode, int scale,
48
+ qdev_realize_and_unref(flash, BUS(fiu->spi), &error_fatal);
271
+ float_status *s)
49
+
272
+{
50
+ flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
273
+ return round_to_int_and_pack(float16_unpack_canonical(a, s),
51
+ qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
274
+ rmode, scale, INT32_MIN, INT32_MAX, s);
275
+}
276
277
-FLOAT_TO_INT(32, 16)
278
-FLOAT_TO_INT(32, 32)
279
-FLOAT_TO_INT(32, 64)
280
+int64_t float16_to_int64_scalbn(float16 a, int rmode, int scale,
281
+ float_status *s)
282
+{
283
+ return round_to_int_and_pack(float16_unpack_canonical(a, s),
284
+ rmode, scale, INT64_MIN, INT64_MAX, s);
285
+}
286
287
-FLOAT_TO_INT(64, 16)
288
-FLOAT_TO_INT(64, 32)
289
-FLOAT_TO_INT(64, 64)
290
+int16_t float32_to_int16_scalbn(float32 a, int rmode, int scale,
291
+ float_status *s)
292
+{
293
+ return round_to_int_and_pack(float32_unpack_canonical(a, s),
294
+ rmode, scale, INT16_MIN, INT16_MAX, s);
295
+}
296
297
-#undef FLOAT_TO_INT
298
+int32_t float32_to_int32_scalbn(float32 a, int rmode, int scale,
299
+ float_status *s)
300
+{
301
+ return round_to_int_and_pack(float32_unpack_canonical(a, s),
302
+ rmode, scale, INT32_MIN, INT32_MAX, s);
303
+}
52
+}
304
+
53
+
305
+int64_t float32_to_int64_scalbn(float32 a, int rmode, int scale,
54
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
306
+ float_status *s)
307
+{
308
+ return round_to_int_and_pack(float32_unpack_canonical(a, s),
309
+ rmode, scale, INT64_MIN, INT64_MAX, s);
310
+}
311
+
312
+int16_t float64_to_int16_scalbn(float64 a, int rmode, int scale,
313
+ float_status *s)
314
+{
315
+ return round_to_int_and_pack(float64_unpack_canonical(a, s),
316
+ rmode, scale, INT16_MIN, INT16_MAX, s);
317
+}
318
+
319
+int32_t float64_to_int32_scalbn(float64 a, int rmode, int scale,
320
+ float_status *s)
321
+{
322
+ return round_to_int_and_pack(float64_unpack_canonical(a, s),
323
+ rmode, scale, INT32_MIN, INT32_MAX, s);
324
+}
325
+
326
+int64_t float64_to_int64_scalbn(float64 a, int rmode, int scale,
327
+ float_status *s)
328
+{
329
+ return round_to_int_and_pack(float64_unpack_canonical(a, s),
330
+ rmode, scale, INT64_MIN, INT64_MAX, s);
331
+}
332
+
333
+int16_t float16_to_int16(float16 a, float_status *s)
334
+{
335
+ return float16_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
336
+}
337
+
338
+int32_t float16_to_int32(float16 a, float_status *s)
339
+{
340
+ return float16_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
341
+}
342
+
343
+int64_t float16_to_int64(float16 a, float_status *s)
344
+{
345
+ return float16_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
346
+}
347
+
348
+int16_t float32_to_int16(float32 a, float_status *s)
349
+{
350
+ return float32_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
351
+}
352
+
353
+int32_t float32_to_int32(float32 a, float_status *s)
354
+{
355
+ return float32_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
356
+}
357
+
358
+int64_t float32_to_int64(float32 a, float_status *s)
359
+{
360
+ return float32_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
361
+}
362
+
363
+int16_t float64_to_int16(float64 a, float_status *s)
364
+{
365
+ return float64_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
366
+}
367
+
368
+int32_t float64_to_int32(float64 a, float_status *s)
369
+{
370
+ return float64_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
371
+}
372
+
373
+int64_t float64_to_int64(float64 a, float_status *s)
374
+{
375
+ return float64_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
376
+}
377
+
378
+int16_t float16_to_int16_round_to_zero(float16 a, float_status *s)
379
+{
380
+ return float16_to_int16_scalbn(a, float_round_to_zero, 0, s);
381
+}
382
+
383
+int32_t float16_to_int32_round_to_zero(float16 a, float_status *s)
384
+{
385
+ return float16_to_int32_scalbn(a, float_round_to_zero, 0, s);
386
+}
387
+
388
+int64_t float16_to_int64_round_to_zero(float16 a, float_status *s)
389
+{
390
+ return float16_to_int64_scalbn(a, float_round_to_zero, 0, s);
391
+}
392
+
393
+int16_t float32_to_int16_round_to_zero(float32 a, float_status *s)
394
+{
395
+ return float32_to_int16_scalbn(a, float_round_to_zero, 0, s);
396
+}
397
+
398
+int32_t float32_to_int32_round_to_zero(float32 a, float_status *s)
399
+{
400
+ return float32_to_int32_scalbn(a, float_round_to_zero, 0, s);
401
+}
402
+
403
+int64_t float32_to_int64_round_to_zero(float32 a, float_status *s)
404
+{
405
+ return float32_to_int64_scalbn(a, float_round_to_zero, 0, s);
406
+}
407
+
408
+int16_t float64_to_int16_round_to_zero(float64 a, float_status *s)
409
+{
410
+ return float64_to_int16_scalbn(a, float_round_to_zero, 0, s);
411
+}
412
+
413
+int32_t float64_to_int32_round_to_zero(float64 a, float_status *s)
414
+{
415
+ return float64_to_int32_scalbn(a, float_round_to_zero, 0, s);
416
+}
417
+
418
+int64_t float64_to_int64_round_to_zero(float64 a, float_status *s)
419
+{
420
+ return float64_to_int64_scalbn(a, float_round_to_zero, 0, s);
421
+}
422
423
/*
424
* Returns the result of converting the floating-point value `a' to
425
@@ -XXX,XX +XXX,XX @@ FLOAT_TO_INT(64, 64)
426
* flag.
427
*/
428
429
-static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
430
- float_status *s)
431
+static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, int scale,
432
+ uint64_t max, float_status *s)
433
{
55
{
434
int orig_flags = get_float_exception_flags(s);
56
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
435
- FloatParts p = round_to_int(in, rmode, s);
57
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
436
+ FloatParts p = round_to_int(in, rmode, scale, s);
58
qdev_realize(DEVICE(soc), NULL, &error_fatal);
437
+ uint64_t r;
59
438
60
npcm7xx_load_bootrom(machine, soc);
439
switch (p.cls) {
61
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
440
case float_class_snan:
62
npcm7xx_load_kernel(machine, soc);
441
@@ -XXX,XX +XXX,XX @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
442
case float_class_zero:
443
return 0;
444
case float_class_normal:
445
- {
446
- uint64_t r;
447
if (p.sign) {
448
s->float_exception_flags = orig_flags | float_flag_invalid;
449
return 0;
450
@@ -XXX,XX +XXX,XX @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
451
if (r > max) {
452
s->float_exception_flags = orig_flags | float_flag_invalid;
453
return max;
454
- } else {
455
- return r;
456
}
457
- }
458
+ return r;
459
default:
460
g_assert_not_reached();
461
}
462
}
63
}
463
64
464
-#define FLOAT_TO_UINT(fsz, isz) \
65
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
465
-uint ## isz ## _t float ## fsz ## _to_uint ## isz(float ## fsz a, \
66
qdev_realize(DEVICE(soc), NULL, &error_fatal);
466
- float_status *s) \
67
467
-{ \
68
npcm7xx_load_bootrom(machine, soc);
468
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
69
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
469
- return round_to_uint_and_pack(p, s->float_rounding_mode, \
70
+ drive_get(IF_MTD, 0, 0));
470
- UINT ## isz ## _MAX, s); \
71
npcm7xx_load_kernel(machine, soc);
471
-} \
472
- \
473
-uint ## isz ## _t float ## fsz ## _to_uint ## isz ## _round_to_zero \
474
- (float ## fsz a, float_status *s) \
475
-{ \
476
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
477
- return round_to_uint_and_pack(p, float_round_to_zero, \
478
- UINT ## isz ## _MAX, s); \
479
+uint16_t float16_to_uint16_scalbn(float16 a, int rmode, int scale,
480
+ float_status *s)
481
+{
482
+ return round_to_uint_and_pack(float16_unpack_canonical(a, s),
483
+ rmode, scale, UINT16_MAX, s);
484
}
72
}
485
73
486
-FLOAT_TO_UINT(16, 16)
487
-FLOAT_TO_UINT(16, 32)
488
-FLOAT_TO_UINT(16, 64)
489
+uint32_t float16_to_uint32_scalbn(float16 a, int rmode, int scale,
490
+ float_status *s)
491
+{
492
+ return round_to_uint_and_pack(float16_unpack_canonical(a, s),
493
+ rmode, scale, UINT32_MAX, s);
494
+}
495
496
-FLOAT_TO_UINT(32, 16)
497
-FLOAT_TO_UINT(32, 32)
498
-FLOAT_TO_UINT(32, 64)
499
+uint64_t float16_to_uint64_scalbn(float16 a, int rmode, int scale,
500
+ float_status *s)
501
+{
502
+ return round_to_uint_and_pack(float16_unpack_canonical(a, s),
503
+ rmode, scale, UINT64_MAX, s);
504
+}
505
506
-FLOAT_TO_UINT(64, 16)
507
-FLOAT_TO_UINT(64, 32)
508
-FLOAT_TO_UINT(64, 64)
509
+uint16_t float32_to_uint16_scalbn(float32 a, int rmode, int scale,
510
+ float_status *s)
511
+{
512
+ return round_to_uint_and_pack(float32_unpack_canonical(a, s),
513
+ rmode, scale, UINT16_MAX, s);
514
+}
515
516
-#undef FLOAT_TO_UINT
517
+uint32_t float32_to_uint32_scalbn(float32 a, int rmode, int scale,
518
+ float_status *s)
519
+{
520
+ return round_to_uint_and_pack(float32_unpack_canonical(a, s),
521
+ rmode, scale, UINT32_MAX, s);
522
+}
523
+
524
+uint64_t float32_to_uint64_scalbn(float32 a, int rmode, int scale,
525
+ float_status *s)
526
+{
527
+ return round_to_uint_and_pack(float32_unpack_canonical(a, s),
528
+ rmode, scale, UINT64_MAX, s);
529
+}
530
+
531
+uint16_t float64_to_uint16_scalbn(float64 a, int rmode, int scale,
532
+ float_status *s)
533
+{
534
+ return round_to_uint_and_pack(float64_unpack_canonical(a, s),
535
+ rmode, scale, UINT16_MAX, s);
536
+}
537
+
538
+uint32_t float64_to_uint32_scalbn(float64 a, int rmode, int scale,
539
+ float_status *s)
540
+{
541
+ return round_to_uint_and_pack(float64_unpack_canonical(a, s),
542
+ rmode, scale, UINT32_MAX, s);
543
+}
544
+
545
+uint64_t float64_to_uint64_scalbn(float64 a, int rmode, int scale,
546
+ float_status *s)
547
+{
548
+ return round_to_uint_and_pack(float64_unpack_canonical(a, s),
549
+ rmode, scale, UINT64_MAX, s);
550
+}
551
+
552
+uint16_t float16_to_uint16(float16 a, float_status *s)
553
+{
554
+ return float16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
555
+}
556
+
557
+uint32_t float16_to_uint32(float16 a, float_status *s)
558
+{
559
+ return float16_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
560
+}
561
+
562
+uint64_t float16_to_uint64(float16 a, float_status *s)
563
+{
564
+ return float16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
565
+}
566
+
567
+uint16_t float32_to_uint16(float32 a, float_status *s)
568
+{
569
+ return float32_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
570
+}
571
+
572
+uint32_t float32_to_uint32(float32 a, float_status *s)
573
+{
574
+ return float32_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
575
+}
576
+
577
+uint64_t float32_to_uint64(float32 a, float_status *s)
578
+{
579
+ return float32_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
580
+}
581
+
582
+uint16_t float64_to_uint16(float64 a, float_status *s)
583
+{
584
+ return float64_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
585
+}
586
+
587
+uint32_t float64_to_uint32(float64 a, float_status *s)
588
+{
589
+ return float64_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
590
+}
591
+
592
+uint64_t float64_to_uint64(float64 a, float_status *s)
593
+{
594
+ return float64_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
595
+}
596
+
597
+uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *s)
598
+{
599
+ return float16_to_uint16_scalbn(a, float_round_to_zero, 0, s);
600
+}
601
+
602
+uint32_t float16_to_uint32_round_to_zero(float16 a, float_status *s)
603
+{
604
+ return float16_to_uint32_scalbn(a, float_round_to_zero, 0, s);
605
+}
606
+
607
+uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *s)
608
+{
609
+ return float16_to_uint64_scalbn(a, float_round_to_zero, 0, s);
610
+}
611
+
612
+uint16_t float32_to_uint16_round_to_zero(float32 a, float_status *s)
613
+{
614
+ return float32_to_uint16_scalbn(a, float_round_to_zero, 0, s);
615
+}
616
+
617
+uint32_t float32_to_uint32_round_to_zero(float32 a, float_status *s)
618
+{
619
+ return float32_to_uint32_scalbn(a, float_round_to_zero, 0, s);
620
+}
621
+
622
+uint64_t float32_to_uint64_round_to_zero(float32 a, float_status *s)
623
+{
624
+ return float32_to_uint64_scalbn(a, float_round_to_zero, 0, s);
625
+}
626
+
627
+uint16_t float64_to_uint16_round_to_zero(float64 a, float_status *s)
628
+{
629
+ return float64_to_uint16_scalbn(a, float_round_to_zero, 0, s);
630
+}
631
+
632
+uint32_t float64_to_uint32_round_to_zero(float64 a, float_status *s)
633
+{
634
+ return float64_to_uint32_scalbn(a, float_round_to_zero, 0, s);
635
+}
636
+
637
+uint64_t float64_to_uint64_round_to_zero(float64 a, float_status *s)
638
+{
639
+ return float64_to_uint64_scalbn(a, float_round_to_zero, 0, s);
640
+}
641
642
/*
643
* Integer to float conversions
644
--
74
--
645
2.18.0
75
2.20.1
646
76
647
77
diff view generated by jsdifflib
Deleted patch
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-4-peter.maydell@linaro.org
9
---
10
hw/arm/vexpress.c | 4 ++++
11
1 file changed, 4 insertions(+)
12
13
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/vexpress.c
16
+++ b/hw/arm/vexpress.c
17
@@ -XXX,XX +XXX,XX @@ static void init_cpus(const char *cpu_type, const char *privdev,
18
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
19
sysbus_connect_irq(busdev, n + smp_cpus,
20
qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
21
+ sysbus_connect_irq(busdev, n + 2 * smp_cpus,
22
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
23
+ sysbus_connect_irq(busdev, n + 3 * smp_cpus,
24
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
25
}
26
}
27
28
--
29
2.18.0
30
31
diff view generated by jsdifflib
Deleted patch
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-5-peter.maydell@linaro.org
9
---
10
hw/arm/highbank.c | 6 ++++++
11
1 file changed, 6 insertions(+)
12
13
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/highbank.c
16
+++ b/hw/arm/highbank.c
17
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
18
int n;
19
qemu_irq cpu_irq[4];
20
qemu_irq cpu_fiq[4];
21
+ qemu_irq cpu_virq[4];
22
+ qemu_irq cpu_vfiq[4];
23
MemoryRegion *sysram;
24
MemoryRegion *dram;
25
MemoryRegion *sysmem;
26
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
27
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
28
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
29
cpu_fiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ);
30
+ cpu_virq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VIRQ);
31
+ cpu_vfiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VFIQ);
32
}
33
34
sysmem = get_system_memory();
35
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
36
for (n = 0; n < smp_cpus; n++) {
37
sysbus_connect_irq(busdev, n, cpu_irq[n]);
38
sysbus_connect_irq(busdev, n + smp_cpus, cpu_fiq[n]);
39
+ sysbus_connect_irq(busdev, n + 2 * smp_cpus, cpu_virq[n]);
40
+ sysbus_connect_irq(busdev, n + 3 * smp_cpus, cpu_vfiq[n]);
41
}
42
43
for (n = 0; n < 128; n++) {
44
--
45
2.18.0
46
47
diff view generated by jsdifflib
Deleted patch
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-6-peter.maydell@linaro.org
9
---
10
hw/arm/fsl-imx6ul.c | 4 ++++
11
1 file changed, 4 insertions(+)
12
13
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/fsl-imx6ul.c
16
+++ b/hw/arm/fsl-imx6ul.c
17
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
18
irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
19
sysbus_connect_irq(sbd, i, irq);
20
sysbus_connect_irq(sbd, i + smp_cpus, qdev_get_gpio_in(d, ARM_CPU_FIQ));
21
+ sysbus_connect_irq(sbd, i + 2 * smp_cpus,
22
+ qdev_get_gpio_in(d, ARM_CPU_VIRQ));
23
+ sysbus_connect_irq(sbd, i + 3 * smp_cpus,
24
+ qdev_get_gpio_in(d, ARM_CPU_VFIQ));
25
}
26
27
/*
28
--
29
2.18.0
30
31
diff view generated by jsdifflib
Deleted patch
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-7-peter.maydell@linaro.org
9
---
10
hw/arm/fsl-imx7.c | 4 ++++
11
1 file changed, 4 insertions(+)
12
13
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/fsl-imx7.c
16
+++ b/hw/arm/fsl-imx7.c
17
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
18
sysbus_connect_irq(sbd, i, irq);
19
irq = qdev_get_gpio_in(d, ARM_CPU_FIQ);
20
sysbus_connect_irq(sbd, i + smp_cpus, irq);
21
+ irq = qdev_get_gpio_in(d, ARM_CPU_VIRQ);
22
+ sysbus_connect_irq(sbd, i + 2 * smp_cpus, irq);
23
+ irq = qdev_get_gpio_in(d, ARM_CPU_VFIQ);
24
+ sysbus_connect_irq(sbd, i + 3 * smp_cpus, irq);
25
}
26
27
/*
28
--
29
2.18.0
30
31
diff view generated by jsdifflib
Deleted patch
1
For the A15MPCore internal peripheral object, we handle GIC
2
security extensions support by checking whether the CPUs
3
have EL3 enabled; if so then we enable it also on the GIC.
4
Handle the virtualization extensions in the same way: if the
5
CPU has EL2 then enable it on the GIC and wire up the
6
virtualization-specific memory regions and the maintenance
7
interrupt.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
11
Message-id: 20180821132811.17675-8-peter.maydell@linaro.org
12
---
13
hw/cpu/a15mpcore.c | 31 ++++++++++++++++++++++++++++---
14
1 file changed, 28 insertions(+), 3 deletions(-)
15
16
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/cpu/a15mpcore.c
19
+++ b/hw/cpu/a15mpcore.c
20
@@ -XXX,XX +XXX,XX @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
21
int i;
22
Error *err = NULL;
23
bool has_el3;
24
+ bool has_el2;
25
Object *cpuobj;
26
27
gicdev = DEVICE(&s->gic);
28
@@ -XXX,XX +XXX,XX @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
29
has_el3 = object_property_find(cpuobj, "has_el3", NULL) &&
30
object_property_get_bool(cpuobj, "has_el3", &error_abort);
31
qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
32
+ /* Similarly for virtualization support */
33
+ has_el2 = object_property_find(cpuobj, "has_el2", NULL) &&
34
+ object_property_get_bool(cpuobj, "has_el2", &error_abort);
35
+ qdev_prop_set_bit(gicdev, "has-virtualization-extensions", has_el2);
36
}
37
38
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
39
@@ -XXX,XX +XXX,XX @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
40
qdev_get_gpio_in(gicdev,
41
ppibase + timer_irq[irq]));
42
}
43
+ if (has_el2) {
44
+ /* Connect the GIC maintenance interrupt to PPI ID 25 */
45
+ sysbus_connect_irq(SYS_BUS_DEVICE(gicdev), i + 4 * s->num_cpu,
46
+ qdev_get_gpio_in(gicdev, ppibase + 25));
47
+ }
48
}
49
50
/* Memory map (addresses are offsets from PERIPHBASE):
51
* 0x0000-0x0fff -- reserved
52
* 0x1000-0x1fff -- GIC Distributor
53
* 0x2000-0x3fff -- GIC CPU interface
54
- * 0x4000-0x4fff -- GIC virtual interface control (not modelled)
55
- * 0x5000-0x5fff -- GIC virtual interface control (not modelled)
56
- * 0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
57
+ * 0x4000-0x4fff -- GIC virtual interface control for this CPU
58
+ * 0x5000-0x51ff -- GIC virtual interface control for CPU 0
59
+ * 0x5200-0x53ff -- GIC virtual interface control for CPU 1
60
+ * 0x5400-0x55ff -- GIC virtual interface control for CPU 2
61
+ * 0x5600-0x57ff -- GIC virtual interface control for CPU 3
62
+ * 0x6000-0x7fff -- GIC virtual CPU interface
63
*/
64
memory_region_add_subregion(&s->container, 0x1000,
65
sysbus_mmio_get_region(busdev, 0));
66
memory_region_add_subregion(&s->container, 0x2000,
67
sysbus_mmio_get_region(busdev, 1));
68
+ if (has_el2) {
69
+ memory_region_add_subregion(&s->container, 0x4000,
70
+ sysbus_mmio_get_region(busdev, 2));
71
+ memory_region_add_subregion(&s->container, 0x6000,
72
+ sysbus_mmio_get_region(busdev, 3));
73
+ for (i = 0; i < s->num_cpu; i++) {
74
+ hwaddr base = 0x5000 + i * 0x200;
75
+ MemoryRegion *mr = sysbus_mmio_get_region(busdev,
76
+ 4 + s->num_cpu + i);
77
+ memory_region_add_subregion(&s->container, base, mr);
78
+ }
79
+ }
80
}
81
82
static Property a15mp_priv_properties[] = {
83
--
84
2.18.0
85
86
diff view generated by jsdifflib
Deleted patch
1
Don't request that the arm_load_kernel() code should boot in secure
2
state if the CPU doesn't have a secure state. Currently this
3
doesn't make a difference because the boot.c code only examines
4
the secure_boot flag in code guarded by an ARM_FEATURE_EL3 check,
5
but upcoming changes for supporting booting into Hyp mode will
6
change that.
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Message-id: 20180821132811.17675-9-peter.maydell@linaro.org
11
---
12
hw/arm/vexpress.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/vexpress.c
18
+++ b/hw/arm/vexpress.c
19
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
20
daughterboard->bootinfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
21
daughterboard->bootinfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
22
daughterboard->bootinfo.modify_dtb = vexpress_modify_dtb;
23
- /* Indicate that when booting Linux we should be in secure state */
24
- daughterboard->bootinfo.secure_boot = true;
25
+ /* When booting Linux we should be in secure state if the CPU has one. */
26
+ daughterboard->bootinfo.secure_boot = vms->secure;
27
arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo);
28
}
29
30
--
31
2.18.0
32
33
diff view generated by jsdifflib
Deleted patch
1
Add a "virtualization" property to the vexpress-a15 board,
2
controlling presence of EL2. As with EL3, we default to
3
enabling it, but the user can disable it if they have an
4
older guest which can't cope with it being present.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-10-peter.maydell@linaro.org
9
---
10
hw/arm/vexpress.c | 56 ++++++++++++++++++++++++++++++++++++++++++++---
11
1 file changed, 53 insertions(+), 3 deletions(-)
12
13
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/vexpress.c
16
+++ b/hw/arm/vexpress.c
17
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
typedef struct {
19
MachineState parent;
20
bool secure;
21
+ bool virt;
22
} VexpressMachineState;
23
24
#define TYPE_VEXPRESS_MACHINE "vexpress"
25
@@ -XXX,XX +XXX,XX @@ struct VEDBoardInfo {
26
};
27
28
static void init_cpus(const char *cpu_type, const char *privdev,
29
- hwaddr periphbase, qemu_irq *pic, bool secure)
30
+ hwaddr periphbase, qemu_irq *pic, bool secure, bool virt)
31
{
32
DeviceState *dev;
33
SysBusDevice *busdev;
34
@@ -XXX,XX +XXX,XX @@ static void init_cpus(const char *cpu_type, const char *privdev,
35
if (!secure) {
36
object_property_set_bool(cpuobj, false, "has_el3", NULL);
37
}
38
+ if (!virt) {
39
+ if (object_property_find(cpuobj, "has_el2", NULL)) {
40
+ object_property_set_bool(cpuobj, false, "has_el2", NULL);
41
+ }
42
+ }
43
44
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
45
object_property_set_int(cpuobj, periphbase,
46
@@ -XXX,XX +XXX,XX @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
47
memory_region_add_subregion(sysmem, 0x60000000, ram);
48
49
/* 0x1e000000 A9MPCore (SCU) private memory region */
50
- init_cpus(cpu_type, TYPE_A9MPCORE_PRIV, 0x1e000000, pic, vms->secure);
51
+ init_cpus(cpu_type, TYPE_A9MPCORE_PRIV, 0x1e000000, pic,
52
+ vms->secure, vms->virt);
53
54
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
55
56
@@ -XXX,XX +XXX,XX @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
57
memory_region_add_subregion(sysmem, 0x80000000, ram);
58
59
/* 0x2c000000 A15MPCore private memory region (GIC) */
60
- init_cpus(cpu_type, TYPE_A15MPCORE_PRIV, 0x2c000000, pic, vms->secure);
61
+ init_cpus(cpu_type, TYPE_A15MPCORE_PRIV, 0x2c000000, pic, vms->secure,
62
+ vms->virt);
63
64
/* A15 daughterboard peripherals: */
65
66
@@ -XXX,XX +XXX,XX @@ static void vexpress_set_secure(Object *obj, bool value, Error **errp)
67
vms->secure = value;
68
}
69
70
+static bool vexpress_get_virt(Object *obj, Error **errp)
71
+{
72
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
73
+
74
+ return vms->virt;
75
+}
76
+
77
+static void vexpress_set_virt(Object *obj, bool value, Error **errp)
78
+{
79
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
80
+
81
+ vms->virt = value;
82
+}
83
+
84
static void vexpress_instance_init(Object *obj)
85
{
86
VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
87
@@ -XXX,XX +XXX,XX @@ static void vexpress_instance_init(Object *obj)
88
NULL);
89
}
90
91
+static void vexpress_a15_instance_init(Object *obj)
92
+{
93
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
94
+
95
+ /*
96
+ * For the vexpress-a15, EL2 is by default enabled if EL3 is,
97
+ * but can also be specifically set to on or off.
98
+ */
99
+ vms->virt = true;
100
+ object_property_add_bool(obj, "virtualization", vexpress_get_virt,
101
+ vexpress_set_virt, NULL);
102
+ object_property_set_description(obj, "virtualization",
103
+ "Set on/off to enable/disable the ARM "
104
+ "Virtualization Extensions "
105
+ "(defaults to same as 'secure')",
106
+ NULL);
107
+}
108
+
109
+static void vexpress_a9_instance_init(Object *obj)
110
+{
111
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
112
+
113
+ /* The A9 doesn't have the virt extensions */
114
+ vms->virt = false;
115
+}
116
+
117
static void vexpress_class_init(ObjectClass *oc, void *data)
118
{
119
MachineClass *mc = MACHINE_CLASS(oc);
120
@@ -XXX,XX +XXX,XX @@ static const TypeInfo vexpress_a9_info = {
121
.name = TYPE_VEXPRESS_A9_MACHINE,
122
.parent = TYPE_VEXPRESS_MACHINE,
123
.class_init = vexpress_a9_class_init,
124
+ .instance_init = vexpress_a9_instance_init,
125
};
126
127
static const TypeInfo vexpress_a15_info = {
128
.name = TYPE_VEXPRESS_A15_MACHINE,
129
.parent = TYPE_VEXPRESS_MACHINE,
130
.class_init = vexpress_a15_class_init,
131
+ .instance_init = vexpress_a15_instance_init,
132
};
133
134
static void vexpress_machine_init(void)
135
--
136
2.18.0
137
138
diff view generated by jsdifflib
Deleted patch
1
The v8 AArch32 HACTLR2 register maps to bits [63:32] of ACTLR_EL2.
2
We implement ACTLR_EL2 as RAZ/WI, so make HACTLR2 also RAZ/WI.
3
(We put the regdef next to ACTLR_EL2 as a reminder in case we
4
ever make ACTLR_EL2 something other than RAZ/WI).
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Message-id: 20180820153020.21478-2-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 10 ++++++++++
13
1 file changed, 10 insertions(+)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
20
REGINFO_SENTINEL
21
};
22
define_arm_cp_regs(cpu, auxcr_reginfo);
23
+ if (arm_feature(env, ARM_FEATURE_V8)) {
24
+ /* HACTLR2 maps to ACTLR_EL2[63:32] and is not in ARMv7 */
25
+ ARMCPRegInfo hactlr2_reginfo = {
26
+ .name = "HACTLR2", .state = ARM_CP_STATE_AA32,
27
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
28
+ .access = PL2_RW, .type = ARM_CP_CONST,
29
+ .resetvalue = 0
30
+ };
31
+ define_one_arm_cp_reg(cpu, &hactlr2_reginfo);
32
+ }
33
}
34
35
if (arm_feature(env, ARM_FEATURE_CBAR)) {
36
--
37
2.18.0
38
39
diff view generated by jsdifflib
Deleted patch
1
Factor out the code which changes the CPU state so as to
2
actually take an exception to AArch32. We're going to want
3
to use this for handling exception entry to Hyp mode.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20180820153020.21478-4-peter.maydell@linaro.org
10
---
11
target/arm/helper.c | 64 +++++++++++++++++++++++++++++----------------
12
1 file changed, 41 insertions(+), 23 deletions(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ void aarch64_sync_64_to_32(CPUARMState *env)
19
env->regs[15] = env->pc;
20
}
21
22
+static void take_aarch32_exception(CPUARMState *env, int new_mode,
23
+ uint32_t mask, uint32_t offset,
24
+ uint32_t newpc)
25
+{
26
+ /* Change the CPU state so as to actually take the exception. */
27
+ switch_mode(env, new_mode);
28
+ /*
29
+ * For exceptions taken to AArch32 we must clear the SS bit in both
30
+ * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
31
+ */
32
+ env->uncached_cpsr &= ~PSTATE_SS;
33
+ env->spsr = cpsr_read(env);
34
+ /* Clear IT bits. */
35
+ env->condexec_bits = 0;
36
+ /* Switch to the new mode, and to the correct instruction set. */
37
+ env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
38
+ /* Set new mode endianness */
39
+ env->uncached_cpsr &= ~CPSR_E;
40
+ if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
41
+ env->uncached_cpsr |= CPSR_E;
42
+ }
43
+ env->daif |= mask;
44
+
45
+ if (new_mode == ARM_CPU_MODE_HYP) {
46
+ env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
47
+ env->elr_el[2] = env->regs[15];
48
+ } else {
49
+ /*
50
+ * this is a lie, as there was no c1_sys on V4T/V5, but who cares
51
+ * and we should just guard the thumb mode on V4
52
+ */
53
+ if (arm_feature(env, ARM_FEATURE_V4T)) {
54
+ env->thumb =
55
+ (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
56
+ }
57
+ env->regs[14] = env->regs[15] + offset;
58
+ }
59
+ env->regs[15] = newpc;
60
+}
61
+
62
static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
63
{
64
ARMCPU *cpu = ARM_CPU(cs);
65
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
66
env->cp15.scr_el3 &= ~SCR_NS;
67
}
68
69
- switch_mode (env, new_mode);
70
- /* For exceptions taken to AArch32 we must clear the SS bit in both
71
- * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
72
- */
73
- env->uncached_cpsr &= ~PSTATE_SS;
74
- env->spsr = cpsr_read(env);
75
- /* Clear IT bits. */
76
- env->condexec_bits = 0;
77
- /* Switch to the new mode, and to the correct instruction set. */
78
- env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
79
- /* Set new mode endianness */
80
- env->uncached_cpsr &= ~CPSR_E;
81
- if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
82
- env->uncached_cpsr |= CPSR_E;
83
- }
84
- env->daif |= mask;
85
- /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
86
- * and we should just guard the thumb mode on V4 */
87
- if (arm_feature(env, ARM_FEATURE_V4T)) {
88
- env->thumb = (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
89
- }
90
- env->regs[14] = env->regs[15] + offset;
91
- env->regs[15] = addr;
92
+ take_aarch32_exception(env, new_mode, mask, offset, addr);
93
}
94
95
/* Handle exception entry to a target EL which is using AArch64 */
96
--
97
2.18.0
98
99
diff view generated by jsdifflib
Deleted patch
1
On 32-bit exception entry, CPSR.J must always be set to 0
2
(see v7A Arm ARM DDI0406C.c B1.8.5). CPSR.IL must also
3
be cleared on 32-bit exception entry (see v8A Arm ARM
4
DDI0487C.a G1.10).
5
1
6
Clear these bits. (This fixes a bug which will never be noticed
7
by non-buggy guests.)
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
13
Message-id: 20180820153020.21478-6-peter.maydell@linaro.org
14
---
15
target/arm/helper.c | 2 ++
16
1 file changed, 2 insertions(+)
17
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
21
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
23
if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
24
env->uncached_cpsr |= CPSR_E;
25
}
26
+ /* J and IL must always be cleared for exception entry */
27
+ env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
28
env->daif |= mask;
29
30
if (new_mode == ARM_CPU_MODE_HYP) {
31
--
32
2.18.0
33
34
diff view generated by jsdifflib
1
The IoTKit does not have any Master Security Contollers itself,
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
but it does provide registers in the secure privilege control
3
block which allow control of MSCs in the external system.
4
Add support for these registers.
5
2
3
When booting directly into a kernel, bypassing the boot loader, the CPU and
4
UART clocks are not set up correctly. This makes the system appear very
5
slow, and causes the initrd boot test to fail when optimization is off.
6
7
The UART clock must run at 24 MHz. The default 25 MHz reference clock
8
cannot achieve this, so switch to PLL2/2 @ 480 MHz, which works
9
perfectly with the default /20 divider.
10
11
The CPU clock should run at 800 MHz, so switch it to PLL1/2. PLL1 runs
12
at 800 MHz by default, so we need to double the feedback divider as well
13
to make it run at 1600 MHz (so PLL1/2 runs at 800 MHz).
14
15
We don't bother checking for PLL lock because we know our emulated PLLs
16
lock instantly.
17
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-13-hskinnemoen@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20180820141116.9118-13-peter.maydell@linaro.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
23
---
11
include/hw/misc/iotkit-secctl.h | 14 +++++++
24
include/hw/arm/npcm7xx.h | 1 +
12
hw/misc/iotkit-secctl.c | 73 +++++++++++++++++++++++++++++----
25
hw/arm/npcm7xx.c | 32 ++++++++++++++++++++++++++++++++
13
2 files changed, 79 insertions(+), 8 deletions(-)
26
2 files changed, 33 insertions(+)
14
27
15
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
28
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
16
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/iotkit-secctl.h
30
--- a/include/hw/arm/npcm7xx.h
18
+++ b/include/hw/misc/iotkit-secctl.h
31
+++ b/include/hw/arm/npcm7xx.h
19
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
20
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
33
#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
21
* should RAZ/WI or bus error
34
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
22
* + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
35
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
23
+ * + named GPIO output "msc_irq" for the combined IRQ line from the MSCs
36
+#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
24
* Controlling the 2 APB PPCs in the IoTKit:
37
25
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
38
typedef struct NPCM7xxMachine {
26
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
39
MachineState parent;
40
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/npcm7xx.c
43
+++ b/hw/arm/npcm7xx.c
27
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@
28
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
45
#define NPCM7XX_ROM_BA (0xffff0000)
29
* might provide:
46
#define NPCM7XX_ROM_SZ (64 * KiB)
30
* + named GPIO inputs mpcexp_status[0..15]
47
31
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
48
+/* Clock configuration values to be fixed up when bypassing bootloader */
32
+ * might provide:
33
+ * + named GPIO inputs mscexp_status[0..15]
34
+ * + named GPIO outputs mscexp_clear[0..15]
35
+ * + named GPIO outputs mscexp_ns[0..15]
36
*/
37
38
#ifndef IOTKIT_SECCTL_H
39
@@ -XXX,XX +XXX,XX @@
40
#define IOTS_NUM_AHB_EXP_PPC 4
41
#define IOTS_NUM_EXP_MPC 16
42
#define IOTS_NUM_MPC 1
43
+#define IOTS_NUM_EXP_MSC 16
44
45
typedef struct IoTKitSecCtl IoTKitSecCtl;
46
47
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
48
uint32_t brginten;
49
uint32_t mpcintstatus;
50
51
+ uint32_t secmscintstat;
52
+ uint32_t secmscinten;
53
+ uint32_t nsmscexp;
54
+ qemu_irq mscexp_clear[IOTS_NUM_EXP_MSC];
55
+ qemu_irq mscexp_ns[IOTS_NUM_EXP_MSC];
56
+ qemu_irq msc_irq;
57
+
49
+
58
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
50
+/* Run PLL1 at 1600 MHz */
59
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
51
+#define NPCM7XX_PLLCON1_FIXUP_VAL (0x00402101)
60
IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
52
+/* Run the CPU from PLL1 and UART from PLL2 */
61
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
53
+#define NPCM7XX_CLKSEL_FIXUP_VAL (0x004aaba9)
62
index XXXXXXX..XXXXXXX 100644
54
+
63
--- a/hw/misc/iotkit-secctl.c
55
/*
64
+++ b/hw/misc/iotkit-secctl.c
56
* Interrupt lines going into the GIC. This does not include internal Cortex-A9
65
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
57
* interrupts.
66
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
58
@@ -XXX,XX +XXX,XX @@ static const struct {
67
break;
59
},
68
case A_SECMSCINTSTAT:
60
};
69
+ r = s->secmscintstat;
61
70
+ break;
62
+static void npcm7xx_write_board_setup(ARMCPU *cpu,
71
case A_SECMSCINTEN:
63
+ const struct arm_boot_info *info)
72
+ r = s->secmscinten;
73
+ break;
74
case A_NSMSCEXP:
75
- qemu_log_mask(LOG_UNIMP,
76
- "IoTKit SecCtl S block read: "
77
- "unimplemented offset 0x%x\n", offset);
78
- r = 0;
79
+ r = s->nsmscexp;
80
break;
81
case A_PID4:
82
case A_PID5:
83
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
84
qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
85
}
86
87
+static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
88
+{
64
+{
65
+ uint32_t board_setup[] = {
66
+ 0xe59f0010, /* ldr r0, clk_base_addr */
67
+ 0xe59f1010, /* ldr r1, pllcon1_value */
68
+ 0xe5801010, /* str r1, [r0, #16] */
69
+ 0xe59f100c, /* ldr r1, clksel_value */
70
+ 0xe5801004, /* str r1, [r0, #4] */
71
+ 0xe12fff1e, /* bx lr */
72
+ NPCM7XX_CLK_BA,
73
+ NPCM7XX_PLLCON1_FIXUP_VAL,
74
+ NPCM7XX_CLKSEL_FIXUP_VAL,
75
+ };
89
+ int i;
76
+ int i;
90
+
77
+
91
+ for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
78
+ for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
92
+ qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
79
+ board_setup[i] = tswap32(board_setup[i]);
93
+ }
80
+ }
81
+ rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
82
+ info->board_setup_addr);
94
+}
83
+}
95
+
84
+
96
+static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
85
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
97
+{
86
const struct arm_boot_info *info)
98
+ /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
99
+ bool level = s->secmscintstat & s->secmscinten;
100
+
101
+ qemu_set_irq(s->msc_irq, level);
102
+}
103
+
104
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
105
uint64_t value,
106
unsigned size, MemTxAttrs attrs)
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
108
iotkit_secctl_ppc_sp_write(ppc, value);
109
break;
110
case A_SECMSCINTCLR:
111
+ iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
112
+ break;
113
case A_SECMSCINTEN:
114
- qemu_log_mask(LOG_UNIMP,
115
- "IoTKit SecCtl S block write: "
116
- "unimplemented offset 0x%x\n", offset);
117
+ s->secmscinten = value;
118
+ iotkit_secctl_update_msc_irq(s);
119
+ break;
120
+ case A_NSMSCEXP:
121
+ s->nsmscexp = value;
122
+ iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
123
break;
124
case A_SECMPCINTSTATUS:
125
case A_SECPPCINTSTAT:
126
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
127
case A_BRGINTSTAT:
128
case A_AHBNSPPC0:
129
case A_AHBSPPPC0:
130
- case A_NSMSCEXP:
131
case A_PID4:
132
case A_PID5:
133
case A_PID6:
134
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
135
s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
136
}
137
138
+static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
139
+{
140
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
141
+
142
+ s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
143
+ iotkit_secctl_update_msc_irq(s);
144
+}
145
+
146
static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
147
{
87
{
148
IoTKitSecCtlPPC *ppc = opaque;
88
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info npcm7xx_binfo = {
149
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
89
.gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
150
qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
90
.write_secondary_boot = npcm7xx_write_secondary_boot,
151
"mpcexp_status", IOTS_NUM_EXP_MPC);
91
.board_id = -1,
152
92
+ .board_setup_addr = NPCM7XX_BOARD_SETUP_ADDR,
153
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
93
+ .write_board_setup = npcm7xx_write_board_setup,
154
+ "mscexp_status", IOTS_NUM_EXP_MSC);
155
+ qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
156
+ IOTS_NUM_EXP_MSC);
157
+ qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
158
+ IOTS_NUM_EXP_MSC);
159
+ qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
160
+
161
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
162
s, "iotkit-secctl-s-regs", 0x1000);
163
memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
164
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
165
}
166
};
94
};
167
95
168
+static bool needed_always(void *opaque)
96
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
169
+{
170
+ return true;
171
+}
172
+
173
+static const VMStateDescription iotkit_secctl_msc_vmstate = {
174
+ .name = "iotkit-secctl/msc",
175
+ .version_id = 1,
176
+ .minimum_version_id = 1,
177
+ .needed = needed_always,
178
+ .fields = (VMStateField[]) {
179
+ VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
180
+ VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
181
+ VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
182
+ VMSTATE_END_OF_LIST()
183
+ }
184
+};
185
+
186
static const VMStateDescription iotkit_secctl_vmstate = {
187
.name = "iotkit-secctl",
188
.version_id = 1,
189
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
190
},
191
.subsections = (const VMStateDescription*[]) {
192
&iotkit_secctl_mpcintstatus_vmstate,
193
+ &iotkit_secctl_msc_vmstate,
194
NULL
195
},
196
};
197
--
97
--
198
2.18.0
98
2.20.1
199
99
200
100
diff view generated by jsdifflib
1
Following the bulk conversion of the iwMMXt code, there are
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
just a handful of hard coded tabs in target/arm; fix them.
3
This is a whitespace-only patch.
4
2
3
Reviewed-by: Cédric Le Goater <clg@kaod.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
6
Message-id: 20200911052101.2602693-14-hskinnemoen@google.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20180821165215.29069-4-peter.maydell@linaro.org
7
---
8
---
8
target/arm/cpu.h | 16 ++++++++--------
9
docs/system/arm/nuvoton.rst | 92 +++++++++++++++++++++++++++++++++++++
9
target/arm/arm-semi.c | 2 +-
10
docs/system/target-arm.rst | 1 +
10
2 files changed, 9 insertions(+), 9 deletions(-)
11
2 files changed, 93 insertions(+)
12
create mode 100644 docs/system/arm/nuvoton.rst
11
13
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
15
new file mode 100644
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/docs/system/arm/nuvoton.rst
19
@@ -XXX,XX +XXX,XX @@
20
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
21
+=====================================================
22
+
23
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
24
+designed to be used as Baseboard Management Controllers (BMCs) in various
25
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
26
+assortment of peripherals targeted for either Enterprise or Data Center /
27
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
28
+all the peripherals of NPCM730 and more.
29
+
30
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
31
+
32
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
33
+segment. The following machines are based on this chip :
34
+
35
+- ``npcm750-evb`` Nuvoton NPCM750 Evaluation board
36
+
37
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
38
+Hyperscale applications. The following machines are based on this chip :
39
+
40
+- ``quanta-gsj`` Quanta GSJ server BMC
41
+
42
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
43
+variants of NPCM750 and NPCM730, respectively. These are currently not
44
+supported by QEMU.
45
+
46
+Supported devices
47
+-----------------
48
+
49
+ * SMP (Dual Core Cortex-A9)
50
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
51
+ and Watchdog.
52
+ * SRAM, ROM and DRAM mappings
53
+ * System Global Control Registers (GCR)
54
+ * Clock and reset controller (CLK)
55
+ * Timer controller (TIM)
56
+ * Serial ports (16550-based)
57
+ * DDR4 memory controller (dummy interface indicating memory training is done)
58
+ * OTP controllers (no protection features)
59
+ * Flash Interface Unit (FIU; no protection features)
60
+
61
+Missing devices
62
+---------------
63
+
64
+ * GPIO controller
65
+ * LPC/eSPI host-to-BMC interface, including
66
+
67
+ * Keyboard and mouse controller interface (KBCI)
68
+ * Keyboard Controller Style (KCS) channels
69
+ * BIOS POST code FIFO
70
+ * System Wake-up Control (SWC)
71
+ * Shared memory (SHM)
72
+ * eSPI slave interface
73
+
74
+ * Ethernet controllers (GMAC and EMC)
75
+ * USB host (USBH)
76
+ * USB device (USBD)
77
+ * SMBus controller (SMBF)
78
+ * Peripheral SPI controller (PSPI)
79
+ * Analog to Digital Converter (ADC)
80
+ * SD/MMC host
81
+ * Random Number Generator (RNG)
82
+ * PECI interface
83
+ * Pulse Width Modulation (PWM)
84
+ * Tachometer
85
+ * PCI and PCIe root complex and bridges
86
+ * VDM and MCTP support
87
+ * Serial I/O expansion
88
+ * LPC/eSPI host
89
+ * Coprocessor
90
+ * Graphics
91
+ * Video capture
92
+ * Encoding compression engine
93
+ * Security features
94
+
95
+Boot options
96
+------------
97
+
98
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
99
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
100
+possibly others can be downloaded from the OpenPOWER jenkins :
101
+
102
+ https://openpower.xyz/
103
+
104
+The firmware image should be attached as an MTD drive. Example :
105
+
106
+.. code-block:: bash
107
+
108
+ $ qemu-system-arm -machine quanta-gsj -nographic \
109
+ -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
110
+
111
+The default root password for test images is usually ``0penBmc``.
112
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
13
index XXXXXXX..XXXXXXX 100644
113
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
114
--- a/docs/system/target-arm.rst
15
+++ b/target/arm/cpu.h
115
+++ b/docs/system/target-arm.rst
16
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
116
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
17
#define ARM_VFP_FPINST2 10
117
arm/musicpal
18
118
arm/gumstix
19
/* iwMMXt coprocessor control registers. */
119
arm/nseries
20
-#define ARM_IWMMXT_wCID        0
120
+ arm/nuvoton
21
-#define ARM_IWMMXT_wCon        1
121
arm/orangepi
22
-#define ARM_IWMMXT_wCSSF    2
122
arm/palm
23
-#define ARM_IWMMXT_wCASF    3
123
arm/xscale
24
-#define ARM_IWMMXT_wCGR0    8
25
-#define ARM_IWMMXT_wCGR1    9
26
-#define ARM_IWMMXT_wCGR2    10
27
-#define ARM_IWMMXT_wCGR3    11
28
+#define ARM_IWMMXT_wCID 0
29
+#define ARM_IWMMXT_wCon 1
30
+#define ARM_IWMMXT_wCSSF 2
31
+#define ARM_IWMMXT_wCASF 3
32
+#define ARM_IWMMXT_wCGR0 8
33
+#define ARM_IWMMXT_wCGR1 9
34
+#define ARM_IWMMXT_wCGR2 10
35
+#define ARM_IWMMXT_wCGR3 11
36
37
/* V7M CCR bits */
38
FIELD(V7M_CCR, NONBASETHRDENA, 0, 1)
39
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/arm-semi.c
42
+++ b/target/arm/arm-semi.c
43
@@ -XXX,XX +XXX,XX @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
44
#ifdef CONFIG_USER_ONLY
45
ts->swi_errno = err;
46
#else
47
-    syscall_err = err;
48
+ syscall_err = err;
49
#endif
50
reg0 = ret;
51
} else {
52
--
124
--
53
2.18.0
125
2.20.1
54
126
55
127
diff view generated by jsdifflib
1
Untabify the arm iwmmxt_helper.c. This affects only the iwMMXt code.
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
We've never touched that code in years, so it's not going to get
3
fixed up by our "change when touched" process, and a bulk change is
4
not going to be too disruptive.
5
2
6
This commit was produced using Emacs "untabify" (plus one
3
This adds two acceptance tests for the quanta-gsj machine.
7
by-hand removal of a space to fix a checkpatch nit); it is
8
a whitespace-only change.
9
4
5
One test downloads a lightly patched openbmc flash image from github and
6
verifies that it boots all the way to the login prompt.
7
8
The other test downloads a kernel, initrd and dtb built from the same
9
openbmc source and verifies that the kernel detects all CPUs and boots
10
to the point where it can't find the root filesystem (because we have no
11
flash image in this case).
12
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20200911052101.2602693-15-hskinnemoen@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20180821165215.29069-3-peter.maydell@linaro.org
12
---
18
---
13
target/arm/iwmmxt_helper.c | 234 ++++++++++++++++++-------------------
19
tests/acceptance/boot_linux_console.py | 83 ++++++++++++++++++++++++++
14
1 file changed, 117 insertions(+), 117 deletions(-)
20
1 file changed, 83 insertions(+)
15
21
16
diff --git a/target/arm/iwmmxt_helper.c b/target/arm/iwmmxt_helper.c
22
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/iwmmxt_helper.c
24
--- a/tests/acceptance/boot_linux_console.py
19
+++ b/target/arm/iwmmxt_helper.c
25
+++ b/tests/acceptance/boot_linux_console.py
20
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
21
/* iwMMXt macros extracted from GNU gdb. */
27
'sda')
22
28
# cubieboard's reboot is not functioning; omit reboot test.
23
/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations. */
29
24
-#define SIMD8_SET( v, n, b)    ((v != 0) << ((((b) + 1) * 4) + (n)))
30
+ def test_arm_quanta_gsj(self):
25
-#define SIMD16_SET(v, n, h)    ((v != 0) << ((((h) + 1) * 8) + (n)))
31
+ """
26
-#define SIMD32_SET(v, n, w)    ((v != 0) << ((((w) + 1) * 16) + (n)))
32
+ :avocado: tags=arch:arm
27
-#define SIMD64_SET(v, n)    ((v != 0) << (32 + (n)))
33
+ :avocado: tags=machine:quanta-gsj
28
+#define SIMD8_SET(v, n, b) ((v != 0) << ((((b) + 1) * 4) + (n)))
34
+ """
29
+#define SIMD16_SET(v, n, h) ((v != 0) << ((((h) + 1) * 8) + (n)))
35
+ # 25 MiB compressed, 32 MiB uncompressed.
30
+#define SIMD32_SET(v, n, w) ((v != 0) << ((((w) + 1) * 16) + (n)))
36
+ image_url = (
31
+#define SIMD64_SET(v, n) ((v != 0) << (32 + (n)))
37
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
32
/* Flags to pass as "n" above. */
38
+ '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
33
-#define SIMD_NBIT    -1
39
+ image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
34
-#define SIMD_ZBIT    -2
40
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
35
-#define SIMD_CBIT    -3
41
+ image_name = 'obmc.mtd'
36
-#define SIMD_VBIT    -4
42
+ image_path = os.path.join(self.workdir, image_name)
37
+#define SIMD_NBIT -1
43
+ archive.gzip_uncompress(image_path_gz, image_path)
38
+#define SIMD_ZBIT -2
44
+
39
+#define SIMD_CBIT -3
45
+ self.vm.set_console()
40
+#define SIMD_VBIT -4
46
+ drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
41
/* Various status bit macros. */
47
+ self.vm.add_args('-drive', drive_args)
42
-#define NBIT8(x)    ((x) & 0x80)
48
+ self.vm.launch()
43
-#define NBIT16(x)    ((x) & 0x8000)
49
+
44
-#define NBIT32(x)    ((x) & 0x80000000)
50
+ # Disable drivers and services that stall for a long time during boot,
45
-#define NBIT64(x)    ((x) & 0x8000000000000000ULL)
51
+ # to avoid running past the 90-second timeout. These may be removed
46
-#define ZBIT8(x)    (((x) & 0xff) == 0)
52
+ # as the corresponding device support is added.
47
-#define ZBIT16(x)    (((x) & 0xffff) == 0)
53
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
48
-#define ZBIT32(x)    (((x) & 0xffffffff) == 0)
54
+ 'console=${console} '
49
-#define ZBIT64(x)    (x == 0)
55
+ 'mem=${mem} '
50
+#define NBIT8(x) ((x) & 0x80)
56
+ 'initcall_blacklist=npcm_i2c_bus_driver_init '
51
+#define NBIT16(x) ((x) & 0x8000)
57
+ 'systemd.mask=systemd-random-seed.service '
52
+#define NBIT32(x) ((x) & 0x80000000)
58
+ 'systemd.mask=dropbearkey.service '
53
+#define NBIT64(x) ((x) & 0x8000000000000000ULL)
59
+ )
54
+#define ZBIT8(x) (((x) & 0xff) == 0)
60
+
55
+#define ZBIT16(x) (((x) & 0xffff) == 0)
61
+ self.wait_for_console_pattern('> BootBlock by Nuvoton')
56
+#define ZBIT32(x) (((x) & 0xffffffff) == 0)
62
+ self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
57
+#define ZBIT64(x) (x == 0)
63
+ self.wait_for_console_pattern('>Skip DDR init.')
58
/* Sign extension macros. */
64
+ self.wait_for_console_pattern('U-Boot ')
59
-#define EXTEND8H(a)    ((uint16_t) (int8_t) (a))
65
+ interrupt_interactive_console_until_pattern(
60
-#define EXTEND8(a)    ((uint32_t) (int8_t) (a))
66
+ self, 'Hit any key to stop autoboot:', 'U-Boot>')
61
-#define EXTEND16(a)    ((uint32_t) (int16_t) (a))
67
+ exec_command_and_wait_for_pattern(
62
-#define EXTEND16S(a)    ((int32_t) (int16_t) (a))
68
+ self, "setenv bootargs ${bootargs} " + kernel_command_line,
63
-#define EXTEND32(a)    ((uint64_t) (int32_t) (a))
69
+ 'U-Boot>')
64
+#define EXTEND8H(a) ((uint16_t) (int8_t) (a))
70
+ exec_command_and_wait_for_pattern(
65
+#define EXTEND8(a) ((uint32_t) (int8_t) (a))
71
+ self, 'run romboot', 'Booting Kernel from flash')
66
+#define EXTEND16(a) ((uint32_t) (int16_t) (a))
72
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
67
+#define EXTEND16S(a) ((int32_t) (int16_t) (a))
73
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
68
+#define EXTEND32(a) ((uint64_t) (int32_t) (a))
74
+ self.wait_for_console_pattern('OpenBMC Project Reference Distro')
69
75
+ self.wait_for_console_pattern('gsj login:')
70
uint64_t HELPER(iwmmxt_maddsq)(uint64_t a, uint64_t b)
76
+
71
{
77
+ def test_arm_quanta_gsj_initrd(self):
72
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(iwmmxt_macuw)(uint64_t a, uint64_t b)
78
+ """
73
#define NZBIT64(x) \
79
+ :avocado: tags=arch:arm
74
SIMD64_SET(NBIT64(x), SIMD_NBIT) | \
80
+ :avocado: tags=machine:quanta-gsj
75
SIMD64_SET(ZBIT64(x), SIMD_ZBIT)
81
+ """
76
-#define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3)            \
82
+ initrd_url = (
77
+#define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3) \
83
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
78
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUARMState *env, \
84
+ '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
79
uint64_t a, uint64_t b) \
85
+ initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
80
-{                                \
86
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
81
- a =                             \
87
+ kernel_url = (
82
- (((a >> SH0) & 0xff) << 0) | (((b >> SH0) & 0xff) << 8) |    \
88
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
83
- (((a >> SH1) & 0xff) << 16) | (((b >> SH1) & 0xff) << 24) |    \
89
+ '20200711-gsj-qemu-0/uImage-gsj.bin')
84
- (((a >> SH2) & 0xff) << 32) | (((b >> SH2) & 0xff) << 40) |    \
90
+ kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
85
- (((a >> SH3) & 0xff) << 48) | (((b >> SH3) & 0xff) << 56);    \
91
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
86
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
92
+ dtb_url = (
87
- NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) |         \
93
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
88
- NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) |        \
94
+ '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
89
- NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) |        \
95
+ dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
90
- NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);        \
96
+ dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
91
+{ \
97
+
92
+ a = \
98
+ self.vm.set_console()
93
+ (((a >> SH0) & 0xff) << 0) | (((b >> SH0) & 0xff) << 8) | \
99
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
94
+ (((a >> SH1) & 0xff) << 16) | (((b >> SH1) & 0xff) << 24) | \
100
+ 'console=ttyS0,115200n8 '
95
+ (((a >> SH2) & 0xff) << 32) | (((b >> SH2) & 0xff) << 40) | \
101
+ 'earlycon=uart8250,mmio32,0xf0001000')
96
+ (((a >> SH3) & 0xff) << 48) | (((b >> SH3) & 0xff) << 56); \
102
+ self.vm.add_args('-kernel', kernel_path,
97
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
103
+ '-initrd', initrd_path,
98
+ NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) | \
104
+ '-dtb', dtb_path,
99
+ NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) | \
105
+ '-append', kernel_command_line)
100
+ NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) | \
106
+ self.vm.launch()
101
+ NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7); \
107
+
102
return a; \
108
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
103
-}                                \
109
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
104
+} \
110
+ self.wait_for_console_pattern(
105
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUARMState *env, \
111
+ 'Give root password for system maintenance')
106
uint64_t a, uint64_t b) \
112
+
107
-{                                \
113
def test_arm_orangepi(self):
108
- a =                             \
114
"""
109
- (((a >> SH0) & 0xffff) << 0) |                \
115
:avocado: tags=arch:arm
110
- (((b >> SH0) & 0xffff) << 16) |             \
111
- (((a >> SH2) & 0xffff) << 32) |             \
112
- (((b >> SH2) & 0xffff) << 48);                \
113
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
114
- NZBIT8(a >> 0, 0) | NZBIT8(a >> 16, 1) |        \
115
- NZBIT8(a >> 32, 2) | NZBIT8(a >> 48, 3);        \
116
+{ \
117
+ a = \
118
+ (((a >> SH0) & 0xffff) << 0) | \
119
+ (((b >> SH0) & 0xffff) << 16) | \
120
+ (((a >> SH2) & 0xffff) << 32) | \
121
+ (((b >> SH2) & 0xffff) << 48); \
122
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
123
+ NZBIT8(a >> 0, 0) | NZBIT8(a >> 16, 1) | \
124
+ NZBIT8(a >> 32, 2) | NZBIT8(a >> 48, 3); \
125
return a; \
126
-}                                \
127
+} \
128
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUARMState *env, \
129
uint64_t a, uint64_t b) \
130
-{                                \
131
- a =                             \
132
- (((a >> SH0) & 0xffffffff) << 0) |            \
133
- (((b >> SH0) & 0xffffffff) << 32);            \
134
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
135
- NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1);        \
136
+{ \
137
+ a = \
138
+ (((a >> SH0) & 0xffffffff) << 0) | \
139
+ (((b >> SH0) & 0xffffffff) << 32); \
140
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
141
+ NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1); \
142
return a; \
143
-}                                \
144
+} \
145
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUARMState *env, \
146
uint64_t x) \
147
-{                                \
148
- x =                             \
149
- (((x >> SH0) & 0xff) << 0) |                \
150
- (((x >> SH1) & 0xff) << 16) |                \
151
- (((x >> SH2) & 0xff) << 32) |                \
152
- (((x >> SH3) & 0xff) << 48);                \
153
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
154
- NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) |        \
155
- NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);        \
156
+{ \
157
+ x = \
158
+ (((x >> SH0) & 0xff) << 0) | \
159
+ (((x >> SH1) & 0xff) << 16) | \
160
+ (((x >> SH2) & 0xff) << 32) | \
161
+ (((x >> SH3) & 0xff) << 48); \
162
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
163
+ NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) | \
164
+ NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3); \
165
return x; \
166
-}                                \
167
+} \
168
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUARMState *env, \
169
uint64_t x) \
170
-{                                \
171
- x =                             \
172
- (((x >> SH0) & 0xffff) << 0) |                \
173
- (((x >> SH2) & 0xffff) << 32);                \
174
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
175
- NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);        \
176
+{ \
177
+ x = \
178
+ (((x >> SH0) & 0xffff) << 0) | \
179
+ (((x >> SH2) & 0xffff) << 32); \
180
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
181
+ NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1); \
182
return x; \
183
-}                                \
184
+} \
185
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(CPUARMState *env, \
186
uint64_t x) \
187
-{                                \
188
- x = (((x >> SH0) & 0xffffffff) << 0);            \
189
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);    \
190
+{ \
191
+ x = (((x >> SH0) & 0xffffffff) << 0); \
192
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0); \
193
return x; \
194
-}                                \
195
+} \
196
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUARMState *env, \
197
uint64_t x) \
198
-{                                \
199
- x =                             \
200
- ((uint64_t) EXTEND8H((x >> SH0) & 0xff) << 0) |     \
201
- ((uint64_t) EXTEND8H((x >> SH1) & 0xff) << 16) |    \
202
- ((uint64_t) EXTEND8H((x >> SH2) & 0xff) << 32) |    \
203
- ((uint64_t) EXTEND8H((x >> SH3) & 0xff) << 48);     \
204
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
205
- NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) |        \
206
- NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);        \
207
+{ \
208
+ x = \
209
+ ((uint64_t) EXTEND8H((x >> SH0) & 0xff) << 0) | \
210
+ ((uint64_t) EXTEND8H((x >> SH1) & 0xff) << 16) | \
211
+ ((uint64_t) EXTEND8H((x >> SH2) & 0xff) << 32) | \
212
+ ((uint64_t) EXTEND8H((x >> SH3) & 0xff) << 48); \
213
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
214
+ NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) | \
215
+ NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3); \
216
return x; \
217
-}                                \
218
+} \
219
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUARMState *env, \
220
uint64_t x) \
221
-{                                \
222
- x =                             \
223
- ((uint64_t) EXTEND16((x >> SH0) & 0xffff) << 0) |    \
224
- ((uint64_t) EXTEND16((x >> SH2) & 0xffff) << 32);    \
225
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
226
- NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);        \
227
+{ \
228
+ x = \
229
+ ((uint64_t) EXTEND16((x >> SH0) & 0xffff) << 0) | \
230
+ ((uint64_t) EXTEND16((x >> SH2) & 0xffff) << 32); \
231
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
232
+ NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1); \
233
return x; \
234
-}                                \
235
+} \
236
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(CPUARMState *env, \
237
uint64_t x) \
238
-{                                \
239
- x = EXTEND32((x >> SH0) & 0xffffffff);            \
240
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);    \
241
+{ \
242
+ x = EXTEND32((x >> SH0) & 0xffffffff); \
243
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0); \
244
return x; \
245
}
246
IWMMXT_OP_UNPACK(l, 0, 8, 16, 24)
247
IWMMXT_OP_UNPACK(h, 32, 40, 48, 56)
248
249
-#define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O)            \
250
+#define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O) \
251
uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUARMState *env, \
252
uint64_t a, uint64_t b) \
253
-{                                \
254
- a =                             \
255
- CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) |        \
256
- CMP(16, Tb, O, 0xff) | CMP(24, Tb, O, 0xff) |        \
257
- CMP(32, Tb, O, 0xff) | CMP(40, Tb, O, 0xff) |        \
258
- CMP(48, Tb, O, 0xff) | CMP(56, Tb, O, 0xff);        \
259
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
260
- NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) |         \
261
- NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) |        \
262
- NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) |        \
263
- NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);        \
264
+{ \
265
+ a = \
266
+ CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) | \
267
+ CMP(16, Tb, O, 0xff) | CMP(24, Tb, O, 0xff) | \
268
+ CMP(32, Tb, O, 0xff) | CMP(40, Tb, O, 0xff) | \
269
+ CMP(48, Tb, O, 0xff) | CMP(56, Tb, O, 0xff); \
270
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
271
+ NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) | \
272
+ NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) | \
273
+ NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) | \
274
+ NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7); \
275
return a; \
276
-}                                \
277
+} \
278
uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUARMState *env, \
279
uint64_t a, uint64_t b) \
280
-{                                \
281
- a = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) |    \
282
- CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff);    \
283
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
284
- NZBIT16(a >> 0, 0) | NZBIT16(a >> 16, 1) |        \
285
- NZBIT16(a >> 32, 2) | NZBIT16(a >> 48, 3);        \
286
+{ \
287
+ a = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) | \
288
+ CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff); \
289
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
290
+ NZBIT16(a >> 0, 0) | NZBIT16(a >> 16, 1) | \
291
+ NZBIT16(a >> 32, 2) | NZBIT16(a >> 48, 3); \
292
return a; \
293
-}                                \
294
+} \
295
uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(CPUARMState *env, \
296
uint64_t a, uint64_t b) \
297
-{                                \
298
- a = CMP(0, Tl, O, 0xffffffff) |                \
299
- CMP(32, Tl, O, 0xffffffff);                \
300
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
301
- NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1);        \
302
+{ \
303
+ a = CMP(0, Tl, O, 0xffffffff) | \
304
+ CMP(32, Tl, O, 0xffffffff); \
305
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
306
+ NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1); \
307
return a; \
308
}
309
#define CMP(SHR, TYPE, OPER, MASK) ((((TYPE) ((a >> SHR) & MASK) OPER \
310
--
116
--
311
2.18.0
117
2.20.1
312
118
313
119
diff view generated by jsdifflib
1
The Arm Cortex-M System Design Kit includes a "dual-input timer module"
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
which combines two programmable down-counters. Implement a model
3
of this device.
4
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
4
implementation. Bus connection and socketCAN connection for each CAN module
5
can be set through command lines.
6
7
Example for using single CAN:
8
-object can-bus,id=canbus0 \
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
24
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Message-id: 1597278668-339715-2-git-send-email-fnu.vikram@xilinx.com
26
[PMM: updated to meson build system]
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-4-peter.maydell@linaro.org
8
---
28
---
9
hw/timer/Makefile.objs | 1 +
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
10
include/hw/timer/cmsdk-apb-dualtimer.h | 72 ++++
30
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++
11
hw/timer/cmsdk-apb-dualtimer.c | 515 +++++++++++++++++++++++++
31
hw/net/can/meson.build | 1 +
12
MAINTAINERS | 2 +
32
3 files changed, 1244 insertions(+)
13
default-configs/arm-softmmu.mak | 1 +
33
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
14
hw/timer/trace-events | 5 +
34
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
15
6 files changed, 596 insertions(+)
16
create mode 100644 include/hw/timer/cmsdk-apb-dualtimer.h
17
create mode 100644 hw/timer/cmsdk-apb-dualtimer.c
18
35
19
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
36
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/timer/Makefile.objs
22
+++ b/hw/timer/Makefile.objs
23
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
24
25
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
26
common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
27
+common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) += cmsdk-apb-dualtimer.o
28
common-obj-$(CONFIG_MSF2) += mss-timer.o
29
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
30
new file mode 100644
37
new file mode 100644
31
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
32
--- /dev/null
39
--- /dev/null
33
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
40
+++ b/include/hw/net/xlnx-zynqmp-can.h
34
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
35
+/*
42
+/*
36
+ * ARM CMSDK APB dual-timer emulation
43
+ * QEMU model of the Xilinx ZynqMP CAN controller.
37
+ *
44
+ *
38
+ * Copyright (c) 2018 Linaro Limited
45
+ * Copyright (c) 2020 Xilinx Inc.
39
+ * Written by Peter Maydell
40
+ *
46
+ *
41
+ * This program is free software; you can redistribute it and/or modify
47
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
42
+ * it under the terms of the GNU General Public License version 2 or
48
+ *
43
+ * (at your option) any later version.
49
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
50
+ * Pavel Pisa.
51
+ *
52
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
53
+ * of this software and associated documentation files (the "Software"), to deal
54
+ * in the Software without restriction, including without limitation the rights
55
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
+ * copies of the Software, and to permit persons to whom the Software is
57
+ * furnished to do so, subject to the following conditions:
58
+ *
59
+ * The above copyright notice and this permission notice shall be included in
60
+ * all copies or substantial portions of the Software.
61
+ *
62
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68
+ * THE SOFTWARE.
44
+ */
69
+ */
45
+
70
+
46
+/*
71
+#ifndef XLNX_ZYNQMP_CAN_H
47
+ * This is a model of the "APB dual-input timer" which is part of the Cortex-M
72
+#define XLNX_ZYNQMP_CAN_H
48
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
73
+
49
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
74
+#include "hw/register.h"
50
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
75
+#include "net/can_emu.h"
51
+ *
76
+#include "net/can_host.h"
52
+ * QEMU interface:
77
+#include "qemu/fifo32.h"
53
+ * + QOM property "pclk-frq": frequency at which the timer is clocked
54
+ * + sysbus MMIO region 0: the register bank
55
+ * + sysbus IRQ 0: combined timer interrupt TIMINTC
56
+ * + sysbus IRO 1: timer block 1 interrupt TIMINT1
57
+ * + sysbus IRQ 2: timer block 2 interrupt TIMINT2
58
+ */
59
+
60
+#ifndef CMSDK_APB_DUALTIMER_H
61
+#define CMSDK_APB_DUALTIMER_H
62
+
63
+#include "hw/sysbus.h"
64
+#include "hw/ptimer.h"
78
+#include "hw/ptimer.h"
65
+
79
+#include "hw/qdev-clock.h"
66
+#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
80
+
67
+#define CMSDK_APB_DUALTIMER(obj) OBJECT_CHECK(CMSDKAPBDualTimer, (obj), \
81
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
68
+ TYPE_CMSDK_APB_DUALTIMER)
82
+
69
+
83
+#define XLNX_ZYNQMP_CAN(obj) \
70
+typedef struct CMSDKAPBDualTimer CMSDKAPBDualTimer;
84
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
71
+
85
+
72
+/* One of the two identical timer modules in the dual-timer module */
86
+#define MAX_CAN_CTRLS 2
73
+typedef struct CMSDKAPBDualTimerModule {
87
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
74
+ CMSDKAPBDualTimer *parent;
88
+#define MAILBOX_CAPACITY 64
75
+ struct ptimer_state *timer;
89
+#define CAN_TIMER_MAX 0XFFFFUL
76
+ qemu_irq timerint;
90
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
77
+ /*
91
+
78
+ * We must track the guest LOAD and VALUE register state by hand
92
+/* Each CAN_FRAME will have 4 * 32bit size. */
79
+ * rather than leaving this state only in the ptimer limit/count,
93
+#define CAN_FRAME_SIZE 4
80
+ * because if CONTROL.SIZE is 0 then only the low 16 bits of the
94
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
81
+ * counter actually counts, but the high half is still guest
95
+
82
+ * accessible.
96
+typedef struct XlnxZynqMPCANState {
83
+ */
97
+ SysBusDevice parent_obj;
84
+ uint32_t load;
98
+ MemoryRegion iomem;
85
+ uint32_t value;
99
+
86
+ uint32_t control;
100
+ qemu_irq irq;
87
+ uint32_t intstatus;
101
+
88
+} CMSDKAPBDualTimerModule;
102
+ CanBusClientState bus_client;
89
+
103
+ CanBusState *canbus;
90
+#define CMSDK_APB_DUALTIMER_NUM_MODULES 2
104
+
91
+
105
+ struct {
92
+struct CMSDKAPBDualTimer {
106
+ uint32_t ext_clk_freq;
93
+ /*< private >*/
107
+ } cfg;
94
+ SysBusDevice parent_obj;
108
+
95
+
109
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
96
+ /*< public >*/
110
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
97
+ MemoryRegion iomem;
111
+
98
+ qemu_irq timerintc;
112
+ Fifo32 rx_fifo;
99
+ uint32_t pclk_frq;
113
+ Fifo32 tx_fifo;
100
+
114
+ Fifo32 txhpb_fifo;
101
+ CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
115
+
102
+ uint32_t timeritcr;
116
+ ptimer_state *can_timer;
103
+ uint32_t timeritop;
117
+} XlnxZynqMPCANState;
104
+};
105
+
118
+
106
+#endif
119
+#endif
107
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
120
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
108
new file mode 100644
121
new file mode 100644
109
index XXXXXXX..XXXXXXX
122
index XXXXXXX..XXXXXXX
110
--- /dev/null
123
--- /dev/null
111
+++ b/hw/timer/cmsdk-apb-dualtimer.c
124
+++ b/hw/net/can/xlnx-zynqmp-can.c
112
@@ -XXX,XX +XXX,XX @@
125
@@ -XXX,XX +XXX,XX @@
113
+/*
126
+/*
114
+ * ARM CMSDK APB dual-timer emulation
127
+ * QEMU model of the Xilinx ZynqMP CAN controller.
128
+ * This implementation is based on the following datasheet:
129
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
115
+ *
130
+ *
116
+ * Copyright (c) 2018 Linaro Limited
131
+ * Copyright (c) 2020 Xilinx Inc.
117
+ * Written by Peter Maydell
118
+ *
132
+ *
119
+ * This program is free software; you can redistribute it and/or modify
133
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
120
+ * it under the terms of the GNU General Public License version 2 or
134
+ *
121
+ * (at your option) any later version.
135
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
136
+ * Pavel Pisa
137
+ *
138
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
139
+ * of this software and associated documentation files (the "Software"), to deal
140
+ * in the Software without restriction, including without limitation the rights
141
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
142
+ * copies of the Software, and to permit persons to whom the Software is
143
+ * furnished to do so, subject to the following conditions:
144
+ *
145
+ * The above copyright notice and this permission notice shall be included in
146
+ * all copies or substantial portions of the Software.
147
+ *
148
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
149
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
151
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
153
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
154
+ * THE SOFTWARE.
122
+ */
155
+ */
123
+
156
+
124
+/*
125
+ * This is a model of the "APB dual-input timer" which is part of the Cortex-M
126
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
127
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
128
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
129
+ */
130
+
131
+#include "qemu/osdep.h"
157
+#include "qemu/osdep.h"
158
+#include "hw/sysbus.h"
159
+#include "hw/register.h"
160
+#include "hw/irq.h"
161
+#include "qapi/error.h"
162
+#include "qemu/bitops.h"
132
+#include "qemu/log.h"
163
+#include "qemu/log.h"
133
+#include "trace.h"
164
+#include "qemu/cutils.h"
134
+#include "qapi/error.h"
165
+#include "sysemu/sysemu.h"
135
+#include "qemu/main-loop.h"
166
+#include "migration/vmstate.h"
136
+#include "hw/sysbus.h"
167
+#include "hw/qdev-properties.h"
137
+#include "hw/registerfields.h"
168
+#include "net/can_emu.h"
138
+#include "hw/timer/cmsdk-apb-dualtimer.h"
169
+#include "net/can_host.h"
139
+
170
+#include "qemu/event_notifier.h"
140
+REG32(TIMER1LOAD, 0x0)
171
+#include "qom/object_interfaces.h"
141
+REG32(TIMER1VALUE, 0x4)
172
+#include "hw/net/xlnx-zynqmp-can.h"
142
+REG32(TIMER1CONTROL, 0x8)
173
+
143
+ FIELD(CONTROL, ONESHOT, 0, 1)
174
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
144
+ FIELD(CONTROL, SIZE, 1, 1)
175
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
145
+ FIELD(CONTROL, PRESCALE, 2, 2)
176
+#endif
146
+ FIELD(CONTROL, INTEN, 5, 1)
177
+
147
+ FIELD(CONTROL, MODE, 6, 1)
178
+#define DB_PRINT(dev, ...) do { \
148
+ FIELD(CONTROL, ENABLE, 7, 1)
179
+ if (XLNX_ZYNQMP_CAN_ERR_DEBUG) { \
149
+#define R_CONTROL_VALID_MASK (R_CONTROL_ONESHOT_MASK | R_CONTROL_SIZE_MASK | \
180
+ g_autofree char *path = object_get_canonical_path(OBJECT(dev)); \
150
+ R_CONTROL_PRESCALE_MASK | R_CONTROL_INTEN_MASK | \
181
+ qemu_log("%s: %s", path, ## __VA_ARGS__); \
151
+ R_CONTROL_MODE_MASK | R_CONTROL_ENABLE_MASK)
182
+ } \
152
+REG32(TIMER1INTCLR, 0xc)
183
+} while (0)
153
+REG32(TIMER1RIS, 0x10)
184
+
154
+REG32(TIMER1MIS, 0x14)
185
+#define MAX_DLC 8
155
+REG32(TIMER1BGLOAD, 0x18)
186
+#undef ERROR
156
+REG32(TIMER2LOAD, 0x20)
187
+
157
+REG32(TIMER2VALUE, 0x24)
188
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
158
+REG32(TIMER2CONTROL, 0x28)
189
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
159
+REG32(TIMER2INTCLR, 0x2c)
190
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
160
+REG32(TIMER2RIS, 0x30)
191
+REG32(MODE_SELECT_REGISTER, 0x4)
161
+REG32(TIMER2MIS, 0x34)
192
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
162
+REG32(TIMER2BGLOAD, 0x38)
193
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
163
+REG32(TIMERITCR, 0xf00)
194
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
164
+ FIELD(TIMERITCR, ENABLE, 0, 1)
195
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
165
+#define R_TIMERITCR_VALID_MASK R_TIMERITCR_ENABLE_MASK
196
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
166
+REG32(TIMERITOP, 0xf04)
197
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
167
+ FIELD(TIMERITOP, TIMINT1, 0, 1)
198
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
168
+ FIELD(TIMERITOP, TIMINT2, 1, 1)
199
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
169
+#define R_TIMERITOP_VALID_MASK (R_TIMERITOP_TIMINT1_MASK | \
200
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
170
+ R_TIMERITOP_TIMINT2_MASK)
201
+REG32(ERROR_COUNTER_REGISTER, 0x10)
171
+REG32(PID4, 0xfd0)
202
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
172
+REG32(PID5, 0xfd4)
203
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
173
+REG32(PID6, 0xfd8)
204
+REG32(ERROR_STATUS_REGISTER, 0x14)
174
+REG32(PID7, 0xfdc)
205
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
175
+REG32(PID0, 0xfe0)
206
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
176
+REG32(PID1, 0xfe4)
207
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
177
+REG32(PID2, 0xfe8)
208
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
178
+REG32(PID3, 0xfec)
209
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
179
+REG32(CID0, 0xff0)
210
+REG32(STATUS_REGISTER, 0x18)
180
+REG32(CID1, 0xff4)
211
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
181
+REG32(CID2, 0xff8)
212
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
182
+REG32(CID3, 0xffc)
213
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
183
+
214
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
184
+/* PID/CID values */
215
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
185
+static const int timer_id[] = {
216
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
186
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
217
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
187
+ 0x23, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
218
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
188
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
219
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
189
+};
220
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
190
+
221
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
191
+static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m)
222
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
192
+{
223
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
193
+ /* Return masked interrupt status for the timer module */
224
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
194
+ return m->intstatus && (m->control & R_CONTROL_INTEN_MASK);
225
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
195
+}
226
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
196
+
227
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
197
+static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
228
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
198
+{
229
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
199
+ bool timint1, timint2, timintc;
230
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
200
+
231
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
201
+ if (s->timeritcr) {
232
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
202
+ /* Integration test mode: outputs driven directly from TIMERITOP bits */
233
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
203
+ timint1 = s->timeritop & R_TIMERITOP_TIMINT1_MASK;
234
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
204
+ timint2 = s->timeritop & R_TIMERITOP_TIMINT2_MASK;
235
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
236
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
237
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
238
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
239
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
240
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
241
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
242
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
243
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
244
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
245
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
246
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
247
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
248
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
249
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
250
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
251
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
252
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
253
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
254
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
255
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
256
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
257
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
258
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
259
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
260
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
261
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
262
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
263
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
264
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
265
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
266
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
267
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
268
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
269
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
270
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
271
+REG32(TIMESTAMP_REGISTER, 0x28)
272
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
273
+REG32(WIR, 0x2c)
274
+ FIELD(WIR, EW, 8, 8)
275
+ FIELD(WIR, FW, 0, 8)
276
+REG32(TXFIFO_ID, 0x30)
277
+ FIELD(TXFIFO_ID, IDH, 21, 11)
278
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
279
+ FIELD(TXFIFO_ID, IDE, 19, 1)
280
+ FIELD(TXFIFO_ID, IDL, 1, 18)
281
+ FIELD(TXFIFO_ID, RTR, 0, 1)
282
+REG32(TXFIFO_DLC, 0x34)
283
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
284
+REG32(TXFIFO_DATA1, 0x38)
285
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
286
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
287
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
288
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
289
+REG32(TXFIFO_DATA2, 0x3c)
290
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
291
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
292
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
293
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
294
+REG32(TXHPB_ID, 0x40)
295
+ FIELD(TXHPB_ID, IDH, 21, 11)
296
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
297
+ FIELD(TXHPB_ID, IDE, 19, 1)
298
+ FIELD(TXHPB_ID, IDL, 1, 18)
299
+ FIELD(TXHPB_ID, RTR, 0, 1)
300
+REG32(TXHPB_DLC, 0x44)
301
+ FIELD(TXHPB_DLC, DLC, 28, 4)
302
+REG32(TXHPB_DATA1, 0x48)
303
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
304
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
305
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
306
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
307
+REG32(TXHPB_DATA2, 0x4c)
308
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
309
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
310
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
311
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
312
+REG32(RXFIFO_ID, 0x50)
313
+ FIELD(RXFIFO_ID, IDH, 21, 11)
314
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
315
+ FIELD(RXFIFO_ID, IDE, 19, 1)
316
+ FIELD(RXFIFO_ID, IDL, 1, 18)
317
+ FIELD(RXFIFO_ID, RTR, 0, 1)
318
+REG32(RXFIFO_DLC, 0x54)
319
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
320
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
321
+REG32(RXFIFO_DATA1, 0x58)
322
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
323
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
324
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
325
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
326
+REG32(RXFIFO_DATA2, 0x5c)
327
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
328
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
329
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
330
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
331
+REG32(AFR, 0x60)
332
+ FIELD(AFR, UAF4, 3, 1)
333
+ FIELD(AFR, UAF3, 2, 1)
334
+ FIELD(AFR, UAF2, 1, 1)
335
+ FIELD(AFR, UAF1, 0, 1)
336
+REG32(AFMR1, 0x64)
337
+ FIELD(AFMR1, AMIDH, 21, 11)
338
+ FIELD(AFMR1, AMSRR, 20, 1)
339
+ FIELD(AFMR1, AMIDE, 19, 1)
340
+ FIELD(AFMR1, AMIDL, 1, 18)
341
+ FIELD(AFMR1, AMRTR, 0, 1)
342
+REG32(AFIR1, 0x68)
343
+ FIELD(AFIR1, AIIDH, 21, 11)
344
+ FIELD(AFIR1, AISRR, 20, 1)
345
+ FIELD(AFIR1, AIIDE, 19, 1)
346
+ FIELD(AFIR1, AIIDL, 1, 18)
347
+ FIELD(AFIR1, AIRTR, 0, 1)
348
+REG32(AFMR2, 0x6c)
349
+ FIELD(AFMR2, AMIDH, 21, 11)
350
+ FIELD(AFMR2, AMSRR, 20, 1)
351
+ FIELD(AFMR2, AMIDE, 19, 1)
352
+ FIELD(AFMR2, AMIDL, 1, 18)
353
+ FIELD(AFMR2, AMRTR, 0, 1)
354
+REG32(AFIR2, 0x70)
355
+ FIELD(AFIR2, AIIDH, 21, 11)
356
+ FIELD(AFIR2, AISRR, 20, 1)
357
+ FIELD(AFIR2, AIIDE, 19, 1)
358
+ FIELD(AFIR2, AIIDL, 1, 18)
359
+ FIELD(AFIR2, AIRTR, 0, 1)
360
+REG32(AFMR3, 0x74)
361
+ FIELD(AFMR3, AMIDH, 21, 11)
362
+ FIELD(AFMR3, AMSRR, 20, 1)
363
+ FIELD(AFMR3, AMIDE, 19, 1)
364
+ FIELD(AFMR3, AMIDL, 1, 18)
365
+ FIELD(AFMR3, AMRTR, 0, 1)
366
+REG32(AFIR3, 0x78)
367
+ FIELD(AFIR3, AIIDH, 21, 11)
368
+ FIELD(AFIR3, AISRR, 20, 1)
369
+ FIELD(AFIR3, AIIDE, 19, 1)
370
+ FIELD(AFIR3, AIIDL, 1, 18)
371
+ FIELD(AFIR3, AIRTR, 0, 1)
372
+REG32(AFMR4, 0x7c)
373
+ FIELD(AFMR4, AMIDH, 21, 11)
374
+ FIELD(AFMR4, AMSRR, 20, 1)
375
+ FIELD(AFMR4, AMIDE, 19, 1)
376
+ FIELD(AFMR4, AMIDL, 1, 18)
377
+ FIELD(AFMR4, AMRTR, 0, 1)
378
+REG32(AFIR4, 0x80)
379
+ FIELD(AFIR4, AIIDH, 21, 11)
380
+ FIELD(AFIR4, AISRR, 20, 1)
381
+ FIELD(AFIR4, AIIDE, 19, 1)
382
+ FIELD(AFIR4, AIIDL, 1, 18)
383
+ FIELD(AFIR4, AIRTR, 0, 1)
384
+
385
+static void can_update_irq(XlnxZynqMPCANState *s)
386
+{
387
+ uint32_t irq;
388
+
389
+ /* Watermark register interrupts. */
390
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
391
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
392
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
393
+ }
394
+
395
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
396
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
397
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
398
+ }
399
+
400
+ /* RX Interrupts. */
401
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
402
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
403
+ }
404
+
405
+ /* TX interrupts. */
406
+ if (fifo32_is_empty(&s->tx_fifo)) {
407
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
408
+ }
409
+
410
+ if (fifo32_is_full(&s->tx_fifo)) {
411
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
412
+ }
413
+
414
+ if (fifo32_is_full(&s->txhpb_fifo)) {
415
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
416
+ }
417
+
418
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
419
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
420
+
421
+ qemu_set_irq(s->irq, irq);
422
+}
423
+
424
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val64)
425
+{
426
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
427
+
428
+ can_update_irq(s);
429
+}
430
+
431
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val64)
432
+{
433
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
434
+ uint32_t val = val64;
435
+
436
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
437
+ can_update_irq(s);
438
+
439
+ return 0;
440
+}
441
+
442
+static void can_config_reset(XlnxZynqMPCANState *s)
443
+{
444
+ /* Reset all the configuration registers. */
445
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
446
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
447
+ register_reset(
448
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
449
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
450
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
451
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
452
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
453
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
454
+ register_reset(&s->reg_info[R_WIR]);
455
+}
456
+
457
+static void can_config_mode(XlnxZynqMPCANState *s)
458
+{
459
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
460
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
461
+
462
+ /* Put XlnxZynqMPCAN in configuration mode. */
463
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
464
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
465
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
466
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
467
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
468
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
469
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
470
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
471
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
472
+
473
+ can_update_irq(s);
474
+}
475
+
476
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
477
+{
478
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
479
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
480
+ /* Wake up interrupt bit. */
481
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
482
+ /* Sleep interrupt bit. */
483
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
484
+
485
+ /* Clear previous core mode status bits. */
486
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
487
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
488
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
489
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
490
+
491
+ /* set current mode bit and generate irqs accordingly. */
492
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
493
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
494
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
495
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
496
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
497
+ sleep_irq_val);
498
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
499
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
205
+ } else {
500
+ } else {
206
+ timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]);
501
+ /*
207
+ timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]);
502
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
208
+ }
503
+ */
209
+
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
210
+ timintc = timint1 || timint2;
505
+ /* Set wakeup interrupt bit. */
211
+
506
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
212
+ qemu_set_irq(s->timermod[0].timerint, timint1);
507
+ wakeup_irq_val);
213
+ qemu_set_irq(s->timermod[1].timerint, timint2);
508
+ }
214
+ qemu_set_irq(s->timerintc, timintc);
509
+
215
+}
510
+ can_update_irq(s);
216
+
511
+}
217
+static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
512
+
218
+ uint32_t newctrl)
513
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
219
+{
514
+{
220
+ /* Handle a write to the CONTROL register */
515
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
221
+ uint32_t changed;
516
+ update_status_register_mode_bits(s);
222
+
517
+}
223
+ newctrl &= R_CONTROL_VALID_MASK;
518
+
224
+
519
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
225
+ changed = m->control ^ newctrl;
520
+{
226
+
521
+ frame->can_id = data[0];
227
+ if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) {
522
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
228
+ /* ENABLE cleared, stop timer before any further changes */
523
+
229
+ ptimer_stop(m->timer);
524
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
230
+ }
525
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
231
+
526
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
232
+ if (changed & R_CONTROL_PRESCALE_MASK) {
527
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
233
+ int divisor;
528
+
234
+
529
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
235
+ switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) {
530
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
236
+ case 0:
531
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
237
+ divisor = 1;
532
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
238
+ break;
533
+}
239
+ case 1:
534
+
240
+ divisor = 16;
535
+static bool tx_ready_check(XlnxZynqMPCANState *s)
241
+ break;
536
+{
242
+ case 2:
537
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
243
+ divisor = 256;
538
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
244
+ break;
539
+
245
+ case 3:
540
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
246
+ /* UNDEFINED; complain, and arbitrarily treat like 2 */
541
+ " data while controller is in reset mode.\n",
247
+ qemu_log_mask(LOG_GUEST_ERROR,
542
+ path);
248
+ "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11"
543
+ return false;
249
+ " is undefined behaviour\n");
544
+ }
250
+ divisor = 256;
545
+
251
+ break;
546
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
252
+ default:
547
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
253
+ g_assert_not_reached();
548
+
254
+ }
549
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
255
+ ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
550
+ " data while controller is in configuration mode. Reset"
256
+ }
551
+ " the core so operations can start fresh.\n",
257
+
552
+ path);
258
+ if (changed & R_CONTROL_MODE_MASK) {
553
+ return false;
259
+ uint32_t load;
554
+ }
260
+ if (newctrl & R_CONTROL_MODE_MASK) {
555
+
261
+ /* Periodic: the limit is the LOAD register value */
556
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
262
+ load = m->load;
557
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
263
+ } else {
558
+
264
+ /* Free-running: counter wraps around */
559
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
265
+ load = ptimer_get_limit(m->timer);
560
+ " data while controller is in SNOOP MODE.\n",
266
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
561
+ path);
267
+ load = deposit32(m->load, 0, 16, load);
562
+ return false;
563
+ }
564
+
565
+ return true;
566
+}
567
+
568
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
569
+{
570
+ qemu_can_frame frame;
571
+ uint32_t data[CAN_FRAME_SIZE];
572
+ int i;
573
+ bool can_tx = tx_ready_check(s);
574
+
575
+ if (can_tx) {
576
+ while (!fifo32_is_empty(fifo)) {
577
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
578
+ data[i] = fifo32_pop(fifo);
268
+ }
579
+ }
269
+ m->load = load;
580
+
270
+ load = 0xffffffff;
581
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
271
+ }
582
+ /*
272
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
583
+ * Controller is in loopback. In Loopback mode, the CAN core
273
+ load &= 0xffff;
584
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
274
+ }
585
+ * Any message transmitted is looped back to the RX line and
275
+ ptimer_set_limit(m->timer, load, 0);
586
+ * acknowledged. The XlnxZynqMPCAN core receives any message
276
+ }
587
+ * that it transmits.
277
+
588
+ */
278
+ if (changed & R_CONTROL_SIZE_MASK) {
589
+ if (fifo32_is_full(&s->rx_fifo)) {
279
+ /* Timer switched between 16 and 32 bit count */
590
+ DB_PRINT(s, "Loopback: RX FIFO is full."
280
+ uint32_t value, load;
591
+ " TX FIFO will be flushed.\n");
281
+
592
+
282
+ value = ptimer_get_count(m->timer);
593
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
283
+ load = ptimer_get_limit(m->timer);
594
+ RXOFLW, 1);
284
+ if (newctrl & R_CONTROL_SIZE_MASK) {
595
+ } else {
285
+ /* 16 -> 32, top half of VALUE is in struct field */
596
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
286
+ value = deposit32(m->value, 0, 16, value);
597
+ fifo32_push(&s->rx_fifo, data[i]);
287
+ } else {
598
+ }
288
+ /* 32 -> 16: save top half to struct field and truncate */
599
+
289
+ m->value = value;
600
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
290
+ value &= 0xffff;
601
+ RXOK, 1);
291
+ }
602
+ }
292
+
293
+ if (newctrl & R_CONTROL_MODE_MASK) {
294
+ /* Periodic, timer limit has LOAD value */
295
+ if (newctrl & R_CONTROL_SIZE_MASK) {
296
+ load = deposit32(m->load, 0, 16, load);
297
+ } else {
603
+ } else {
298
+ m->load = load;
604
+ /* Normal mode Tx. */
299
+ load &= 0xffff;
605
+ generate_frame(&frame, data);
300
+ }
606
+
301
+ } else {
607
+ can_bus_client_send(&s->bus_client, &frame, 1);
302
+ /* Free-running, timer limit is set to give wraparound */
303
+ if (newctrl & R_CONTROL_SIZE_MASK) {
304
+ load = 0xffffffff;
305
+ } else {
306
+ load = 0xffff;
307
+ }
608
+ }
308
+ }
609
+ }
309
+ ptimer_set_count(m->timer, value);
610
+
310
+ ptimer_set_limit(m->timer, load, 0);
611
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
311
+ }
612
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
312
+
613
+
313
+ if (newctrl & R_CONTROL_ENABLE_MASK) {
614
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
314
+ /*
615
+ can_exit_sleep_mode(s);
315
+ * ENABLE is set; start the timer after all other changes.
316
+ * We start it even if the ENABLE bit didn't actually change,
317
+ * in case the timer was an expired one-shot timer that has
318
+ * now been changed into a free-running or periodic timer.
319
+ */
320
+ ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK));
321
+ }
322
+
323
+ m->control = newctrl;
324
+}
325
+
326
+static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
327
+ unsigned size)
328
+{
329
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
330
+ uint64_t r;
331
+
332
+ if (offset >= A_TIMERITCR) {
333
+ switch (offset) {
334
+ case A_TIMERITCR:
335
+ r = s->timeritcr;
336
+ break;
337
+ case A_PID4 ... A_CID3:
338
+ r = timer_id[(offset - A_PID4) / 4];
339
+ break;
340
+ default:
341
+ bad_offset:
342
+ qemu_log_mask(LOG_GUEST_ERROR,
343
+ "CMSDK APB dual-timer read: bad offset %x\n",
344
+ (int) offset);
345
+ r = 0;
346
+ break;
347
+ }
616
+ }
348
+ } else {
617
+ } else {
349
+ int timer = offset >> 5;
618
+ DB_PRINT(s, "Not enabled for data transfer.\n");
350
+ CMSDKAPBDualTimerModule *m;
619
+ }
351
+
620
+
352
+ if (timer >= ARRAY_SIZE(s->timermod)) {
621
+ can_update_irq(s);
353
+ goto bad_offset;
622
+}
623
+
624
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val64)
625
+{
626
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
627
+ uint32_t val = val64;
628
+
629
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
630
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
631
+
632
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
633
+ DB_PRINT(s, "Resetting controller.\n");
634
+
635
+ /* First, core will do software reset then will enter in config mode. */
636
+ can_config_reset(s);
637
+ }
638
+
639
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
640
+ can_config_mode(s);
641
+ } else {
642
+ /*
643
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
644
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
645
+ * register states.
646
+ */
647
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
648
+
649
+ ptimer_transaction_begin(s->can_timer);
650
+ ptimer_set_count(s->can_timer, 0);
651
+ ptimer_transaction_commit(s->can_timer);
652
+
653
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
654
+ transfer_fifo(s, &s->txhpb_fifo);
655
+ transfer_fifo(s, &s->tx_fifo);
656
+ }
657
+
658
+ update_status_register_mode_bits(s);
659
+
660
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
661
+}
662
+
663
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val64)
664
+{
665
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
666
+ uint32_t val = val64;
667
+ uint8_t multi_mode;
668
+
669
+ /*
670
+ * Multiple mode set check. This is done to make sure user doesn't set
671
+ * multiple modes.
672
+ */
673
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
674
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
675
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
676
+
677
+ if (multi_mode > 1) {
678
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
679
+
680
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
681
+ " several modes simultaneously. One mode will be selected"
682
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
683
+ path);
684
+ }
685
+
686
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
687
+ /* We are in configuration mode, any mode can be selected. */
688
+ s->regs[R_MODE_SELECT_REGISTER] = val;
689
+ } else {
690
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
691
+
692
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
693
+
694
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
695
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
696
+
697
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
698
+ " LBACK mode without setting CEN bit as 0.\n",
699
+ path);
700
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
701
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
702
+
703
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
704
+ " SNOOP mode without setting CEN bit as 0.\n",
705
+ path);
354
+ }
706
+ }
355
+
707
+
356
+ m = &s->timermod[timer];
708
+ update_status_register_mode_bits(s);
357
+
709
+ }
358
+ switch (offset & 0x1F) {
710
+
359
+ case A_TIMER1LOAD:
711
+ return s->regs[R_MODE_SELECT_REGISTER];
360
+ case A_TIMER1BGLOAD:
712
+}
361
+ if (m->control & R_CONTROL_MODE_MASK) {
713
+
362
+ /*
714
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val64)
363
+ * Periodic: the ptimer limit is the LOAD register value, (or
715
+{
364
+ * just the low 16 bits of it if the timer is in 16-bit mode)
716
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
365
+ */
717
+ uint32_t val = val64;
366
+ r = ptimer_get_limit(m->timer);
718
+
367
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
719
+ /* Only allow writes when in config mode. */
368
+ r = deposit32(m->load, 0, 16, r);
720
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
369
+ }
721
+ val = s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
370
+ } else {
722
+ }
371
+ /* Free-running: LOAD register value is just in m->load */
723
+
372
+ r = m->load;
724
+ return val;
373
+ }
725
+}
374
+ break;
726
+
375
+ case A_TIMER1VALUE:
727
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val64)
376
+ r = ptimer_get_count(m->timer);
728
+{
377
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
729
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
378
+ r = deposit32(m->value, 0, 16, r);
730
+ uint32_t val = val64;
379
+ }
731
+
380
+ break;
732
+ /* Only allow writes when in config mode. */
381
+ case A_TIMER1CONTROL:
733
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
382
+ r = m->control;
734
+ val = s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
383
+ break;
735
+ }
384
+ case A_TIMER1RIS:
736
+
385
+ r = m->intstatus;
737
+ return val;
386
+ break;
738
+}
387
+ case A_TIMER1MIS:
739
+
388
+ r = cmsdk_dualtimermod_intstatus(m);
740
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val64)
389
+ break;
741
+{
390
+ default:
742
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
391
+ goto bad_offset;
743
+ uint32_t val = val64;
744
+
745
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
746
+ ptimer_transaction_begin(s->can_timer);
747
+ ptimer_set_count(s->can_timer, 0);
748
+ ptimer_transaction_commit(s->can_timer);
749
+ }
750
+
751
+ return 0;
752
+}
753
+
754
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
755
+{
756
+ bool filter_pass = false;
757
+ uint16_t timestamp = 0;
758
+
759
+ /* If no filter is enabled. Message will be stored in FIFO. */
760
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
761
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
762
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
763
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
764
+ filter_pass = true;
765
+ }
766
+
767
+ /*
768
+ * Messages that pass any of the acceptance filters will be stored in
769
+ * the RX FIFO.
770
+ */
771
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
772
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
773
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
774
+
775
+ if (filter_id_masked == id_masked) {
776
+ filter_pass = true;
392
+ }
777
+ }
393
+ }
778
+ }
394
+
779
+
395
+ trace_cmsdk_apb_dualtimer_read(offset, r, size);
780
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
781
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
782
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
783
+
784
+ if (filter_id_masked == id_masked) {
785
+ filter_pass = true;
786
+ }
787
+ }
788
+
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
790
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
799
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ /* Store the message in fifo if it passed through any of the filters. */
808
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
809
+
810
+ if (fifo32_is_full(&s->rx_fifo)) {
811
+ DB_PRINT(s, "RX FIFO is full.\n");
812
+
813
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
814
+ } else {
815
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
816
+
817
+ fifo32_push(&s->rx_fifo, frame->can_id);
818
+
819
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
820
+ R_RXFIFO_DLC_DLC_LENGTH,
821
+ frame->can_dlc) |
822
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
823
+ R_RXFIFO_DLC_RXT_LENGTH,
824
+ timestamp));
825
+
826
+ /* First 32 bit of the data. */
827
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
828
+ R_TXFIFO_DATA1_DB3_LENGTH,
829
+ frame->data[0]) |
830
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
831
+ R_TXFIFO_DATA1_DB2_LENGTH,
832
+ frame->data[1]) |
833
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
834
+ R_TXFIFO_DATA1_DB1_LENGTH,
835
+ frame->data[2]) |
836
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
837
+ R_TXFIFO_DATA1_DB0_LENGTH,
838
+ frame->data[3]));
839
+ /* Last 32 bit of the data. */
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
841
+ R_TXFIFO_DATA2_DB7_LENGTH,
842
+ frame->data[4]) |
843
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
844
+ R_TXFIFO_DATA2_DB6_LENGTH,
845
+ frame->data[5]) |
846
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
847
+ R_TXFIFO_DATA2_DB5_LENGTH,
848
+ frame->data[6]) |
849
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
850
+ R_TXFIFO_DATA2_DB4_LENGTH,
851
+ frame->data[7]));
852
+
853
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
854
+ }
855
+
856
+ can_update_irq(s);
857
+ } else {
858
+ DB_PRINT(s, "Message didn't pass through any filter or dlc"
859
+ " is not in range.\n");
860
+ }
861
+}
862
+
863
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val64)
864
+{
865
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
866
+ uint32_t r = 0;
867
+
868
+ if (!fifo32_is_empty(&s->rx_fifo)) {
869
+ r = fifo32_pop(&s->rx_fifo);
870
+ } else {
871
+ DB_PRINT(s, "No message in RXFIFO.\n");
872
+
873
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
874
+ }
875
+
876
+ can_update_irq(s);
396
+ return r;
877
+ return r;
397
+}
878
+}
398
+
879
+
399
+static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
880
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val64)
400
+ uint64_t value, unsigned size)
881
+{
401
+{
882
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
402
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
883
+
403
+
884
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
404
+ trace_cmsdk_apb_dualtimer_write(offset, value, size);
885
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
405
+
886
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
406
+ if (offset >= A_TIMERITCR) {
887
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
407
+ switch (offset) {
888
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
408
+ case A_TIMERITCR:
889
+ } else {
409
+ s->timeritcr = value & R_TIMERITCR_VALID_MASK;
890
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
410
+ cmsdk_apb_dualtimer_update(s);
891
+ }
411
+ case A_TIMERITOP:
892
+}
412
+ s->timeritop = value & R_TIMERITOP_VALID_MASK;
893
+
413
+ cmsdk_apb_dualtimer_update(s);
894
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val64)
414
+ default:
895
+{
415
+ bad_offset:
896
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
416
+ qemu_log_mask(LOG_GUEST_ERROR,
897
+ uint32_t reg_idx = (reg->access->addr) / 4;
417
+ "CMSDK APB dual-timer write: bad offset %x\n",
898
+ uint32_t val = val64;
418
+ (int) offset);
899
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
419
+ break;
900
+
901
+ /* modify an acceptance filter, the corresponding UAF bit should be '0.' */
902
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
903
+ s->regs[reg_idx] = val;
904
+ } else {
905
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
906
+
907
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
908
+ " mask is not set as corresponding UAF bit is not 0.\n",
909
+ path, filter_number + 1);
910
+ }
911
+
912
+ return s->regs[reg_idx];
913
+}
914
+
915
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val64)
916
+{
917
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
918
+ uint32_t reg_idx = (reg->access->addr) / 4;
919
+ uint32_t val = val64;
920
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
921
+
922
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
923
+ s->regs[reg_idx] = val;
924
+ } else {
925
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
926
+
927
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
928
+ " id is not set as corresponding UAF bit is not 0.\n",
929
+ path, filter_number + 1);
930
+ }
931
+
932
+ return s->regs[reg_idx];
933
+}
934
+
935
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val64)
936
+{
937
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
938
+ uint32_t val = val64;
939
+
940
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
941
+
942
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
943
+ (reg->access->addr == A_TXHPB_DATA2);
944
+
945
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
946
+
947
+ DB_PRINT(s, "TX FIFO write.\n");
948
+
949
+ if (!fifo32_is_full(f)) {
950
+ fifo32_push(f, val);
951
+ } else {
952
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
953
+
954
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
955
+ }
956
+
957
+ /* Initiate the message send if TX register is written. */
958
+ if (initiate_transfer &&
959
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
960
+ transfer_fifo(s, f);
961
+ }
962
+
963
+ can_update_irq(s);
964
+}
965
+
966
+static const RegisterAccessInfo can_regs_info[] = {
967
+ { .name = "SOFTWARE_RESET_REGISTER",
968
+ .addr = A_SOFTWARE_RESET_REGISTER,
969
+ .rsvd = 0xfffffffc,
970
+ .pre_write = can_srr_pre_write,
971
+ },{ .name = "MODE_SELECT_REGISTER",
972
+ .addr = A_MODE_SELECT_REGISTER,
973
+ .rsvd = 0xfffffff8,
974
+ .pre_write = can_msr_pre_write,
975
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
976
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
977
+ .rsvd = 0xffffff00,
978
+ .pre_write = can_brpr_pre_write,
979
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
980
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
981
+ .rsvd = 0xfffffe00,
982
+ .pre_write = can_btr_pre_write,
983
+ },{ .name = "ERROR_COUNTER_REGISTER",
984
+ .addr = A_ERROR_COUNTER_REGISTER,
985
+ .rsvd = 0xffff0000,
986
+ .ro = 0xffffffff,
987
+ },{ .name = "ERROR_STATUS_REGISTER",
988
+ .addr = A_ERROR_STATUS_REGISTER,
989
+ .rsvd = 0xffffffe0,
990
+ .w1c = 0x1f,
991
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
992
+ .reset = 0x1,
993
+ .rsvd = 0xffffe000,
994
+ .ro = 0x1fff,
995
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
996
+ .addr = A_INTERRUPT_STATUS_REGISTER,
997
+ .reset = 0x6000,
998
+ .rsvd = 0xffff8000,
999
+ .ro = 0x7fff,
1000
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1001
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1002
+ .rsvd = 0xffff8000,
1003
+ .post_write = can_ier_post_write,
1004
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1005
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1006
+ .rsvd = 0xffff8000,
1007
+ .pre_write = can_icr_pre_write,
1008
+ },{ .name = "TIMESTAMP_REGISTER",
1009
+ .addr = A_TIMESTAMP_REGISTER,
1010
+ .rsvd = 0xfffffffe,
1011
+ .pre_write = can_tcr_pre_write,
1012
+ },{ .name = "WIR", .addr = A_WIR,
1013
+ .reset = 0x3f3f,
1014
+ .rsvd = 0xffff0000,
1015
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1016
+ .post_write = can_tx_post_write,
1017
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1018
+ .rsvd = 0xfffffff,
1019
+ .post_write = can_tx_post_write,
1020
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1021
+ .post_write = can_tx_post_write,
1022
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1023
+ .post_write = can_tx_post_write,
1024
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1025
+ .post_write = can_tx_post_write,
1026
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1027
+ .rsvd = 0xfffffff,
1028
+ .post_write = can_tx_post_write,
1029
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1030
+ .post_write = can_tx_post_write,
1031
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1032
+ .post_write = can_tx_post_write,
1033
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1034
+ .ro = 0xffffffff,
1035
+ .post_read = can_rxfifo_pre_read,
1036
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1037
+ .rsvd = 0xfff0000,
1038
+ .post_read = can_rxfifo_pre_read,
1039
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1040
+ .post_read = can_rxfifo_pre_read,
1041
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1042
+ .post_read = can_rxfifo_pre_read,
1043
+ },{ .name = "AFR", .addr = A_AFR,
1044
+ .rsvd = 0xfffffff0,
1045
+ .post_write = can_filter_enable_post_write,
1046
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1047
+ .pre_write = can_filter_mask_pre_write,
1048
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1049
+ .pre_write = can_filter_id_pre_write,
1050
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1051
+ .pre_write = can_filter_mask_pre_write,
1052
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1053
+ .pre_write = can_filter_id_pre_write,
1054
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1055
+ .pre_write = can_filter_mask_pre_write,
1056
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1057
+ .pre_write = can_filter_id_pre_write,
1058
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1059
+ .pre_write = can_filter_mask_pre_write,
1060
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1061
+ .pre_write = can_filter_id_pre_write,
1062
+ }
1063
+};
1064
+
1065
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1066
+{
1067
+ /* No action required on the timer rollover. */
1068
+}
1069
+
1070
+static const MemoryRegionOps can_ops = {
1071
+ .read = register_read_memory,
1072
+ .write = register_write_memory,
1073
+ .endianness = DEVICE_LITTLE_ENDIAN,
1074
+ .valid = {
1075
+ .min_access_size = 4,
1076
+ .max_access_size = 4,
1077
+ },
1078
+};
1079
+
1080
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1081
+{
1082
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1083
+ unsigned int i;
1084
+
1085
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1086
+ register_reset(&s->reg_info[i]);
1087
+ }
1088
+
1089
+ ptimer_transaction_begin(s->can_timer);
1090
+ ptimer_set_count(s->can_timer, 0);
1091
+ ptimer_transaction_commit(s->can_timer);
1092
+}
1093
+
1094
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1095
+{
1096
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1097
+ unsigned int i;
1098
+
1099
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1100
+ register_reset(&s->reg_info[i]);
1101
+ }
1102
+
1103
+ /*
1104
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1105
+ * done by post_write which gets called from register_reset function,
1106
+ * post_write handle will not be able to trigger tx because CAN will be
1107
+ * disabled when software_reset_register is cleared first.
1108
+ */
1109
+ fifo32_reset(&s->rx_fifo);
1110
+ fifo32_reset(&s->tx_fifo);
1111
+ fifo32_reset(&s->txhpb_fifo);
1112
+}
1113
+
1114
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1115
+{
1116
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1117
+ bus_client);
1118
+
1119
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1120
+ DB_PRINT(s, "Controller is in reset.\n");
1121
+ return false;
1122
+ } else if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1123
+ DB_PRINT(s, "Controller is disabled. Incoming messages"
1124
+ " will be discarded.\n");
1125
+ return false;
1126
+ } else {
1127
+ return true;
1128
+ }
1129
+}
1130
+
1131
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1132
+ const qemu_can_frame *buf, size_t buf_size) {
1133
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1134
+ bus_client);
1135
+ const qemu_can_frame *frame = buf;
1136
+
1137
+ DB_PRINT(s, "Incoming data.\n");
1138
+
1139
+ if (buf_size <= 0) {
1140
+ DB_PRINT(s, "Junk data received.\n");
1141
+ return 0;
1142
+ }
1143
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
1144
+ /*
1145
+ * XlnxZynqMPCAN will not participate in normal bus communication
1146
+ * and will not receive any messages transmitted by other CAN nodes.
1147
+ */
1148
+ DB_PRINT(s, "Controller is in loopback mode. It will not"
1149
+ " receive data.\n");
1150
+
1151
+ } else if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1152
+ /* Snoop Mode: Just keep the data. no response back. */
1153
+ update_rx_fifo(s, frame);
1154
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1155
+ /*
1156
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1157
+ * up state.
1158
+ */
1159
+ can_exit_sleep_mode(s);
1160
+ update_rx_fifo(s, frame);
1161
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1162
+ update_rx_fifo(s, frame);
1163
+ } else {
1164
+ DB_PRINT(s, "Cannot receive data as controller is not configured"
1165
+ " correctly.\n");
1166
+ }
1167
+
1168
+ return 1;
1169
+}
1170
+
1171
+static CanBusClientInfo can_xilinx_bus_client_info = {
1172
+ .can_receive = xlnx_zynqmp_can_can_receive,
1173
+ .receive = xlnx_zynqmp_can_receive,
1174
+};
1175
+
1176
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1177
+ CanBusState *bus)
1178
+{
1179
+ s->bus_client.info = &can_xilinx_bus_client_info;
1180
+
1181
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1182
+ return -1;
1183
+ }
1184
+ return 0;
1185
+}
1186
+
1187
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1188
+{
1189
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1190
+
1191
+ if (s->canbus) {
1192
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1193
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1194
+
1195
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1196
+ " failed.", path);
1197
+ return;
420
+ }
1198
+ }
1199
+
421
+ } else {
1200
+ } else {
422
+ int timer = offset >> 5;
1201
+ /* If no bus is set. */
423
+ CMSDKAPBDualTimerModule *m;
1202
+ DB_PRINT(s, "Canbus property is not set.\n");
424
+
1203
+ }
425
+ if (timer >= ARRAY_SIZE(s->timermod)) {
1204
+
426
+ goto bad_offset;
1205
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
427
+ }
1206
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
428
+
1207
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
429
+ m = &s->timermod[timer];
1208
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
430
+
1209
+
431
+ switch (offset & 0x1F) {
1210
+ /* Allocate a new timer. */
432
+ case A_TIMER1LOAD:
1211
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
433
+ /* Set the limit, and immediately reload the count from it */
1212
+ PTIMER_POLICY_DEFAULT);
434
+ m->load = value;
1213
+
435
+ m->value = value;
1214
+ ptimer_transaction_begin(s->can_timer);
436
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
1215
+
437
+ value &= 0xffff;
1216
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
438
+ }
1217
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
439
+ if (!(m->control & R_CONTROL_MODE_MASK)) {
1218
+ ptimer_run(s->can_timer, 0);
440
+ /*
1219
+ ptimer_transaction_commit(s->can_timer);
441
+ * In free-running mode this won't set the limit but will
1220
+}
442
+ * still change the current count value.
1221
+
443
+ */
1222
+static void xlnx_zynqmp_can_init(Object *obj)
444
+ ptimer_set_count(m->timer, value);
1223
+{
445
+ } else {
1224
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
446
+ if (!value) {
447
+ ptimer_stop(m->timer);
448
+ }
449
+ ptimer_set_limit(m->timer, value, 1);
450
+ if (value && (m->control & R_CONTROL_ENABLE_MASK)) {
451
+ /* Force possibly-expired oneshot timer to restart */
452
+ ptimer_run(m->timer, 1);
453
+ }
454
+ }
455
+ break;
456
+ case A_TIMER1BGLOAD:
457
+ /* Set the limit, but not the current count */
458
+ m->load = value;
459
+ if (!(m->control & R_CONTROL_MODE_MASK)) {
460
+ /* In free-running mode there is no limit */
461
+ break;
462
+ }
463
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
464
+ value &= 0xffff;
465
+ }
466
+ ptimer_set_limit(m->timer, value, 0);
467
+ break;
468
+ case A_TIMER1CONTROL:
469
+ cmsdk_dualtimermod_write_control(m, value);
470
+ cmsdk_apb_dualtimer_update(s);
471
+ break;
472
+ case A_TIMER1INTCLR:
473
+ m->intstatus = 0;
474
+ cmsdk_apb_dualtimer_update(s);
475
+ break;
476
+ default:
477
+ goto bad_offset;
478
+ }
479
+ }
480
+}
481
+
482
+static const MemoryRegionOps cmsdk_apb_dualtimer_ops = {
483
+ .read = cmsdk_apb_dualtimer_read,
484
+ .write = cmsdk_apb_dualtimer_write,
485
+ .endianness = DEVICE_LITTLE_ENDIAN,
486
+ /* byte/halfword accesses are just zero-padded on reads and writes */
487
+ .impl.min_access_size = 4,
488
+ .impl.max_access_size = 4,
489
+ .valid.min_access_size = 1,
490
+ .valid.max_access_size = 4,
491
+};
492
+
493
+static void cmsdk_dualtimermod_tick(void *opaque)
494
+{
495
+ CMSDKAPBDualTimerModule *m = opaque;
496
+
497
+ m->intstatus = 1;
498
+ cmsdk_apb_dualtimer_update(m->parent);
499
+}
500
+
501
+static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
502
+{
503
+ m->control = R_CONTROL_INTEN_MASK;
504
+ m->intstatus = 0;
505
+ m->load = 0;
506
+ m->value = 0xffffffff;
507
+ ptimer_stop(m->timer);
508
+ /*
509
+ * We start in free-running mode, with VALUE at 0xffffffff, and
510
+ * in 16-bit counter mode. This means that the ptimer count and
511
+ * limit must both be set to 0xffff, so we wrap at 16 bits.
512
+ */
513
+ ptimer_set_limit(m->timer, 0xffff, 1);
514
+ ptimer_set_freq(m->timer, m->parent->pclk_frq);
515
+}
516
+
517
+static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
518
+{
519
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
520
+ int i;
521
+
522
+ trace_cmsdk_apb_dualtimer_reset();
523
+
524
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
525
+ cmsdk_dualtimermod_reset(&s->timermod[i]);
526
+ }
527
+ s->timeritcr = 0;
528
+ s->timeritop = 0;
529
+}
530
+
531
+static void cmsdk_apb_dualtimer_init(Object *obj)
532
+{
533
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1225
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
534
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj);
1226
+
535
+ int i;
1227
+ RegisterInfoArray *reg_array;
536
+
1228
+
537
+ memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops,
1229
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
538
+ s, "cmsdk-apb-dualtimer", 0x1000);
1230
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1231
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1232
+ ARRAY_SIZE(can_regs_info),
1233
+ s->reg_info, s->regs,
1234
+ &can_ops,
1235
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1236
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1237
+
1238
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
539
+ sysbus_init_mmio(sbd, &s->iomem);
1239
+ sysbus_init_mmio(sbd, &s->iomem);
540
+ sysbus_init_irq(sbd, &s->timerintc);
1240
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
541
+
1241
+}
542
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
1242
+
543
+ sysbus_init_irq(sbd, &s->timermod[i].timerint);
1243
+static const VMStateDescription vmstate_can = {
544
+ }
1244
+ .name = TYPE_XLNX_ZYNQMP_CAN,
545
+}
546
+
547
+static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
548
+{
549
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
550
+ int i;
551
+
552
+ if (s->pclk_frq == 0) {
553
+ error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
554
+ return;
555
+ }
556
+
557
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
558
+ CMSDKAPBDualTimerModule *m = &s->timermod[i];
559
+ QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m);
560
+
561
+ m->parent = s;
562
+ m->timer = ptimer_init(bh,
563
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
564
+ PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
565
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
566
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
567
+ }
568
+}
569
+
570
+static const VMStateDescription cmsdk_dualtimermod_vmstate = {
571
+ .name = "cmsdk-apb-dualtimer-module",
572
+ .version_id = 1,
1245
+ .version_id = 1,
573
+ .minimum_version_id = 1,
1246
+ .minimum_version_id = 1,
574
+ .fields = (VMStateField[]) {
1247
+ .fields = (VMStateField[]) {
575
+ VMSTATE_PTIMER(timer, CMSDKAPBDualTimerModule),
1248
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
576
+ VMSTATE_UINT32(load, CMSDKAPBDualTimerModule),
1249
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
577
+ VMSTATE_UINT32(value, CMSDKAPBDualTimerModule),
1250
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
578
+ VMSTATE_UINT32(control, CMSDKAPBDualTimerModule),
1251
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
579
+ VMSTATE_UINT32(intstatus, CMSDKAPBDualTimerModule),
1252
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
580
+ VMSTATE_END_OF_LIST()
1253
+ VMSTATE_END_OF_LIST(),
581
+ }
1254
+ }
582
+};
1255
+};
583
+
1256
+
584
+static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
1257
+static Property xlnx_zynqmp_can_properties[] = {
585
+ .name = "cmsdk-apb-dualtimer",
1258
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
586
+ .version_id = 1,
1259
+ CAN_DEFAULT_CLOCK),
587
+ .minimum_version_id = 1,
1260
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
588
+ .fields = (VMStateField[]) {
1261
+ CanBusState *),
589
+ VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
590
+ CMSDK_APB_DUALTIMER_NUM_MODULES,
591
+ 1, cmsdk_dualtimermod_vmstate,
592
+ CMSDKAPBDualTimerModule),
593
+ VMSTATE_UINT32(timeritcr, CMSDKAPBDualTimer),
594
+ VMSTATE_UINT32(timeritop, CMSDKAPBDualTimer),
595
+ VMSTATE_END_OF_LIST()
596
+ }
597
+};
598
+
599
+static Property cmsdk_apb_dualtimer_properties[] = {
600
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
601
+ DEFINE_PROP_END_OF_LIST(),
1262
+ DEFINE_PROP_END_OF_LIST(),
602
+};
1263
+};
603
+
1264
+
604
+static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
1265
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
605
+{
1266
+{
606
+ DeviceClass *dc = DEVICE_CLASS(klass);
1267
+ DeviceClass *dc = DEVICE_CLASS(klass);
607
+
1268
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
608
+ dc->realize = cmsdk_apb_dualtimer_realize;
1269
+
609
+ dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
1270
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
610
+ dc->reset = cmsdk_apb_dualtimer_reset;
1271
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
611
+ dc->props = cmsdk_apb_dualtimer_properties;
1272
+ dc->realize = xlnx_zynqmp_can_realize;
612
+}
1273
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
613
+
1274
+ dc->vmsd = &vmstate_can;
614
+static const TypeInfo cmsdk_apb_dualtimer_info = {
1275
+}
615
+ .name = TYPE_CMSDK_APB_DUALTIMER,
1276
+
616
+ .parent = TYPE_SYS_BUS_DEVICE,
1277
+static const TypeInfo can_info = {
617
+ .instance_size = sizeof(CMSDKAPBDualTimer),
1278
+ .name = TYPE_XLNX_ZYNQMP_CAN,
618
+ .instance_init = cmsdk_apb_dualtimer_init,
1279
+ .parent = TYPE_SYS_BUS_DEVICE,
619
+ .class_init = cmsdk_apb_dualtimer_class_init,
1280
+ .instance_size = sizeof(XlnxZynqMPCANState),
1281
+ .class_init = xlnx_zynqmp_can_class_init,
1282
+ .instance_init = xlnx_zynqmp_can_init,
620
+};
1283
+};
621
+
1284
+
622
+static void cmsdk_apb_dualtimer_register_types(void)
1285
+static void can_register_types(void)
623
+{
1286
+{
624
+ type_register_static(&cmsdk_apb_dualtimer_info);
1287
+ type_register_static(&can_info);
625
+}
1288
+}
626
+
1289
+
627
+type_init(cmsdk_apb_dualtimer_register_types);
1290
+type_init(can_register_types)
628
diff --git a/MAINTAINERS b/MAINTAINERS
1291
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
629
index XXXXXXX..XXXXXXX 100644
1292
index XXXXXXX..XXXXXXX 100644
630
--- a/MAINTAINERS
1293
--- a/hw/net/can/meson.build
631
+++ b/MAINTAINERS
1294
+++ b/hw/net/can/meson.build
632
@@ -XXX,XX +XXX,XX @@ F: hw/timer/pl031.c
1295
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_SJA1000', if_true: files('can_sja1000.c'))
633
F: include/hw/arm/primecell.h
1296
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_kvaser_pci.c'))
634
F: hw/timer/cmsdk-apb-timer.c
1297
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
635
F: include/hw/timer/cmsdk-apb-timer.h
1298
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
636
+F: hw/timer/cmsdk-apb-dualtimer.c
1299
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
637
+F: include/hw/timer/cmsdk-apb-dualtimer.h
638
F: hw/char/cmsdk-apb-uart.c
639
F: include/hw/char/cmsdk-apb-uart.h
640
F: hw/watchdog/cmsdk-apb-watchdog.c
641
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
642
index XXXXXXX..XXXXXXX 100644
643
--- a/default-configs/arm-softmmu.mak
644
+++ b/default-configs/arm-softmmu.mak
645
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F2XX_SPI=y
646
CONFIG_STM32F205_SOC=y
647
648
CONFIG_CMSDK_APB_TIMER=y
649
+CONFIG_CMSDK_APB_DUALTIMER=y
650
CONFIG_CMSDK_APB_UART=y
651
CONFIG_CMSDK_APB_WATCHDOG=y
652
653
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
654
index XXXXXXX..XXXXXXX 100644
655
--- a/hw/timer/trace-events
656
+++ b/hw/timer/trace-events
657
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB t
658
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
659
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
660
661
+# hw/timer/cmsdk_apb_dualtimer.c
662
+cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
663
+cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
664
+cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
665
+
666
# hw/timer/xlnx-zynqmp-rtc.c
667
xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
668
--
1300
--
669
2.18.0
1301
2.20.1
670
1302
671
1303
diff view generated by jsdifflib
1
The MPS2 FPGAIO block includes some simple free-running counters.
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
Implement these.
3
2
3
Connect CAN0 and CAN1 on the ZynqMP.
4
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Message-id: 1597278668-339715-3-git-send-email-fnu.vikram@xilinx.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180820141116.9118-2-peter.maydell@linaro.org
7
---
10
---
8
include/hw/misc/mps2-fpgaio.h | 4 +++
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
9
hw/misc/mps2-fpgaio.c | 53 ++++++++++++++++++++++++++++++++++-
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
10
2 files changed, 56 insertions(+), 1 deletion(-)
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
3 files changed, 62 insertions(+)
11
15
12
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/misc/mps2-fpgaio.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
15
+++ b/include/hw/misc/mps2-fpgaio.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
20
@@ -XXX,XX +XXX,XX @@
17
uint32_t misc;
21
#include "hw/intc/arm_gic.h"
18
22
#include "hw/net/cadence_gem.h"
19
uint32_t prescale_clk;
23
#include "hw/char/cadence_uart.h"
24
+#include "hw/net/xlnx-zynqmp-can.h"
25
#include "hw/ide/ahci.h"
26
#include "hw/sd/sdhci.h"
27
#include "hw/ssi/xilinx_spips.h"
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/cpu/cluster.h"
30
#include "target/arm/cpu.h"
31
#include "qom/object.h"
32
+#include "net/can_emu.h"
33
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
35
typedef struct XlnxZynqMPState XlnxZynqMPState;
36
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(XlnxZynqMPState, XLNX_ZYNQMP,
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
38
#define XLNX_ZYNQMP_NUM_GEMS 4
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
20
+
57
+
21
+ /* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
58
+ /* CAN bus. */
22
+ int64_t clk1hz_tick_offset;
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
23
+ int64_t clk100hz_tick_offset;
60
};
24
} MPS2FPGAIO;
25
61
26
#endif
62
#endif
27
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
28
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/misc/mps2-fpgaio.c
65
--- a/hw/arm/xlnx-zcu102.c
30
+++ b/hw/misc/mps2-fpgaio.c
66
+++ b/hw/arm/xlnx-zcu102.c
31
@@ -XXX,XX +XXX,XX @@
67
@@ -XXX,XX +XXX,XX @@
32
#include "hw/sysbus.h"
68
#include "sysemu/qtest.h"
33
#include "hw/registerfields.h"
69
#include "sysemu/device_tree.h"
34
#include "hw/misc/mps2-fpgaio.h"
70
#include "qom/object.h"
35
+#include "qemu/timer.h"
71
+#include "net/can_emu.h"
36
72
37
REG32(LED0, 0)
73
struct XlnxZCU102 {
38
REG32(BUTTON, 8)
74
MachineState parent_obj;
39
@@ -XXX,XX +XXX,XX @@ REG32(PRESCALE, 0x1c)
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
40
REG32(PSCNTR, 0x20)
76
bool secure;
41
REG32(MISC, 0x4c)
77
bool virt;
42
78
43
+static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq)
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
44
+{
45
+ return muldiv64(now - tick_offset, frq, NANOSECONDS_PER_SECOND);
46
+}
47
+
80
+
48
+static int64_t tickoff_from_counter(int64_t now, uint32_t count, int frq)
81
struct arm_boot_info binfo;
49
+{
82
};
50
+ return now - muldiv64(count, NANOSECONDS_PER_SECOND, frq);
83
typedef struct XlnxZCU102 XlnxZCU102;
51
+}
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
86
&error_fatal);
87
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
52
+
90
+
53
static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
54
{
92
+ OBJECT(s->canbus[i]), &error_fatal);
55
MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
93
+ g_free(bus_name);
56
uint64_t r;
94
+ }
57
+ int64_t now;
95
+
58
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
59
switch (offset) {
97
60
case A_LED0:
98
/* Create and plug in the SD cards */
61
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
62
r = s->misc;
100
"Set on/off to enable/disable emulating a "
63
break;
101
"guest CPU which implements the ARM "
64
case A_CLK1HZ:
102
"Virtualization Extensions");
65
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
66
+ r = counter_from_tickoff(now, s->clk1hz_tick_offset, 1);
104
+ (Object **)&s->canbus[0],
67
+ break;
105
+ object_property_allow_set_link,
68
case A_CLK100HZ:
106
+ 0);
69
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
107
+
70
+ r = counter_from_tickoff(now, s->clk100hz_tick_offset, 100);
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
71
+ break;
109
+ (Object **)&s->canbus[1],
72
case A_COUNTER:
110
+ object_property_allow_set_link,
73
case A_PSCNTR:
111
+ 0);
74
- /* These are all upcounters of various frequencies. */
75
qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
76
r = 0;
77
break;
78
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
82
+ int64_t now;
83
84
trace_mps2_fpgaio_write(offset, value, size);
85
86
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
87
"MPS2 FPGAIO: MISC control bits unimplemented\n");
88
s->misc = value;
89
break;
90
+ case A_CLK1HZ:
91
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
92
+ s->clk1hz_tick_offset = tickoff_from_counter(now, value, 1);
93
+ break;
94
+ case A_CLK100HZ:
95
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
96
+ s->clk100hz_tick_offset = tickoff_from_counter(now, value, 100);
97
+ break;
98
default:
99
qemu_log_mask(LOG_GUEST_ERROR,
100
"MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
101
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps mps2_fpgaio_ops = {
102
static void mps2_fpgaio_reset(DeviceState *dev)
103
{
104
MPS2FPGAIO *s = MPS2_FPGAIO(dev);
105
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
106
107
trace_mps2_fpgaio_reset();
108
s->led0 = 0;
109
s->prescale = 0;
110
s->misc = 0;
111
+ s->clk1hz_tick_offset = tickoff_from_counter(now, 0, 1);
112
+ s->clk100hz_tick_offset = tickoff_from_counter(now, 0, 100);
113
}
112
}
114
113
115
static void mps2_fpgaio_init(Object *obj)
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
116
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_init(Object *obj)
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
117
sysbus_init_mmio(sbd, &s->iomem);
116
index XXXXXXX..XXXXXXX 100644
118
}
117
--- a/hw/arm/xlnx-zynqmp.c
119
118
+++ b/hw/arm/xlnx-zynqmp.c
120
+static bool mps2_fpgaio_counters_needed(void *opaque)
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
121
+{
120
21, 22,
122
+ /* Currently vmstate.c insists all subsections have a 'needed' function */
121
};
123
+ return true;
122
124
+}
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
125
+
124
+ 0xFF060000, 0xFF070000,
126
+static const VMStateDescription mps2_fpgaio_counters_vmstate = {
127
+ .name = "mps2-fpgaio/counters",
128
+ .version_id = 1,
129
+ .minimum_version_id = 1,
130
+ .needed = mps2_fpgaio_counters_needed,
131
+ .fields = (VMStateField[]) {
132
+ VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
133
+ VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
134
+ VMSTATE_END_OF_LIST()
135
+ }
136
+};
125
+};
137
+
126
+
138
static const VMStateDescription mps2_fpgaio_vmstate = {
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
139
.name = "mps2-fpgaio",
128
+ 23, 24,
140
.version_id = 1,
129
+};
141
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_fpgaio_vmstate = {
130
+
142
VMSTATE_UINT32(prescale, MPS2FPGAIO),
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
143
VMSTATE_UINT32(misc, MPS2FPGAIO),
132
0xFF160000, 0xFF170000,
144
VMSTATE_END_OF_LIST()
133
};
145
+ },
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
146
+ .subsections = (const VMStateDescription*[]) {
135
TYPE_CADENCE_UART);
147
+ &mps2_fpgaio_counters_vmstate,
148
+ NULL
149
}
136
}
137
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
140
+ TYPE_XLNX_ZYNQMP_CAN);
141
+ }
142
+
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
144
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
147
gic_spi[uart_intr[i]]);
148
}
149
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
153
+
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
155
+ OBJECT(s->canbus[i]), &error_fatal);
156
+
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
158
+ if (err) {
159
+ error_propagate(errp, err);
160
+ return;
161
+ }
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
164
+ gic_spi[can_intr[i]]);
165
+ }
166
+
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
168
&error_abort);
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
150
};
179
};
151
180
152
--
181
--
153
2.18.0
182
2.20.1
154
183
155
184
diff view generated by jsdifflib
Deleted patch
1
Now we have a model of the CMSDK dual timer, we can wire it
2
up in the IoTKit.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-5-peter.maydell@linaro.org
8
---
9
include/hw/arm/iotkit.h | 3 ++-
10
hw/arm/iotkit.c | 8 +++++---
11
2 files changed, 7 insertions(+), 4 deletions(-)
12
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/iotkit.h
16
+++ b/include/hw/arm/iotkit.h
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/misc/tz-ppc.h"
19
#include "hw/misc/tz-mpc.h"
20
#include "hw/timer/cmsdk-apb-timer.h"
21
+#include "hw/timer/cmsdk-apb-dualtimer.h"
22
#include "hw/misc/unimp.h"
23
#include "hw/or-irq.h"
24
#include "hw/core/split-irq.h"
25
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
26
SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
27
qemu_or_irq mpc_irq_orgate;
28
29
- UnimplementedDeviceState dualtimer;
30
+ CMSDKAPBDualTimer dualtimer;
31
UnimplementedDeviceState s32ktimer;
32
33
MemoryRegion container;
34
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/iotkit.c
37
+++ b/hw/arm/iotkit.c
38
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
39
sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
40
TYPE_CMSDK_APB_TIMER);
41
sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
42
- TYPE_UNIMPLEMENTED_DEVICE);
43
+ TYPE_CMSDK_APB_DUALTIMER);
44
object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
45
sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
46
&error_abort, NULL);
47
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
48
return;
49
}
50
51
- qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
52
- qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
53
+
54
+ qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
55
object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
56
if (err) {
57
error_propagate(errp, err);
58
return;
59
}
60
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
61
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 5));
62
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
63
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
64
if (err) {
65
--
66
2.18.0
67
68
diff view generated by jsdifflib
Deleted patch
1
The IoTKit has a CMSDK timer device that runs on the S32KCLK.
2
Create this and wire it up.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-8-peter.maydell@linaro.org
8
---
9
include/hw/arm/iotkit.h | 2 +-
10
hw/arm/iotkit.c | 9 +++++----
11
2 files changed, 6 insertions(+), 5 deletions(-)
12
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/iotkit.h
16
+++ b/include/hw/arm/iotkit.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
18
TZMPC mpc;
19
CMSDKAPBTIMER timer0;
20
CMSDKAPBTIMER timer1;
21
+ CMSDKAPBTIMER s32ktimer;
22
qemu_or_irq ppc_irq_orgate;
23
SplitIRQ sec_resp_splitter;
24
SplitIRQ ppc_irq_splitter[NUM_PPCS];
25
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
26
qemu_or_irq nmi_orgate;
27
28
CMSDKAPBDualTimer dualtimer;
29
- UnimplementedDeviceState s32ktimer;
30
31
CMSDKAPBWatchdog s32kwatchdog;
32
CMSDKAPBWatchdog nswatchdog;
33
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/iotkit.c
36
+++ b/hw/arm/iotkit.c
37
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
38
TYPE_CMSDK_APB_TIMER);
39
sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
40
TYPE_CMSDK_APB_TIMER);
41
+ sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
42
+ TYPE_CMSDK_APB_TIMER);
43
sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
44
TYPE_CMSDK_APB_DUALTIMER);
45
sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog,
46
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
47
TYPE_SPLIT_IRQ, &error_abort, NULL);
48
g_free(name);
49
}
50
- sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
51
- TYPE_UNIMPLEMENTED_DEVICE);
52
}
53
54
static void iotkit_exp_irq(void *opaque, int n, int level)
55
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
56
/* Devices behind APB PPC1:
57
* 0x4002f000: S32K timer
58
*/
59
- qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
60
- qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
61
+ qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
62
object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
63
if (err) {
64
error_propagate(errp, err);
65
return;
66
}
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
68
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 2));
69
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
70
object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
71
if (err) {
72
--
73
2.18.0
74
75
diff view generated by jsdifflib
Deleted patch
1
Wire up the system control element's register banks
2
(sysctl and sysinfo).
3
1
4
This is the last of the previously completely unimplemented
5
components in the IoTKit.
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180820141116.9118-11-peter.maydell@linaro.org
11
---
12
include/hw/arm/iotkit.h | 6 +++++-
13
hw/arm/iotkit.c | 26 ++++++++++++++++++--------
14
2 files changed, 23 insertions(+), 9 deletions(-)
15
16
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/iotkit.h
19
+++ b/include/hw/arm/iotkit.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/timer/cmsdk-apb-timer.h"
22
#include "hw/timer/cmsdk-apb-dualtimer.h"
23
#include "hw/watchdog/cmsdk-apb-watchdog.h"
24
-#include "hw/misc/unimp.h"
25
+#include "hw/misc/iotkit-sysctl.h"
26
+#include "hw/misc/iotkit-sysinfo.h"
27
#include "hw/or-irq.h"
28
#include "hw/core/split-irq.h"
29
30
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
31
CMSDKAPBWatchdog nswatchdog;
32
CMSDKAPBWatchdog swatchdog;
33
34
+ IoTKitSysCtl sysctl;
35
+ IoTKitSysCtl sysinfo;
36
+
37
MemoryRegion container;
38
MemoryRegion alias1;
39
MemoryRegion alias2;
40
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/iotkit.c
43
+++ b/hw/arm/iotkit.c
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/sysbus.h"
46
#include "hw/registerfields.h"
47
#include "hw/arm/iotkit.h"
48
-#include "hw/misc/unimp.h"
49
#include "hw/arm/arm.h"
50
51
/* Clock frequency in HZ of the 32KHz "slow clock" */
52
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
53
sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
54
sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
55
sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
56
+ sysbus_init_child_obj(obj, "iotkit-sysctl", &s->sysctl,
57
+ sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
58
+ sysbus_init_child_obj(obj, "iotkit-sysinfo", &s->sysinfo,
59
+ sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
60
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
61
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
62
&error_abort, NULL);
63
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
64
qdev_get_gpio_in_named(dev_apb_ppc1,
65
"cfg_sec_resp", 0));
66
67
- /* Using create_unimplemented_device() maps the stub into the
68
- * system address space rather than into our container, but the
69
- * overall effect to the guest is the same.
70
- */
71
- create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
72
-
73
- create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
74
+ object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
75
+ if (err) {
76
+ error_propagate(errp, err);
77
+ return;
78
+ }
79
+ /* System information registers */
80
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
81
+ /* System control registers */
82
+ object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
83
+ if (err) {
84
+ error_propagate(errp, err);
85
+ return;
86
+ }
87
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
88
89
/* This OR gate wires together outputs from the secure watchdogs to NMI */
90
object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
91
--
92
2.18.0
93
94
diff view generated by jsdifflib
1
Create a new include file for the pl022's device struct,
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
type macros, etc, so that it can be instantiated using
2
3
the "embedded struct" coding style.
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
4
4
Tests the CAN controller in loopback, sleep and snoop mode.
5
While we're adding the new file to MAINTAINERS, add
5
Tests filtering of incoming CAN messages.
6
also the .c file, which was missing an entry.
6
7
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
Message-id: 1597278668-339715-4-git-send-email-fnu.vikram@xilinx.com
10
[PMM: updated to meson build system]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20180820141116.9118-16-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
12
---
13
include/hw/ssi/pl022.h | 51 ++++++++++++++++++++++++++++++++++++++++++
13
tests/qtest/xlnx-can-test.c | 359 ++++++++++++++++++++++++++++++++++++
14
hw/ssi/pl022.c | 26 +--------------------
14
tests/qtest/meson.build | 1 +
15
MAINTAINERS | 2 ++
15
2 files changed, 360 insertions(+)
16
3 files changed, 54 insertions(+), 25 deletions(-)
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
create mode 100644 include/hw/ssi/pl022.h
17
18
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
19
diff --git a/include/hw/ssi/pl022.h b/include/hw/ssi/pl022.h
20
new file mode 100644
19
new file mode 100644
21
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
22
--- /dev/null
21
--- /dev/null
23
+++ b/include/hw/ssi/pl022.h
22
+++ b/tests/qtest/xlnx-can-test.c
24
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
25
+/*
24
+/*
26
+ * ARM PrimeCell PL022 Synchronous Serial Port
25
+ * QTests for the Xilinx ZynqMP CAN controller.
27
+ *
26
+ *
28
+ * Copyright (c) 2007 CodeSourcery.
27
+ * Copyright (c) 2020 Xilinx Inc.
29
+ * Written by Paul Brook
28
+ *
30
+ *
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
31
+ * This program is free software; you can redistribute it and/or modify
30
+ *
32
+ * it under the terms of the GNU General Public License version 2 or
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
33
+ * (at your option) any later version.
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
34
+ */
48
+ */
35
+
49
+
36
+/* This is a model of the Arm PrimeCell PL022 synchronous serial port.
50
+#include "qemu/osdep.h"
37
+ * The PL022 TRM is:
51
+#include "libqos/libqtest.h"
38
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/DDI0194H_ssp_pl022_trm.pdf
52
+
39
+ *
53
+/* Base address. */
40
+ * QEMU interface:
54
+#define CAN0_BASE_ADDR 0xFF060000
41
+ * + sysbus IRQ: SSPINTR combined interrupt line
55
+#define CAN1_BASE_ADDR 0xFF070000
42
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
56
+
57
+/* Register addresses. */
58
+#define R_SRR_OFFSET 0x00
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(uint32_t *buf_tx, uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
111
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
113
+{
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
130
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_tx)
132
+{
133
+ uint32_t int_status;
134
+
135
+ /* Write the TX register data for CAN. */
136
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
137
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
138
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
140
+
141
+ /* Read the interrupt on CAN for tx. */
142
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
143
+
144
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
145
+
146
+ /* Clear the interrupt for tx. */
147
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
148
+}
149
+
150
+/*
151
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
152
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
153
+ * the data sent from CAN0 with received on CAN1.
43
+ */
154
+ */
44
+
155
+static void test_can_bus(void)
45
+#ifndef HW_SSI_PL022_H
156
+{
46
+#define HW_SSI_PL022_H
157
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
47
+
158
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
48
+#include "hw/sysbus.h"
159
+ uint32_t status = 0;
49
+
160
+ uint8_t can_timestamp = 1;
50
+#define TYPE_PL022 "pl022"
161
+
51
+#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
162
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
52
+
163
+ " -object can-bus,id=canbus0"
53
+typedef struct PL022State {
164
+ " -machine xlnx-zcu102.canbus0=canbus0"
54
+ SysBusDevice parent_obj;
165
+ " -machine xlnx-zcu102.canbus1=canbus0"
55
+
166
+ );
56
+ MemoryRegion iomem;
167
+
57
+ uint32_t cr0;
168
+ /* Configure the CAN0 and CAN1. */
58
+ uint32_t cr1;
169
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
59
+ uint32_t bitmask;
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
60
+ uint32_t sr;
171
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
61
+ uint32_t cpsr;
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
62
+ uint32_t is;
173
+
63
+ uint32_t im;
174
+ /* Check here if CAN0 and CAN1 are in normal mode. */
64
+ /* The FIFO head points to the next empty entry. */
175
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
65
+ int tx_fifo_head;
176
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
66
+ int rx_fifo_head;
177
+
67
+ int tx_fifo_len;
178
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
68
+ int rx_fifo_len;
179
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
69
+ uint16_t tx_fifo[8];
180
+
70
+ uint16_t rx_fifo[8];
181
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
71
+ qemu_irq irq;
182
+
72
+ SSIBus *ssi;
183
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
73
+} PL022State;
184
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
74
+
185
+
75
+#endif
186
+ qtest_quit(qts);
76
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
187
+}
188
+
189
+/*
190
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
191
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
192
+ */
193
+static void test_can_loopback(void)
194
+{
195
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
196
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
197
+ uint32_t status = 0;
198
+
199
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
200
+ " -object can-bus,id=canbus0"
201
+ " -machine xlnx-zcu102.canbus0=canbus0"
202
+ " -machine xlnx-zcu102.canbus1=canbus0"
203
+ );
204
+
205
+ /* Configure the CAN0 in loopback mode. */
206
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
209
+
210
+ /* Check here if CAN0 is set in loopback mode. */
211
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
212
+
213
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
214
+
215
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
216
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
217
+ match_rx_tx_data(buf_tx, buf_rx, 0);
218
+
219
+ /* Configure the CAN1 in loopback mode. */
220
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
223
+
224
+ /* Check here if CAN1 is set in loopback mode. */
225
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
226
+
227
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
228
+
229
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
230
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
231
+ match_rx_tx_data(buf_tx, buf_rx, 0);
232
+
233
+ qtest_quit(qts);
234
+}
235
+
236
+/*
237
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
238
+ * test message will pass through filter 2.
239
+ */
240
+static void test_can_filter(void)
241
+{
242
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
243
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
244
+ uint32_t status = 0;
245
+ uint8_t can_timestamp = 1;
246
+
247
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
248
+ " -object can-bus,id=canbus0"
249
+ " -machine xlnx-zcu102.canbus0=canbus0"
250
+ " -machine xlnx-zcu102.canbus1=canbus0"
251
+ );
252
+
253
+ /* Configure the CAN0 and CAN1. */
254
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
256
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
258
+
259
+ /* Check here if CAN0 and CAN1 are in normal mode. */
260
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
261
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
262
+
263
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
264
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
265
+
266
+ /* Set filter for CAN1 for incoming messages. */
267
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
276
+
277
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
278
+
279
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
280
+
281
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
282
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
283
+
284
+ qtest_quit(qts);
285
+}
286
+
287
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
288
+static void test_can_sleepmode(void)
289
+{
290
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
291
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
292
+ uint32_t status = 0;
293
+ uint8_t can_timestamp = 1;
294
+
295
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
296
+ " -object can-bus,id=canbus0"
297
+ " -machine xlnx-zcu102.canbus0=canbus0"
298
+ " -machine xlnx-zcu102.canbus1=canbus0"
299
+ );
300
+
301
+ /* Configure the CAN0. */
302
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
305
+
306
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
308
+
309
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
310
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
311
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
312
+
313
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
314
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
315
+
316
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
317
+
318
+ /*
319
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
320
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
321
+ * incoming data.
322
+ */
323
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
324
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
325
+
326
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
327
+
328
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
329
+
330
+ qtest_quit(qts);
331
+}
332
+
333
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
334
+static void test_can_snoopmode(void)
335
+{
336
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
337
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
338
+ uint32_t status = 0;
339
+ uint8_t can_timestamp = 1;
340
+
341
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
342
+ " -object can-bus,id=canbus0"
343
+ " -machine xlnx-zcu102.canbus0=canbus0"
344
+ " -machine xlnx-zcu102.canbus1=canbus0"
345
+ );
346
+
347
+ /* Configure the CAN0. */
348
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
351
+
352
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
354
+
355
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
356
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
357
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
358
+
359
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
360
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
361
+
362
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
363
+
364
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
365
+
366
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
367
+
368
+ qtest_quit(qts);
369
+}
370
+
371
+int main(int argc, char **argv)
372
+{
373
+ g_test_init(&argc, &argv, NULL);
374
+
375
+ qtest_add_func("/net/can/can_bus", test_can_bus);
376
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
377
+ qtest_add_func("/net/can/can_filter", test_can_filter);
378
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
379
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
380
+
381
+ return g_test_run();
382
+}
383
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
77
index XXXXXXX..XXXXXXX 100644
384
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/ssi/pl022.c
385
--- a/tests/qtest/meson.build
79
+++ b/hw/ssi/pl022.c
386
+++ b/tests/qtest/meson.build
80
@@ -XXX,XX +XXX,XX @@
387
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
81
388
(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \
82
#include "qemu/osdep.h"
389
['numa-test',
83
#include "hw/sysbus.h"
390
'boot-serial-test',
84
+#include "hw/ssi/pl022.h"
391
+ 'xlnx-can-test',
85
#include "hw/ssi/ssi.h"
392
'migration-test']
86
#include "qemu/log.h"
393
87
394
qtests_s390x = \
88
@@ -XXX,XX +XXX,XX @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
89
#define PL022_INT_RX 0x04
90
#define PL022_INT_TX 0x08
91
92
-#define TYPE_PL022 "pl022"
93
-#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
94
-
95
-typedef struct PL022State {
96
- SysBusDevice parent_obj;
97
-
98
- MemoryRegion iomem;
99
- uint32_t cr0;
100
- uint32_t cr1;
101
- uint32_t bitmask;
102
- uint32_t sr;
103
- uint32_t cpsr;
104
- uint32_t is;
105
- uint32_t im;
106
- /* The FIFO head points to the next empty entry. */
107
- int tx_fifo_head;
108
- int rx_fifo_head;
109
- int tx_fifo_len;
110
- int rx_fifo_len;
111
- uint16_t tx_fifo[8];
112
- uint16_t rx_fifo[8];
113
- qemu_irq irq;
114
- SSIBus *ssi;
115
-} PL022State;
116
-
117
static const unsigned char pl022_id[8] =
118
{ 0x22, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
119
120
diff --git a/MAINTAINERS b/MAINTAINERS
121
index XXXXXXX..XXXXXXX 100644
122
--- a/MAINTAINERS
123
+++ b/MAINTAINERS
124
@@ -XXX,XX +XXX,XX @@ F: hw/gpio/pl061.c
125
F: hw/input/pl050.c
126
F: hw/intc/pl190.c
127
F: hw/sd/pl181.c
128
+F: hw/ssi/pl022.c
129
+F: include/hw/ssi/pl022.h
130
F: hw/timer/pl031.c
131
F: include/hw/arm/primecell.h
132
F: hw/timer/cmsdk-apb-timer.c
133
--
395
--
134
2.18.0
396
2.20.1
135
397
136
398
diff view generated by jsdifflib
Deleted patch
1
In the PL022, register offset 0x20 is the ICR, a write-only
2
interrupt-clear register. Register offset 0x24 is DMACR, the DMA
3
control register. We were incorrectly implementing (a stub version
4
of) DMACR at 0x20, and not implementing anything at 0x24. Fix this
5
bug.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20180820141116.9118-21-peter.maydell@linaro.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
hw/ssi/pl022.c | 12 ++++++++++--
12
1 file changed, 10 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/ssi/pl022.c
17
+++ b/hw/ssi/pl022.c
18
@@ -XXX,XX +XXX,XX @@ static uint64_t pl022_read(void *opaque, hwaddr offset,
19
return s->is;
20
case 0x1c: /* MIS */
21
return s->im & s->is;
22
- case 0x20: /* DMACR */
23
+ case 0x24: /* DMACR */
24
/* Not implemented. */
25
return 0;
26
default:
27
@@ -XXX,XX +XXX,XX @@ static void pl022_write(void *opaque, hwaddr offset,
28
s->im = value;
29
pl022_update(s);
30
break;
31
- case 0x20: /* DMACR */
32
+ case 0x20: /* ICR */
33
+ /*
34
+ * write-1-to-clear: bit 0 clears ROR, bit 1 clears RT;
35
+ * RX and TX interrupts cannot be cleared this way.
36
+ */
37
+ value &= PL022_INT_ROR | PL022_INT_RT;
38
+ s->is &= ~value;
39
+ break;
40
+ case 0x24: /* DMACR */
41
if (value) {
42
qemu_log_mask(LOG_UNIMP, "pl022: DMA not implemented\n");
43
}
44
--
45
2.18.0
46
47
diff view generated by jsdifflib
Deleted patch
1
The SPI controllers in the MPS2 AN505 board are PL022s.
2
We have a model of the PL022, so create these devices.
3
1
4
We don't currently model the LCD controller that sits behind
5
one of the PL022s; the others are intended to control devices
6
that sit on the FPGA's general purpose SPI connector or
7
"shield" expansion connectors.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20180820141116.9118-22-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
hw/arm/mps2-tz.c | 38 ++++++++++++++++++++++++++++++++------
14
1 file changed, 32 insertions(+), 6 deletions(-)
15
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/mps2-tz.c
19
+++ b/hw/arm/mps2-tz.c
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/misc/tz-msc.h"
22
#include "hw/arm/iotkit.h"
23
#include "hw/dma/pl080.h"
24
+#include "hw/ssi/pl022.h"
25
#include "hw/devices.h"
26
#include "net/net.h"
27
#include "hw/core/split-irq.h"
28
@@ -XXX,XX +XXX,XX @@ typedef struct {
29
MPS2FPGAIO fpgaio;
30
TZPPC ppc[5];
31
TZMPC ssram_mpc[3];
32
- UnimplementedDeviceState spi[5];
33
+ PL022State spi[5];
34
UnimplementedDeviceState i2c[4];
35
UnimplementedDeviceState i2s_audio;
36
UnimplementedDeviceState gpio[4];
37
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
38
return sysbus_mmio_get_region(s, 0);
39
}
40
41
+static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
42
+ const char *name, hwaddr size)
43
+{
44
+ /*
45
+ * The AN505 has five PL022 SPI controllers.
46
+ * One of these should have the LCD controller behind it; the others
47
+ * are connected only to the FPGA's "general purpose SPI connector"
48
+ * or "shield" expansion connectors.
49
+ * Note that if we do implement devices behind SPI, the chip select
50
+ * lines are set via the "MISC" register in the MPS2 FPGAIO device.
51
+ */
52
+ PL022State *spi = opaque;
53
+ int i = spi - &mms->spi[0];
54
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
55
+ SysBusDevice *s;
56
+
57
+ sysbus_init_child_obj(OBJECT(mms), name, spi, sizeof(mms->spi[0]),
58
+ TYPE_PL022);
59
+ object_property_set_bool(OBJECT(spi), true, "realized", &error_fatal);
60
+ s = SYS_BUS_DEVICE(spi);
61
+ sysbus_connect_irq(s, 0,
62
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 51 + i));
63
+ return sysbus_mmio_get_region(s, 0);
64
+}
65
+
66
static void mps2tz_common_init(MachineState *machine)
67
{
68
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
69
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
70
}, {
71
.name = "apb_ppcexp1",
72
.ports = {
73
- { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
74
- { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
75
- { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
76
- { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
77
- { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
78
+ { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000 },
79
+ { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000 },
80
+ { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000 },
81
+ { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000 },
82
+ { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000 },
83
{ "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
84
{ "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
85
{ "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
86
--
87
2.18.0
88
89
diff view generated by jsdifflib
Deleted patch
1
Some of the config register values we were setting for the MPS2 SCC
2
weren't correct:
3
* the SCC_AID bits [23:20] specify the FPGA build target board revision,
4
and the SCC_CFG4 register specifies the actual board revision, so
5
these should have matching values. Claim to be board revision C,
6
consistently -- we had the revision in the wrong part of SCC_AID.
7
* SCC_ID bits [15:4] should be 0x505, not decimal 505
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20180820141116.9118-23-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
hw/arm/mps2-tz.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/mps2-tz.c
19
+++ b/hw/arm/mps2-tz.c
20
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
21
sccdev = DEVICE(scc);
22
qdev_set_parent_bus(sccdev, sysbus_get_default());
23
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
24
- qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
25
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
26
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
27
object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
28
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
29
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
30
mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
31
mmc->fpga_type = FPGA_AN505;
32
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
33
- mmc->scc_id = 0x41040000 | (505 << 4);
34
+ mmc->scc_id = 0x41045050;
35
}
36
37
static const TypeInfo mps2tz_info = {
38
--
39
2.18.0
40
41
diff view generated by jsdifflib
1
Untabify the arm translate.c. This affects only some lines,
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
mostly comments, in the iwMMXt code. We've never touched
3
that code in years, so it's not going to get fixed up
4
by our "change when touched" process, and a bulk change
5
is not going to be too disruptive.
6
2
7
This commit was produced using Emacs "untabify"; it is
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
a whitespace-only change.
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
Message-id: 1597278668-339715-5-git-send-email-fnu.vikram@xilinx.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
MAINTAINERS | 8 ++++++++
10
1 file changed, 8 insertions(+)
9
11
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
diff --git a/MAINTAINERS b/MAINTAINERS
11
Message-id: 20180821165215.29069-2-peter.maydell@linaro.org
12
---
13
target/arm/translate.c | 122 ++++++++++++++++++++---------------------
14
1 file changed, 61 insertions(+), 61 deletions(-)
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
14
--- a/MAINTAINERS
19
+++ b/target/arm/translate.c
15
+++ b/MAINTAINERS
20
@@ -XXX,XX +XXX,XX @@ static inline void gen_mov_vreg_F0(int dp, int reg)
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
21
tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
17
22
}
18
Devices
23
19
-------
24
-#define ARM_CP_RW_BIT    (1 << 20)
20
+Xilinx CAN
25
+#define ARM_CP_RW_BIT (1 << 20)
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
26
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
27
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
23
+S: Maintained
28
{
24
+F: hw/net/can/xlnx-*
29
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
25
+F: include/hw/net/xlnx-*
30
wrd = insn & 0xf;
26
+F: tests/qtest/xlnx-can-test*
31
rdlo = (insn >> 12) & 0xf;
27
+
32
rdhi = (insn >> 16) & 0xf;
28
EDU
33
- if (insn & ARM_CP_RW_BIT) {            /* TMRRC */
29
M: Jiri Slaby <jslaby@suse.cz>
34
+ if (insn & ARM_CP_RW_BIT) { /* TMRRC */
30
S: Maintained
35
iwmmxt_load_reg(cpu_V0, wrd);
36
tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
37
tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
38
tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
39
- } else {                    /* TMCRR */
40
+ } else { /* TMCRR */
41
tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
42
iwmmxt_store_reg(cpu_V0, wrd);
43
gen_op_iwmmxt_set_mup();
44
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
45
return 1;
46
}
47
if (insn & ARM_CP_RW_BIT) {
48
- if ((insn >> 28) == 0xf) {            /* WLDRW wCx */
49
+ if ((insn >> 28) == 0xf) { /* WLDRW wCx */
50
tmp = tcg_temp_new_i32();
51
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
52
iwmmxt_store_creg(wrd, tmp);
53
} else {
54
i = 1;
55
if (insn & (1 << 8)) {
56
- if (insn & (1 << 22)) {        /* WLDRD */
57
+ if (insn & (1 << 22)) { /* WLDRD */
58
gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
59
i = 0;
60
- } else {                /* WLDRW wRd */
61
+ } else { /* WLDRW wRd */
62
tmp = tcg_temp_new_i32();
63
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
64
}
65
} else {
66
tmp = tcg_temp_new_i32();
67
- if (insn & (1 << 22)) {        /* WLDRH */
68
+ if (insn & (1 << 22)) { /* WLDRH */
69
gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
70
- } else {                /* WLDRB */
71
+ } else { /* WLDRB */
72
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
73
}
74
}
75
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
76
gen_op_iwmmxt_movq_wRn_M0(wrd);
77
}
78
} else {
79
- if ((insn >> 28) == 0xf) {            /* WSTRW wCx */
80
+ if ((insn >> 28) == 0xf) { /* WSTRW wCx */
81
tmp = iwmmxt_load_creg(wrd);
82
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
83
} else {
84
gen_op_iwmmxt_movq_M0_wRn(wrd);
85
tmp = tcg_temp_new_i32();
86
if (insn & (1 << 8)) {
87
- if (insn & (1 << 22)) {        /* WSTRD */
88
+ if (insn & (1 << 22)) { /* WSTRD */
89
gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
90
- } else {                /* WSTRW wRd */
91
+ } else { /* WSTRW wRd */
92
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
93
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
94
}
95
} else {
96
- if (insn & (1 << 22)) {        /* WSTRH */
97
+ if (insn & (1 << 22)) { /* WSTRH */
98
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
99
gen_aa32_st16(s, tmp, addr, get_mem_index(s));
100
- } else {                /* WSTRB */
101
+ } else { /* WSTRB */
102
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
103
gen_aa32_st8(s, tmp, addr, get_mem_index(s));
104
}
105
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
106
return 1;
107
108
switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
109
- case 0x000:                        /* WOR */
110
+ case 0x000: /* WOR */
111
wrd = (insn >> 12) & 0xf;
112
rd0 = (insn >> 0) & 0xf;
113
rd1 = (insn >> 16) & 0xf;
114
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
115
gen_op_iwmmxt_set_mup();
116
gen_op_iwmmxt_set_cup();
117
break;
118
- case 0x011:                        /* TMCR */
119
+ case 0x011: /* TMCR */
120
if (insn & 0xf)
121
return 1;
122
rd = (insn >> 12) & 0xf;
123
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
124
return 1;
125
}
126
break;
127
- case 0x100:                        /* WXOR */
128
+ case 0x100: /* WXOR */
129
wrd = (insn >> 12) & 0xf;
130
rd0 = (insn >> 0) & 0xf;
131
rd1 = (insn >> 16) & 0xf;
132
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
133
gen_op_iwmmxt_set_mup();
134
gen_op_iwmmxt_set_cup();
135
break;
136
- case 0x111:                        /* TMRC */
137
+ case 0x111: /* TMRC */
138
if (insn & 0xf)
139
return 1;
140
rd = (insn >> 12) & 0xf;
141
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
142
tmp = iwmmxt_load_creg(wrd);
143
store_reg(s, rd, tmp);
144
break;
145
- case 0x300:                        /* WANDN */
146
+ case 0x300: /* WANDN */
147
wrd = (insn >> 12) & 0xf;
148
rd0 = (insn >> 0) & 0xf;
149
rd1 = (insn >> 16) & 0xf;
150
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
151
gen_op_iwmmxt_set_mup();
152
gen_op_iwmmxt_set_cup();
153
break;
154
- case 0x200:                        /* WAND */
155
+ case 0x200: /* WAND */
156
wrd = (insn >> 12) & 0xf;
157
rd0 = (insn >> 0) & 0xf;
158
rd1 = (insn >> 16) & 0xf;
159
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
160
gen_op_iwmmxt_set_mup();
161
gen_op_iwmmxt_set_cup();
162
break;
163
- case 0x810: case 0xa10:                /* WMADD */
164
+ case 0x810: case 0xa10: /* WMADD */
165
wrd = (insn >> 12) & 0xf;
166
rd0 = (insn >> 0) & 0xf;
167
rd1 = (insn >> 16) & 0xf;
168
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
169
gen_op_iwmmxt_movq_wRn_M0(wrd);
170
gen_op_iwmmxt_set_mup();
171
break;
172
- case 0x10e: case 0x50e: case 0x90e: case 0xd0e:    /* WUNPCKIL */
173
+ case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
174
wrd = (insn >> 12) & 0xf;
175
rd0 = (insn >> 16) & 0xf;
176
rd1 = (insn >> 0) & 0xf;
177
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
178
gen_op_iwmmxt_set_mup();
179
gen_op_iwmmxt_set_cup();
180
break;
181
- case 0x10c: case 0x50c: case 0x90c: case 0xd0c:    /* WUNPCKIH */
182
+ case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
183
wrd = (insn >> 12) & 0xf;
184
rd0 = (insn >> 16) & 0xf;
185
rd1 = (insn >> 0) & 0xf;
186
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
187
gen_op_iwmmxt_set_mup();
188
gen_op_iwmmxt_set_cup();
189
break;
190
- case 0x012: case 0x112: case 0x412: case 0x512:    /* WSAD */
191
+ case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
192
wrd = (insn >> 12) & 0xf;
193
rd0 = (insn >> 16) & 0xf;
194
rd1 = (insn >> 0) & 0xf;
195
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
196
gen_op_iwmmxt_movq_wRn_M0(wrd);
197
gen_op_iwmmxt_set_mup();
198
break;
199
- case 0x010: case 0x110: case 0x210: case 0x310:    /* WMUL */
200
+ case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
201
wrd = (insn >> 12) & 0xf;
202
rd0 = (insn >> 16) & 0xf;
203
rd1 = (insn >> 0) & 0xf;
204
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
205
gen_op_iwmmxt_movq_wRn_M0(wrd);
206
gen_op_iwmmxt_set_mup();
207
break;
208
- case 0x410: case 0x510: case 0x610: case 0x710:    /* WMAC */
209
+ case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
210
wrd = (insn >> 12) & 0xf;
211
rd0 = (insn >> 16) & 0xf;
212
rd1 = (insn >> 0) & 0xf;
213
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
214
gen_op_iwmmxt_movq_wRn_M0(wrd);
215
gen_op_iwmmxt_set_mup();
216
break;
217
- case 0x006: case 0x406: case 0x806: case 0xc06:    /* WCMPEQ */
218
+ case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
219
wrd = (insn >> 12) & 0xf;
220
rd0 = (insn >> 16) & 0xf;
221
rd1 = (insn >> 0) & 0xf;
222
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
223
gen_op_iwmmxt_set_mup();
224
gen_op_iwmmxt_set_cup();
225
break;
226
- case 0x800: case 0x900: case 0xc00: case 0xd00:    /* WAVG2 */
227
+ case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
228
wrd = (insn >> 12) & 0xf;
229
rd0 = (insn >> 16) & 0xf;
230
rd1 = (insn >> 0) & 0xf;
231
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
232
gen_op_iwmmxt_set_mup();
233
gen_op_iwmmxt_set_cup();
234
break;
235
- case 0x802: case 0x902: case 0xa02: case 0xb02:    /* WALIGNR */
236
+ case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
237
wrd = (insn >> 12) & 0xf;
238
rd0 = (insn >> 16) & 0xf;
239
rd1 = (insn >> 0) & 0xf;
240
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
241
gen_op_iwmmxt_movq_wRn_M0(wrd);
242
gen_op_iwmmxt_set_mup();
243
break;
244
- case 0x601: case 0x605: case 0x609: case 0x60d:    /* TINSR */
245
+ case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
246
if (((insn >> 6) & 3) == 3)
247
return 1;
248
rd = (insn >> 12) & 0xf;
249
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
250
gen_op_iwmmxt_movq_wRn_M0(wrd);
251
gen_op_iwmmxt_set_mup();
252
break;
253
- case 0x107: case 0x507: case 0x907: case 0xd07:    /* TEXTRM */
254
+ case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
255
rd = (insn >> 12) & 0xf;
256
wrd = (insn >> 16) & 0xf;
257
if (rd == 15 || ((insn >> 22) & 3) == 3)
258
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
259
}
260
store_reg(s, rd, tmp);
261
break;
262
- case 0x117: case 0x517: case 0x917: case 0xd17:    /* TEXTRC */
263
+ case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
264
if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
265
return 1;
266
tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
267
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
268
gen_set_nzcv(tmp);
269
tcg_temp_free_i32(tmp);
270
break;
271
- case 0x401: case 0x405: case 0x409: case 0x40d:    /* TBCST */
272
+ case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
273
if (((insn >> 6) & 3) == 3)
274
return 1;
275
rd = (insn >> 12) & 0xf;
276
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
277
gen_op_iwmmxt_movq_wRn_M0(wrd);
278
gen_op_iwmmxt_set_mup();
279
break;
280
- case 0x113: case 0x513: case 0x913: case 0xd13:    /* TANDC */
281
+ case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
282
if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
283
return 1;
284
tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
285
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
286
tcg_temp_free_i32(tmp2);
287
tcg_temp_free_i32(tmp);
288
break;
289
- case 0x01c: case 0x41c: case 0x81c: case 0xc1c:    /* WACC */
290
+ case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
291
wrd = (insn >> 12) & 0xf;
292
rd0 = (insn >> 16) & 0xf;
293
gen_op_iwmmxt_movq_M0_wRn(rd0);
294
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
295
gen_op_iwmmxt_movq_wRn_M0(wrd);
296
gen_op_iwmmxt_set_mup();
297
break;
298
- case 0x115: case 0x515: case 0x915: case 0xd15:    /* TORC */
299
+ case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
300
if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
301
return 1;
302
tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
303
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
304
tcg_temp_free_i32(tmp2);
305
tcg_temp_free_i32(tmp);
306
break;
307
- case 0x103: case 0x503: case 0x903: case 0xd03:    /* TMOVMSK */
308
+ case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
309
rd = (insn >> 12) & 0xf;
310
rd0 = (insn >> 16) & 0xf;
311
if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
312
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
313
}
314
store_reg(s, rd, tmp);
315
break;
316
- case 0x106: case 0x306: case 0x506: case 0x706:    /* WCMPGT */
317
+ case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
318
case 0x906: case 0xb06: case 0xd06: case 0xf06:
319
wrd = (insn >> 12) & 0xf;
320
rd0 = (insn >> 16) & 0xf;
321
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
322
gen_op_iwmmxt_set_mup();
323
gen_op_iwmmxt_set_cup();
324
break;
325
- case 0x00e: case 0x20e: case 0x40e: case 0x60e:    /* WUNPCKEL */
326
+ case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
327
case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
328
wrd = (insn >> 12) & 0xf;
329
rd0 = (insn >> 16) & 0xf;
330
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
331
gen_op_iwmmxt_set_mup();
332
gen_op_iwmmxt_set_cup();
333
break;
334
- case 0x00c: case 0x20c: case 0x40c: case 0x60c:    /* WUNPCKEH */
335
+ case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
336
case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
337
wrd = (insn >> 12) & 0xf;
338
rd0 = (insn >> 16) & 0xf;
339
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
340
gen_op_iwmmxt_set_mup();
341
gen_op_iwmmxt_set_cup();
342
break;
343
- case 0x204: case 0x604: case 0xa04: case 0xe04:    /* WSRL */
344
+ case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
345
case 0x214: case 0x614: case 0xa14: case 0xe14:
346
if (((insn >> 22) & 3) == 0)
347
return 1;
348
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
349
gen_op_iwmmxt_set_mup();
350
gen_op_iwmmxt_set_cup();
351
break;
352
- case 0x004: case 0x404: case 0x804: case 0xc04:    /* WSRA */
353
+ case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
354
case 0x014: case 0x414: case 0x814: case 0xc14:
355
if (((insn >> 22) & 3) == 0)
356
return 1;
357
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
358
gen_op_iwmmxt_set_mup();
359
gen_op_iwmmxt_set_cup();
360
break;
361
- case 0x104: case 0x504: case 0x904: case 0xd04:    /* WSLL */
362
+ case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
363
case 0x114: case 0x514: case 0x914: case 0xd14:
364
if (((insn >> 22) & 3) == 0)
365
return 1;
366
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
367
gen_op_iwmmxt_set_mup();
368
gen_op_iwmmxt_set_cup();
369
break;
370
- case 0x304: case 0x704: case 0xb04: case 0xf04:    /* WROR */
371
+ case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
372
case 0x314: case 0x714: case 0xb14: case 0xf14:
373
if (((insn >> 22) & 3) == 0)
374
return 1;
375
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
376
gen_op_iwmmxt_set_mup();
377
gen_op_iwmmxt_set_cup();
378
break;
379
- case 0x116: case 0x316: case 0x516: case 0x716:    /* WMIN */
380
+ case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
381
case 0x916: case 0xb16: case 0xd16: case 0xf16:
382
wrd = (insn >> 12) & 0xf;
383
rd0 = (insn >> 16) & 0xf;
384
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
385
gen_op_iwmmxt_movq_wRn_M0(wrd);
386
gen_op_iwmmxt_set_mup();
387
break;
388
- case 0x016: case 0x216: case 0x416: case 0x616:    /* WMAX */
389
+ case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
390
case 0x816: case 0xa16: case 0xc16: case 0xe16:
391
wrd = (insn >> 12) & 0xf;
392
rd0 = (insn >> 16) & 0xf;
393
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
394
gen_op_iwmmxt_movq_wRn_M0(wrd);
395
gen_op_iwmmxt_set_mup();
396
break;
397
- case 0x002: case 0x102: case 0x202: case 0x302:    /* WALIGNI */
398
+ case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
399
case 0x402: case 0x502: case 0x602: case 0x702:
400
wrd = (insn >> 12) & 0xf;
401
rd0 = (insn >> 16) & 0xf;
402
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
403
gen_op_iwmmxt_movq_wRn_M0(wrd);
404
gen_op_iwmmxt_set_mup();
405
break;
406
- case 0x01a: case 0x11a: case 0x21a: case 0x31a:    /* WSUB */
407
+ case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
408
case 0x41a: case 0x51a: case 0x61a: case 0x71a:
409
case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
410
case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
411
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
412
gen_op_iwmmxt_set_mup();
413
gen_op_iwmmxt_set_cup();
414
break;
415
- case 0x01e: case 0x11e: case 0x21e: case 0x31e:    /* WSHUFH */
416
+ case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
417
case 0x41e: case 0x51e: case 0x61e: case 0x71e:
418
case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
419
case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
420
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
421
gen_op_iwmmxt_set_mup();
422
gen_op_iwmmxt_set_cup();
423
break;
424
- case 0x018: case 0x118: case 0x218: case 0x318:    /* WADD */
425
+ case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
426
case 0x418: case 0x518: case 0x618: case 0x718:
427
case 0x818: case 0x918: case 0xa18: case 0xb18:
428
case 0xc18: case 0xd18: case 0xe18: case 0xf18:
429
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
430
gen_op_iwmmxt_set_mup();
431
gen_op_iwmmxt_set_cup();
432
break;
433
- case 0x008: case 0x108: case 0x208: case 0x308:    /* WPACK */
434
+ case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
435
case 0x408: case 0x508: case 0x608: case 0x708:
436
case 0x808: case 0x908: case 0xa08: case 0xb08:
437
case 0xc08: case 0xd08: case 0xe08: case 0xf08:
438
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
439
tmp = load_reg(s, rd0);
440
tmp2 = load_reg(s, rd1);
441
switch ((insn >> 16) & 0xf) {
442
- case 0x0:                    /* TMIA */
443
+ case 0x0: /* TMIA */
444
gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
445
break;
446
- case 0x8:                    /* TMIAPH */
447
+ case 0x8: /* TMIAPH */
448
gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
449
break;
450
- case 0xc: case 0xd: case 0xe: case 0xf:        /* TMIAxy */
451
+ case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
452
if (insn & (1 << 16))
453
tcg_gen_shri_i32(tmp, tmp, 16);
454
if (insn & (1 << 17))
455
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
456
tmp = load_reg(s, rd0);
457
tmp2 = load_reg(s, rd1);
458
switch ((insn >> 16) & 0xf) {
459
- case 0x0:                    /* MIA */
460
+ case 0x0: /* MIA */
461
gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
462
break;
463
- case 0x8:                    /* MIAPH */
464
+ case 0x8: /* MIAPH */
465
gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
466
break;
467
- case 0xc:                    /* MIABB */
468
- case 0xd:                    /* MIABT */
469
- case 0xe:                    /* MIATB */
470
- case 0xf:                    /* MIATT */
471
+ case 0xc: /* MIABB */
472
+ case 0xd: /* MIABT */
473
+ case 0xe: /* MIATB */
474
+ case 0xf: /* MIATT */
475
if (insn & (1 << 16))
476
tcg_gen_shri_i32(tmp, tmp, 16);
477
if (insn & (1 << 17))
478
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
479
if (acc != 0)
480
return 1;
481
482
- if (insn & ARM_CP_RW_BIT) {            /* MRA */
483
+ if (insn & ARM_CP_RW_BIT) { /* MRA */
484
iwmmxt_load_reg(cpu_V0, acc);
485
tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
486
tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
487
tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
488
tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
489
- } else {                    /* MAR */
490
+ } else { /* MAR */
491
tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
492
iwmmxt_store_reg(cpu_V0, acc);
493
}
494
--
31
--
495
2.18.0
32
2.20.1
496
33
497
34
diff view generated by jsdifflib