1
This is almost all the mps3-an547 series, but there are a few
1
Just one bugfix patch for this rc:
2
other bits in there too.
3
2
4
thanks
3
The following changes since commit ca5f3d4df1b47d7f66a109cdb504e83dfd7ec433:
5
-- PMM
6
4
7
5
Merge tag 'pull-la-20220808' of https://gitlab.com/rth7680/qemu into staging (2022-08-08 19:51:12 -0700)
8
The following changes since commit 0436c55edf6b357ff56e2a5bf688df8636f83456:
9
10
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-03-08 13:51:41 +0000)
11
6
12
are available in the Git repository at:
7
are available in the Git repository at:
13
8
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210308-1
9
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220809
15
10
16
for you to fetch changes up to da2140183ac3a04b1ccb861aeac1f2c048c71b66:
11
for you to fetch changes up to c7f26ded6d5065e4116f630f6a490b55f6c5f58e:
17
12
18
hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() (2021-03-08 17:20:04 +0000)
13
icount: Take iothread lock when running QEMU timers (2022-08-09 10:55:14 +0100)
19
14
20
----------------------------------------------------------------
15
----------------------------------------------------------------
21
* Add new mps3-an547 board
16
target-arm queue:
22
* target/arm: Restrict v7A TCG cpus to TCG accel
17
* icount: Take iothread lock when running QEMU timers
23
* Implement a Xilinx CSU DMA model
24
* hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()
25
18
26
----------------------------------------------------------------
19
----------------------------------------------------------------
27
Peter Maydell (48):
20
Peter Maydell (1):
28
clock: Add ClockEvent parameter to callbacks
21
icount: Take iothread lock when running QEMU timers
29
clock: Add ClockPreUpdate callback event type
30
clock: Add clock_ns_to_ticks() function
31
hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks()
32
hw/arm/armsse: Introduce SSE subsystem version property
33
hw/misc/iotkit-sysctl: Remove is_sse200 flag
34
hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values
35
hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values
36
hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300
37
hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR
38
hw/timer/sse-counter: Model the SSE Subsystem System Counter
39
hw/timer/sse-timer: Model the SSE Subsystem System Timer
40
hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour
41
hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300
42
hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300
43
hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register
44
hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers
45
hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values
46
hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc
47
hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block
48
hw/arm/armsse: Use an array for apb_ppc fields in the state structure
49
hw/arm/armsse: Add a define for number of IRQs used by the SSE itself
50
hw/arm/armsse: Add framework for data-driven device placement
51
hw/arm/armsse: Move dual-timer device into data-driven framework
52
hw/arm/armsse: Move watchdogs into data-driven framework
53
hw/arm/armsse: Move s32ktimer into data-driven framework
54
hw/arm/armsse: Move sysinfo register block into data-driven framework
55
hw/arm/armsse: Move sysctl register block into data-driven framework
56
hw/arm/armsse: Move PPUs into data-driven framework
57
hw/arm/armsse: Add missing SSE-200 SYS_PPU
58
hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo
59
hw/arm/armsse: Add support for SSE variants with a system counter
60
hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo
61
hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block
62
hw/arm/armsse: Add SSE-300 support
63
hw/arm/mps2-tz: Make UART overflow IRQ board-specific
64
hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate
65
hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register
66
hw/misc/mps2-scc: Implement changes for AN547
67
hw/arm/mps2-tz: Support running APB peripherals on different clock
68
hw/arm/mps2-tz: Make initsvtor0 setting board-specific
69
hw/arm/mps2-tz: Add new mps3-an547 board
70
docs/system/arm/mps2.rst: Document the new mps3-an547 board
71
tests/qtest/sse-timer-test: Add simple test of the SSE counter
72
tests/qtest/sse-timer-test: Test the system timer
73
tests/qtest/sse-timer-test: Test counter scaling changes
74
hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_
75
hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()
76
22
77
Philippe Mathieu-Daudé (1):
23
accel/tcg/tcg-accel-ops-icount.c | 6 ++++++
78
target/arm: Restrict v7A TCG cpus to TCG accel
24
1 file changed, 6 insertions(+)
79
80
Xuzhou Cheng (5):
81
hw/dma: Implement a Xilinx CSU DMA model
82
hw/arm: xlnx-zynqmp: Clean up coding convention issues
83
hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI
84
hw/ssi: xilinx_spips: Clean up coding convention issues
85
hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips
86
87
docs/devel/clocks.rst | 71 ++-
88
docs/system/arm/mps2.rst | 6 +-
89
include/hw/arm/armsse-version.h | 42 ++
90
include/hw/arm/armsse.h | 40 +-
91
include/hw/arm/xlnx-zynqmp.h | 5 +-
92
include/hw/clock.h | 63 ++-
93
include/hw/dma/xlnx_csu_dma.h | 52 ++
94
include/hw/misc/armsse-cpu-pwrctrl.h | 40 ++
95
include/hw/misc/iotkit-secctl.h | 2 +
96
include/hw/misc/iotkit-sysctl.h | 13 +-
97
include/hw/misc/iotkit-sysinfo.h | 2 +
98
include/hw/misc/mps2-fpgaio.h | 2 +
99
include/hw/qdev-clock.h | 17 +-
100
include/hw/ssi/xilinx_spips.h | 2 +-
101
include/hw/timer/sse-counter.h | 105 ++++
102
include/hw/timer/sse-timer.h | 53 ++
103
hw/adc/npcm7xx_adc.c | 2 +-
104
hw/arm/armsse.c | 1008 +++++++++++++++++++++++++---------
105
hw/arm/mps2-tz.c | 168 +++++-
106
hw/arm/xlnx-zynqmp.c | 21 +-
107
hw/char/cadence_uart.c | 4 +-
108
hw/char/ibex_uart.c | 4 +-
109
hw/char/pl011.c | 5 +-
110
hw/core/clock.c | 24 +-
111
hw/core/qdev-clock.c | 8 +-
112
hw/dma/xlnx_csu_dma.c | 745 +++++++++++++++++++++++++
113
hw/mips/cps.c | 2 +-
114
hw/misc/armsse-cpu-pwrctrl.c | 149 +++++
115
hw/misc/bcm2835_cprman.c | 23 +-
116
hw/misc/iotkit-secctl.c | 50 +-
117
hw/misc/iotkit-sysctl.c | 522 +++++++++++++++---
118
hw/misc/iotkit-sysinfo.c | 51 +-
119
hw/misc/mps2-fpgaio.c | 52 +-
120
hw/misc/mps2-scc.c | 15 +-
121
hw/misc/npcm7xx_clk.c | 26 +-
122
hw/misc/npcm7xx_pwm.c | 2 +-
123
hw/misc/zynq_slcr.c | 5 +-
124
hw/ssi/xilinx_spips.c | 33 +-
125
hw/timer/cmsdk-apb-dualtimer.c | 5 +-
126
hw/timer/cmsdk-apb-timer.c | 4 +-
127
hw/timer/npcm7xx_timer.c | 6 +-
128
hw/timer/renesas_tmr.c | 33 +-
129
hw/timer/sse-counter.c | 474 ++++++++++++++++
130
hw/timer/sse-timer.c | 470 ++++++++++++++++
131
hw/watchdog/cmsdk-apb-watchdog.c | 5 +-
132
target/arm/cpu.c | 335 -----------
133
target/arm/cpu_tcg.c | 318 +++++++++++
134
target/mips/cpu.c | 2 +-
135
tests/qtest/sse-timer-test.c | 240 ++++++++
136
MAINTAINERS | 7 +
137
hw/arm/Kconfig | 10 +-
138
hw/dma/Kconfig | 4 +
139
hw/dma/meson.build | 1 +
140
hw/misc/Kconfig | 9 +
141
hw/misc/meson.build | 1 +
142
hw/misc/trace-events | 4 +
143
hw/timer/Kconfig | 6 +
144
hw/timer/meson.build | 2 +
145
hw/timer/trace-events | 12 +
146
tests/qtest/meson.build | 1 +
147
60 files changed, 4537 insertions(+), 846 deletions(-)
148
create mode 100644 include/hw/arm/armsse-version.h
149
create mode 100644 include/hw/dma/xlnx_csu_dma.h
150
create mode 100644 include/hw/misc/armsse-cpu-pwrctrl.h
151
create mode 100644 include/hw/timer/sse-counter.h
152
create mode 100644 include/hw/timer/sse-timer.h
153
create mode 100644 hw/dma/xlnx_csu_dma.c
154
create mode 100644 hw/misc/armsse-cpu-pwrctrl.c
155
create mode 100644 hw/timer/sse-counter.c
156
create mode 100644 hw/timer/sse-timer.c
157
create mode 100644 tests/qtest/sse-timer-test.c
158
diff view generated by jsdifflib
1
The Clock framework allows users to specify a callback which is
1
The function icount_prepare_for_run() is called with the iothread
2
called after the clock's period has been updated. Some users need to
2
unlocked, but it can call icount_notify_aio_contexts() which will
3
also have a callback which is called before the clock period is
3
run qemu timer handlers. Those are supposed to be run only with
4
updated.
4
the iothread lock held, so take the lock while we do that.
5
5
6
As the first step in adding support for notifying Clock users on
6
Since icount mode runs everything on a single thread anyway,
7
pre-update events, add an argument to the ClockCallback to specify
7
not holding the lock is likely mostly not going to introduce
8
what event is being notified, and add an argument to the various
8
races, but it can cause us to trip over assertions that we
9
functions for registering a callback to specify which events are
9
do hold the lock, such as the one reported in issue 1130.
10
of interest to that callback.
11
10
12
Note that the documentation update renders correct the previously
11
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1130
13
incorrect claim in 'Adding a new clock' that callbacks "will be
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
explained in a following section".
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Tested-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
15
Message-id: 20220801164527.3134765-1-peter.maydell@linaro.org
16
---
17
accel/tcg/tcg-accel-ops-icount.c | 6 ++++++
18
1 file changed, 6 insertions(+)
15
19
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
diff --git a/accel/tcg/tcg-accel-ops-icount.c b/accel/tcg/tcg-accel-ops-icount.c
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Luc Michel <luc@lmichel.fr>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20210219144617.4782-2-peter.maydell@linaro.org
22
---
23
docs/devel/clocks.rst | 52 +++++++++++++++++++++++++++-----
24
include/hw/clock.h | 21 +++++++++++--
25
include/hw/qdev-clock.h | 17 ++++++++---
26
hw/adc/npcm7xx_adc.c | 2 +-
27
hw/arm/armsse.c | 9 +++---
28
hw/char/cadence_uart.c | 4 +--
29
hw/char/ibex_uart.c | 4 +--
30
hw/char/pl011.c | 5 +--
31
hw/core/clock.c | 21 ++++++++++---
32
hw/core/qdev-clock.c | 8 +++--
33
hw/mips/cps.c | 2 +-
34
hw/misc/bcm2835_cprman.c | 23 ++++++++------
35
hw/misc/npcm7xx_clk.c | 26 +++++++++++++---
36
hw/misc/npcm7xx_pwm.c | 2 +-
37
hw/misc/zynq_slcr.c | 5 +--
38
hw/timer/cmsdk-apb-dualtimer.c | 5 +--
39
hw/timer/cmsdk-apb-timer.c | 4 +--
40
hw/timer/npcm7xx_timer.c | 2 +-
41
hw/watchdog/cmsdk-apb-watchdog.c | 5 +--
42
target/mips/cpu.c | 2 +-
43
20 files changed, 161 insertions(+), 58 deletions(-)
44
45
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
46
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
47
--- a/docs/devel/clocks.rst
22
--- a/accel/tcg/tcg-accel-ops-icount.c
48
+++ b/docs/devel/clocks.rst
23
+++ b/accel/tcg/tcg-accel-ops-icount.c
49
@@ -XXX,XX +XXX,XX @@ Adding clocks to a device must be done during the init method of the Device
24
@@ -XXX,XX +XXX,XX @@ void icount_prepare_for_run(CPUState *cpu)
50
instance.
25
replay_mutex_lock();
51
26
52
To add an input clock to a device, the function ``qdev_init_clock_in()``
27
if (cpu->icount_budget == 0) {
53
-must be used. It takes the name, a callback and an opaque parameter
28
+ /*
54
-for the callback (this will be explained in a following section).
29
+ * We're called without the iothread lock, so must take it while
55
+must be used. It takes the name, a callback, an opaque parameter
30
+ * we're calling timer handlers.
56
+for the callback and a mask of events when the callback should be
31
+ */
57
+called (this will be explained in a following section).
32
+ qemu_mutex_lock_iothread();
58
Output is simpler; only the name is required. Typically::
33
icount_notify_aio_contexts();
59
34
+ qemu_mutex_unlock_iothread();
60
- qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev);
61
+ qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev, ClockUpdate);
62
qdev_init_clock_out(DEVICE(dev), "clk_out");
63
64
Both functions return the created Clock pointer, which should be saved in the
65
@@ -XXX,XX +XXX,XX @@ output.
66
* callback for the input clock (see "Callback on input clock
67
* change" section below for more information).
68
*/
69
- static void clk_in_callback(void *opaque);
70
+ static void clk_in_callback(void *opaque, ClockEvent event);
71
72
/*
73
* static array describing clocks:
74
@@ -XXX,XX +XXX,XX @@ output.
75
* the clk_out field of a MyDeviceState structure.
76
*/
77
static const ClockPortInitArray mydev_clocks = {
78
- QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback),
79
+ QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback, ClockUpdate),
80
QDEV_CLOCK_OUT(MyDeviceState, clk_out),
81
QDEV_CLOCK_END
82
};
83
@@ -XXX,XX +XXX,XX @@ nothing else to do. This value will be propagated to other clocks when
84
connecting the clocks together and devices will fetch the right value during
85
the first reset.
86
87
+Clock callbacks
88
+---------------
89
+
90
+You can give a clock a callback function in several ways:
91
+
92
+ * by passing it as an argument to ``qdev_init_clock_in()``
93
+ * as an argument to the ``QDEV_CLOCK_IN()`` macro initializing an
94
+ array to be passed to ``qdev_init_clocks()``
95
+ * by directly calling the ``clock_set_callback()`` function
96
+
97
+The callback function must be of this type:
98
+
99
+.. code-block:: c
100
+
101
+ typedef void ClockCallback(void *opaque, ClockEvent event);
102
+
103
+The ``opaque`` argument is the pointer passed to ``qdev_init_clock_in()``
104
+or ``clock_set_callback()``; for ``qdev_init_clocks()`` it is the
105
+``dev`` device pointer.
106
+
107
+The ``event`` argument specifies why the callback has been called.
108
+When you register the callback you specify a mask of ClockEvent values
109
+that you are interested in. The callback will only be called for those
110
+events.
111
+
112
+The events currently supported are:
113
+
114
+ * ``ClockUpdate`` : called after the input clock's period has changed
115
+
116
+Note that a clock only has one callback: it is not possible to register
117
+different functions for different events. You must register a single
118
+callback which listens for all of the events you are interested in,
119
+and use the ``event`` argument to identify which event has happened.
120
+
121
Retrieving clocks from a device
122
-------------------------------
123
124
@@ -XXX,XX +XXX,XX @@ object during device instance init. For example:
125
.. code-block:: c
126
127
clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback,
128
- dev);
129
+ dev, ClockUpdate);
130
/* set initial value to 10ns / 100MHz */
131
clock_set_ns(clk, 10);
132
133
@@ -XXX,XX +XXX,XX @@ next lowest integer. This implies some inaccuracy due to the rounding,
134
so be cautious about using it in calculations.
135
136
It is also possible to register a callback on clock frequency changes.
137
-Here is an example:
138
+Here is an example, which assumes that ``clock_callback`` has been
139
+specified as the callback for the ``ClockUpdate`` event:
140
141
.. code-block:: c
142
143
- void clock_callback(void *opaque) {
144
+ void clock_callback(void *opaque, ClockEvent event) {
145
MyDeviceState *s = (MyDeviceState *) opaque;
146
/*
147
* 'opaque' is the argument passed to qdev_init_clock_in();
148
diff --git a/include/hw/clock.h b/include/hw/clock.h
149
index XXXXXXX..XXXXXXX 100644
150
--- a/include/hw/clock.h
151
+++ b/include/hw/clock.h
152
@@ -XXX,XX +XXX,XX @@
153
#define TYPE_CLOCK "clock"
154
OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
155
156
-typedef void ClockCallback(void *opaque);
157
+/*
158
+ * Argument to ClockCallback functions indicating why the callback
159
+ * has been called. A mask of these values logically ORed together
160
+ * is used to specify which events are interesting when the callback
161
+ * is registered, so these values must all be different bit values.
162
+ */
163
+typedef enum ClockEvent {
164
+ ClockUpdate = 1, /* Clock period has just updated */
165
+} ClockEvent;
166
+
167
+typedef void ClockCallback(void *opaque, ClockEvent event);
168
169
/*
170
* clock store a value representing the clock's period in 2^-32ns unit.
171
@@ -XXX,XX +XXX,XX @@ typedef void ClockCallback(void *opaque);
172
* @canonical_path: clock path string cache (used for trace purpose)
173
* @callback: called when clock changes
174
* @callback_opaque: argument for @callback
175
+ * @callback_events: mask of events when callback should be called
176
* @source: source (or parent in clock tree) of the clock
177
* @children: list of clocks connected to this one (it is their source)
178
* @sibling: structure used to form a clock list
179
@@ -XXX,XX +XXX,XX @@ struct Clock {
180
char *canonical_path;
181
ClockCallback *callback;
182
void *callback_opaque;
183
+ unsigned int callback_events;
184
185
/* Clocks are organized in a clock tree */
186
Clock *source;
187
@@ -XXX,XX +XXX,XX @@ Clock *clock_new(Object *parent, const char *name);
188
* @clk: the clock to register the callback into
189
* @cb: the callback function
190
* @opaque: the argument to the callback
191
+ * @events: the events the callback should be called for
192
+ * (logical OR of ClockEvent enum values)
193
*
194
* Register a callback called on every clock update.
195
+ * Note that a clock has only one callback: you cannot register
196
+ * different callback functions for different events.
197
*/
198
-void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque);
199
+void clock_set_callback(Clock *clk, ClockCallback *cb,
200
+ void *opaque, unsigned int events);
201
202
/**
203
* clock_clear_callback:
204
diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
205
index XXXXXXX..XXXXXXX 100644
206
--- a/include/hw/qdev-clock.h
207
+++ b/include/hw/qdev-clock.h
208
@@ -XXX,XX +XXX,XX @@
209
* @name: the name of the clock (can't be NULL).
210
* @callback: optional callback to be called on update or NULL.
211
* @opaque: argument for the callback
212
+ * @events: the events the callback should be called for
213
+ * (logical OR of ClockEvent enum values)
214
* @returns: a pointer to the newly added clock
215
*
216
* Add an input clock to device @dev as a clock named @name.
217
@@ -XXX,XX +XXX,XX @@
218
* The callback will be called with @opaque as opaque parameter.
219
*/
220
Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
221
- ClockCallback *callback, void *opaque);
222
+ ClockCallback *callback, void *opaque,
223
+ unsigned int events);
224
225
/**
226
* qdev_init_clock_out:
227
@@ -XXX,XX +XXX,XX @@ void qdev_finalize_clocklist(DeviceState *dev);
228
* @output: indicates whether the clock is input or output
229
* @callback: for inputs, optional callback to be called on clock's update
230
* with device as opaque
231
+ * @callback_events: mask of ClockEvent values for when callback is called
232
* @offset: optional offset to store the ClockIn or ClockOut pointer in device
233
* state structure (0 means unused)
234
*/
235
@@ -XXX,XX +XXX,XX @@ struct ClockPortInitElem {
236
const char *name;
237
bool is_output;
238
ClockCallback *callback;
239
+ unsigned int callback_events;
240
size_t offset;
241
};
242
243
@@ -XXX,XX +XXX,XX @@ struct ClockPortInitElem {
244
(offsetof(devstate, field) + \
245
type_check(Clock *, typeof_field(devstate, field)))
246
247
-#define QDEV_CLOCK(out_not_in, devstate, field, cb) { \
248
+#define QDEV_CLOCK(out_not_in, devstate, field, cb, cbevents) { \
249
.name = (stringify(field)), \
250
.is_output = out_not_in, \
251
.callback = cb, \
252
+ .callback_events = cbevents, \
253
.offset = clock_offset_value(devstate, field), \
254
}
255
256
@@ -XXX,XX +XXX,XX @@ struct ClockPortInitElem {
257
* @field: a field in @_devstate (must be Clock*)
258
* @callback: (for input only) callback (or NULL) to be called with the device
259
* state as argument
260
+ * @cbevents: (for input only) ClockEvent mask for when callback is called
261
*
262
* The name of the clock will be derived from @field
263
*/
264
-#define QDEV_CLOCK_IN(devstate, field, callback) \
265
- QDEV_CLOCK(false, devstate, field, callback)
266
+#define QDEV_CLOCK_IN(devstate, field, callback, cbevents) \
267
+ QDEV_CLOCK(false, devstate, field, callback, cbevents)
268
269
#define QDEV_CLOCK_OUT(devstate, field) \
270
- QDEV_CLOCK(true, devstate, field, NULL)
271
+ QDEV_CLOCK(true, devstate, field, NULL, 0)
272
273
#define QDEV_CLOCK_END { .name = NULL }
274
275
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/hw/adc/npcm7xx_adc.c
278
+++ b/hw/adc/npcm7xx_adc.c
279
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_adc_init(Object *obj)
280
memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
281
TYPE_NPCM7XX_ADC, 4 * KiB);
282
sysbus_init_mmio(sbd, &s->iomem);
283
- s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
284
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL, 0);
285
286
for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
287
object_property_add_uint32_ptr(obj, "adci[*]",
288
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
289
index XXXXXXX..XXXXXXX 100644
290
--- a/hw/arm/armsse.c
291
+++ b/hw/arm/armsse.c
292
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
293
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
294
}
295
296
-static void armsse_mainclk_update(void *opaque)
297
+static void armsse_mainclk_update(void *opaque, ClockEvent event)
298
{
299
ARMSSE *s = ARM_SSE(opaque);
300
+
301
/*
302
* Set system_clock_scale from our Clock input; this is what
303
* controls the tick rate of the CPU SysTick timer.
304
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
305
assert(info->num_cpus <= SSE_MAX_CPUS);
306
307
s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
308
- armsse_mainclk_update, s);
309
- s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
310
+ armsse_mainclk_update, s, ClockUpdate);
311
+ s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL, 0);
312
313
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
314
315
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
316
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
317
318
/* Set initial system_clock_scale from MAINCLK */
319
- armsse_mainclk_update(s);
320
+ armsse_mainclk_update(s, ClockUpdate);
321
}
322
323
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
324
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/hw/char/cadence_uart.c
327
+++ b/hw/char/cadence_uart.c
328
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
329
uart_event, NULL, s, NULL, true);
330
}
331
332
-static void cadence_uart_refclk_update(void *opaque)
333
+static void cadence_uart_refclk_update(void *opaque, ClockEvent event)
334
{
335
CadenceUARTState *s = opaque;
336
337
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_init(Object *obj)
338
sysbus_init_irq(sbd, &s->irq);
339
340
s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk",
341
- cadence_uart_refclk_update, s);
342
+ cadence_uart_refclk_update, s, ClockUpdate);
343
/* initialize the frequency in case the clock remains unconnected */
344
clock_set_hz(s->refclk, UART_DEFAULT_REF_CLK);
345
346
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
347
index XXXXXXX..XXXXXXX 100644
348
--- a/hw/char/ibex_uart.c
349
+++ b/hw/char/ibex_uart.c
350
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_write(void *opaque, hwaddr addr,
351
}
35
}
352
}
36
}
353
37
354
-static void ibex_uart_clk_update(void *opaque)
355
+static void ibex_uart_clk_update(void *opaque, ClockEvent event)
356
{
357
IbexUartState *s = opaque;
358
359
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_init(Object *obj)
360
IbexUartState *s = IBEX_UART(obj);
361
362
s->f_clk = qdev_init_clock_in(DEVICE(obj), "f_clock",
363
- ibex_uart_clk_update, s);
364
+ ibex_uart_clk_update, s, ClockUpdate);
365
clock_set_hz(s->f_clk, IBEX_UART_CLOCK);
366
367
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_watermark);
368
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
369
index XXXXXXX..XXXXXXX 100644
370
--- a/hw/char/pl011.c
371
+++ b/hw/char/pl011.c
372
@@ -XXX,XX +XXX,XX @@ static void pl011_event(void *opaque, QEMUChrEvent event)
373
pl011_put_fifo(opaque, 0x400);
374
}
375
376
-static void pl011_clock_update(void *opaque)
377
+static void pl011_clock_update(void *opaque, ClockEvent event)
378
{
379
PL011State *s = PL011(opaque);
380
381
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
382
sysbus_init_irq(sbd, &s->irq[i]);
383
}
384
385
- s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s);
386
+ s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
387
+ ClockUpdate);
388
389
s->read_trigger = 1;
390
s->ifl = 0x12;
391
diff --git a/hw/core/clock.c b/hw/core/clock.c
392
index XXXXXXX..XXXXXXX 100644
393
--- a/hw/core/clock.c
394
+++ b/hw/core/clock.c
395
@@ -XXX,XX +XXX,XX @@ Clock *clock_new(Object *parent, const char *name)
396
return clk;
397
}
398
399
-void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque)
400
+void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque,
401
+ unsigned int events)
402
{
403
clk->callback = cb;
404
clk->callback_opaque = opaque;
405
+ clk->callback_events = events;
406
}
407
408
void clock_clear_callback(Clock *clk)
409
{
410
- clock_set_callback(clk, NULL, NULL);
411
+ clock_set_callback(clk, NULL, NULL, 0);
412
}
413
414
bool clock_set(Clock *clk, uint64_t period)
415
@@ -XXX,XX +XXX,XX @@ bool clock_set(Clock *clk, uint64_t period)
416
return true;
417
}
418
419
+static void clock_call_callback(Clock *clk, ClockEvent event)
420
+{
421
+ /*
422
+ * Call the Clock's callback for this event, if it has one and
423
+ * is interested in this event.
424
+ */
425
+ if (clk->callback && (clk->callback_events & event)) {
426
+ clk->callback(clk->callback_opaque, event);
427
+ }
428
+}
429
+
430
static void clock_propagate_period(Clock *clk, bool call_callbacks)
431
{
432
Clock *child;
433
@@ -XXX,XX +XXX,XX @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
434
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
435
CLOCK_PERIOD_TO_HZ(clk->period),
436
call_callbacks);
437
- if (call_callbacks && child->callback) {
438
- child->callback(child->callback_opaque);
439
+ if (call_callbacks) {
440
+ clock_call_callback(child, ClockUpdate);
441
}
442
clock_propagate_period(child, call_callbacks);
443
}
444
diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/hw/core/qdev-clock.c
447
+++ b/hw/core/qdev-clock.c
448
@@ -XXX,XX +XXX,XX @@ Clock *qdev_init_clock_out(DeviceState *dev, const char *name)
449
}
450
451
Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
452
- ClockCallback *callback, void *opaque)
453
+ ClockCallback *callback, void *opaque,
454
+ unsigned int events)
455
{
456
NamedClockList *ncl;
457
458
@@ -XXX,XX +XXX,XX @@ Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
459
ncl = qdev_init_clocklist(dev, name, false, NULL);
460
461
if (callback) {
462
- clock_set_callback(ncl->clock, callback, opaque);
463
+ clock_set_callback(ncl->clock, callback, opaque, events);
464
}
465
return ncl->clock;
466
}
467
@@ -XXX,XX +XXX,XX @@ void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks)
468
if (elem->is_output) {
469
*clkp = qdev_init_clock_out(dev, elem->name);
470
} else {
471
- *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev);
472
+ *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev,
473
+ elem->callback_events);
474
}
475
}
476
}
477
diff --git a/hw/mips/cps.c b/hw/mips/cps.c
478
index XXXXXXX..XXXXXXX 100644
479
--- a/hw/mips/cps.c
480
+++ b/hw/mips/cps.c
481
@@ -XXX,XX +XXX,XX @@ static void mips_cps_init(Object *obj)
482
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
483
MIPSCPSState *s = MIPS_CPS(obj);
484
485
- s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL);
486
+ s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL, 0);
487
/*
488
* Cover entire address space as there do not seem to be any
489
* constraints for the base address of CPC and GIC.
490
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
491
index XXXXXXX..XXXXXXX 100644
492
--- a/hw/misc/bcm2835_cprman.c
493
+++ b/hw/misc/bcm2835_cprman.c
494
@@ -XXX,XX +XXX,XX @@ static void pll_update(CprmanPllState *pll)
495
clock_update_hz(pll->out, freq);
496
}
497
498
-static void pll_xosc_update(void *opaque)
499
+static void pll_xosc_update(void *opaque, ClockEvent event)
500
{
501
pll_update(CPRMAN_PLL(opaque));
502
}
503
@@ -XXX,XX +XXX,XX @@ static void pll_init(Object *obj)
504
{
505
CprmanPllState *s = CPRMAN_PLL(obj);
506
507
- s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s);
508
+ s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update,
509
+ s, ClockUpdate);
510
s->out = qdev_init_clock_out(DEVICE(s), "out");
511
}
512
513
@@ -XXX,XX +XXX,XX @@ static void pll_update_all_channels(BCM2835CprmanState *s,
514
}
515
}
516
517
-static void pll_channel_pll_in_update(void *opaque)
518
+static void pll_channel_pll_in_update(void *opaque, ClockEvent event)
519
{
520
pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
521
}
522
@@ -XXX,XX +XXX,XX @@ static void pll_channel_init(Object *obj)
523
CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
524
525
s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
526
- pll_channel_pll_in_update, s);
527
+ pll_channel_pll_in_update, s,
528
+ ClockUpdate);
529
s->out = qdev_init_clock_out(DEVICE(s), "out");
530
}
531
532
@@ -XXX,XX +XXX,XX @@ static void clock_mux_update(CprmanClockMuxState *mux)
533
clock_update_hz(mux->out, freq);
534
}
535
536
-static void clock_mux_src_update(void *opaque)
537
+static void clock_mux_src_update(void *opaque, ClockEvent event)
538
{
539
CprmanClockMuxState **backref = opaque;
540
CprmanClockMuxState *s = *backref;
541
@@ -XXX,XX +XXX,XX @@ static void clock_mux_init(Object *obj)
542
s->backref[i] = s;
543
s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
544
clock_mux_src_update,
545
- &s->backref[i]);
546
+ &s->backref[i],
547
+ ClockUpdate);
548
g_free(name);
549
}
550
551
@@ -XXX,XX +XXX,XX @@ static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s)
552
clock_update(s->out, clock_get(src));
553
}
554
555
-static void dsi0hsck_mux_in_update(void *opaque)
556
+static void dsi0hsck_mux_in_update(void *opaque, ClockEvent event)
557
{
558
dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque));
559
}
560
@@ -XXX,XX +XXX,XX @@ static void dsi0hsck_mux_init(Object *obj)
561
CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj);
562
DeviceState *dev = DEVICE(obj);
563
564
- s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, s);
565
- s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, s);
566
+ s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update,
567
+ s, ClockUpdate);
568
+ s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update,
569
+ s, ClockUpdate);
570
s->out = qdev_init_clock_out(DEVICE(s), "out");
571
}
572
573
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
574
index XXXXXXX..XXXXXXX 100644
575
--- a/hw/misc/npcm7xx_clk.c
576
+++ b/hw/misc/npcm7xx_clk.c
577
@@ -XXX,XX +XXX,XX @@ static const DividerInitInfo divider_init_info_list[] = {
578
},
579
};
580
581
+static void npcm7xx_clk_update_pll_cb(void *opaque, ClockEvent event)
582
+{
583
+ npcm7xx_clk_update_pll(opaque);
584
+}
585
+
586
static void npcm7xx_clk_pll_init(Object *obj)
587
{
588
NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
589
590
pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
591
- npcm7xx_clk_update_pll, pll);
592
+ npcm7xx_clk_update_pll_cb, pll,
593
+ ClockUpdate);
594
pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
595
}
596
597
+static void npcm7xx_clk_update_sel_cb(void *opaque, ClockEvent event)
598
+{
599
+ npcm7xx_clk_update_sel(opaque);
600
+}
601
+
602
static void npcm7xx_clk_sel_init(Object *obj)
603
{
604
int i;
605
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_sel_init(Object *obj)
606
for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
607
sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
608
g_strdup_printf("clock-in[%d]", i),
609
- npcm7xx_clk_update_sel, sel);
610
+ npcm7xx_clk_update_sel_cb, sel, ClockUpdate);
611
}
612
sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
613
}
614
+
615
+static void npcm7xx_clk_update_divider_cb(void *opaque, ClockEvent event)
616
+{
617
+ npcm7xx_clk_update_divider(opaque);
618
+}
619
+
620
static void npcm7xx_clk_divider_init(Object *obj)
621
{
622
NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
623
624
div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
625
- npcm7xx_clk_update_divider, div);
626
+ npcm7xx_clk_update_divider_cb,
627
+ div, ClockUpdate);
628
div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
629
}
630
631
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
632
{
633
int i;
634
635
- s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
636
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL, 0);
637
638
/* First pass: init all converter modules */
639
QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
640
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
641
index XXXXXXX..XXXXXXX 100644
642
--- a/hw/misc/npcm7xx_pwm.c
643
+++ b/hw/misc/npcm7xx_pwm.c
644
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
645
memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
646
TYPE_NPCM7XX_PWM, 4 * KiB);
647
sysbus_init_mmio(sbd, &s->iomem);
648
- s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
649
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL, 0);
650
651
for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
652
object_property_add_uint32_ptr(obj, "freq[*]",
653
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
654
index XXXXXXX..XXXXXXX 100644
655
--- a/hw/misc/zynq_slcr.c
656
+++ b/hw/misc/zynq_slcr.c
657
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_propagate_clocks(ZynqSLCRState *s)
658
clock_propagate(s->uart1_ref_clk);
659
}
660
661
-static void zynq_slcr_ps_clk_callback(void *opaque)
662
+static void zynq_slcr_ps_clk_callback(void *opaque, ClockEvent event)
663
{
664
ZynqSLCRState *s = (ZynqSLCRState *) opaque;
665
+
666
zynq_slcr_compute_clocks(s);
667
zynq_slcr_propagate_clocks(s);
668
}
669
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps slcr_ops = {
670
};
671
672
static const ClockPortInitArray zynq_slcr_clocks = {
673
- QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback),
674
+ QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback, ClockUpdate),
675
QDEV_CLOCK_OUT(ZynqSLCRState, uart0_ref_clk),
676
QDEV_CLOCK_OUT(ZynqSLCRState, uart1_ref_clk),
677
QDEV_CLOCK_END
678
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
679
index XXXXXXX..XXXXXXX 100644
680
--- a/hw/timer/cmsdk-apb-dualtimer.c
681
+++ b/hw/timer/cmsdk-apb-dualtimer.c
682
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
683
s->timeritop = 0;
684
}
685
686
-static void cmsdk_apb_dualtimer_clk_update(void *opaque)
687
+static void cmsdk_apb_dualtimer_clk_update(void *opaque, ClockEvent event)
688
{
689
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
690
int i;
691
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
692
sysbus_init_irq(sbd, &s->timermod[i].timerint);
693
}
694
s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
695
- cmsdk_apb_dualtimer_clk_update, s);
696
+ cmsdk_apb_dualtimer_clk_update, s,
697
+ ClockUpdate);
698
}
699
700
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
701
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
702
index XXXXXXX..XXXXXXX 100644
703
--- a/hw/timer/cmsdk-apb-timer.c
704
+++ b/hw/timer/cmsdk-apb-timer.c
705
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
706
ptimer_transaction_commit(s->timer);
707
}
708
709
-static void cmsdk_apb_timer_clk_update(void *opaque)
710
+static void cmsdk_apb_timer_clk_update(void *opaque, ClockEvent event)
711
{
712
CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
713
714
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
715
sysbus_init_mmio(sbd, &s->iomem);
716
sysbus_init_irq(sbd, &s->timerint);
717
s->pclk = qdev_init_clock_in(DEVICE(s), "pclk",
718
- cmsdk_apb_timer_clk_update, s);
719
+ cmsdk_apb_timer_clk_update, s, ClockUpdate);
720
}
721
722
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
723
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
724
index XXXXXXX..XXXXXXX 100644
725
--- a/hw/timer/npcm7xx_timer.c
726
+++ b/hw/timer/npcm7xx_timer.c
727
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_init(Object *obj)
728
sysbus_init_mmio(sbd, &s->iomem);
729
qdev_init_gpio_out_named(dev, &w->reset_signal,
730
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
731
- s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
732
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL, 0);
733
}
734
735
static const VMStateDescription vmstate_npcm7xx_base_timer = {
736
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
737
index XXXXXXX..XXXXXXX 100644
738
--- a/hw/watchdog/cmsdk-apb-watchdog.c
739
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
740
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
741
ptimer_transaction_commit(s->timer);
742
}
743
744
-static void cmsdk_apb_watchdog_clk_update(void *opaque)
745
+static void cmsdk_apb_watchdog_clk_update(void *opaque, ClockEvent event)
746
{
747
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
748
749
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
750
sysbus_init_mmio(sbd, &s->iomem);
751
sysbus_init_irq(sbd, &s->wdogint);
752
s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK",
753
- cmsdk_apb_watchdog_clk_update, s);
754
+ cmsdk_apb_watchdog_clk_update, s,
755
+ ClockUpdate);
756
757
s->is_luminary = false;
758
s->id = cmsdk_apb_watchdog_id;
759
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
760
index XXXXXXX..XXXXXXX 100644
761
--- a/target/mips/cpu.c
762
+++ b/target/mips/cpu.c
763
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_initfn(Object *obj)
764
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj);
765
766
cpu_set_cpustate_pointers(cpu);
767
- cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu);
768
+ cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0);
769
env->cpu_model = mcc->cpu_def;
770
}
771
772
--
38
--
773
2.20.1
39
2.25.1
774
775
diff view generated by jsdifflib
Deleted patch
1
Add a new callback event type ClockPreUpdate, which is called on
2
period changes before the period is updated.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Reviewed-by: Hao Wu <wuhaotsh@google.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210219144617.4782-3-peter.maydell@linaro.org
10
---
11
docs/devel/clocks.rst | 9 ++++++++-
12
include/hw/clock.h | 1 +
13
hw/core/clock.c | 3 +++
14
3 files changed, 12 insertions(+), 1 deletion(-)
15
16
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
17
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/devel/clocks.rst
19
+++ b/docs/devel/clocks.rst
20
@@ -XXX,XX +XXX,XX @@ events.
21
22
The events currently supported are:
23
24
- * ``ClockUpdate`` : called after the input clock's period has changed
25
+ * ``ClockPreUpdate`` : called when the input clock's period is about to
26
+ update. This is useful if the device needs to do some action for
27
+ which it needs to know the old value of the clock period. During
28
+ this callback, Clock API functions like ``clock_get()`` or
29
+ ``clock_ticks_to_ns()`` will use the old period.
30
+ * ``ClockUpdate`` : called after the input clock's period has changed.
31
+ During this callback, Clock API functions like ``clock_ticks_to_ns()``
32
+ will use the new period.
33
34
Note that a clock only has one callback: it is not possible to register
35
different functions for different events. You must register a single
36
diff --git a/include/hw/clock.h b/include/hw/clock.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/clock.h
39
+++ b/include/hw/clock.h
40
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
41
*/
42
typedef enum ClockEvent {
43
ClockUpdate = 1, /* Clock period has just updated */
44
+ ClockPreUpdate = 2, /* Clock period is about to update */
45
} ClockEvent;
46
47
typedef void ClockCallback(void *opaque, ClockEvent event);
48
diff --git a/hw/core/clock.c b/hw/core/clock.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/core/clock.c
51
+++ b/hw/core/clock.c
52
@@ -XXX,XX +XXX,XX @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
53
54
QLIST_FOREACH(child, &clk->children, sibling) {
55
if (child->period != clk->period) {
56
+ if (call_callbacks) {
57
+ clock_call_callback(child, ClockPreUpdate);
58
+ }
59
child->period = clk->period;
60
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
61
CLOCK_PERIOD_TO_HZ(clk->period),
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
Deleted patch
1
Add a clock_ns_to_ticks() function which does the opposite of
2
clock_ticks_to_ns(): given a duration in nanoseconds, it returns the
3
number of clock ticks that would happen in that time. This is useful
4
for devices that have a free running counter register whose value can
5
be calculated when it is read.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Reviewed-by: Hao Wu <wuhaotsh@google.com>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20210219144617.4782-4-peter.maydell@linaro.org
12
---
13
docs/devel/clocks.rst | 12 ++++++++++++
14
include/hw/clock.h | 41 +++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 53 insertions(+)
16
17
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/devel/clocks.rst
20
+++ b/docs/devel/clocks.rst
21
@@ -XXX,XX +XXX,XX @@ rather than simply passing it to a QEMUTimer function like
22
``timer_mod_ns()`` then you should be careful to avoid overflow
23
in those calculations, of course.)
24
25
+Obtaining tick counts
26
+---------------------
27
+
28
+For calculations where you need to know the number of ticks in
29
+a given duration, use ``clock_ns_to_ticks()``. This function handles
30
+possible non-whole-number-of-nanoseconds periods and avoids
31
+potential rounding errors. It will return '0' if the clock is stopped
32
+(i.e. it has period zero). If the inputs imply a tick count that
33
+overflows a 64-bit value (a very long duration for a clock with a
34
+very short period) the output value is truncated, so effectively
35
+the 64-bit output wraps around.
36
+
37
Changing a clock period
38
-----------------------
39
40
diff --git a/include/hw/clock.h b/include/hw/clock.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/clock.h
43
+++ b/include/hw/clock.h
44
@@ -XXX,XX +XXX,XX @@ static inline uint64_t clock_ticks_to_ns(const Clock *clk, uint64_t ticks)
45
return ns_low >> 32 | ns_high << 32;
46
}
47
48
+/**
49
+ * clock_ns_to_ticks:
50
+ * @clk: the clock to query
51
+ * @ns: duration in nanoseconds
52
+ *
53
+ * Returns the number of ticks this clock would make in the given
54
+ * number of nanoseconds. Because a clock can have a period which
55
+ * is not a whole number of nanoseconds, it is important to use this
56
+ * function rather than attempting to obtain a "period in nanoseconds"
57
+ * value and then dividing the duration by that value.
58
+ *
59
+ * If the clock is stopped (ie it has period zero), returns 0.
60
+ *
61
+ * For some inputs the result could overflow a 64-bit value (because
62
+ * the clock's period is short and the duration is long). In these
63
+ * cases we truncate the result to a 64-bit value. This is on the
64
+ * assumption that generally the result is going to be used to report
65
+ * a 32-bit or 64-bit guest register value, so wrapping either cannot
66
+ * happen or is the desired behaviour.
67
+ */
68
+static inline uint64_t clock_ns_to_ticks(const Clock *clk, uint64_t ns)
69
+{
70
+ /*
71
+ * ticks = duration_in_ns / period_in_ns
72
+ * = ns / (period / 2^32)
73
+ * = (ns * 2^32) / period
74
+ * The hi, lo inputs to divu128() are (ns << 32) as a 128 bit value.
75
+ */
76
+ uint64_t lo = ns << 32;
77
+ uint64_t hi = ns >> 32;
78
+ if (clk->period == 0) {
79
+ return 0;
80
+ }
81
+ /*
82
+ * Ignore divu128() return value as we've caught div-by-zero and don't
83
+ * need different behaviour for overflow.
84
+ */
85
+ divu128(&lo, &hi, clk->period);
86
+ return lo;
87
+}
88
+
89
/**
90
* clock_is_enabled:
91
* @clk: a clock
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
Use the new clock_ns_to_ticks() function in npcm7xx_timer where
2
appropriate.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210219144617.4782-5-peter.maydell@linaro.org
10
---
11
hw/timer/npcm7xx_timer.c | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/timer/npcm7xx_timer.c
17
+++ b/hw/timer/npcm7xx_timer.c
18
@@ -XXX,XX +XXX,XX @@ static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
19
/* Convert a time interval in nanoseconds to a timer cycle count. */
20
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
21
{
22
- return ns / clock_ticks_to_ns(t->ctrl->clock,
23
- npcm7xx_tcsr_prescaler(t->tcsr));
24
+ return clock_ns_to_ticks(t->ctrl->clock, ns) /
25
+ npcm7xx_tcsr_prescaler(t->tcsr);
26
}
27
28
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
Deleted patch
1
We model Arm "Subsystems for Embedded" SoC subsystems using generic
2
code which is split into various sub-devices which are configurable
3
by QOM properties to handle the behaviour differences between the SSE
4
subsystems we implement. Currently the only sub-device which needs
5
to change is the IOTKIT_SYSCTL device, and we do this with a mix of
6
properties that directly specify divergent behaviours (eg
7
CPUWAIT_RST) and passing it the SYS_VERSION register value as a way
8
for it to distinguish IoTKit from SSE-200.
9
1
10
The "pass SYS_VERSION" approach is already a bit hacky, since the
11
IOTKIT_SYSCTL device has to know that the different part of the
12
register value happens to be bits [31:28]. For SSE-300 this register
13
is renamed SOC_IDENTITY and has a different format entirely, all of
14
whose fields can be configured by the SoC integrator when they
15
integrate the SSE into their SoC, and so "pass SYS_VERSION" breaks
16
down completely.
17
18
Switch to using a simple integer property representing an
19
internal-to-QEMU enumeration of the SSE flavour. For the moment we
20
only need this in IOTKIT_SYSCTL, but as we add SSE-300 support a few
21
of the other devices will also need to know.
22
23
We define and permit a value for the SSE-300 so we can start using
24
it in subsequent commits which add SSE-300 support.
25
26
The now-redundant is_sse200 flag in IoTKitSysCtl will be removed
27
in the following commit.
28
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Message-id: 20210219144617.4782-6-peter.maydell@linaro.org
33
---
34
include/hw/arm/armsse-version.h | 42 +++++++++++++++++++++++++++++++++
35
include/hw/misc/iotkit-sysctl.h | 7 +++---
36
hw/arm/armsse.c | 8 +++++--
37
hw/misc/iotkit-sysctl.c | 11 +++++----
38
4 files changed, 58 insertions(+), 10 deletions(-)
39
create mode 100644 include/hw/arm/armsse-version.h
40
41
diff --git a/include/hw/arm/armsse-version.h b/include/hw/arm/armsse-version.h
42
new file mode 100644
43
index XXXXXXX..XXXXXXX
44
--- /dev/null
45
+++ b/include/hw/arm/armsse-version.h
46
@@ -XXX,XX +XXX,XX @@
47
+/*
48
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
49
+ *
50
+ * Copyright (c) 2020 Linaro Limited
51
+ * Written by Peter Maydell
52
+ *
53
+ * This program is free software; you can redistribute it and/or modify
54
+ * it under the terms of the GNU General Public License version 2 or
55
+ * (at your option) any later version.
56
+ */
57
+
58
+#ifndef ARMSSE_VERSION_H
59
+#define ARMSSE_VERSION_H
60
+
61
+
62
+/*
63
+ * Define an enumeration of the possible values of the sse-version
64
+ * property implemented by various sub-devices of the SSE, and
65
+ * a validation function that checks that a valid value has been passed.
66
+ * These are arbitrary QEMU-internal values (nobody should be creating
67
+ * the sub-devices of the SSE except for the SSE object itself), but
68
+ * we pick obvious numbers for the benefit of people debugging with gdb.
69
+ */
70
+enum {
71
+ ARMSSE_IOTKIT = 0,
72
+ ARMSSE_SSE200 = 200,
73
+ ARMSSE_SSE300 = 300,
74
+};
75
+
76
+static inline bool armsse_version_valid(uint32_t sse_version)
77
+{
78
+ switch (sse_version) {
79
+ case ARMSSE_IOTKIT:
80
+ case ARMSSE_SSE200:
81
+ case ARMSSE_SSE300:
82
+ return true;
83
+ default:
84
+ return false;
85
+ }
86
+}
87
+
88
+#endif
89
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
90
index XXXXXXX..XXXXXXX 100644
91
--- a/include/hw/misc/iotkit-sysctl.h
92
+++ b/include/hw/misc/iotkit-sysctl.h
93
@@ -XXX,XX +XXX,XX @@
94
* "system control register" blocks.
95
*
96
* QEMU interface:
97
- * + QOM property "SYS_VERSION": value of the SYS_VERSION register of the
98
- * system information block of the SSE
99
- * (used to identify whether to provide SSE-200-only registers)
100
+ * + QOM property "sse-version": indicates which SSE version this is part of
101
+ * (used to identify whether to provide SSE-200-only registers, etc)
102
* + sysbus MMIO region 0: the system information register bank
103
* + sysbus MMIO region 1: the system control register bank
104
*/
105
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
106
uint32_t pdcm_pd_sram3_sense;
107
108
/* Properties */
109
- uint32_t sys_version;
110
+ uint32_t sse_version;
111
uint32_t cpuwait_rst;
112
uint32_t initsvtor0_rst;
113
uint32_t initsvtor1_rst;
114
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/hw/arm/armsse.c
117
+++ b/hw/arm/armsse.c
118
@@ -XXX,XX +XXX,XX @@
119
#include "migration/vmstate.h"
120
#include "hw/registerfields.h"
121
#include "hw/arm/armsse.h"
122
+#include "hw/arm/armsse-version.h"
123
#include "hw/arm/boot.h"
124
#include "hw/irq.h"
125
#include "hw/qdev-clock.h"
126
@@ -XXX,XX +XXX,XX @@ typedef enum SysConfigFormat {
127
128
struct ARMSSEInfo {
129
const char *name;
130
+ uint32_t sse_version;
131
int sram_banks;
132
int num_cpus;
133
uint32_t sys_version;
134
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
135
static const ARMSSEInfo armsse_variants[] = {
136
{
137
.name = TYPE_IOTKIT,
138
+ .sse_version = ARMSSE_IOTKIT,
139
.sram_banks = 1,
140
.num_cpus = 1,
141
.sys_version = 0x41743,
142
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
143
},
144
{
145
.name = TYPE_SSE200,
146
+ .sse_version = ARMSSE_SSE200,
147
.sram_banks = 4,
148
.num_cpus = 2,
149
.sys_version = 0x22041743,
150
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
151
/* System information registers */
152
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
153
/* System control registers */
154
- object_property_set_int(OBJECT(&s->sysctl), "SYS_VERSION",
155
- info->sys_version, &error_abort);
156
+ object_property_set_int(OBJECT(&s->sysctl), "sse-version",
157
+ info->sse_version, &error_abort);
158
object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
159
info->cpuwait_rst, &error_abort);
160
object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
161
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/hw/misc/iotkit-sysctl.c
164
+++ b/hw/misc/iotkit-sysctl.c
165
@@ -XXX,XX +XXX,XX @@
166
#include "hw/registerfields.h"
167
#include "hw/misc/iotkit-sysctl.h"
168
#include "hw/qdev-properties.h"
169
+#include "hw/arm/armsse-version.h"
170
#include "target/arm/arm-powerctl.h"
171
#include "target/arm/cpu.h"
172
173
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
174
{
175
IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
176
177
- /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
178
- if (extract32(s->sys_version, 28, 4) == 2) {
179
- s->is_sse200 = true;
180
+ if (!armsse_version_valid(s->sse_version)) {
181
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
182
+ return;
183
}
184
+
185
+ s->is_sse200 = s->sse_version == ARMSSE_SSE200;
186
}
187
188
static bool sse200_needed(void *opaque)
189
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_sysctl_vmstate = {
190
};
191
192
static Property iotkit_sysctl_props[] = {
193
- DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
194
+ DEFINE_PROP_UINT32("sse-version", IoTKitSysCtl, sse_version, 0),
195
DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
196
DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
197
0x10000000),
198
--
199
2.20.1
200
201
diff view generated by jsdifflib
Deleted patch
1
Remove the is_sse200 flag in favour of just directly testing the new
2
sse_version field.
3
1
4
Since some of these registers exist in the SSE-300 but some do not or
5
have different behaviour, we expand out the if() statements in the
6
read and write functions into switch()es, so we have an easy place to
7
put SSE-300 specific behaviour.
8
9
(Until we do add the SSE-300 behaviour, the thing preventing us
10
reaching the "unreachable" default cases is that armsse.c doesn't
11
yet pass us an ARMSSE_SSE300 version.)
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210219144617.4782-7-peter.maydell@linaro.org
17
---
18
include/hw/misc/iotkit-sysctl.h | 2 -
19
hw/misc/iotkit-sysctl.c | 256 +++++++++++++++++++++++---------
20
2 files changed, 187 insertions(+), 71 deletions(-)
21
22
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/misc/iotkit-sysctl.h
25
+++ b/include/hw/misc/iotkit-sysctl.h
26
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
27
uint32_t cpuwait_rst;
28
uint32_t initsvtor0_rst;
29
uint32_t initsvtor1_rst;
30
-
31
- bool is_sse200;
32
};
33
34
#endif
35
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/iotkit-sysctl.c
38
+++ b/hw/misc/iotkit-sysctl.c
39
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
40
r = s->secure_debug;
41
break;
42
case A_SCSECCTRL:
43
- if (!s->is_sse200) {
44
+ switch (s->sse_version) {
45
+ case ARMSSE_IOTKIT:
46
goto bad_offset;
47
+ case ARMSSE_SSE200:
48
+ r = s->scsecctrl;
49
+ break;
50
+ default:
51
+ g_assert_not_reached();
52
}
53
- r = s->scsecctrl;
54
break;
55
case A_FCLK_DIV:
56
- if (!s->is_sse200) {
57
+ switch (s->sse_version) {
58
+ case ARMSSE_IOTKIT:
59
goto bad_offset;
60
+ case ARMSSE_SSE200:
61
+ r = s->fclk_div;
62
+ break;
63
+ default:
64
+ g_assert_not_reached();
65
}
66
- r = s->fclk_div;
67
break;
68
case A_SYSCLK_DIV:
69
- if (!s->is_sse200) {
70
+ switch (s->sse_version) {
71
+ case ARMSSE_IOTKIT:
72
goto bad_offset;
73
+ case ARMSSE_SSE200:
74
+ r = s->sysclk_div;
75
+ break;
76
+ default:
77
+ g_assert_not_reached();
78
}
79
- r = s->sysclk_div;
80
break;
81
case A_CLOCK_FORCE:
82
- if (!s->is_sse200) {
83
+ switch (s->sse_version) {
84
+ case ARMSSE_IOTKIT:
85
goto bad_offset;
86
+ case ARMSSE_SSE200:
87
+ r = s->clock_force;
88
+ break;
89
+ default:
90
+ g_assert_not_reached();
91
}
92
- r = s->clock_force;
93
break;
94
case A_RESET_SYNDROME:
95
r = s->reset_syndrome;
96
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
97
r = s->initsvtor0;
98
break;
99
case A_INITSVTOR1:
100
- if (!s->is_sse200) {
101
+ switch (s->sse_version) {
102
+ case ARMSSE_IOTKIT:
103
goto bad_offset;
104
+ case ARMSSE_SSE200:
105
+ r = s->initsvtor1;
106
+ break;
107
+ default:
108
+ g_assert_not_reached();
109
}
110
- r = s->initsvtor1;
111
break;
112
case A_CPUWAIT:
113
r = s->cpuwait;
114
break;
115
case A_NMI_ENABLE:
116
- /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
117
- if (!s->is_sse200) {
118
+ switch (s->sse_version) {
119
+ case ARMSSE_IOTKIT:
120
+ /* In IoTKit this is named BUSWAIT but marked reserved, R/O, zero */
121
r = 0;
122
break;
123
+ case ARMSSE_SSE200:
124
+ r = s->nmi_enable;
125
+ break;
126
+ default:
127
+ g_assert_not_reached();
128
}
129
- r = s->nmi_enable;
130
break;
131
case A_WICCTRL:
132
r = s->wicctrl;
133
break;
134
case A_EWCTRL:
135
- if (!s->is_sse200) {
136
+ switch (s->sse_version) {
137
+ case ARMSSE_IOTKIT:
138
goto bad_offset;
139
+ case ARMSSE_SSE200:
140
+ r = s->ewctrl;
141
+ break;
142
+ default:
143
+ g_assert_not_reached();
144
}
145
- r = s->ewctrl;
146
break;
147
case A_PDCM_PD_SYS_SENSE:
148
- if (!s->is_sse200) {
149
+ switch (s->sse_version) {
150
+ case ARMSSE_IOTKIT:
151
goto bad_offset;
152
+ case ARMSSE_SSE200:
153
+ r = s->pdcm_pd_sys_sense;
154
+ break;
155
+ default:
156
+ g_assert_not_reached();
157
}
158
- r = s->pdcm_pd_sys_sense;
159
break;
160
case A_PDCM_PD_SRAM0_SENSE:
161
- if (!s->is_sse200) {
162
+ switch (s->sse_version) {
163
+ case ARMSSE_IOTKIT:
164
goto bad_offset;
165
+ case ARMSSE_SSE200:
166
+ r = s->pdcm_pd_sram0_sense;
167
+ break;
168
+ default:
169
+ g_assert_not_reached();
170
}
171
- r = s->pdcm_pd_sram0_sense;
172
break;
173
case A_PDCM_PD_SRAM1_SENSE:
174
- if (!s->is_sse200) {
175
+ switch (s->sse_version) {
176
+ case ARMSSE_IOTKIT:
177
goto bad_offset;
178
+ case ARMSSE_SSE200:
179
+ r = s->pdcm_pd_sram1_sense;
180
+ break;
181
+ default:
182
+ g_assert_not_reached();
183
}
184
- r = s->pdcm_pd_sram1_sense;
185
break;
186
case A_PDCM_PD_SRAM2_SENSE:
187
- if (!s->is_sse200) {
188
+ switch (s->sse_version) {
189
+ case ARMSSE_IOTKIT:
190
goto bad_offset;
191
+ case ARMSSE_SSE200:
192
+ r = s->pdcm_pd_sram2_sense;
193
+ break;
194
+ default:
195
+ g_assert_not_reached();
196
}
197
- r = s->pdcm_pd_sram2_sense;
198
break;
199
case A_PDCM_PD_SRAM3_SENSE:
200
- if (!s->is_sse200) {
201
+ switch (s->sse_version) {
202
+ case ARMSSE_IOTKIT:
203
goto bad_offset;
204
+ case ARMSSE_SSE200:
205
+ r = s->pdcm_pd_sram3_sense;
206
+ break;
207
+ default:
208
+ g_assert_not_reached();
209
}
210
- r = s->pdcm_pd_sram3_sense;
211
break;
212
case A_PID4 ... A_CID3:
213
r = sysctl_id[(offset - A_PID4) / 4];
214
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
215
}
216
break;
217
case A_SCSECCTRL:
218
- if (!s->is_sse200) {
219
+ switch (s->sse_version) {
220
+ case ARMSSE_IOTKIT:
221
goto bad_offset;
222
+ case ARMSSE_SSE200:
223
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
224
+ s->scsecctrl = value;
225
+ break;
226
+ default:
227
+ g_assert_not_reached();
228
}
229
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
230
- s->scsecctrl = value;
231
break;
232
case A_FCLK_DIV:
233
- if (!s->is_sse200) {
234
+ switch (s->sse_version) {
235
+ case ARMSSE_IOTKIT:
236
goto bad_offset;
237
+ case ARMSSE_SSE200:
238
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
239
+ s->fclk_div = value;
240
+ break;
241
+ default:
242
+ g_assert_not_reached();
243
}
244
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
245
- s->fclk_div = value;
246
break;
247
case A_SYSCLK_DIV:
248
- if (!s->is_sse200) {
249
+ switch (s->sse_version) {
250
+ case ARMSSE_IOTKIT:
251
goto bad_offset;
252
+ case ARMSSE_SSE200:
253
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
254
+ s->sysclk_div = value;
255
+ break;
256
+ default:
257
+ g_assert_not_reached();
258
}
259
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
260
- s->sysclk_div = value;
261
break;
262
case A_CLOCK_FORCE:
263
- if (!s->is_sse200) {
264
+ switch (s->sse_version) {
265
+ case ARMSSE_IOTKIT:
266
goto bad_offset;
267
+ case ARMSSE_SSE200:
268
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
269
+ s->clock_force = value;
270
+ break;
271
+ default:
272
+ g_assert_not_reached();
273
}
274
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
275
- s->clock_force = value;
276
break;
277
case A_INITSVTOR1:
278
- if (!s->is_sse200) {
279
+ switch (s->sse_version) {
280
+ case ARMSSE_IOTKIT:
281
goto bad_offset;
282
+ case ARMSSE_SSE200:
283
+ s->initsvtor1 = value;
284
+ set_init_vtor(1, s->initsvtor1);
285
+ break;
286
+ default:
287
+ g_assert_not_reached();
288
}
289
- s->initsvtor1 = value;
290
- set_init_vtor(1, s->initsvtor1);
291
break;
292
case A_EWCTRL:
293
- if (!s->is_sse200) {
294
+ switch (s->sse_version) {
295
+ case ARMSSE_IOTKIT:
296
goto bad_offset;
297
+ case ARMSSE_SSE200:
298
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
299
+ s->ewctrl = value;
300
+ break;
301
+ default:
302
+ g_assert_not_reached();
303
}
304
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
305
- s->ewctrl = value;
306
break;
307
case A_PDCM_PD_SYS_SENSE:
308
- if (!s->is_sse200) {
309
+ switch (s->sse_version) {
310
+ case ARMSSE_IOTKIT:
311
goto bad_offset;
312
+ case ARMSSE_SSE200:
313
+ qemu_log_mask(LOG_UNIMP,
314
+ "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
315
+ s->pdcm_pd_sys_sense = value;
316
+ break;
317
+ default:
318
+ g_assert_not_reached();
319
}
320
- qemu_log_mask(LOG_UNIMP,
321
- "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
322
- s->pdcm_pd_sys_sense = value;
323
break;
324
case A_PDCM_PD_SRAM0_SENSE:
325
- if (!s->is_sse200) {
326
+ switch (s->sse_version) {
327
+ case ARMSSE_IOTKIT:
328
goto bad_offset;
329
+ case ARMSSE_SSE200:
330
+ qemu_log_mask(LOG_UNIMP,
331
+ "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
332
+ s->pdcm_pd_sram0_sense = value;
333
+ break;
334
+ default:
335
+ g_assert_not_reached();
336
}
337
- qemu_log_mask(LOG_UNIMP,
338
- "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
339
- s->pdcm_pd_sram0_sense = value;
340
break;
341
case A_PDCM_PD_SRAM1_SENSE:
342
- if (!s->is_sse200) {
343
+ switch (s->sse_version) {
344
+ case ARMSSE_IOTKIT:
345
goto bad_offset;
346
+ case ARMSSE_SSE200:
347
+ qemu_log_mask(LOG_UNIMP,
348
+ "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
349
+ s->pdcm_pd_sram1_sense = value;
350
+ break;
351
+ default:
352
+ g_assert_not_reached();
353
}
354
- qemu_log_mask(LOG_UNIMP,
355
- "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
356
- s->pdcm_pd_sram1_sense = value;
357
break;
358
case A_PDCM_PD_SRAM2_SENSE:
359
- if (!s->is_sse200) {
360
+ switch (s->sse_version) {
361
+ case ARMSSE_IOTKIT:
362
goto bad_offset;
363
+ case ARMSSE_SSE200:
364
+ qemu_log_mask(LOG_UNIMP,
365
+ "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
366
+ s->pdcm_pd_sram2_sense = value;
367
+ break;
368
+ default:
369
+ g_assert_not_reached();
370
}
371
- qemu_log_mask(LOG_UNIMP,
372
- "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
373
- s->pdcm_pd_sram2_sense = value;
374
break;
375
case A_PDCM_PD_SRAM3_SENSE:
376
- if (!s->is_sse200) {
377
+ switch (s->sse_version) {
378
+ case ARMSSE_IOTKIT:
379
goto bad_offset;
380
+ case ARMSSE_SSE200:
381
+ qemu_log_mask(LOG_UNIMP,
382
+ "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
383
+ s->pdcm_pd_sram3_sense = value;
384
+ break;
385
+ default:
386
+ g_assert_not_reached();
387
}
388
- qemu_log_mask(LOG_UNIMP,
389
- "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
390
- s->pdcm_pd_sram3_sense = value;
391
break;
392
case A_NMI_ENABLE:
393
/* In IoTKit this is BUSWAIT: reserved, R/O, zero */
394
- if (!s->is_sse200) {
395
+ switch (s->sse_version) {
396
+ case ARMSSE_IOTKIT:
397
goto ro_offset;
398
+ case ARMSSE_SSE200:
399
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
400
+ s->nmi_enable = value;
401
+ break;
402
+ default:
403
+ g_assert_not_reached();
404
}
405
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
406
- s->nmi_enable = value;
407
break;
408
case A_SECDBGSTAT:
409
case A_PID4 ... A_CID3:
410
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
411
error_setg(errp, "invalid sse-version value %d", s->sse_version);
412
return;
413
}
414
-
415
- s->is_sse200 = s->sse_version == ARMSSE_SSE200;
416
}
417
418
static bool sse200_needed(void *opaque)
419
{
420
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
421
422
- return s->is_sse200;
423
+ return s->sse_version == ARMSSE_SSE200;
424
}
425
426
static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
427
--
428
2.20.1
429
430
diff view generated by jsdifflib
Deleted patch
1
The versions of the Secure Access Configuration Register Block
2
and Non-secure Access Configuration Register Block in the SSE-300
3
are the same as those in the SSE-200, but the CIDR/PIDR ID
4
register values are different.
5
1
6
Plumb through the sse-version property and use it to select
7
the correct ID register values.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-8-peter.maydell@linaro.org
13
---
14
include/hw/misc/iotkit-secctl.h | 2 ++
15
hw/arm/armsse.c | 2 ++
16
hw/misc/iotkit-secctl.c | 50 +++++++++++++++++++++++++++++++--
17
3 files changed, 52 insertions(+), 2 deletions(-)
18
19
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/iotkit-secctl.h
22
+++ b/include/hw/misc/iotkit-secctl.h
23
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
24
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
25
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
26
IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
27
+
28
+ uint32_t sse_version;
29
};
30
31
#endif
32
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armsse.c
35
+++ b/hw/arm/armsse.c
36
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
37
}
38
39
/* Security controller */
40
+ object_property_set_int(OBJECT(&s->secctl), "sse-version",
41
+ info->sse_version, &error_abort);
42
if (!sysbus_realize(SYS_BUS_DEVICE(&s->secctl), errp)) {
43
return;
44
}
45
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/misc/iotkit-secctl.c
48
+++ b/hw/misc/iotkit-secctl.c
49
@@ -XXX,XX +XXX,XX @@
50
#include "hw/registerfields.h"
51
#include "hw/irq.h"
52
#include "hw/misc/iotkit-secctl.h"
53
+#include "hw/arm/armsse-version.h"
54
+#include "hw/qdev-properties.h"
55
56
/* Registers in the secure privilege control block */
57
REG32(SECRESPCFG, 0x10)
58
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
59
0x0d, 0xf0, 0x05, 0xb1,
60
};
61
62
+static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
63
+ 0x04, 0x00, 0x00, 0x00,
64
+ 0x52, 0xb8, 0x2b, 0x00,
65
+ 0x0d, 0xf0, 0x05, 0xb1,
66
+};
67
+
68
+static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
69
+ 0x04, 0x00, 0x00, 0x00,
70
+ 0x53, 0xb8, 0x2b, 0x00,
71
+ 0x0d, 0xf0, 0x05, 0xb1,
72
+};
73
+
74
+
75
/* The register sets for the various PPCs (AHB internal, APB internal,
76
* AHB expansion, APB expansion) are all set up so that they are
77
* in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
78
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
79
case A_CID1:
80
case A_CID2:
81
case A_CID3:
82
- r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
83
+ switch (s->sse_version) {
84
+ case ARMSSE_SSE300:
85
+ r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
86
+ break;
87
+ default:
88
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
89
+ break;
90
+ }
91
break;
92
case A_SECPPCINTCLR:
93
case A_SECMSCINTCLR:
94
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
95
case A_CID1:
96
case A_CID2:
97
case A_CID3:
98
- r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
99
+ switch (s->sse_version) {
100
+ case ARMSSE_SSE300:
101
+ r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
102
+ break;
103
+ default:
104
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
105
+ break;
106
+ }
107
break;
108
default:
109
qemu_log_mask(LOG_GUEST_ERROR,
110
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
111
sysbus_init_mmio(sbd, &s->ns_regs);
112
}
113
114
+static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
115
+{
116
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
117
+
118
+ if (!armsse_version_valid(s->sse_version)) {
119
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
120
+ return;
121
+ }
122
+}
123
+
124
static const VMStateDescription iotkit_secctl_ppc_vmstate = {
125
.name = "iotkit-secctl-ppc",
126
.version_id = 1,
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
128
},
129
};
130
131
+static Property iotkit_secctl_props[] = {
132
+ DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
133
+ DEFINE_PROP_END_OF_LIST()
134
+};
135
+
136
static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
137
{
138
DeviceClass *dc = DEVICE_CLASS(klass);
139
140
dc->vmsd = &iotkit_secctl_vmstate;
141
dc->reset = iotkit_secctl_reset;
142
+ dc->realize = iotkit_secctl_realize;
143
+ device_class_set_props(dc, iotkit_secctl_props);
144
}
145
146
static const TypeInfo iotkit_secctl_info = {
147
--
148
2.20.1
149
150
diff view generated by jsdifflib
Deleted patch
1
The version of the SYSINFO Register Block in the SSE-300 has
2
different CIDR/PIDR register values to the SSE-200; pass in
3
the sse-version property and use it to select the correct
4
ID register values.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-9-peter.maydell@linaro.org
10
---
11
include/hw/misc/iotkit-sysinfo.h | 1 +
12
hw/arm/armsse.c | 2 ++
13
hw/misc/iotkit-sysinfo.c | 29 +++++++++++++++++++++++++++--
14
3 files changed, 30 insertions(+), 2 deletions(-)
15
16
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/misc/iotkit-sysinfo.h
19
+++ b/include/hw/misc/iotkit-sysinfo.h
20
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysInfo {
21
/* Properties */
22
uint32_t sys_version;
23
uint32_t sys_config;
24
+ uint32_t sse_version;
25
};
26
27
#endif
28
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/armsse.c
31
+++ b/hw/arm/armsse.c
32
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
33
armsse_sys_config_value(s, info), errp)) {
34
return;
35
}
36
+ object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
37
+ info->sse_version, &error_abort);
38
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
39
return;
40
}
41
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/misc/iotkit-sysinfo.c
44
+++ b/hw/misc/iotkit-sysinfo.c
45
@@ -XXX,XX +XXX,XX @@
46
#include "hw/registerfields.h"
47
#include "hw/misc/iotkit-sysinfo.h"
48
#include "hw/qdev-properties.h"
49
+#include "hw/arm/armsse-version.h"
50
51
REG32(SYS_VERSION, 0x0)
52
REG32(SYS_CONFIG, 0x4)
53
@@ -XXX,XX +XXX,XX @@ static const int sysinfo_id[] = {
54
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
55
};
56
57
+static const int sysinfo_sse300_id[] = {
58
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
59
+ 0x58, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
60
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
61
+};
62
+
63
static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
64
unsigned size)
65
{
66
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
67
r = s->sys_config;
68
break;
69
case A_PID4 ... A_CID3:
70
- r = sysinfo_id[(offset - A_PID4) / 4];
71
+ switch (s->sse_version) {
72
+ case ARMSSE_SSE300:
73
+ r = sysinfo_sse300_id[(offset - A_PID4) / 4];
74
+ break;
75
+ default:
76
+ r = sysinfo_id[(offset - A_PID4) / 4];
77
+ break;
78
+ }
79
break;
80
default:
81
qemu_log_mask(LOG_GUEST_ERROR,
82
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
83
static Property iotkit_sysinfo_props[] = {
84
DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
85
DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
86
+ DEFINE_PROP_UINT32("sse-version", IoTKitSysInfo, sse_version, 0),
87
DEFINE_PROP_END_OF_LIST()
88
};
89
90
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysinfo_init(Object *obj)
91
sysbus_init_mmio(sbd, &s->iomem);
92
}
93
94
+static void iotkit_sysinfo_realize(DeviceState *dev, Error **errp)
95
+{
96
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(dev);
97
+
98
+ if (!armsse_version_valid(s->sse_version)) {
99
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
100
+ return;
101
+ }
102
+}
103
+
104
static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
105
{
106
DeviceClass *dc = DEVICE_CLASS(klass);
107
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
108
* This device has no guest-modifiable state and so it
109
* does not need a reset function or VMState.
110
*/
111
-
112
+ dc->realize = iotkit_sysinfo_realize;
113
device_class_set_props(dc, iotkit_sysinfo_props);
114
}
115
116
--
117
2.20.1
118
119
diff view generated by jsdifflib
Deleted patch
1
In the SSE-300, the format of the SYS_CONFIG0 register has changed again;
2
pass through the correct value to the SYSINFO register block device.
3
1
4
We drop the old SysConfigFormat enum, which was implemented in the
5
hope that different flavours of SSE would share the same format;
6
since they all seem to be different and we now have an sse_version
7
enum to key off, just use that.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-10-peter.maydell@linaro.org
13
---
14
hw/arm/armsse.c | 21 +++++++++------------
15
1 file changed, 9 insertions(+), 12 deletions(-)
16
17
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/armsse.c
20
+++ b/hw/arm/armsse.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "hw/irq.h"
23
#include "hw/qdev-clock.h"
24
25
-/* Format of the System Information block SYS_CONFIG register */
26
-typedef enum SysConfigFormat {
27
- IoTKitFormat,
28
- SSE200Format,
29
-} SysConfigFormat;
30
-
31
struct ARMSSEInfo {
32
const char *name;
33
uint32_t sse_version;
34
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
35
int num_cpus;
36
uint32_t sys_version;
37
uint32_t cpuwait_rst;
38
- SysConfigFormat sys_config_format;
39
bool has_mhus;
40
bool has_ppus;
41
bool has_cachectrl;
42
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
43
.num_cpus = 1,
44
.sys_version = 0x41743,
45
.cpuwait_rst = 0,
46
- .sys_config_format = IoTKitFormat,
47
.has_mhus = false,
48
.has_ppus = false,
49
.has_cachectrl = false,
50
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
51
.num_cpus = 2,
52
.sys_version = 0x22041743,
53
.cpuwait_rst = 2,
54
- .sys_config_format = SSE200Format,
55
.has_mhus = true,
56
.has_ppus = true,
57
.has_cachectrl = true,
58
@@ -XXX,XX +XXX,XX @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
59
/* Return the SYS_CONFIG value for this SSE */
60
uint32_t sys_config;
61
62
- switch (info->sys_config_format) {
63
- case IoTKitFormat:
64
+ switch (info->sse_version) {
65
+ case ARMSSE_IOTKIT:
66
sys_config = 0;
67
sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
68
sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
69
break;
70
- case SSE200Format:
71
+ case ARMSSE_SSE200:
72
sys_config = 0;
73
sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
74
sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
75
@@ -XXX,XX +XXX,XX @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
76
sys_config = deposit32(sys_config, 28, 4, 2);
77
}
78
break;
79
+ case ARMSSE_SSE300:
80
+ sys_config = 0;
81
+ sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
82
+ sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
83
+ sys_config = deposit32(sys_config, 16, 3, 3); /* CPU0 = Cortex-M55 */
84
+ break;
85
default:
86
g_assert_not_reached();
87
}
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
Deleted patch
1
For SSE-300, the SYSINFO register block has two new registers:
2
1
3
* SYS_CONFIG1 indicates the config for a potential CPU2 and CPU3;
4
since the SSE-300 can only be configured with a single CPU it
5
is always zero
6
7
* IIDR is the subsystem implementation identity register;
8
its value is set by the SoC integrator, so we plumb this in from
9
the armsse.c code as we do with SYS_VERSION and SYS_CONFIG
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210219144617.4782-11-peter.maydell@linaro.org
15
---
16
include/hw/misc/iotkit-sysinfo.h | 1 +
17
hw/arm/armsse.c | 5 +++++
18
hw/misc/iotkit-sysinfo.c | 22 ++++++++++++++++++++++
19
3 files changed, 28 insertions(+)
20
21
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/misc/iotkit-sysinfo.h
24
+++ b/include/hw/misc/iotkit-sysinfo.h
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysInfo {
26
uint32_t sys_version;
27
uint32_t sys_config;
28
uint32_t sse_version;
29
+ uint32_t iidr;
30
};
31
32
#endif
33
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/armsse.c
36
+++ b/hw/arm/armsse.c
37
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
38
int sram_banks;
39
int num_cpus;
40
uint32_t sys_version;
41
+ uint32_t iidr;
42
uint32_t cpuwait_rst;
43
bool has_mhus;
44
bool has_ppus;
45
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
46
.sram_banks = 1,
47
.num_cpus = 1,
48
.sys_version = 0x41743,
49
+ .iidr = 0,
50
.cpuwait_rst = 0,
51
.has_mhus = false,
52
.has_ppus = false,
53
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
54
.sram_banks = 4,
55
.num_cpus = 2,
56
.sys_version = 0x22041743,
57
+ .iidr = 0,
58
.cpuwait_rst = 2,
59
.has_mhus = true,
60
.has_ppus = true,
61
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
62
}
63
object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
64
info->sse_version, &error_abort);
65
+ object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
66
+ info->iidr, &error_abort);
67
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
68
return;
69
}
70
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/misc/iotkit-sysinfo.c
73
+++ b/hw/misc/iotkit-sysinfo.c
74
@@ -XXX,XX +XXX,XX @@
75
76
REG32(SYS_VERSION, 0x0)
77
REG32(SYS_CONFIG, 0x4)
78
+REG32(SYS_CONFIG1, 0x8)
79
+REG32(IIDR, 0xfc8)
80
REG32(PID4, 0xfd0)
81
REG32(PID5, 0xfd4)
82
REG32(PID6, 0xfd8)
83
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
84
case A_SYS_CONFIG:
85
r = s->sys_config;
86
break;
87
+ case A_SYS_CONFIG1:
88
+ switch (s->sse_version) {
89
+ case ARMSSE_SSE300:
90
+ return 0;
91
+ break;
92
+ default:
93
+ goto bad_read;
94
+ }
95
+ break;
96
+ case A_IIDR:
97
+ switch (s->sse_version) {
98
+ case ARMSSE_SSE300:
99
+ return s->iidr;
100
+ break;
101
+ default:
102
+ goto bad_read;
103
+ }
104
+ break;
105
case A_PID4 ... A_CID3:
106
switch (s->sse_version) {
107
case ARMSSE_SSE300:
108
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
109
}
110
break;
111
default:
112
+ bad_read:
113
qemu_log_mask(LOG_GUEST_ERROR,
114
"IoTKit SysInfo read: bad offset %x\n", (int)offset);
115
r = 0;
116
@@ -XXX,XX +XXX,XX @@ static Property iotkit_sysinfo_props[] = {
117
DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
118
DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
119
DEFINE_PROP_UINT32("sse-version", IoTKitSysInfo, sse_version, 0),
120
+ DEFINE_PROP_UINT32("IIDR", IoTKitSysInfo, iidr, 0),
121
DEFINE_PROP_END_OF_LIST()
122
};
123
124
--
125
2.20.1
126
127
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 includes a counter module; implement a model of it.
2
1
3
This counter is documented in the SSE-123 Example Subsystem
4
Technical Reference Manual:
5
https://developer.arm.com/documentation/101370/latest/
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-12-peter.maydell@linaro.org
11
---
12
include/hw/timer/sse-counter.h | 105 ++++++++
13
hw/timer/sse-counter.c | 474 +++++++++++++++++++++++++++++++++
14
MAINTAINERS | 2 +
15
hw/arm/Kconfig | 1 +
16
hw/timer/Kconfig | 3 +
17
hw/timer/meson.build | 1 +
18
hw/timer/trace-events | 7 +
19
7 files changed, 593 insertions(+)
20
create mode 100644 include/hw/timer/sse-counter.h
21
create mode 100644 hw/timer/sse-counter.c
22
23
diff --git a/include/hw/timer/sse-counter.h b/include/hw/timer/sse-counter.h
24
new file mode 100644
25
index XXXXXXX..XXXXXXX
26
--- /dev/null
27
+++ b/include/hw/timer/sse-counter.h
28
@@ -XXX,XX +XXX,XX @@
29
+/*
30
+ * Arm SSE Subsystem System Counter
31
+ *
32
+ * Copyright (c) 2020 Linaro Limited
33
+ * Written by Peter Maydell
34
+ *
35
+ * This program is free software; you can redistribute it and/or modify
36
+ * it under the terms of the GNU General Public License version 2 or
37
+ * (at your option) any later version.
38
+ */
39
+
40
+/*
41
+ * This is a model of the "System counter" which is documented in
42
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
43
+ * https://developer.arm.com/documentation/101370/latest/
44
+ *
45
+ * QEMU interface:
46
+ * + Clock input "CLK": clock
47
+ * + sysbus MMIO region 0: the control register frame
48
+ * + sysbus MMIO region 1: the status register frame
49
+ *
50
+ * Consumers of the system counter's timestamp, such as the SSE
51
+ * System Timer device, can also use the APIs sse_counter_for_timestamp(),
52
+ * sse_counter_tick_to_time() and sse_counter_register_consumer() to
53
+ * interact with an instance of the System Counter. Generally the
54
+ * consumer device should have a QOM link property which the board
55
+ * code can set to the appropriate instance of the system counter.
56
+ */
57
+
58
+#ifndef SSE_COUNTER_H
59
+#define SSE_COUNTER_H
60
+
61
+#include "hw/sysbus.h"
62
+#include "qom/object.h"
63
+#include "qemu/notify.h"
64
+
65
+#define TYPE_SSE_COUNTER "sse-counter"
66
+OBJECT_DECLARE_SIMPLE_TYPE(SSECounter, SSE_COUNTER)
67
+
68
+struct SSECounter {
69
+ /*< private >*/
70
+ SysBusDevice parent_obj;
71
+
72
+ /*< public >*/
73
+ MemoryRegion control_mr;
74
+ MemoryRegion status_mr;
75
+ Clock *clk;
76
+ NotifierList notifier_list;
77
+
78
+ uint32_t cntcr;
79
+ uint32_t cntscr0;
80
+
81
+ /*
82
+ * These are used for handling clock frequency changes: they are a
83
+ * tuple of (QEMU_CLOCK_VIRTUAL timestamp, CNTCV at that time),
84
+ * taken when the clock frequency changes. sse_cntcv() needs them
85
+ * to calculate the current CNTCV.
86
+ */
87
+ uint64_t ns_then;
88
+ uint64_t ticks_then;
89
+};
90
+
91
+/*
92
+ * These functions are the interface by which a consumer of
93
+ * the system timestamp (such as the SSE system timer device)
94
+ * can communicate with the SSECounter.
95
+ */
96
+
97
+/**
98
+ * sse_counter_for_timestamp:
99
+ * @counter: SSECounter
100
+ * @ns: timestamp of QEMU_CLOCK_VIRTUAL in nanoseconds
101
+ *
102
+ * Returns the value of the timestamp counter at the specified
103
+ * point in time (assuming that no changes to scale factor, enable, etc
104
+ * happen in the meantime).
105
+ */
106
+uint64_t sse_counter_for_timestamp(SSECounter *counter, uint64_t ns);
107
+
108
+/**
109
+ * sse_counter_tick_to_time:
110
+ * @counter: SSECounter
111
+ * @tick: tick value
112
+ *
113
+ * Returns the time (a QEMU_CLOCK_VIRTUAL timestamp in nanoseconds)
114
+ * when the timestamp counter will reach the specified tick count.
115
+ * If the counter is not currently running, returns UINT64_MAX.
116
+ */
117
+uint64_t sse_counter_tick_to_time(SSECounter *counter, uint64_t tick);
118
+
119
+/**
120
+ * sse_counter_register_consumer:
121
+ * @counter: SSECounter
122
+ * @notifier: Notifier which is notified on counter changes
123
+ *
124
+ * Registers @notifier with the SSECounter. When the counter's
125
+ * configuration changes in a way that might invalidate information
126
+ * previously returned via sse_counter_for_timestamp() or
127
+ * sse_counter_tick_to_time(), the notifier will be called.
128
+ * Devices which consume the timestamp counter can use this as
129
+ * a cue to recalculate timer events.
130
+ */
131
+void sse_counter_register_consumer(SSECounter *counter, Notifier *notifier);
132
+
133
+#endif
134
diff --git a/hw/timer/sse-counter.c b/hw/timer/sse-counter.c
135
new file mode 100644
136
index XXXXXXX..XXXXXXX
137
--- /dev/null
138
+++ b/hw/timer/sse-counter.c
139
@@ -XXX,XX +XXX,XX @@
140
+/*
141
+ * Arm SSE Subsystem System Counter
142
+ *
143
+ * Copyright (c) 2020 Linaro Limited
144
+ * Written by Peter Maydell
145
+ *
146
+ * This program is free software; you can redistribute it and/or modify
147
+ * it under the terms of the GNU General Public License version 2 or
148
+ * (at your option) any later version.
149
+ */
150
+
151
+/*
152
+ * This is a model of the "System counter" which is documented in
153
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
154
+ * https://developer.arm.com/documentation/101370/latest/
155
+ *
156
+ * The system counter is a non-stop 64-bit up-counter. It provides
157
+ * this count value to other devices like the SSE system timer,
158
+ * which are driven by this system timestamp rather than directly
159
+ * from a clock. Internally to the counter the count is actually
160
+ * 88-bit precision (64.24 fixed point), with a programmable scale factor.
161
+ *
162
+ * The hardware has the optional feature that it supports dynamic
163
+ * clock switching, where two clock inputs are connected, and which
164
+ * one is used is selected via a CLKSEL input signal. Since the
165
+ * users of this device in QEMU don't use this feature, we only model
166
+ * the HWCLKSW=0 configuration.
167
+ */
168
+#include "qemu/osdep.h"
169
+#include "qemu/log.h"
170
+#include "qemu/timer.h"
171
+#include "qapi/error.h"
172
+#include "trace.h"
173
+#include "hw/timer/sse-counter.h"
174
+#include "hw/sysbus.h"
175
+#include "hw/irq.h"
176
+#include "hw/registerfields.h"
177
+#include "hw/clock.h"
178
+#include "hw/qdev-clock.h"
179
+#include "migration/vmstate.h"
180
+
181
+/* Registers in the control frame */
182
+REG32(CNTCR, 0x0)
183
+ FIELD(CNTCR, EN, 0, 1)
184
+ FIELD(CNTCR, HDBG, 1, 1)
185
+ FIELD(CNTCR, SCEN, 2, 1)
186
+ FIELD(CNTCR, INTRMASK, 3, 1)
187
+ FIELD(CNTCR, PSLVERRDIS, 4, 1)
188
+ FIELD(CNTCR, INTRCLR, 5, 1)
189
+/*
190
+ * Although CNTCR defines interrupt-related bits, the counter doesn't
191
+ * appear to actually have an interrupt output. So INTRCLR is
192
+ * effectively a RAZ/WI bit, as are the reserved bits [31:6].
193
+ */
194
+#define CNTCR_VALID_MASK (R_CNTCR_EN_MASK | R_CNTCR_HDBG_MASK | \
195
+ R_CNTCR_SCEN_MASK | R_CNTCR_INTRMASK_MASK | \
196
+ R_CNTCR_PSLVERRDIS_MASK)
197
+REG32(CNTSR, 0x4)
198
+REG32(CNTCV_LO, 0x8)
199
+REG32(CNTCV_HI, 0xc)
200
+REG32(CNTSCR, 0x10) /* Aliased with CNTSCR0 */
201
+REG32(CNTID, 0x1c)
202
+ FIELD(CNTID, CNTSC, 0, 4)
203
+ FIELD(CNTID, CNTCS, 16, 1)
204
+ FIELD(CNTID, CNTSELCLK, 17, 2)
205
+ FIELD(CNTID, CNTSCR_OVR, 19, 1)
206
+REG32(CNTSCR0, 0xd0)
207
+REG32(CNTSCR1, 0xd4)
208
+
209
+/* Registers in the status frame */
210
+REG32(STATUS_CNTCV_LO, 0x0)
211
+REG32(STATUS_CNTCV_HI, 0x4)
212
+
213
+/* Standard ID registers, present in both frames */
214
+REG32(PID4, 0xFD0)
215
+REG32(PID5, 0xFD4)
216
+REG32(PID6, 0xFD8)
217
+REG32(PID7, 0xFDC)
218
+REG32(PID0, 0xFE0)
219
+REG32(PID1, 0xFE4)
220
+REG32(PID2, 0xFE8)
221
+REG32(PID3, 0xFEC)
222
+REG32(CID0, 0xFF0)
223
+REG32(CID1, 0xFF4)
224
+REG32(CID2, 0xFF8)
225
+REG32(CID3, 0xFFC)
226
+
227
+/* PID/CID values */
228
+static const int control_id[] = {
229
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
230
+ 0xba, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
231
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
232
+};
233
+
234
+static const int status_id[] = {
235
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
236
+ 0xbb, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
237
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
238
+};
239
+
240
+static void sse_counter_notify_users(SSECounter *s)
241
+{
242
+ /*
243
+ * Notify users of the count timestamp that they may
244
+ * need to recalculate.
245
+ */
246
+ notifier_list_notify(&s->notifier_list, NULL);
247
+}
248
+
249
+static bool sse_counter_enabled(SSECounter *s)
250
+{
251
+ return (s->cntcr & R_CNTCR_EN_MASK) != 0;
252
+}
253
+
254
+uint64_t sse_counter_tick_to_time(SSECounter *s, uint64_t tick)
255
+{
256
+ if (!sse_counter_enabled(s)) {
257
+ return UINT64_MAX;
258
+ }
259
+
260
+ tick -= s->ticks_then;
261
+
262
+ if (s->cntcr & R_CNTCR_SCEN_MASK) {
263
+ /* Adjust the tick count to account for the scale factor */
264
+ tick = muldiv64(tick, 0x01000000, s->cntscr0);
265
+ }
266
+
267
+ return s->ns_then + clock_ticks_to_ns(s->clk, tick);
268
+}
269
+
270
+void sse_counter_register_consumer(SSECounter *s, Notifier *notifier)
271
+{
272
+ /*
273
+ * For the moment we assume that both we and the devices
274
+ * which consume us last for the life of the simulation,
275
+ * and so there is no mechanism for removing a notifier.
276
+ */
277
+ notifier_list_add(&s->notifier_list, notifier);
278
+}
279
+
280
+uint64_t sse_counter_for_timestamp(SSECounter *s, uint64_t now)
281
+{
282
+ /* Return the CNTCV value for a particular timestamp (clock ns value). */
283
+ uint64_t ticks;
284
+
285
+ if (!sse_counter_enabled(s)) {
286
+ /* Counter is disabled and does not increment */
287
+ return s->ticks_then;
288
+ }
289
+
290
+ ticks = clock_ns_to_ticks(s->clk, now - s->ns_then);
291
+ if (s->cntcr & R_CNTCR_SCEN_MASK) {
292
+ /*
293
+ * Scaling is enabled. The CNTSCR value is the amount added to
294
+ * the underlying 88-bit counter for every tick of the
295
+ * underlying clock; CNTCV is the top 64 bits of that full
296
+ * 88-bit value. Multiplying the tick count by CNTSCR tells us
297
+ * how much the full 88-bit counter has moved on; we then
298
+ * divide that by 0x01000000 to find out how much the 64-bit
299
+ * visible portion has advanced. muldiv64() gives us the
300
+ * necessary at-least-88-bit precision for the intermediate
301
+ * result.
302
+ */
303
+ ticks = muldiv64(ticks, s->cntscr0, 0x01000000);
304
+ }
305
+ return s->ticks_then + ticks;
306
+}
307
+
308
+static uint64_t sse_cntcv(SSECounter *s)
309
+{
310
+ /* Return the CNTCV value for the current time */
311
+ return sse_counter_for_timestamp(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
312
+}
313
+
314
+static void sse_write_cntcv(SSECounter *s, uint32_t value, unsigned startbit)
315
+{
316
+ /*
317
+ * Write one 32-bit half of the counter value; startbit is the
318
+ * bit position of this half in the 64-bit word, either 0 or 32.
319
+ */
320
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
321
+ uint64_t cntcv = sse_counter_for_timestamp(s, now);
322
+
323
+ cntcv = deposit64(cntcv, startbit, 32, value);
324
+ s->ticks_then = cntcv;
325
+ s->ns_then = now;
326
+ sse_counter_notify_users(s);
327
+}
328
+
329
+static uint64_t sse_counter_control_read(void *opaque, hwaddr offset,
330
+ unsigned size)
331
+{
332
+ SSECounter *s = SSE_COUNTER(opaque);
333
+ uint64_t r;
334
+
335
+ switch (offset) {
336
+ case A_CNTCR:
337
+ r = s->cntcr;
338
+ break;
339
+ case A_CNTSR:
340
+ /*
341
+ * The only bit here is DBGH, indicating that the counter has been
342
+ * halted via the Halt-on-Debug signal. We don't implement halting
343
+ * debug, so the whole register always reads as zero.
344
+ */
345
+ r = 0;
346
+ break;
347
+ case A_CNTCV_LO:
348
+ r = extract64(sse_cntcv(s), 0, 32);
349
+ break;
350
+ case A_CNTCV_HI:
351
+ r = extract64(sse_cntcv(s), 32, 32);
352
+ break;
353
+ case A_CNTID:
354
+ /*
355
+ * For our implementation:
356
+ * - CNTSCR can only be written when CNTCR.EN == 0
357
+ * - HWCLKSW=0, so selected clock is always CLK0
358
+ * - counter scaling is implemented
359
+ */
360
+ r = (1 << R_CNTID_CNTSELCLK_SHIFT) | (1 << R_CNTID_CNTSC_SHIFT);
361
+ break;
362
+ case A_CNTSCR:
363
+ case A_CNTSCR0:
364
+ r = s->cntscr0;
365
+ break;
366
+ case A_CNTSCR1:
367
+ /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
368
+ r = 0;
369
+ break;
370
+ case A_PID4 ... A_CID3:
371
+ r = control_id[(offset - A_PID4) / 4];
372
+ break;
373
+ default:
374
+ qemu_log_mask(LOG_GUEST_ERROR,
375
+ "SSE System Counter control frame read: bad offset 0x%x",
376
+ (unsigned)offset);
377
+ r = 0;
378
+ break;
379
+ }
380
+
381
+ trace_sse_counter_control_read(offset, r, size);
382
+ return r;
383
+}
384
+
385
+static void sse_counter_control_write(void *opaque, hwaddr offset,
386
+ uint64_t value, unsigned size)
387
+{
388
+ SSECounter *s = SSE_COUNTER(opaque);
389
+
390
+ trace_sse_counter_control_write(offset, value, size);
391
+
392
+ switch (offset) {
393
+ case A_CNTCR:
394
+ /*
395
+ * Although CNTCR defines interrupt-related bits, the counter doesn't
396
+ * appear to actually have an interrupt output. So INTRCLR is
397
+ * effectively a RAZ/WI bit, as are the reserved bits [31:6].
398
+ * The documentation does not explicitly say so, but we assume
399
+ * that changing the scale factor while the counter is enabled
400
+ * by toggling CNTCR.SCEN has the same behaviour (making the counter
401
+ * value UNKNOWN) as changing it by writing to CNTSCR, and so we
402
+ * don't need to try to recalculate for that case.
403
+ */
404
+ value &= CNTCR_VALID_MASK;
405
+ if ((value ^ s->cntcr) & R_CNTCR_EN_MASK) {
406
+ /*
407
+ * Whether the counter is being enabled or disabled, the
408
+ * required action is the same: sync the (ns_then, ticks_then)
409
+ * tuple.
410
+ */
411
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
412
+ s->ticks_then = sse_counter_for_timestamp(s, now);
413
+ s->ns_then = now;
414
+ sse_counter_notify_users(s);
415
+ }
416
+ s->cntcr = value;
417
+ break;
418
+ case A_CNTCV_LO:
419
+ sse_write_cntcv(s, value, 0);
420
+ break;
421
+ case A_CNTCV_HI:
422
+ sse_write_cntcv(s, value, 32);
423
+ break;
424
+ case A_CNTSCR:
425
+ case A_CNTSCR0:
426
+ /*
427
+ * If the scale registers are changed when the counter is enabled,
428
+ * the count value becomes UNKNOWN. So we don't try to recalculate
429
+ * anything here but only do it on a write to CNTCR.EN.
430
+ */
431
+ s->cntscr0 = value;
432
+ break;
433
+ case A_CNTSCR1:
434
+ /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
435
+ break;
436
+ case A_CNTSR:
437
+ case A_CNTID:
438
+ case A_PID4 ... A_CID3:
439
+ qemu_log_mask(LOG_GUEST_ERROR,
440
+ "SSE System Counter control frame: write to RO offset 0x%x\n",
441
+ (unsigned)offset);
442
+ break;
443
+ default:
444
+ qemu_log_mask(LOG_GUEST_ERROR,
445
+ "SSE System Counter control frame: write to bad offset 0x%x\n",
446
+ (unsigned)offset);
447
+ break;
448
+ }
449
+}
450
+
451
+static uint64_t sse_counter_status_read(void *opaque, hwaddr offset,
452
+ unsigned size)
453
+{
454
+ SSECounter *s = SSE_COUNTER(opaque);
455
+ uint64_t r;
456
+
457
+ switch (offset) {
458
+ case A_STATUS_CNTCV_LO:
459
+ r = extract64(sse_cntcv(s), 0, 32);
460
+ break;
461
+ case A_STATUS_CNTCV_HI:
462
+ r = extract64(sse_cntcv(s), 32, 32);
463
+ break;
464
+ case A_PID4 ... A_CID3:
465
+ r = status_id[(offset - A_PID4) / 4];
466
+ break;
467
+ default:
468
+ qemu_log_mask(LOG_GUEST_ERROR,
469
+ "SSE System Counter status frame read: bad offset 0x%x",
470
+ (unsigned)offset);
471
+ r = 0;
472
+ break;
473
+ }
474
+
475
+ trace_sse_counter_status_read(offset, r, size);
476
+ return r;
477
+}
478
+
479
+static void sse_counter_status_write(void *opaque, hwaddr offset,
480
+ uint64_t value, unsigned size)
481
+{
482
+ trace_sse_counter_status_write(offset, value, size);
483
+
484
+ switch (offset) {
485
+ case A_STATUS_CNTCV_LO:
486
+ case A_STATUS_CNTCV_HI:
487
+ case A_PID4 ... A_CID3:
488
+ qemu_log_mask(LOG_GUEST_ERROR,
489
+ "SSE System Counter status frame: write to RO offset 0x%x\n",
490
+ (unsigned)offset);
491
+ break;
492
+ default:
493
+ qemu_log_mask(LOG_GUEST_ERROR,
494
+ "SSE System Counter status frame: write to bad offset 0x%x\n",
495
+ (unsigned)offset);
496
+ break;
497
+ }
498
+}
499
+
500
+static const MemoryRegionOps sse_counter_control_ops = {
501
+ .read = sse_counter_control_read,
502
+ .write = sse_counter_control_write,
503
+ .endianness = DEVICE_LITTLE_ENDIAN,
504
+ .valid.min_access_size = 4,
505
+ .valid.max_access_size = 4,
506
+};
507
+
508
+static const MemoryRegionOps sse_counter_status_ops = {
509
+ .read = sse_counter_status_read,
510
+ .write = sse_counter_status_write,
511
+ .endianness = DEVICE_LITTLE_ENDIAN,
512
+ .valid.min_access_size = 4,
513
+ .valid.max_access_size = 4,
514
+};
515
+
516
+static void sse_counter_reset(DeviceState *dev)
517
+{
518
+ SSECounter *s = SSE_COUNTER(dev);
519
+
520
+ trace_sse_counter_reset();
521
+
522
+ s->cntcr = 0;
523
+ s->cntscr0 = 0x01000000;
524
+ s->ns_then = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
525
+ s->ticks_then = 0;
526
+}
527
+
528
+static void sse_clk_callback(void *opaque, ClockEvent event)
529
+{
530
+ SSECounter *s = SSE_COUNTER(opaque);
531
+ uint64_t now;
532
+
533
+ switch (event) {
534
+ case ClockPreUpdate:
535
+ /*
536
+ * Before the clock period updates, set (ticks_then, ns_then)
537
+ * to the current time and tick count (as calculated with
538
+ * the old clock period).
539
+ */
540
+ if (sse_counter_enabled(s)) {
541
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
542
+ s->ticks_then = sse_counter_for_timestamp(s, now);
543
+ s->ns_then = now;
544
+ }
545
+ break;
546
+ case ClockUpdate:
547
+ sse_counter_notify_users(s);
548
+ break;
549
+ default:
550
+ break;
551
+ }
552
+}
553
+
554
+static void sse_counter_init(Object *obj)
555
+{
556
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
557
+ SSECounter *s = SSE_COUNTER(obj);
558
+
559
+ notifier_list_init(&s->notifier_list);
560
+
561
+ s->clk = qdev_init_clock_in(DEVICE(obj), "CLK", sse_clk_callback, s,
562
+ ClockPreUpdate | ClockUpdate);
563
+ memory_region_init_io(&s->control_mr, obj, &sse_counter_control_ops,
564
+ s, "sse-counter-control", 0x1000);
565
+ memory_region_init_io(&s->status_mr, obj, &sse_counter_status_ops,
566
+ s, "sse-counter-status", 0x1000);
567
+ sysbus_init_mmio(sbd, &s->control_mr);
568
+ sysbus_init_mmio(sbd, &s->status_mr);
569
+}
570
+
571
+static void sse_counter_realize(DeviceState *dev, Error **errp)
572
+{
573
+ SSECounter *s = SSE_COUNTER(dev);
574
+
575
+ if (!clock_has_source(s->clk)) {
576
+ error_setg(errp, "SSE system counter: CLK must be connected");
577
+ return;
578
+ }
579
+}
580
+
581
+static const VMStateDescription sse_counter_vmstate = {
582
+ .name = "sse-counter",
583
+ .version_id = 1,
584
+ .minimum_version_id = 1,
585
+ .fields = (VMStateField[]) {
586
+ VMSTATE_CLOCK(clk, SSECounter),
587
+ VMSTATE_END_OF_LIST()
588
+ }
589
+};
590
+
591
+static void sse_counter_class_init(ObjectClass *klass, void *data)
592
+{
593
+ DeviceClass *dc = DEVICE_CLASS(klass);
594
+
595
+ dc->realize = sse_counter_realize;
596
+ dc->vmsd = &sse_counter_vmstate;
597
+ dc->reset = sse_counter_reset;
598
+}
599
+
600
+static const TypeInfo sse_counter_info = {
601
+ .name = TYPE_SSE_COUNTER,
602
+ .parent = TYPE_SYS_BUS_DEVICE,
603
+ .instance_size = sizeof(SSECounter),
604
+ .instance_init = sse_counter_init,
605
+ .class_init = sse_counter_class_init,
606
+};
607
+
608
+static void sse_counter_register_types(void)
609
+{
610
+ type_register_static(&sse_counter_info);
611
+}
612
+
613
+type_init(sse_counter_register_types);
614
diff --git a/MAINTAINERS b/MAINTAINERS
615
index XXXXXXX..XXXXXXX 100644
616
--- a/MAINTAINERS
617
+++ b/MAINTAINERS
618
@@ -XXX,XX +XXX,XX @@ F: hw/misc/armsse-cpuid.c
619
F: include/hw/misc/armsse-cpuid.h
620
F: hw/misc/armsse-mhu.c
621
F: include/hw/misc/armsse-mhu.h
622
+F: hw/timer/sse-counter.c
623
+F: include/hw/timer/sse-counter.h
624
F: docs/system/arm/mps2.rst
625
626
Musca
627
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
628
index XXXXXXX..XXXXXXX 100644
629
--- a/hw/arm/Kconfig
630
+++ b/hw/arm/Kconfig
631
@@ -XXX,XX +XXX,XX @@ config ARMSSE
632
select TZ_MSC
633
select TZ_PPC
634
select UNIMP
635
+ select SSE_COUNTER
636
637
config ARMSSE_CPUID
638
bool
639
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
640
index XXXXXXX..XXXXXXX 100644
641
--- a/hw/timer/Kconfig
642
+++ b/hw/timer/Kconfig
643
@@ -XXX,XX +XXX,XX @@ config RENESAS_TMR
644
config RENESAS_CMT
645
bool
646
647
+config SSE_COUNTER
648
+ bool
649
+
650
config AVR_TIMER16
651
bool
652
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
653
index XXXXXXX..XXXXXXX 100644
654
--- a/hw/timer/meson.build
655
+++ b/hw/timer/meson.build
656
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_timer.c'))
657
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c'))
658
softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_timer.c'))
659
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c'))
660
+softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c'))
661
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
662
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
663
664
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
665
index XXXXXXX..XXXXXXX 100644
666
--- a/hw/timer/trace-events
667
+++ b/hw/timer/trace-events
668
@@ -XXX,XX +XXX,XX @@ avr_timer16_interrupt_count(uint8_t cnt) "count: %u"
669
avr_timer16_interrupt_overflow(const char *reason) "overflow: %s"
670
avr_timer16_next_alarm(uint64_t delay_ns) "next alarm: %" PRIu64 " ns from now"
671
avr_timer16_clksrc_update(uint64_t freq_hz, uint64_t period_ns, uint64_t delay_s) "timer frequency: %" PRIu64 " Hz, period: %" PRIu64 " ns (%" PRId64 " us)"
672
+
673
+# sse_counter.c
674
+sse_counter_control_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
675
+sse_counter_control_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control framen write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
676
+sse_counter_status_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
677
+sse_counter_status_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
678
+sse_counter_reset(void) "SSE system counter: reset"
679
--
680
2.20.1
681
682
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 includes some timers which are a different kind to
2
those in the SSE-200. Model them.
3
1
4
These timers are documented in the SSE-123 Example Subsystem
5
Technical Reference Manual:
6
https://developer.arm.com/documentation/101370/latest/
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-13-peter.maydell@linaro.org
12
---
13
include/hw/timer/sse-timer.h | 53 ++++
14
hw/timer/sse-timer.c | 470 +++++++++++++++++++++++++++++++++++
15
MAINTAINERS | 2 +
16
hw/arm/Kconfig | 1 +
17
hw/timer/Kconfig | 3 +
18
hw/timer/meson.build | 1 +
19
hw/timer/trace-events | 5 +
20
7 files changed, 535 insertions(+)
21
create mode 100644 include/hw/timer/sse-timer.h
22
create mode 100644 hw/timer/sse-timer.c
23
24
diff --git a/include/hw/timer/sse-timer.h b/include/hw/timer/sse-timer.h
25
new file mode 100644
26
index XXXXXXX..XXXXXXX
27
--- /dev/null
28
+++ b/include/hw/timer/sse-timer.h
29
@@ -XXX,XX +XXX,XX @@
30
+/*
31
+ * Arm SSE Subsystem System Timer
32
+ *
33
+ * Copyright (c) 2020 Linaro Limited
34
+ * Written by Peter Maydell
35
+ *
36
+ * This program is free software; you can redistribute it and/or modify
37
+ * it under the terms of the GNU General Public License version 2 or
38
+ * (at your option) any later version.
39
+ */
40
+
41
+/*
42
+ * This is a model of the "System timer" which is documented in
43
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
44
+ * https://developer.arm.com/documentation/101370/latest/
45
+ *
46
+ * QEMU interface:
47
+ * + QOM property "counter": link property to be set to the
48
+ * TYPE_SSE_COUNTER timestamp counter device this timer runs off
49
+ * + sysbus MMIO region 0: the register bank
50
+ * + sysbus IRQ 0: timer interrupt
51
+ */
52
+
53
+#ifndef SSE_TIMER_H
54
+#define SSE_TIMER_H
55
+
56
+#include "hw/sysbus.h"
57
+#include "qom/object.h"
58
+#include "hw/timer/sse-counter.h"
59
+
60
+#define TYPE_SSE_TIMER "sse-timer"
61
+OBJECT_DECLARE_SIMPLE_TYPE(SSETimer, SSE_TIMER)
62
+
63
+struct SSETimer {
64
+ /*< private >*/
65
+ SysBusDevice parent_obj;
66
+
67
+ /*< public >*/
68
+ MemoryRegion iomem;
69
+ qemu_irq irq;
70
+ SSECounter *counter;
71
+ QEMUTimer timer;
72
+ Notifier counter_notifier;
73
+
74
+ uint32_t cntfrq;
75
+ uint32_t cntp_ctl;
76
+ uint64_t cntp_cval;
77
+ uint64_t cntp_aival;
78
+ uint32_t cntp_aival_ctl;
79
+ uint32_t cntp_aival_reload;
80
+};
81
+
82
+#endif
83
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
84
new file mode 100644
85
index XXXXXXX..XXXXXXX
86
--- /dev/null
87
+++ b/hw/timer/sse-timer.c
88
@@ -XXX,XX +XXX,XX @@
89
+/*
90
+ * Arm SSE Subsystem System Timer
91
+ *
92
+ * Copyright (c) 2020 Linaro Limited
93
+ * Written by Peter Maydell
94
+ *
95
+ * This program is free software; you can redistribute it and/or modify
96
+ * it under the terms of the GNU General Public License version 2 or
97
+ * (at your option) any later version.
98
+ */
99
+
100
+/*
101
+ * This is a model of the "System timer" which is documented in
102
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
103
+ * https://developer.arm.com/documentation/101370/latest/
104
+ *
105
+ * The timer is based around a simple 64-bit incrementing counter
106
+ * (readable from CNTPCT_HI/LO). The timer fires when
107
+ * Counter - CompareValue >= 0.
108
+ * The CompareValue is guest-writable, via CNTP_CVAL_HI/LO.
109
+ * CNTP_TVAL is an alternative view of the CompareValue defined by
110
+ * TimerValue = CompareValue[31:0] - Counter[31:0]
111
+ * which can be both read and written.
112
+ * This part is similar to the generic timer in an Arm A-class CPU.
113
+ *
114
+ * The timer also has a separate auto-increment timer. When this
115
+ * timer is enabled, then the AutoIncrValue is set to:
116
+ * AutoIncrValue = Reload + Counter
117
+ * and this timer fires when
118
+ * Counter - AutoIncrValue >= 0
119
+ * at which point, an interrupt is generated and the new AutoIncrValue
120
+ * is calculated.
121
+ * When the auto-increment timer is enabled, interrupt generation
122
+ * via the compare/timervalue registers is disabled.
123
+ */
124
+#include "qemu/osdep.h"
125
+#include "qemu/log.h"
126
+#include "qemu/timer.h"
127
+#include "qapi/error.h"
128
+#include "trace.h"
129
+#include "hw/timer/sse-timer.h"
130
+#include "hw/timer/sse-counter.h"
131
+#include "hw/sysbus.h"
132
+#include "hw/irq.h"
133
+#include "hw/registerfields.h"
134
+#include "hw/clock.h"
135
+#include "hw/qdev-clock.h"
136
+#include "hw/qdev-properties.h"
137
+#include "migration/vmstate.h"
138
+
139
+REG32(CNTPCT_LO, 0x0)
140
+REG32(CNTPCT_HI, 0x4)
141
+REG32(CNTFRQ, 0x10)
142
+REG32(CNTP_CVAL_LO, 0x20)
143
+REG32(CNTP_CVAL_HI, 0x24)
144
+REG32(CNTP_TVAL, 0x28)
145
+REG32(CNTP_CTL, 0x2c)
146
+ FIELD(CNTP_CTL, ENABLE, 0, 1)
147
+ FIELD(CNTP_CTL, IMASK, 1, 1)
148
+ FIELD(CNTP_CTL, ISTATUS, 2, 1)
149
+REG32(CNTP_AIVAL_LO, 0x40)
150
+REG32(CNTP_AIVAL_HI, 0x44)
151
+REG32(CNTP_AIVAL_RELOAD, 0x48)
152
+REG32(CNTP_AIVAL_CTL, 0x4c)
153
+ FIELD(CNTP_AIVAL_CTL, EN, 0, 1)
154
+ FIELD(CNTP_AIVAL_CTL, CLR, 1, 1)
155
+REG32(CNTP_CFG, 0x50)
156
+ FIELD(CNTP_CFG, AIVAL, 0, 4)
157
+#define R_CNTP_CFG_AIVAL_IMPLEMENTED 1
158
+REG32(PID4, 0xFD0)
159
+REG32(PID5, 0xFD4)
160
+REG32(PID6, 0xFD8)
161
+REG32(PID7, 0xFDC)
162
+REG32(PID0, 0xFE0)
163
+REG32(PID1, 0xFE4)
164
+REG32(PID2, 0xFE8)
165
+REG32(PID3, 0xFEC)
166
+REG32(CID0, 0xFF0)
167
+REG32(CID1, 0xFF4)
168
+REG32(CID2, 0xFF8)
169
+REG32(CID3, 0xFFC)
170
+
171
+/* PID/CID values */
172
+static const int timer_id[] = {
173
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
174
+ 0xb7, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
175
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
176
+};
177
+
178
+static bool sse_is_autoinc(SSETimer *s)
179
+{
180
+ return (s->cntp_aival_ctl & R_CNTP_AIVAL_CTL_EN_MASK) != 0;
181
+}
182
+
183
+static bool sse_enabled(SSETimer *s)
184
+{
185
+ return (s->cntp_ctl & R_CNTP_CTL_ENABLE_MASK) != 0;
186
+}
187
+
188
+static uint64_t sse_cntpct(SSETimer *s)
189
+{
190
+ /* Return the CNTPCT value for the current time */
191
+ return sse_counter_for_timestamp(s->counter,
192
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
193
+}
194
+
195
+static bool sse_timer_status(SSETimer *s)
196
+{
197
+ /*
198
+ * Return true if timer condition is met. This is used for both
199
+ * the CNTP_CTL.ISTATUS bit and for whether (unless masked) we
200
+ * assert our IRQ.
201
+ * The documentation is unclear about the behaviour of ISTATUS when
202
+ * in autoincrement mode; we assume that it follows CNTP_AIVAL_CTL.CLR
203
+ * (ie whether the autoincrement timer is asserting the interrupt).
204
+ */
205
+ if (!sse_enabled(s)) {
206
+ return false;
207
+ }
208
+
209
+ if (sse_is_autoinc(s)) {
210
+ return s->cntp_aival_ctl & R_CNTP_AIVAL_CTL_CLR_MASK;
211
+ } else {
212
+ return sse_cntpct(s) >= s->cntp_cval;
213
+ }
214
+}
215
+
216
+static void sse_update_irq(SSETimer *s)
217
+{
218
+ bool irqstate = (!(s->cntp_ctl & R_CNTP_CTL_IMASK_MASK) &&
219
+ sse_timer_status(s));
220
+
221
+ qemu_set_irq(s->irq, irqstate);
222
+}
223
+
224
+static void sse_set_timer(SSETimer *s, uint64_t nexttick)
225
+{
226
+ /* Set the timer to expire at nexttick */
227
+ uint64_t expiry = sse_counter_tick_to_time(s->counter, nexttick);
228
+
229
+ if (expiry <= INT64_MAX) {
230
+ timer_mod_ns(&s->timer, expiry);
231
+ } else {
232
+ /*
233
+ * nexttick is so far in the future that it would overflow the
234
+ * signed 64-bit range of a QEMUTimer. Since timer_mod_ns()
235
+ * expiry times are absolute, not relative, we are never going
236
+ * to be able to set the timer to this value, so we must just
237
+ * assume that guest execution can never run so long that it
238
+ * reaches the theoretical point when the timer fires.
239
+ * This is also the code path for "counter is not running",
240
+ * which is signalled by expiry == UINT64_MAX.
241
+ */
242
+ timer_del(&s->timer);
243
+ }
244
+}
245
+
246
+static void sse_recalc_timer(SSETimer *s)
247
+{
248
+ /* Recalculate the normal timer */
249
+ uint64_t count, nexttick;
250
+
251
+ if (sse_is_autoinc(s)) {
252
+ return;
253
+ }
254
+
255
+ if (!sse_enabled(s)) {
256
+ timer_del(&s->timer);
257
+ return;
258
+ }
259
+
260
+ count = sse_cntpct(s);
261
+
262
+ if (count >= s->cntp_cval) {
263
+ /*
264
+ * Timer condition already met. In theory we have a transition when
265
+ * the count rolls back over to 0, but that is so far in the future
266
+ * that it is not representable as a timer_mod() expiry, so in
267
+ * fact sse_set_timer() will always just delete the timer.
268
+ */
269
+ nexttick = UINT64_MAX;
270
+ } else {
271
+ /* Next transition is when count hits cval */
272
+ nexttick = s->cntp_cval;
273
+ }
274
+ sse_set_timer(s, nexttick);
275
+ sse_update_irq(s);
276
+}
277
+
278
+static void sse_autoinc(SSETimer *s)
279
+{
280
+ /* Auto-increment the AIVAL, and set the timer accordingly */
281
+ s->cntp_aival = sse_cntpct(s) + s->cntp_aival_reload;
282
+ sse_set_timer(s, s->cntp_aival);
283
+}
284
+
285
+static void sse_timer_cb(void *opaque)
286
+{
287
+ SSETimer *s = SSE_TIMER(opaque);
288
+
289
+ if (sse_is_autoinc(s)) {
290
+ uint64_t count = sse_cntpct(s);
291
+
292
+ if (count >= s->cntp_aival) {
293
+ /* Timer condition met, set CLR and do another autoinc */
294
+ s->cntp_aival_ctl |= R_CNTP_AIVAL_CTL_CLR_MASK;
295
+ s->cntp_aival = count + s->cntp_aival_reload;
296
+ }
297
+ sse_set_timer(s, s->cntp_aival);
298
+ sse_update_irq(s);
299
+ } else {
300
+ sse_recalc_timer(s);
301
+ }
302
+}
303
+
304
+static uint64_t sse_timer_read(void *opaque, hwaddr offset, unsigned size)
305
+{
306
+ SSETimer *s = SSE_TIMER(opaque);
307
+ uint64_t r;
308
+
309
+ switch (offset) {
310
+ case A_CNTPCT_LO:
311
+ r = extract64(sse_cntpct(s), 0, 32);
312
+ break;
313
+ case A_CNTPCT_HI:
314
+ r = extract64(sse_cntpct(s), 32, 32);
315
+ break;
316
+ case A_CNTFRQ:
317
+ r = s->cntfrq;
318
+ break;
319
+ case A_CNTP_CVAL_LO:
320
+ r = extract64(s->cntp_cval, 0, 32);
321
+ break;
322
+ case A_CNTP_CVAL_HI:
323
+ r = extract64(s->cntp_cval, 32, 32);
324
+ break;
325
+ case A_CNTP_TVAL:
326
+ r = extract64(s->cntp_cval - sse_cntpct(s), 0, 32);
327
+ break;
328
+ case A_CNTP_CTL:
329
+ r = s->cntp_ctl;
330
+ if (sse_timer_status(s)) {
331
+ r |= R_CNTP_CTL_ISTATUS_MASK;
332
+ }
333
+ break;
334
+ case A_CNTP_AIVAL_LO:
335
+ r = extract64(s->cntp_aival, 0, 32);
336
+ break;
337
+ case A_CNTP_AIVAL_HI:
338
+ r = extract64(s->cntp_aival, 32, 32);
339
+ break;
340
+ case A_CNTP_AIVAL_RELOAD:
341
+ r = s->cntp_aival_reload;
342
+ break;
343
+ case A_CNTP_AIVAL_CTL:
344
+ /*
345
+ * All the bits of AIVAL_CTL are documented as WO, but this is probably
346
+ * a documentation error. We implement them as readable.
347
+ */
348
+ r = s->cntp_aival_ctl;
349
+ break;
350
+ case A_CNTP_CFG:
351
+ r = R_CNTP_CFG_AIVAL_IMPLEMENTED << R_CNTP_CFG_AIVAL_SHIFT;
352
+ break;
353
+ case A_PID4 ... A_CID3:
354
+ r = timer_id[(offset - A_PID4) / 4];
355
+ break;
356
+ default:
357
+ qemu_log_mask(LOG_GUEST_ERROR,
358
+ "SSE System Timer read: bad offset 0x%x",
359
+ (unsigned) offset);
360
+ r = 0;
361
+ break;
362
+ }
363
+
364
+ trace_sse_timer_read(offset, r, size);
365
+ return r;
366
+}
367
+
368
+static void sse_timer_write(void *opaque, hwaddr offset, uint64_t value,
369
+ unsigned size)
370
+{
371
+ SSETimer *s = SSE_TIMER(opaque);
372
+
373
+ trace_sse_timer_write(offset, value, size);
374
+
375
+ switch (offset) {
376
+ case A_CNTFRQ:
377
+ s->cntfrq = value;
378
+ break;
379
+ case A_CNTP_CVAL_LO:
380
+ s->cntp_cval = deposit64(s->cntp_cval, 0, 32, value);
381
+ sse_recalc_timer(s);
382
+ break;
383
+ case A_CNTP_CVAL_HI:
384
+ s->cntp_cval = deposit64(s->cntp_cval, 32, 32, value);
385
+ sse_recalc_timer(s);
386
+ break;
387
+ case A_CNTP_TVAL:
388
+ s->cntp_cval = sse_cntpct(s) + sextract64(value, 0, 32);
389
+ sse_recalc_timer(s);
390
+ break;
391
+ case A_CNTP_CTL:
392
+ {
393
+ uint32_t old_ctl = s->cntp_ctl;
394
+ value &= R_CNTP_CTL_ENABLE_MASK | R_CNTP_CTL_IMASK_MASK;
395
+ s->cntp_ctl = value;
396
+ if ((old_ctl ^ s->cntp_ctl) & R_CNTP_CTL_ENABLE_MASK) {
397
+ if (sse_enabled(s)) {
398
+ if (sse_is_autoinc(s)) {
399
+ sse_autoinc(s);
400
+ } else {
401
+ sse_recalc_timer(s);
402
+ }
403
+ }
404
+ }
405
+ sse_update_irq(s);
406
+ break;
407
+ }
408
+ case A_CNTP_AIVAL_RELOAD:
409
+ s->cntp_aival_reload = value;
410
+ break;
411
+ case A_CNTP_AIVAL_CTL:
412
+ {
413
+ uint32_t old_ctl = s->cntp_aival_ctl;
414
+
415
+ /* EN bit is writeable; CLR bit is write-0-to-clear, write-1-ignored */
416
+ s->cntp_aival_ctl &= ~R_CNTP_AIVAL_CTL_EN_MASK;
417
+ s->cntp_aival_ctl |= value & R_CNTP_AIVAL_CTL_EN_MASK;
418
+ if (!(value & R_CNTP_AIVAL_CTL_CLR_MASK)) {
419
+ s->cntp_aival_ctl &= ~R_CNTP_AIVAL_CTL_CLR_MASK;
420
+ }
421
+ if ((old_ctl ^ s->cntp_aival_ctl) & R_CNTP_AIVAL_CTL_EN_MASK) {
422
+ /* Auto-increment toggled on/off */
423
+ if (sse_enabled(s)) {
424
+ if (sse_is_autoinc(s)) {
425
+ sse_autoinc(s);
426
+ } else {
427
+ sse_recalc_timer(s);
428
+ }
429
+ }
430
+ }
431
+ sse_update_irq(s);
432
+ break;
433
+ }
434
+ case A_CNTPCT_LO:
435
+ case A_CNTPCT_HI:
436
+ case A_CNTP_CFG:
437
+ case A_CNTP_AIVAL_LO:
438
+ case A_CNTP_AIVAL_HI:
439
+ case A_PID4 ... A_CID3:
440
+ qemu_log_mask(LOG_GUEST_ERROR,
441
+ "SSE System Timer write: write to RO offset 0x%x\n",
442
+ (unsigned)offset);
443
+ break;
444
+ default:
445
+ qemu_log_mask(LOG_GUEST_ERROR,
446
+ "SSE System Timer write: bad offset 0x%x\n",
447
+ (unsigned)offset);
448
+ break;
449
+ }
450
+}
451
+
452
+static const MemoryRegionOps sse_timer_ops = {
453
+ .read = sse_timer_read,
454
+ .write = sse_timer_write,
455
+ .endianness = DEVICE_LITTLE_ENDIAN,
456
+ .valid.min_access_size = 4,
457
+ .valid.max_access_size = 4,
458
+};
459
+
460
+static void sse_timer_reset(DeviceState *dev)
461
+{
462
+ SSETimer *s = SSE_TIMER(dev);
463
+
464
+ trace_sse_timer_reset();
465
+
466
+ timer_del(&s->timer);
467
+ s->cntfrq = 0;
468
+ s->cntp_ctl = 0;
469
+ s->cntp_cval = 0;
470
+ s->cntp_aival = 0;
471
+ s->cntp_aival_ctl = 0;
472
+ s->cntp_aival_reload = 0;
473
+}
474
+
475
+static void sse_timer_counter_callback(Notifier *notifier, void *data)
476
+{
477
+ SSETimer *s = container_of(notifier, SSETimer, counter_notifier);
478
+
479
+ /* System counter told us we need to recalculate */
480
+ if (sse_enabled(s)) {
481
+ if (sse_is_autoinc(s)) {
482
+ sse_set_timer(s, s->cntp_aival);
483
+ } else {
484
+ sse_recalc_timer(s);
485
+ }
486
+ }
487
+}
488
+
489
+static void sse_timer_init(Object *obj)
490
+{
491
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
492
+ SSETimer *s = SSE_TIMER(obj);
493
+
494
+ memory_region_init_io(&s->iomem, obj, &sse_timer_ops,
495
+ s, "sse-timer", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->iomem);
497
+ sysbus_init_irq(sbd, &s->irq);
498
+}
499
+
500
+static void sse_timer_realize(DeviceState *dev, Error **errp)
501
+{
502
+ SSETimer *s = SSE_TIMER(dev);
503
+
504
+ if (!s->counter) {
505
+ error_setg(errp, "counter property was not set");
506
+ }
507
+
508
+ s->counter_notifier.notify = sse_timer_counter_callback;
509
+ sse_counter_register_consumer(s->counter, &s->counter_notifier);
510
+
511
+ timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, sse_timer_cb, s);
512
+}
513
+
514
+static const VMStateDescription sse_timer_vmstate = {
515
+ .name = "sse-timer",
516
+ .version_id = 1,
517
+ .minimum_version_id = 1,
518
+ .fields = (VMStateField[]) {
519
+ VMSTATE_TIMER(timer, SSETimer),
520
+ VMSTATE_UINT32(cntfrq, SSETimer),
521
+ VMSTATE_UINT32(cntp_ctl, SSETimer),
522
+ VMSTATE_UINT64(cntp_cval, SSETimer),
523
+ VMSTATE_UINT64(cntp_aival, SSETimer),
524
+ VMSTATE_UINT32(cntp_aival_ctl, SSETimer),
525
+ VMSTATE_UINT32(cntp_aival_reload, SSETimer),
526
+ VMSTATE_END_OF_LIST()
527
+ }
528
+};
529
+
530
+static Property sse_timer_properties[] = {
531
+ DEFINE_PROP_LINK("counter", SSETimer, counter, TYPE_SSE_COUNTER, SSECounter *),
532
+ DEFINE_PROP_END_OF_LIST(),
533
+};
534
+
535
+static void sse_timer_class_init(ObjectClass *klass, void *data)
536
+{
537
+ DeviceClass *dc = DEVICE_CLASS(klass);
538
+
539
+ dc->realize = sse_timer_realize;
540
+ dc->vmsd = &sse_timer_vmstate;
541
+ dc->reset = sse_timer_reset;
542
+ device_class_set_props(dc, sse_timer_properties);
543
+}
544
+
545
+static const TypeInfo sse_timer_info = {
546
+ .name = TYPE_SSE_TIMER,
547
+ .parent = TYPE_SYS_BUS_DEVICE,
548
+ .instance_size = sizeof(SSETimer),
549
+ .instance_init = sse_timer_init,
550
+ .class_init = sse_timer_class_init,
551
+};
552
+
553
+static void sse_timer_register_types(void)
554
+{
555
+ type_register_static(&sse_timer_info);
556
+}
557
+
558
+type_init(sse_timer_register_types);
559
diff --git a/MAINTAINERS b/MAINTAINERS
560
index XXXXXXX..XXXXXXX 100644
561
--- a/MAINTAINERS
562
+++ b/MAINTAINERS
563
@@ -XXX,XX +XXX,XX @@ F: hw/misc/armsse-mhu.c
564
F: include/hw/misc/armsse-mhu.h
565
F: hw/timer/sse-counter.c
566
F: include/hw/timer/sse-counter.h
567
+F: hw/timer/sse-timer.c
568
+F: include/hw/timer/sse-timer.h
569
F: docs/system/arm/mps2.rst
570
571
Musca
572
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
573
index XXXXXXX..XXXXXXX 100644
574
--- a/hw/arm/Kconfig
575
+++ b/hw/arm/Kconfig
576
@@ -XXX,XX +XXX,XX @@ config ARMSSE
577
select TZ_PPC
578
select UNIMP
579
select SSE_COUNTER
580
+ select SSE_TIMER
581
582
config ARMSSE_CPUID
583
bool
584
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
585
index XXXXXXX..XXXXXXX 100644
586
--- a/hw/timer/Kconfig
587
+++ b/hw/timer/Kconfig
588
@@ -XXX,XX +XXX,XX @@ config RENESAS_CMT
589
config SSE_COUNTER
590
bool
591
592
+config SSE_TIMER
593
+ bool
594
+
595
config AVR_TIMER16
596
bool
597
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
598
index XXXXXXX..XXXXXXX 100644
599
--- a/hw/timer/meson.build
600
+++ b/hw/timer/meson.build
601
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c'))
602
softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_timer.c'))
603
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c'))
604
softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c'))
605
+softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c'))
606
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
607
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
608
609
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
610
index XXXXXXX..XXXXXXX 100644
611
--- a/hw/timer/trace-events
612
+++ b/hw/timer/trace-events
613
@@ -XXX,XX +XXX,XX @@ sse_counter_control_write(uint64_t offset, uint64_t data, unsigned size) "SSE sy
614
sse_counter_status_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
615
sse_counter_status_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
616
sse_counter_reset(void) "SSE system counter: reset"
617
+
618
+# sse_timer.c
619
+sse_timer_read(uint64_t offset, uint64_t data, unsigned size) "SSE system timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
620
+sse_timer_write(uint64_t offset, uint64_t data, unsigned size) "SSE system timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
621
+sse_timer_reset(void) "SSE system timer: reset"
622
--
623
2.20.1
624
625
diff view generated by jsdifflib
Deleted patch
1
The SSE-300's iokit-sysctl device is similar to the SSE-200, but
2
some registers have moved address or have different behaviours.
3
In this commit we add case statements for the registers where
4
the SSE-300 and SSE-200 have the same behaviour. Some registers
5
are the same on all SSE versions and so need no code change at all.
6
Putting both of these categories together covers:
7
1
8
0x0 SECDBGSTAT
9
0x4 SECDBGSET
10
0x8 SECDBGCLR
11
0xc SCSECCTRL
12
0x10 CLK_CFG0 -- this is like SSE-200 FCLK_DIV but with a
13
different set of clocks being controlled; our implementation
14
is a dummy reads-as-written anyway
15
0x14 CLK_CFG1 -- similar to SSE-200 SYSCLK_DIV; our implementation
16
is a dummy
17
0x18 CLK_FORCE -- similar to SSE-200 but different bit allocations;
18
we have a dummy implementation
19
0x100 RESET_SYNDROME -- bit allocation differs from SSE-200 but our
20
implementation is a dummy
21
0x104 RESET_MASK -- bit allocation differs from SSE-200 but our
22
implementation is a dummy
23
0x108 SWRESET
24
0x10c GRETREG
25
0x200 PDCM_PD_SYS_SENSE -- some bit allocations differ, but our
26
implementation is a dummy
27
28
We also need to migrate the state of these registers which are shared
29
between the SSE-200 and SSE-300, so update the vmstate 'needed'
30
function to do this.
31
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
34
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Message-id: 20210219144617.4782-14-peter.maydell@linaro.org
36
---
37
hw/misc/iotkit-sysctl.c | 12 +++++++++++-
38
1 file changed, 11 insertions(+), 1 deletion(-)
39
40
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/misc/iotkit-sysctl.c
43
+++ b/hw/misc/iotkit-sysctl.c
44
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
45
case ARMSSE_IOTKIT:
46
goto bad_offset;
47
case ARMSSE_SSE200:
48
+ case ARMSSE_SSE300:
49
r = s->scsecctrl;
50
break;
51
default:
52
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
53
case ARMSSE_IOTKIT:
54
goto bad_offset;
55
case ARMSSE_SSE200:
56
+ case ARMSSE_SSE300:
57
r = s->fclk_div;
58
break;
59
default:
60
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
61
case ARMSSE_IOTKIT:
62
goto bad_offset;
63
case ARMSSE_SSE200:
64
+ case ARMSSE_SSE300:
65
r = s->sysclk_div;
66
break;
67
default:
68
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
69
case ARMSSE_IOTKIT:
70
goto bad_offset;
71
case ARMSSE_SSE200:
72
+ case ARMSSE_SSE300:
73
r = s->clock_force;
74
break;
75
default:
76
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
77
case ARMSSE_IOTKIT:
78
goto bad_offset;
79
case ARMSSE_SSE200:
80
+ case ARMSSE_SSE300:
81
r = s->pdcm_pd_sys_sense;
82
break;
83
default:
84
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
85
case ARMSSE_IOTKIT:
86
goto bad_offset;
87
case ARMSSE_SSE200:
88
+ case ARMSSE_SSE300:
89
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
90
s->scsecctrl = value;
91
break;
92
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
93
case ARMSSE_IOTKIT:
94
goto bad_offset;
95
case ARMSSE_SSE200:
96
+ case ARMSSE_SSE300:
97
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
98
s->fclk_div = value;
99
break;
100
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
101
case ARMSSE_IOTKIT:
102
goto bad_offset;
103
case ARMSSE_SSE200:
104
+ case ARMSSE_SSE300:
105
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
106
s->sysclk_div = value;
107
break;
108
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
109
case ARMSSE_IOTKIT:
110
goto bad_offset;
111
case ARMSSE_SSE200:
112
+ case ARMSSE_SSE300:
113
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
114
s->clock_force = value;
115
break;
116
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
117
case ARMSSE_IOTKIT:
118
goto bad_offset;
119
case ARMSSE_SSE200:
120
+ case ARMSSE_SSE300:
121
qemu_log_mask(LOG_UNIMP,
122
"IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
123
s->pdcm_pd_sys_sense = value;
124
@@ -XXX,XX +XXX,XX @@ static bool sse200_needed(void *opaque)
125
{
126
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
127
128
- return s->sse_version == ARMSSE_SSE200;
129
+ return s->sse_version != ARMSSE_IOTKIT;
130
}
131
132
static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
133
--
134
2.20.1
135
136
diff view generated by jsdifflib
Deleted patch
1
In the SSE-300 the CPU_WAIT and NMI_ENABLE registers have
2
moved offsets, so they are now where the SSE-200's WICCTRL
3
and EWCTRL were. The SSE-300 does not have WICCTLR or EWCTRL
4
at all, and the old offsets are reserved:
5
1
6
Offset SSE-200 SSE-300
7
-----------------------------------
8
0x118 CPUWAIT reserved
9
0x118 NMI_ENABLE reserved
10
0x120 WICCTRL CPUWAIT
11
0x124 EWCTRL NMI_ENABLE
12
13
Handle this reshuffle, and the fact that SSE-300 has only
14
one CPU and so only one active bit in CPUWAIT.
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20210219144617.4782-15-peter.maydell@linaro.org
20
---
21
hw/misc/iotkit-sysctl.c | 88 +++++++++++++++++++++++++++++++++++------
22
1 file changed, 76 insertions(+), 12 deletions(-)
23
24
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/iotkit-sysctl.c
27
+++ b/hw/misc/iotkit-sysctl.c
28
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
29
}
30
break;
31
case A_CPUWAIT:
32
- r = s->cpuwait;
33
+ switch (s->sse_version) {
34
+ case ARMSSE_IOTKIT:
35
+ case ARMSSE_SSE200:
36
+ r = s->cpuwait;
37
+ break;
38
+ case ARMSSE_SSE300:
39
+ /* In SSE300 this is reserved (for INITSVTOR2) */
40
+ goto bad_offset;
41
+ default:
42
+ g_assert_not_reached();
43
+ }
44
break;
45
case A_NMI_ENABLE:
46
switch (s->sse_version) {
47
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
48
case ARMSSE_SSE200:
49
r = s->nmi_enable;
50
break;
51
+ case ARMSSE_SSE300:
52
+ /* In SSE300 this is reserved (for INITSVTOR3) */
53
+ goto bad_offset;
54
default:
55
g_assert_not_reached();
56
}
57
break;
58
case A_WICCTRL:
59
- r = s->wicctrl;
60
+ switch (s->sse_version) {
61
+ case ARMSSE_IOTKIT:
62
+ case ARMSSE_SSE200:
63
+ r = s->wicctrl;
64
+ break;
65
+ case ARMSSE_SSE300:
66
+ /* In SSE300 this offset is CPUWAIT */
67
+ r = s->cpuwait;
68
+ break;
69
+ default:
70
+ g_assert_not_reached();
71
+ }
72
break;
73
case A_EWCTRL:
74
switch (s->sse_version) {
75
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
76
case ARMSSE_SSE200:
77
r = s->ewctrl;
78
break;
79
+ case ARMSSE_SSE300:
80
+ /* In SSE300 this offset is is NMI_ENABLE */
81
+ r = s->nmi_enable;
82
+ break;
83
default:
84
g_assert_not_reached();
85
}
86
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
87
return r;
88
}
89
90
+static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
91
+{
92
+ int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
93
+ int i;
94
+
95
+ for (i = 0; i < num_cpus; i++) {
96
+ uint32_t mask = 1 << i;
97
+ if ((s->cpuwait & mask) && !(value & mask)) {
98
+ /* Powering up CPU 0 */
99
+ arm_set_cpu_on_and_reset(i);
100
+ }
101
+ }
102
+ s->cpuwait = value;
103
+}
104
+
105
static void iotkit_sysctl_write(void *opaque, hwaddr offset,
106
uint64_t value, unsigned size)
107
{
108
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
109
set_init_vtor(0, s->initsvtor0);
110
break;
111
case A_CPUWAIT:
112
- if ((s->cpuwait & 1) && !(value & 1)) {
113
- /* Powering up CPU 0 */
114
- arm_set_cpu_on_and_reset(0);
115
+ switch (s->sse_version) {
116
+ case ARMSSE_IOTKIT:
117
+ case ARMSSE_SSE200:
118
+ cpuwait_write(s, value);
119
+ break;
120
+ case ARMSSE_SSE300:
121
+ /* In SSE300 this is reserved (for INITSVTOR2) */
122
+ goto bad_offset;
123
+ default:
124
+ g_assert_not_reached();
125
}
126
- if ((s->cpuwait & 2) && !(value & 2)) {
127
- /* Powering up CPU 1 */
128
- arm_set_cpu_on_and_reset(1);
129
- }
130
- s->cpuwait = value;
131
break;
132
case A_WICCTRL:
133
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
134
- s->wicctrl = value;
135
+ switch (s->sse_version) {
136
+ case ARMSSE_IOTKIT:
137
+ case ARMSSE_SSE200:
138
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
139
+ s->wicctrl = value;
140
+ break;
141
+ case ARMSSE_SSE300:
142
+ /* In SSE300 this offset is CPUWAIT */
143
+ cpuwait_write(s, value);
144
+ break;
145
+ default:
146
+ g_assert_not_reached();
147
+ }
148
break;
149
case A_SECDBGSET:
150
/* write-1-to-set */
151
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
152
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
153
s->ewctrl = value;
154
break;
155
+ case ARMSSE_SSE300:
156
+ /* In SSE300 this offset is is NMI_ENABLE */
157
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
158
+ s->nmi_enable = value;
159
+ break;
160
default:
161
g_assert_not_reached();
162
}
163
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
164
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
165
s->nmi_enable = value;
166
break;
167
+ case ARMSSE_SSE300:
168
+ /* In SSE300 this is reserved (for INITSVTOR3) */
169
+ goto bad_offset;
170
default:
171
g_assert_not_reached();
172
}
173
--
174
2.20.1
175
176
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has only one CPU and so no INITSVTOR1. It does
2
have INITSVTOR0, but unlike the SSE-200 this register now
3
has a LOCK bit which can be set to 1 to prevent any further
4
writes to the register. Implement these differences.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-16-peter.maydell@linaro.org
10
---
11
hw/misc/iotkit-sysctl.c | 27 +++++++++++++++++++++++++--
12
1 file changed, 25 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/misc/iotkit-sysctl.c
17
+++ b/hw/misc/iotkit-sysctl.c
18
@@ -XXX,XX +XXX,XX @@ REG32(SWRESET, 0x108)
19
FIELD(SWRESET, SWRESETREQ, 9, 1)
20
REG32(GRETREG, 0x10c)
21
REG32(INITSVTOR0, 0x110)
22
+ FIELD(INITSVTOR0, LOCK, 0, 1)
23
+ FIELD(INITSVTOR0, VTOR, 7, 25)
24
REG32(INITSVTOR1, 0x114)
25
REG32(CPUWAIT, 0x118)
26
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
27
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
28
case ARMSSE_SSE200:
29
r = s->initsvtor1;
30
break;
31
+ case ARMSSE_SSE300:
32
+ goto bad_offset;
33
default:
34
g_assert_not_reached();
35
}
36
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
37
s->gretreg = value;
38
break;
39
case A_INITSVTOR0:
40
- s->initsvtor0 = value;
41
- set_init_vtor(0, s->initsvtor0);
42
+ switch (s->sse_version) {
43
+ case ARMSSE_SSE300:
44
+ /* SSE300 has a LOCK bit which prevents further writes when set */
45
+ if (s->initsvtor0 & R_INITSVTOR0_LOCK_MASK) {
46
+ qemu_log_mask(LOG_GUEST_ERROR,
47
+ "IoTKit INITSVTOR0 write when register locked\n");
48
+ break;
49
+ }
50
+ s->initsvtor0 = value;
51
+ set_init_vtor(0, s->initsvtor0 & R_INITSVTOR0_VTOR_MASK);
52
+ break;
53
+ case ARMSSE_IOTKIT:
54
+ case ARMSSE_SSE200:
55
+ s->initsvtor0 = value;
56
+ set_init_vtor(0, s->initsvtor0);
57
+ break;
58
+ default:
59
+ g_assert_not_reached();
60
+ }
61
break;
62
case A_CPUWAIT:
63
switch (s->sse_version) {
64
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
65
s->initsvtor1 = value;
66
set_init_vtor(1, s->initsvtor1);
67
break;
68
+ case ARMSSE_SSE300:
69
+ goto bad_offset;
70
default:
71
g_assert_not_reached();
72
}
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a new PWRCTRL register at offset 0x1fc (previously
2
reserved). This register controls accessibility of some registers
3
in the Power Policy Units (PPUs). Since QEMU doesn't implement
4
the PPUs, we don't need to implement any real behaviour for this
5
register, so we just handle the UNLOCK bit which controls whether
6
writes to the register itself are permitted and otherwise make it
7
be reads-as-written.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-17-peter.maydell@linaro.org
13
---
14
include/hw/misc/iotkit-sysctl.h | 1 +
15
hw/misc/iotkit-sysctl.c | 52 +++++++++++++++++++++++++++++++++
16
2 files changed, 53 insertions(+)
17
18
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/misc/iotkit-sysctl.h
21
+++ b/include/hw/misc/iotkit-sysctl.h
22
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
23
uint32_t initsvtor1;
24
uint32_t nmi_enable;
25
uint32_t ewctrl;
26
+ uint32_t pwrctrl;
27
uint32_t pdcm_pd_sys_sense;
28
uint32_t pdcm_pd_sram0_sense;
29
uint32_t pdcm_pd_sram1_sense;
30
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/iotkit-sysctl.c
33
+++ b/hw/misc/iotkit-sysctl.c
34
@@ -XXX,XX +XXX,XX @@ REG32(CPUWAIT, 0x118)
35
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
36
REG32(WICCTRL, 0x120)
37
REG32(EWCTRL, 0x124)
38
+REG32(PWRCTRL, 0x1fc)
39
+ FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
40
+ FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
41
REG32(PDCM_PD_SYS_SENSE, 0x200)
42
REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
43
REG32(PDCM_PD_SRAM1_SENSE, 0x210)
44
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
45
g_assert_not_reached();
46
}
47
break;
48
+ case A_PWRCTRL:
49
+ switch (s->sse_version) {
50
+ case ARMSSE_IOTKIT:
51
+ case ARMSSE_SSE200:
52
+ goto bad_offset;
53
+ case ARMSSE_SSE300:
54
+ r = s->pwrctrl;
55
+ break;
56
+ default:
57
+ g_assert_not_reached();
58
+ }
59
+ break;
60
case A_PDCM_PD_SYS_SENSE:
61
switch (s->sse_version) {
62
case ARMSSE_IOTKIT:
63
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
64
g_assert_not_reached();
65
}
66
break;
67
+ case A_PWRCTRL:
68
+ switch (s->sse_version) {
69
+ case ARMSSE_IOTKIT:
70
+ case ARMSSE_SSE200:
71
+ goto bad_offset;
72
+ case ARMSSE_SSE300:
73
+ if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
74
+ qemu_log_mask(LOG_GUEST_ERROR,
75
+ "IoTKit PWRCTRL write when register locked\n");
76
+ break;
77
+ }
78
+ s->pwrctrl = value;
79
+ break;
80
+ default:
81
+ g_assert_not_reached();
82
+ }
83
+ break;
84
case A_PDCM_PD_SYS_SENSE:
85
switch (s->sse_version) {
86
case ARMSSE_IOTKIT:
87
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_reset(DeviceState *dev)
88
s->clock_force = 0;
89
s->nmi_enable = 0;
90
s->ewctrl = 0;
91
+ s->pwrctrl = 0x3;
92
s->pdcm_pd_sys_sense = 0x7f;
93
s->pdcm_pd_sram0_sense = 0;
94
s->pdcm_pd_sram1_sense = 0;
95
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
96
}
97
}
98
99
+static bool sse300_needed(void *opaque)
100
+{
101
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
102
+
103
+ return s->sse_version == ARMSSE_SSE300;
104
+}
105
+
106
+static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
107
+ .name = "iotkit-sysctl/sse-300",
108
+ .version_id = 1,
109
+ .minimum_version_id = 1,
110
+ .needed = sse300_needed,
111
+ .fields = (VMStateField[]) {
112
+ VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
113
+ VMSTATE_END_OF_LIST()
114
+ }
115
+};
116
+
117
static bool sse200_needed(void *opaque)
118
{
119
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
120
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_sysctl_vmstate = {
121
},
122
.subsections = (const VMStateDescription*[]) {
123
&iotkit_sysctl_sse200_vmstate,
124
+ &iotkit_sysctl_sse300_vmstate,
125
NULL
126
}
127
};
128
--
129
2.20.1
130
131
diff view generated by jsdifflib
Deleted patch
1
The sysctl PDCM_PD_*_SENSE registers control various power domains in
2
the system and allow the guest to configure which conditions keep a
3
power domain awake and what power state to use when the domain is in
4
a low power state. QEMU doesn't model power domains, so for us these
5
registers are dummy reads-as-written implementations.
6
1
7
The SSE-300 has a different power domain setup, so the set of
8
registers is slightly different:
9
10
Offset SSE-200 SSE-300
11
---------------------------------------------------
12
0x200 PDCM_PD_SYS_SENSE PDCM_PD_SYS_SENSE
13
0x204 reserved PDCM_PD_CPU0_SENSE
14
0x208 reserved reserved
15
0x20c PDCM_PD_SRAM0_SENSE reserved
16
0x210 PDCM_PD_SRAM1_SENSE reserved
17
0x214 PDCM_PD_SRAM2_SENSE PDCM_PD_VMR0_SENSE
18
0x218 PDCM_PD_SRAM3_SENSE PDCM_PD_VMR1_SENSE
19
20
Offsets 0x200 and 0x208 are the same for both, so handled in a
21
previous commit; here we deal with 0x204, 0x20c, 0x210, 0x214, 0x218.
22
23
(We can safely add new lines to the SSE300 vmstate because no board
24
uses this device in an SSE300 yet.)
25
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20210219144617.4782-18-peter.maydell@linaro.org
30
---
31
include/hw/misc/iotkit-sysctl.h | 3 ++
32
hw/misc/iotkit-sysctl.c | 61 +++++++++++++++++++++++++++++++--
33
2 files changed, 62 insertions(+), 2 deletions(-)
34
35
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/misc/iotkit-sysctl.h
38
+++ b/include/hw/misc/iotkit-sysctl.h
39
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
40
uint32_t pdcm_pd_sram1_sense;
41
uint32_t pdcm_pd_sram2_sense;
42
uint32_t pdcm_pd_sram3_sense;
43
+ uint32_t pdcm_pd_cpu0_sense;
44
+ uint32_t pdcm_pd_vmr0_sense;
45
+ uint32_t pdcm_pd_vmr1_sense;
46
47
/* Properties */
48
uint32_t sse_version;
49
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/misc/iotkit-sysctl.c
52
+++ b/hw/misc/iotkit-sysctl.c
53
@@ -XXX,XX +XXX,XX @@ REG32(PWRCTRL, 0x1fc)
54
FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
55
FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
56
REG32(PDCM_PD_SYS_SENSE, 0x200)
57
+REG32(PDCM_PD_CPU0_SENSE, 0x204)
58
REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
59
REG32(PDCM_PD_SRAM1_SENSE, 0x210)
60
-REG32(PDCM_PD_SRAM2_SENSE, 0x214)
61
-REG32(PDCM_PD_SRAM3_SENSE, 0x218)
62
+REG32(PDCM_PD_SRAM2_SENSE, 0x214) /* PDCM_PD_VMR0_SENSE on SSE300 */
63
+REG32(PDCM_PD_SRAM3_SENSE, 0x218) /* PDCM_PD_VMR1_SENSE on SSE300 */
64
REG32(PID4, 0xfd0)
65
REG32(PID5, 0xfd4)
66
REG32(PID6, 0xfd8)
67
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
68
g_assert_not_reached();
69
}
70
break;
71
+ case A_PDCM_PD_CPU0_SENSE:
72
+ switch (s->sse_version) {
73
+ case ARMSSE_IOTKIT:
74
+ case ARMSSE_SSE200:
75
+ goto bad_offset;
76
+ case ARMSSE_SSE300:
77
+ r = s->pdcm_pd_cpu0_sense;
78
+ break;
79
+ default:
80
+ g_assert_not_reached();
81
+ }
82
+ break;
83
case A_PDCM_PD_SRAM0_SENSE:
84
switch (s->sse_version) {
85
case ARMSSE_IOTKIT:
86
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
87
case ARMSSE_SSE200:
88
r = s->pdcm_pd_sram0_sense;
89
break;
90
+ case ARMSSE_SSE300:
91
+ goto bad_offset;
92
default:
93
g_assert_not_reached();
94
}
95
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
96
case ARMSSE_SSE200:
97
r = s->pdcm_pd_sram1_sense;
98
break;
99
+ case ARMSSE_SSE300:
100
+ goto bad_offset;
101
default:
102
g_assert_not_reached();
103
}
104
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
105
case ARMSSE_SSE200:
106
r = s->pdcm_pd_sram2_sense;
107
break;
108
+ case ARMSSE_SSE300:
109
+ r = s->pdcm_pd_vmr0_sense;
110
+ break;
111
default:
112
g_assert_not_reached();
113
}
114
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
115
case ARMSSE_SSE200:
116
r = s->pdcm_pd_sram3_sense;
117
break;
118
+ case ARMSSE_SSE300:
119
+ r = s->pdcm_pd_vmr1_sense;
120
+ break;
121
default:
122
g_assert_not_reached();
123
}
124
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
125
g_assert_not_reached();
126
}
127
break;
128
+ case A_PDCM_PD_CPU0_SENSE:
129
+ switch (s->sse_version) {
130
+ case ARMSSE_IOTKIT:
131
+ case ARMSSE_SSE200:
132
+ goto bad_offset;
133
+ case ARMSSE_SSE300:
134
+ qemu_log_mask(LOG_UNIMP,
135
+ "IoTKit SysCtl PDCM_PD_CPU0_SENSE unimplemented\n");
136
+ s->pdcm_pd_cpu0_sense = value;
137
+ break;
138
+ default:
139
+ g_assert_not_reached();
140
+ }
141
+ break;
142
case A_PDCM_PD_SRAM0_SENSE:
143
switch (s->sse_version) {
144
case ARMSSE_IOTKIT:
145
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
146
"IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
147
s->pdcm_pd_sram0_sense = value;
148
break;
149
+ case ARMSSE_SSE300:
150
+ goto bad_offset;
151
default:
152
g_assert_not_reached();
153
}
154
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
155
"IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
156
s->pdcm_pd_sram1_sense = value;
157
break;
158
+ case ARMSSE_SSE300:
159
+ goto bad_offset;
160
default:
161
g_assert_not_reached();
162
}
163
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
164
"IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
165
s->pdcm_pd_sram2_sense = value;
166
break;
167
+ case ARMSSE_SSE300:
168
+ qemu_log_mask(LOG_UNIMP,
169
+ "IoTKit SysCtl PDCM_PD_VMR0_SENSE unimplemented\n");
170
+ s->pdcm_pd_vmr0_sense = value;
171
+ break;
172
default:
173
g_assert_not_reached();
174
}
175
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
176
"IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
177
s->pdcm_pd_sram3_sense = value;
178
break;
179
+ case ARMSSE_SSE300:
180
+ qemu_log_mask(LOG_UNIMP,
181
+ "IoTKit SysCtl PDCM_PD_VMR1_SENSE unimplemented\n");
182
+ s->pdcm_pd_vmr1_sense = value;
183
+ break;
184
default:
185
g_assert_not_reached();
186
}
187
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_reset(DeviceState *dev)
188
s->pdcm_pd_sram1_sense = 0;
189
s->pdcm_pd_sram2_sense = 0;
190
s->pdcm_pd_sram3_sense = 0;
191
+ s->pdcm_pd_cpu0_sense = 0;
192
+ s->pdcm_pd_vmr0_sense = 0;
193
+ s->pdcm_pd_vmr1_sense = 0;
194
}
195
196
static void iotkit_sysctl_init(Object *obj)
197
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
198
.needed = sse300_needed,
199
.fields = (VMStateField[]) {
200
VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
201
+ VMSTATE_UINT32(pdcm_pd_cpu0_sense, IoTKitSysCtl),
202
+ VMSTATE_UINT32(pdcm_pd_vmr0_sense, IoTKitSysCtl),
203
+ VMSTATE_UINT32(pdcm_pd_vmr1_sense, IoTKitSysCtl),
204
VMSTATE_END_OF_LIST()
205
}
206
};
207
--
208
2.20.1
209
210
diff view generated by jsdifflib
Deleted patch
1
The SSE-200 and SSE-300 have different PID register values from the
2
IoTKit for the sysctl register block. We incorrectly implemented the
3
SSE-200 with the same PID values as IoTKit. Fix the SSE-200 bug and
4
report these register values for SSE-300.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-19-peter.maydell@linaro.org
10
---
11
hw/misc/iotkit-sysctl.c | 21 +++++++++++++++++++--
12
1 file changed, 19 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/misc/iotkit-sysctl.c
17
+++ b/hw/misc/iotkit-sysctl.c
18
@@ -XXX,XX +XXX,XX @@ REG32(CID2, 0xff8)
19
REG32(CID3, 0xffc)
20
21
/* PID/CID values */
22
-static const int sysctl_id[] = {
23
+static const int iotkit_sysctl_id[] = {
24
0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
25
0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
26
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
27
};
28
29
+/* Also used by the SSE300 */
30
+static const int sse200_sysctl_id[] = {
31
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
32
+ 0x54, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
33
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
34
+};
35
+
36
/*
37
* Set the initial secure vector table offset address for the core.
38
* This will take effect when the CPU next resets.
39
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
40
}
41
break;
42
case A_PID4 ... A_CID3:
43
- r = sysctl_id[(offset - A_PID4) / 4];
44
+ switch (s->sse_version) {
45
+ case ARMSSE_IOTKIT:
46
+ r = iotkit_sysctl_id[(offset - A_PID4) / 4];
47
+ break;
48
+ case ARMSSE_SSE200:
49
+ case ARMSSE_SSE300:
50
+ r = sse200_sysctl_id[(offset - A_PID4) / 4];
51
+ break;
52
+ default:
53
+ g_assert_not_reached();
54
+ }
55
break;
56
case A_SECDBGSET:
57
case A_SECDBGCLR:
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
Deleted patch
1
The ARMSSE_CPUID and ARMSSE_MHU Kconfig stanzas are for the devices
2
implemented by hw/misc/cpuid.c and hw/misc/armsse-mhu.c. Move them
3
to hw/misc/Kconfig where they belong.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-20-peter.maydell@linaro.org
10
---
11
hw/arm/Kconfig | 6 ------
12
hw/misc/Kconfig | 6 ++++++
13
2 files changed, 6 insertions(+), 6 deletions(-)
14
15
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/Kconfig
18
+++ b/hw/arm/Kconfig
19
@@ -XXX,XX +XXX,XX @@ config ARMSSE
20
select UNIMP
21
select SSE_COUNTER
22
select SSE_TIMER
23
-
24
-config ARMSSE_CPUID
25
- bool
26
-
27
-config ARMSSE_MHU
28
- bool
29
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/misc/Kconfig
32
+++ b/hw/misc/Kconfig
33
@@ -XXX,XX +XXX,XX @@ config APPLESMC
34
bool
35
depends on ISA_BUS
36
37
+config ARMSSE_CPUID
38
+ bool
39
+
40
+config ARMSSE_MHU
41
+ bool
42
+
43
config MAX111X
44
bool
45
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a new register block CPU<N>_PWRCTRL. There is one
2
instance of this per CPU in the system (so just one for the SSE-300),
3
and as well as the usual CIDR/PIDR ID registers it has just one
4
register, CPUPWRCFG. This register allows the guest to configure
5
behaviour of the system in power-down and deep-sleep states. Since
6
QEMU does not model those, we make the register a dummy
7
reads-as-written implementation.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-21-peter.maydell@linaro.org
13
---
14
include/hw/misc/armsse-cpu-pwrctrl.h | 40 +++++++
15
hw/misc/armsse-cpu-pwrctrl.c | 149 +++++++++++++++++++++++++++
16
MAINTAINERS | 2 +
17
hw/arm/Kconfig | 1 +
18
hw/misc/Kconfig | 3 +
19
hw/misc/meson.build | 1 +
20
hw/misc/trace-events | 4 +
21
7 files changed, 200 insertions(+)
22
create mode 100644 include/hw/misc/armsse-cpu-pwrctrl.h
23
create mode 100644 hw/misc/armsse-cpu-pwrctrl.c
24
25
diff --git a/include/hw/misc/armsse-cpu-pwrctrl.h b/include/hw/misc/armsse-cpu-pwrctrl.h
26
new file mode 100644
27
index XXXXXXX..XXXXXXX
28
--- /dev/null
29
+++ b/include/hw/misc/armsse-cpu-pwrctrl.h
30
@@ -XXX,XX +XXX,XX @@
31
+/*
32
+ * ARM SSE CPU PWRCTRL register block
33
+ *
34
+ * Copyright (c) 2021 Linaro Limited
35
+ * Written by Peter Maydell
36
+ *
37
+ * This program is free software; you can redistribute it and/or modify
38
+ * it under the terms of the GNU General Public License version 2 or
39
+ * (at your option) any later version.
40
+ */
41
+
42
+/*
43
+ * This is a model of the "CPU<N>_PWRCTRL block" which is part of the
44
+ * Arm Corstone SSE-300 Example Subsystem and documented in
45
+ * https://developer.arm.com/documentation/101773/0000
46
+ *
47
+ * QEMU interface:
48
+ * + sysbus MMIO region 0: the register bank
49
+ */
50
+
51
+#ifndef HW_MISC_ARMSSE_CPU_PWRCTRL_H
52
+#define HW_MISC_ARMSSE_CPU_PWRCTRL_H
53
+
54
+#include "hw/sysbus.h"
55
+#include "qom/object.h"
56
+
57
+#define TYPE_ARMSSE_CPU_PWRCTRL "armsse-cpu-pwrctrl"
58
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUPwrCtrl, ARMSSE_CPU_PWRCTRL)
59
+
60
+struct ARMSSECPUPwrCtrl {
61
+ /*< private >*/
62
+ SysBusDevice parent_obj;
63
+
64
+ /*< public >*/
65
+ MemoryRegion iomem;
66
+
67
+ uint32_t cpupwrcfg;
68
+};
69
+
70
+#endif
71
diff --git a/hw/misc/armsse-cpu-pwrctrl.c b/hw/misc/armsse-cpu-pwrctrl.c
72
new file mode 100644
73
index XXXXXXX..XXXXXXX
74
--- /dev/null
75
+++ b/hw/misc/armsse-cpu-pwrctrl.c
76
@@ -XXX,XX +XXX,XX @@
77
+/*
78
+ * Arm SSE CPU PWRCTRL register block
79
+ *
80
+ * Copyright (c) 2021 Linaro Limited
81
+ * Written by Peter Maydell
82
+ *
83
+ * This program is free software; you can redistribute it and/or modify
84
+ * it under the terms of the GNU General Public License version 2 or
85
+ * (at your option) any later version.
86
+ */
87
+
88
+/*
89
+ * This is a model of the "CPU<N>_PWRCTRL block" which is part of the
90
+ * Arm Corstone SSE-300 Example Subsystem and documented in
91
+ * https://developer.arm.com/documentation/101773/0000
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qemu/module.h"
97
+#include "trace.h"
98
+#include "qapi/error.h"
99
+#include "migration/vmstate.h"
100
+#include "hw/sysbus.h"
101
+#include "hw/registerfields.h"
102
+#include "hw/misc/armsse-cpu-pwrctrl.h"
103
+
104
+REG32(CPUPWRCFG, 0x0)
105
+REG32(PID4, 0xfd0)
106
+REG32(PID5, 0xfd4)
107
+REG32(PID6, 0xfd8)
108
+REG32(PID7, 0xfdc)
109
+REG32(PID0, 0xfe0)
110
+REG32(PID1, 0xfe4)
111
+REG32(PID2, 0xfe8)
112
+REG32(PID3, 0xfec)
113
+REG32(CID0, 0xff0)
114
+REG32(CID1, 0xff4)
115
+REG32(CID2, 0xff8)
116
+REG32(CID3, 0xffc)
117
+
118
+/* PID/CID values */
119
+static const int cpu_pwrctrl_id[] = {
120
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
121
+ 0x5a, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
122
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
123
+};
124
+
125
+static uint64_t pwrctrl_read(void *opaque, hwaddr offset, unsigned size)
126
+{
127
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
128
+ uint64_t r;
129
+
130
+ switch (offset) {
131
+ case A_CPUPWRCFG:
132
+ r = s->cpupwrcfg;
133
+ break;
134
+ case A_PID4 ... A_CID3:
135
+ r = cpu_pwrctrl_id[(offset - A_PID4) / 4];
136
+ break;
137
+ default:
138
+ qemu_log_mask(LOG_GUEST_ERROR,
139
+ "SSE CPU_PWRCTRL read: bad offset %x\n", (int)offset);
140
+ r = 0;
141
+ break;
142
+ }
143
+ trace_armsse_cpu_pwrctrl_read(offset, r, size);
144
+ return r;
145
+}
146
+
147
+static void pwrctrl_write(void *opaque, hwaddr offset,
148
+ uint64_t value, unsigned size)
149
+{
150
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
151
+
152
+ trace_armsse_cpu_pwrctrl_write(offset, value, size);
153
+
154
+ switch (offset) {
155
+ case A_CPUPWRCFG:
156
+ qemu_log_mask(LOG_UNIMP,
157
+ "SSE CPU_PWRCTRL: CPUPWRCFG unimplemented\n");
158
+ s->cpupwrcfg = value;
159
+ break;
160
+ default:
161
+ qemu_log_mask(LOG_GUEST_ERROR,
162
+ "SSE CPU_PWRCTRL write: bad offset 0x%x\n", (int)offset);
163
+ break;
164
+ }
165
+}
166
+
167
+static const MemoryRegionOps pwrctrl_ops = {
168
+ .read = pwrctrl_read,
169
+ .write = pwrctrl_write,
170
+ .endianness = DEVICE_LITTLE_ENDIAN,
171
+ .impl.min_access_size = 4,
172
+ .impl.max_access_size = 4,
173
+ .valid.min_access_size = 4,
174
+ .valid.max_access_size = 4,
175
+};
176
+
177
+static void pwrctrl_reset(DeviceState *dev)
178
+{
179
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(dev);
180
+
181
+ s->cpupwrcfg = 0;
182
+}
183
+
184
+static const VMStateDescription pwrctrl_vmstate = {
185
+ .name = "armsse-cpu-pwrctrl",
186
+ .version_id = 1,
187
+ .minimum_version_id = 1,
188
+ .fields = (VMStateField[]) {
189
+ VMSTATE_UINT32(cpupwrcfg, ARMSSECPUPwrCtrl),
190
+ VMSTATE_END_OF_LIST()
191
+ },
192
+};
193
+
194
+static void pwrctrl_init(Object *obj)
195
+{
196
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
197
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(obj);
198
+
199
+ memory_region_init_io(&s->iomem, obj, &pwrctrl_ops,
200
+ s, "armsse-cpu-pwrctrl", 0x1000);
201
+ sysbus_init_mmio(sbd, &s->iomem);
202
+}
203
+
204
+static void pwrctrl_class_init(ObjectClass *klass, void *data)
205
+{
206
+ DeviceClass *dc = DEVICE_CLASS(klass);
207
+
208
+ dc->reset = pwrctrl_reset;
209
+ dc->vmsd = &pwrctrl_vmstate;
210
+}
211
+
212
+static const TypeInfo pwrctrl_info = {
213
+ .name = TYPE_ARMSSE_CPU_PWRCTRL,
214
+ .parent = TYPE_SYS_BUS_DEVICE,
215
+ .instance_size = sizeof(ARMSSECPUPwrCtrl),
216
+ .instance_init = pwrctrl_init,
217
+ .class_init = pwrctrl_class_init,
218
+};
219
+
220
+static void pwrctrl_register_types(void)
221
+{
222
+ type_register_static(&pwrctrl_info);
223
+}
224
+
225
+type_init(pwrctrl_register_types);
226
diff --git a/MAINTAINERS b/MAINTAINERS
227
index XXXXXXX..XXXXXXX 100644
228
--- a/MAINTAINERS
229
+++ b/MAINTAINERS
230
@@ -XXX,XX +XXX,XX @@ F: hw/misc/iotkit-sysctl.c
231
F: include/hw/misc/iotkit-sysctl.h
232
F: hw/misc/iotkit-sysinfo.c
233
F: include/hw/misc/iotkit-sysinfo.h
234
+F: hw/misc/armsse-cpu-pwrctrl.c
235
+F: include/hw/misc/armsse-cpu-pwrctrl.h
236
F: hw/misc/armsse-cpuid.c
237
F: include/hw/misc/armsse-cpuid.h
238
F: hw/misc/armsse-mhu.c
239
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
240
index XXXXXXX..XXXXXXX 100644
241
--- a/hw/arm/Kconfig
242
+++ b/hw/arm/Kconfig
243
@@ -XXX,XX +XXX,XX @@ config ARM11MPCORE
244
config ARMSSE
245
bool
246
select ARM_V7M
247
+ select ARMSSE_CPU_PWRCTRL
248
select ARMSSE_CPUID
249
select ARMSSE_MHU
250
select CMSDK_APB_TIMER
251
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
252
index XXXXXXX..XXXXXXX 100644
253
--- a/hw/misc/Kconfig
254
+++ b/hw/misc/Kconfig
255
@@ -XXX,XX +XXX,XX @@ config ARMSSE_CPUID
256
config ARMSSE_MHU
257
bool
258
259
+config ARMSSE_CPU_PWRCTRL
260
+ bool
261
+
262
config MAX111X
263
bool
264
265
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
266
index XXXXXXX..XXXXXXX 100644
267
--- a/hw/misc/meson.build
268
+++ b/hw/misc/meson.build
269
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_TZ_MSC', if_true: files('tz-msc.c'))
270
softmmu_ss.add(when: 'CONFIG_TZ_PPC', if_true: files('tz-ppc.c'))
271
softmmu_ss.add(when: 'CONFIG_IOTKIT_SECCTL', if_true: files('iotkit-secctl.c'))
272
softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c'))
273
+softmmu_ss.add(when: 'CONFIG_ARMSSE_CPU_PWRCTRL', if_true: files('armsse-cpu-pwrctrl.c'))
274
softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
275
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
276
277
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
278
index XXXXXXX..XXXXXXX 100644
279
--- a/hw/misc/trace-events
280
+++ b/hw/misc/trace-events
281
@@ -XXX,XX +XXX,XX @@ iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl
282
iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
283
iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
284
285
+# armsse-cpu-pwrctrl.c
286
+armsse_cpu_pwrctrl_read(uint64_t offset, uint64_t data, unsigned size) "SSE-300 CPU_PWRCTRL read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
287
+armsse_cpu_pwrctrl_write(uint64_t offset, uint64_t data, unsigned size) "SSE-300 CPU_PWRCTRL write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
288
+
289
# armsse-cpuid.c
290
armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
291
armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
292
--
293
2.20.1
294
295
diff view generated by jsdifflib
Deleted patch
1
Convert the apb_ppc0 and apb_ppc1 fields in the ARMSSE state struct
2
to use an array instead of two separate fields. We already had one
3
place in the code that wanted to be able to refer to the PPC by
4
index, and we're about to add more code like that.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-22-peter.maydell@linaro.org
11
---
12
include/hw/arm/armsse.h | 6 +++---
13
hw/arm/armsse.c | 32 ++++++++++++++++++--------------
14
2 files changed, 21 insertions(+), 17 deletions(-)
15
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/armsse.h
19
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
21
/* We have an IRQ splitter and an OR gate input for each external PPC
22
* and the 2 internal PPCs
23
*/
24
+#define NUM_INTERNAL_PPCS 2
25
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
26
-#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
27
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + NUM_INTERNAL_PPCS)
28
29
#define MAX_SRAM_BANKS 4
30
#if MAX_SRAM_BANKS > IOTS_NUM_MPC
31
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
32
ARMv7MState armv7m[SSE_MAX_CPUS];
33
CPUClusterState cluster[SSE_MAX_CPUS];
34
IoTKitSecCtl secctl;
35
- TZPPC apb_ppc0;
36
- TZPPC apb_ppc1;
37
+ TZPPC apb_ppc[NUM_INTERNAL_PPCS];
38
TZMPC mpc[IOTS_NUM_MPC];
39
CMSDKAPBTimer timer0;
40
CMSDKAPBTimer timer1;
41
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/armsse.c
44
+++ b/hw/arm/armsse.c
45
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
46
}
47
48
object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
49
- object_initialize_child(obj, "apb-ppc0", &s->apb_ppc0, TYPE_TZ_PPC);
50
- object_initialize_child(obj, "apb-ppc1", &s->apb_ppc1, TYPE_TZ_PPC);
51
+
52
+ for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
53
+ g_autofree char *name = g_strdup_printf("apb-ppc%d", i);
54
+ object_initialize_child(obj, name, &s->apb_ppc[i], TYPE_TZ_PPC);
55
+ }
56
+
57
for (i = 0; i < info->sram_banks; i++) {
58
char *name = g_strdup_printf("mpc%d", i);
59
object_initialize_child(obj, name, &s->mpc[i], TYPE_TZ_MPC);
60
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
61
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
62
armsse_get_common_irq_in(s, 3));
63
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
64
- object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr),
65
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[0]", OBJECT(mr),
66
&error_abort);
67
68
qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
69
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
70
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
71
armsse_get_common_irq_in(s, 4));
72
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
73
- object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr),
74
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[1]", OBJECT(mr),
75
&error_abort);
76
77
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
78
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
79
sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
80
armsse_get_common_irq_in(s, 5));
81
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
82
- object_property_set_link(OBJECT(&s->apb_ppc0), "port[2]", OBJECT(mr),
83
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[2]", OBJECT(mr),
84
&error_abort);
85
86
if (info->has_mhus) {
87
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
88
}
89
port = g_strdup_printf("port[%d]", i + 3);
90
mr = sysbus_mmio_get_region(mhu_sbd, 0);
91
- object_property_set_link(OBJECT(&s->apb_ppc0), port, OBJECT(mr),
92
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), port, OBJECT(mr),
93
&error_abort);
94
g_free(port);
95
96
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
97
}
98
}
99
100
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc0), errp)) {
101
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[0]), errp)) {
102
return;
103
}
104
105
- sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
106
- dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
107
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
108
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
109
110
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
111
memory_region_add_subregion(&s->container, 0x40000000, mr);
112
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
113
sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
114
armsse_get_common_irq_in(s, 2));
115
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
116
- object_property_set_link(OBJECT(&s->apb_ppc1), "port[0]", OBJECT(mr),
117
+ object_property_set_link(OBJECT(&s->apb_ppc[1]), "port[0]", OBJECT(mr),
118
&error_abort);
119
120
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc1), errp)) {
121
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
122
return;
123
}
124
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
125
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc[1]), 0);
126
memory_region_add_subregion(&s->container, 0x4002f000, mr);
127
128
- dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
129
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
130
qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
131
qdev_get_gpio_in_named(dev_apb_ppc1,
132
"cfg_nonsec", 0));
133
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
134
DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
135
char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
136
i - NUM_EXTERNAL_PPCS);
137
- TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
138
+ TZPPC *ppc = &s->apb_ppc[i - NUM_EXTERNAL_PPCS];
139
140
qdev_connect_gpio_out(devs, 0,
141
qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
142
--
143
2.20.1
144
145
diff view generated by jsdifflib
Deleted patch
1
The SSE uses 32 interrupts for its own devices, and then passes through
2
its expansion IRQ inputs to the CPU's interrupts 33 and upward.
3
Add a define for the number of IRQs the SSE uses for itself, instead
4
of hardcoding 32.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-23-peter.maydell@linaro.org
11
---
12
include/hw/arm/armsse.h | 5 ++++-
13
hw/arm/armsse.c | 4 ++--
14
2 files changed, 6 insertions(+), 3 deletions(-)
15
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/armsse.h
19
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
21
#define RAM3_PPU 6
22
#define NUM_PPUS 7
23
24
+/* Number of CPU IRQs used by the SSE itself */
25
+#define NUM_SSE_IRQS 32
26
+
27
struct ARMSSE {
28
/*< private >*/
29
SysBusDevice parent_obj;
30
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
31
qemu_or_irq mpc_irq_orgate;
32
qemu_or_irq nmi_orgate;
33
34
- SplitIRQ cpu_irq_splitter[32];
35
+ SplitIRQ cpu_irq_splitter[NUM_SSE_IRQS];
36
37
CMSDKAPBDualTimer dualtimer;
38
39
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/armsse.c
42
+++ b/hw/arm/armsse.c
43
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
44
int j;
45
char *gpioname;
46
47
- qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
48
+ qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + NUM_SSE_IRQS);
49
/*
50
* In real hardware the initial Secure VTOR is set from the INITSVTOR*
51
* registers in the IoT Kit System Control Register block. In QEMU
52
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
53
/* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
54
s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
55
for (j = 0; j < s->exp_numirq; j++) {
56
- s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + 32);
57
+ s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + NUM_SSE_IRQS);
58
}
59
if (i == 0) {
60
gpioname = g_strdup("EXP_IRQ");
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 is mostly the same as the SSE-200, but it has moved some
2
of the devices in the memory map and uses different device types in
3
some cases. To accommodate this, add a framework where the placement
4
and wiring of some devices can be specified in a data table.
5
1
6
This commit adds the framework for this data-driven device placement,
7
and makes the CMSDK APB timer devices use it. Subsequent commits
8
will convert the other devices which differ between SSE-200 and
9
SSE-300.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210219144617.4782-24-peter.maydell@linaro.org
15
---
16
include/hw/arm/armsse.h | 3 +-
17
hw/arm/armsse.c | 147 +++++++++++++++++++++++++++++++++-------
18
2 files changed, 125 insertions(+), 25 deletions(-)
19
20
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/armsse.h
23
+++ b/include/hw/arm/armsse.h
24
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
25
IoTKitSecCtl secctl;
26
TZPPC apb_ppc[NUM_INTERNAL_PPCS];
27
TZMPC mpc[IOTS_NUM_MPC];
28
- CMSDKAPBTimer timer0;
29
- CMSDKAPBTimer timer1;
30
+ CMSDKAPBTimer timer[2];
31
CMSDKAPBTimer s32ktimer;
32
qemu_or_irq ppc_irq_orgate;
33
SplitIRQ sec_resp_splitter;
34
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/armsse.c
37
+++ b/hw/arm/armsse.c
38
@@ -XXX,XX +XXX,XX @@
39
#include "hw/irq.h"
40
#include "hw/qdev-clock.h"
41
42
+/*
43
+ * The SSE-300 puts some devices in different places to the
44
+ * SSE-200 (and original IoTKit). We use an array of these structs
45
+ * to define how each variant lays out these devices. (Parts of the
46
+ * SoC that are the same for all variants aren't handled via these
47
+ * data structures.)
48
+ */
49
+
50
+#define NO_IRQ -1
51
+#define NO_PPC -1
52
+
53
+typedef struct ARMSSEDeviceInfo {
54
+ const char *name; /* name to use for the QOM object; NULL terminates list */
55
+ const char *type; /* QOM type name */
56
+ unsigned int index; /* Which of the N devices of this type is this ? */
57
+ hwaddr addr;
58
+ int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
59
+ int ppc_port; /* Port number of this device on the PPC */
60
+ int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1 */
61
+} ARMSSEDeviceInfo;
62
+
63
struct ARMSSEInfo {
64
const char *name;
65
uint32_t sse_version;
66
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
67
bool has_cpusecctrl;
68
bool has_cpuid;
69
Property *props;
70
+ const ARMSSEDeviceInfo *devinfo;
71
};
72
73
static Property iotkit_properties[] = {
74
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
75
DEFINE_PROP_END_OF_LIST()
76
};
77
78
+static const ARMSSEDeviceInfo sse200_devices[] = {
79
+ {
80
+ .name = "timer0",
81
+ .type = TYPE_CMSDK_APB_TIMER,
82
+ .index = 0,
83
+ .addr = 0x40000000,
84
+ .ppc = 0,
85
+ .ppc_port = 0,
86
+ .irq = 3,
87
+ },
88
+ {
89
+ .name = "timer1",
90
+ .type = TYPE_CMSDK_APB_TIMER,
91
+ .index = 1,
92
+ .addr = 0x40001000,
93
+ .ppc = 0,
94
+ .ppc_port = 1,
95
+ .irq = 4,
96
+ },
97
+ {
98
+ .name = NULL,
99
+ }
100
+};
101
+
102
static const ARMSSEInfo armsse_variants[] = {
103
{
104
.name = TYPE_IOTKIT,
105
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
106
.has_cpusecctrl = false,
107
.has_cpuid = false,
108
.props = iotkit_properties,
109
+ .devinfo = sse200_devices,
110
},
111
{
112
.name = TYPE_SSE200,
113
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
114
.has_cpusecctrl = true,
115
.has_cpuid = true,
116
.props = armsse_properties,
117
+ .devinfo = sse200_devices,
118
},
119
};
120
121
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
122
ARMSSE *s = ARM_SSE(obj);
123
ARMSSEClass *asc = ARM_SSE_GET_CLASS(obj);
124
const ARMSSEInfo *info = asc->info;
125
+ const ARMSSEDeviceInfo *devinfo;
126
int i;
127
128
assert(info->sram_banks <= MAX_SRAM_BANKS);
129
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
130
}
131
}
132
133
+ for (devinfo = info->devinfo; devinfo->name; devinfo++) {
134
+ assert(devinfo->ppc == NO_PPC || devinfo->ppc < ARRAY_SIZE(s->apb_ppc));
135
+ if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
136
+ assert(devinfo->index < ARRAY_SIZE(s->timer));
137
+ object_initialize_child(obj, devinfo->name,
138
+ &s->timer[devinfo->index],
139
+ TYPE_CMSDK_APB_TIMER);
140
+ } else {
141
+ g_assert_not_reached();
142
+ }
143
+ }
144
+
145
object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
146
147
for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
148
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
149
object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
150
g_free(name);
151
}
152
- object_initialize_child(obj, "timer0", &s->timer0, TYPE_CMSDK_APB_TIMER);
153
- object_initialize_child(obj, "timer1", &s->timer1, TYPE_CMSDK_APB_TIMER);
154
object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
155
TYPE_CMSDK_APB_TIMER);
156
object_initialize_child(obj, "dualtimer", &s->dualtimer,
157
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
158
ARMSSE *s = ARM_SSE(dev);
159
ARMSSEClass *asc = ARM_SSE_GET_CLASS(dev);
160
const ARMSSEInfo *info = asc->info;
161
+ const ARMSSEDeviceInfo *devinfo;
162
int i;
163
MemoryRegion *mr;
164
Error *err = NULL;
165
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
166
* it to the appropriate PPC port; then we can realize the PPC and
167
* map its upstream ends to the right place in the container.
168
*/
169
- qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
170
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
171
- return;
172
- }
173
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
174
- armsse_get_common_irq_in(s, 3));
175
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
176
- object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[0]", OBJECT(mr),
177
- &error_abort);
178
+ for (devinfo = info->devinfo; devinfo->name; devinfo++) {
179
+ SysBusDevice *sbd;
180
+ qemu_irq irq;
181
182
- qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
183
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
184
- return;
185
+ if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
186
+ sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
187
+
188
+ qdev_connect_clock_in(DEVICE(sbd), "pclk", s->mainclk);
189
+ if (!sysbus_realize(sbd, errp)) {
190
+ return;
191
+ }
192
+ mr = sysbus_mmio_get_region(sbd, 0);
193
+ } else {
194
+ g_assert_not_reached();
195
+ }
196
+
197
+ switch (devinfo->irq) {
198
+ case NO_IRQ:
199
+ irq = NULL;
200
+ break;
201
+ case 0 ... NUM_SSE_IRQS - 1:
202
+ irq = armsse_get_common_irq_in(s, devinfo->irq);
203
+ break;
204
+ default:
205
+ g_assert_not_reached();
206
+ }
207
+
208
+ if (irq) {
209
+ sysbus_connect_irq(sbd, 0, irq);
210
+ }
211
+
212
+ /*
213
+ * Devices connected to a PPC are connected to the port here;
214
+ * we will map the upstream end of that port to the right address
215
+ * in the container later after the PPC has been realized.
216
+ * Devices not connected to a PPC can be mapped immediately.
217
+ */
218
+ if (devinfo->ppc != NO_PPC) {
219
+ TZPPC *ppc = &s->apb_ppc[devinfo->ppc];
220
+ g_autofree char *portname = g_strdup_printf("port[%d]",
221
+ devinfo->ppc_port);
222
+ object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
223
+ &error_abort);
224
+ } else {
225
+ memory_region_add_subregion(&s->container, devinfo->addr, mr);
226
+ }
227
}
228
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
229
- armsse_get_common_irq_in(s, 4));
230
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
231
- object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[1]", OBJECT(mr),
232
- &error_abort);
233
234
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
235
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
236
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
237
sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
238
dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
239
240
- mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
241
- memory_region_add_subregion(&s->container, 0x40000000, mr);
242
- mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
243
- memory_region_add_subregion(&s->container, 0x40001000, mr);
244
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
245
memory_region_add_subregion(&s->container, 0x40002000, mr);
246
if (info->has_mhus) {
247
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
248
qdev_get_gpio_in_named(dev_apb_ppc1,
249
"cfg_sec_resp", 0));
250
251
+ /*
252
+ * Now both PPCs are realized we can map the upstream ends of
253
+ * ports which correspond to entries in the devinfo array.
254
+ * The ports which are connected to non-devinfo devices have
255
+ * already been mapped.
256
+ */
257
+ for (devinfo = info->devinfo; devinfo->name; devinfo++) {
258
+ SysBusDevice *ppc_sbd;
259
+
260
+ if (devinfo->ppc == NO_PPC) {
261
+ continue;
262
+ }
263
+ ppc_sbd = SYS_BUS_DEVICE(&s->apb_ppc[devinfo->ppc]);
264
+ mr = sysbus_mmio_get_region(ppc_sbd, devinfo->ppc_port);
265
+ memory_region_add_subregion(&s->container, devinfo->addr, mr);
266
+ }
267
+
268
if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
269
info->sys_version, errp)) {
270
return;
271
--
272
2.20.1
273
274
diff view generated by jsdifflib
Deleted patch
1
Move the CMSDK dualtimer device handling into the data-driven
2
device placement framework.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-25-peter.maydell@linaro.org
8
---
9
hw/arm/armsse.c | 35 +++++++++++++++++++++--------------
10
1 file changed, 21 insertions(+), 14 deletions(-)
11
12
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/armsse.c
15
+++ b/hw/arm/armsse.c
16
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
17
.ppc_port = 1,
18
.irq = 4,
19
},
20
+ {
21
+ .name = "dualtimer",
22
+ .type = TYPE_CMSDK_APB_DUALTIMER,
23
+ .index = 0,
24
+ .addr = 0x40002000,
25
+ .ppc = 0,
26
+ .ppc_port = 2,
27
+ .irq = 5,
28
+ },
29
{
30
.name = NULL,
31
}
32
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
33
object_initialize_child(obj, devinfo->name,
34
&s->timer[devinfo->index],
35
TYPE_CMSDK_APB_TIMER);
36
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
37
+ assert(devinfo->index == 0);
38
+ object_initialize_child(obj, devinfo->name, &s->dualtimer,
39
+ TYPE_CMSDK_APB_DUALTIMER);
40
} else {
41
g_assert_not_reached();
42
}
43
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
44
}
45
object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
46
TYPE_CMSDK_APB_TIMER);
47
- object_initialize_child(obj, "dualtimer", &s->dualtimer,
48
- TYPE_CMSDK_APB_DUALTIMER);
49
object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog,
50
TYPE_CMSDK_APB_WATCHDOG);
51
object_initialize_child(obj, "nswatchdog", &s->nswatchdog,
52
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
53
return;
54
}
55
mr = sysbus_mmio_get_region(sbd, 0);
56
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
57
+ sbd = SYS_BUS_DEVICE(&s->dualtimer);
58
+
59
+ qdev_connect_clock_in(DEVICE(sbd), "TIMCLK", s->mainclk);
60
+ if (!sysbus_realize(sbd, errp)) {
61
+ return;
62
+ }
63
+ mr = sysbus_mmio_get_region(sbd, 0);
64
} else {
65
g_assert_not_reached();
66
}
67
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
68
}
69
}
70
71
- qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
72
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
73
- return;
74
- }
75
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
76
- armsse_get_common_irq_in(s, 5));
77
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
78
- object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[2]", OBJECT(mr),
79
- &error_abort);
80
-
81
if (info->has_mhus) {
82
/*
83
* An SSE-200 with only one CPU should have only one MHU created,
84
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
85
sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
86
dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
87
88
- mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
89
- memory_region_add_subregion(&s->container, 0x40002000, mr);
90
if (info->has_mhus) {
91
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
92
memory_region_add_subregion(&s->container, 0x40003000, mr);
93
--
94
2.20.1
95
96
diff view generated by jsdifflib
Deleted patch
1
Move the CMSDK watchdog device handling into the data-driven device
2
placement framework. This is slightly more complicated because these
3
devices might wire their IRQs up to the NMI line, and because one of
4
them uses the slow 32KHz clock rather than the main clock.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-26-peter.maydell@linaro.org
10
---
11
include/hw/arm/armsse.h | 4 +-
12
hw/arm/armsse.c | 109 ++++++++++++++++++++++++----------------
13
2 files changed, 66 insertions(+), 47 deletions(-)
14
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/armsse.h
18
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
20
21
CMSDKAPBDualTimer dualtimer;
22
23
- CMSDKAPBWatchdog s32kwatchdog;
24
- CMSDKAPBWatchdog nswatchdog;
25
- CMSDKAPBWatchdog swatchdog;
26
+ CMSDKAPBWatchdog cmsdk_watchdog[3];
27
28
IoTKitSysCtl sysctl;
29
IoTKitSysCtl sysinfo;
30
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/armsse.c
33
+++ b/hw/arm/armsse.c
34
@@ -XXX,XX +XXX,XX @@
35
36
#define NO_IRQ -1
37
#define NO_PPC -1
38
+/*
39
+ * Special values for ARMSSEDeviceInfo::irq to indicate that this
40
+ * device uses one of the inputs to the OR gate that feeds into the
41
+ * CPU NMI input.
42
+ */
43
+#define NMI_0 10000
44
+#define NMI_1 10001
45
46
typedef struct ARMSSEDeviceInfo {
47
const char *name; /* name to use for the QOM object; NULL terminates list */
48
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSEDeviceInfo {
49
hwaddr addr;
50
int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
51
int ppc_port; /* Port number of this device on the PPC */
52
- int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1 */
53
+ int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1, or NMI_0 or NMI_1 */
54
+ bool slowclk; /* true if device uses the slow 32KHz clock */
55
} ARMSSEDeviceInfo;
56
57
struct ARMSSEInfo {
58
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
59
.ppc_port = 2,
60
.irq = 5,
61
},
62
+ {
63
+ .name = "s32kwatchdog",
64
+ .type = TYPE_CMSDK_APB_WATCHDOG,
65
+ .index = 0,
66
+ .addr = 0x5002e000,
67
+ .ppc = NO_PPC,
68
+ .irq = NMI_0,
69
+ .slowclk = true,
70
+ },
71
+ {
72
+ .name = "nswatchdog",
73
+ .type = TYPE_CMSDK_APB_WATCHDOG,
74
+ .index = 1,
75
+ .addr = 0x40081000,
76
+ .ppc = NO_PPC,
77
+ .irq = 1,
78
+ },
79
+ {
80
+ .name = "swatchdog",
81
+ .type = TYPE_CMSDK_APB_WATCHDOG,
82
+ .index = 2,
83
+ .addr = 0x50081000,
84
+ .ppc = NO_PPC,
85
+ .irq = NMI_1,
86
+ },
87
{
88
.name = NULL,
89
}
90
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
91
assert(devinfo->index == 0);
92
object_initialize_child(obj, devinfo->name, &s->dualtimer,
93
TYPE_CMSDK_APB_DUALTIMER);
94
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
95
+ assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
96
+ object_initialize_child(obj, devinfo->name,
97
+ &s->cmsdk_watchdog[devinfo->index],
98
+ TYPE_CMSDK_APB_WATCHDOG);
99
} else {
100
g_assert_not_reached();
101
}
102
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
103
object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
104
g_free(name);
105
}
106
+
107
object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
108
TYPE_CMSDK_APB_TIMER);
109
- object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog,
110
- TYPE_CMSDK_APB_WATCHDOG);
111
- object_initialize_child(obj, "nswatchdog", &s->nswatchdog,
112
- TYPE_CMSDK_APB_WATCHDOG);
113
- object_initialize_child(obj, "swatchdog", &s->swatchdog,
114
- TYPE_CMSDK_APB_WATCHDOG);
115
object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
116
TYPE_IOTKIT_SYSCTL);
117
object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
118
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
119
qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
120
armsse_get_common_irq_in(s, 9));
121
122
+ /* This OR gate wires together outputs from the secure watchdogs to NMI */
123
+ if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
124
+ errp)) {
125
+ return;
126
+ }
127
+ if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
128
+ return;
129
+ }
130
+ qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
131
+ qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
132
+
133
/* Devices behind APB PPC0:
134
* 0x40000000: timer0
135
* 0x40001000: timer1
136
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
137
return;
138
}
139
mr = sysbus_mmio_get_region(sbd, 0);
140
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
141
+ sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
142
+
143
+ qdev_connect_clock_in(DEVICE(sbd), "WDOGCLK",
144
+ devinfo->slowclk ? s->s32kclk : s->mainclk);
145
+ if (!sysbus_realize(sbd, errp)) {
146
+ return;
147
+ }
148
+ mr = sysbus_mmio_get_region(sbd, 0);
149
} else {
150
g_assert_not_reached();
151
}
152
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
153
case 0 ... NUM_SSE_IRQS - 1:
154
irq = armsse_get_common_irq_in(s, devinfo->irq);
155
break;
156
+ case NMI_0:
157
+ case NMI_1:
158
+ irq = qdev_get_gpio_in(DEVICE(&s->nmi_orgate),
159
+ devinfo->irq - NMI_0);
160
+ break;
161
default:
162
g_assert_not_reached();
163
}
164
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
165
}
166
}
167
168
- /* This OR gate wires together outputs from the secure watchdogs to NMI */
169
- if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
170
- errp)) {
171
- return;
172
- }
173
- if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
174
- return;
175
- }
176
- qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
177
- qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
178
-
179
- qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
180
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
181
- return;
182
- }
183
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
184
- qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
185
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
186
-
187
- /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
188
-
189
- qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
190
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
191
- return;
192
- }
193
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
194
- armsse_get_common_irq_in(s, 1));
195
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
196
-
197
- qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
198
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
199
- return;
200
- }
201
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
202
- qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
203
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
204
-
205
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
206
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
207
208
--
209
2.20.1
210
211
diff view generated by jsdifflib
Deleted patch
1
Move the CMSDK timer that uses the S32K slow clock into the data-driven
2
device placement framework.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-27-peter.maydell@linaro.org
8
---
9
include/hw/arm/armsse.h | 3 +--
10
hw/arm/armsse.c | 31 ++++++++++++-------------------
11
2 files changed, 13 insertions(+), 21 deletions(-)
12
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armsse.h
16
+++ b/include/hw/arm/armsse.h
17
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
18
IoTKitSecCtl secctl;
19
TZPPC apb_ppc[NUM_INTERNAL_PPCS];
20
TZMPC mpc[IOTS_NUM_MPC];
21
- CMSDKAPBTimer timer[2];
22
- CMSDKAPBTimer s32ktimer;
23
+ CMSDKAPBTimer timer[3];
24
qemu_or_irq ppc_irq_orgate;
25
SplitIRQ sec_resp_splitter;
26
SplitIRQ ppc_irq_splitter[NUM_PPCS];
27
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/armsse.c
30
+++ b/hw/arm/armsse.c
31
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
32
.ppc_port = 1,
33
.irq = 4,
34
},
35
+ {
36
+ .name = "s32ktimer",
37
+ .type = TYPE_CMSDK_APB_TIMER,
38
+ .index = 2,
39
+ .addr = 0x4002f000,
40
+ .ppc = 1,
41
+ .ppc_port = 0,
42
+ .irq = 2,
43
+ .slowclk = true,
44
+ },
45
{
46
.name = "dualtimer",
47
.type = TYPE_CMSDK_APB_DUALTIMER,
48
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
49
g_free(name);
50
}
51
52
- object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
53
- TYPE_CMSDK_APB_TIMER);
54
object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
55
TYPE_IOTKIT_SYSCTL);
56
object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
57
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
58
if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
59
sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
60
61
- qdev_connect_clock_in(DEVICE(sbd), "pclk", s->mainclk);
62
+ qdev_connect_clock_in(DEVICE(sbd), "pclk",
63
+ devinfo->slowclk ? s->s32kclk : s->mainclk);
64
if (!sysbus_realize(sbd, errp)) {
65
return;
66
}
67
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
68
}
69
}
70
71
- /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
72
- /* Devices behind APB PPC1:
73
- * 0x4002f000: S32K timer
74
- */
75
- qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
76
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
77
- return;
78
- }
79
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
80
- armsse_get_common_irq_in(s, 2));
81
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
82
- object_property_set_link(OBJECT(&s->apb_ppc[1]), "port[0]", OBJECT(mr),
83
- &error_abort);
84
-
85
if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
86
return;
87
}
88
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc[1]), 0);
89
- memory_region_add_subregion(&s->container, 0x4002f000, mr);
90
91
dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
92
qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
93
--
94
2.20.1
95
96
diff view generated by jsdifflib
Deleted patch
1
Move the sysinfo register block into the data-driven framework.
2
1
3
While we are moving the code for configuring this device around,
4
regularize on using &error_abortw when setting the integer
5
properties: they are all simple DEFINE_PROP_UINT32 properties so the
6
setting can never fail.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-28-peter.maydell@linaro.org
12
---
13
hw/arm/armsse.c | 47 ++++++++++++++++++++++++++++-------------------
14
1 file changed, 28 insertions(+), 19 deletions(-)
15
16
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/armsse.c
19
+++ b/hw/arm/armsse.c
20
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
21
.ppc = NO_PPC,
22
.irq = NMI_1,
23
},
24
+ {
25
+ .name = "armsse-sysinfo",
26
+ .type = TYPE_IOTKIT_SYSINFO,
27
+ .index = 0,
28
+ .addr = 0x40020000,
29
+ .ppc = NO_PPC,
30
+ .irq = NO_IRQ,
31
+ },
32
{
33
.name = NULL,
34
}
35
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
36
object_initialize_child(obj, devinfo->name,
37
&s->cmsdk_watchdog[devinfo->index],
38
TYPE_CMSDK_APB_WATCHDOG);
39
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
40
+ assert(devinfo->index == 0);
41
+ object_initialize_child(obj, devinfo->name, &s->sysinfo,
42
+ TYPE_IOTKIT_SYSINFO);
43
} else {
44
g_assert_not_reached();
45
}
46
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
47
48
object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
49
TYPE_IOTKIT_SYSCTL);
50
- object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
51
- TYPE_IOTKIT_SYSINFO);
52
if (info->has_mhus) {
53
object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
54
object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
55
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
56
return;
57
}
58
mr = sysbus_mmio_get_region(sbd, 0);
59
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
60
+ sbd = SYS_BUS_DEVICE(&s->sysinfo);
61
+
62
+ object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
63
+ info->sys_version, &error_abort);
64
+ object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
65
+ armsse_sys_config_value(s, info),
66
+ &error_abort);
67
+ object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
68
+ info->sse_version, &error_abort);
69
+ object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
70
+ info->iidr, &error_abort);
71
+ if (!sysbus_realize(sbd, errp)) {
72
+ return;
73
+ }
74
+ mr = sysbus_mmio_get_region(sbd, 0);
75
} else {
76
g_assert_not_reached();
77
}
78
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
79
memory_region_add_subregion(&s->container, devinfo->addr, mr);
80
}
81
82
- if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
83
- info->sys_version, errp)) {
84
- return;
85
- }
86
- if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
87
- armsse_sys_config_value(s, info), errp)) {
88
- return;
89
- }
90
- object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
91
- info->sse_version, &error_abort);
92
- object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
93
- info->iidr, &error_abort);
94
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
95
- return;
96
- }
97
- /* System information registers */
98
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
99
/* System control registers */
100
object_property_set_int(OBJECT(&s->sysctl), "sse-version",
101
info->sse_version, &error_abort);
102
--
103
2.20.1
104
105
diff view generated by jsdifflib
Deleted patch
1
Move the sysctl register block into the data-driven device placement
2
framework.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-29-peter.maydell@linaro.org
8
---
9
hw/arm/armsse.c | 44 ++++++++++++++++++++++++++++----------------
10
1 file changed, 28 insertions(+), 16 deletions(-)
11
12
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/armsse.c
15
+++ b/hw/arm/armsse.c
16
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
17
.ppc = NO_PPC,
18
.irq = NO_IRQ,
19
},
20
+ {
21
+ .name = "armsse-sysctl",
22
+ .type = TYPE_IOTKIT_SYSCTL,
23
+ .index = 0,
24
+ .addr = 0x50021000,
25
+ .ppc = NO_PPC,
26
+ .irq = NO_IRQ,
27
+ },
28
{
29
.name = NULL,
30
}
31
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
32
assert(devinfo->index == 0);
33
object_initialize_child(obj, devinfo->name, &s->sysinfo,
34
TYPE_IOTKIT_SYSINFO);
35
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
36
+ assert(devinfo->index == 0);
37
+ object_initialize_child(obj, devinfo->name, &s->sysctl,
38
+ TYPE_IOTKIT_SYSCTL);
39
} else {
40
g_assert_not_reached();
41
}
42
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
43
g_free(name);
44
}
45
46
- object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
47
- TYPE_IOTKIT_SYSCTL);
48
if (info->has_mhus) {
49
object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
50
object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
51
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
52
return;
53
}
54
mr = sysbus_mmio_get_region(sbd, 0);
55
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
56
+ /* System control registers */
57
+ sbd = SYS_BUS_DEVICE(&s->sysctl);
58
+
59
+ object_property_set_int(OBJECT(&s->sysctl), "sse-version",
60
+ info->sse_version, &error_abort);
61
+ object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
62
+ info->cpuwait_rst, &error_abort);
63
+ object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
64
+ s->init_svtor, &error_abort);
65
+ object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
66
+ s->init_svtor, &error_abort);
67
+ if (!sysbus_realize(sbd, errp)) {
68
+ return;
69
+ }
70
+ mr = sysbus_mmio_get_region(sbd, 0);
71
} else {
72
g_assert_not_reached();
73
}
74
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
75
memory_region_add_subregion(&s->container, devinfo->addr, mr);
76
}
77
78
- /* System control registers */
79
- object_property_set_int(OBJECT(&s->sysctl), "sse-version",
80
- info->sse_version, &error_abort);
81
- object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
82
- info->cpuwait_rst, &error_abort);
83
- object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
84
- s->init_svtor, &error_abort);
85
- object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
86
- s->init_svtor, &error_abort);
87
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysctl), errp)) {
88
- return;
89
- }
90
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
91
-
92
if (info->has_ppus) {
93
/* CPUnCORE_PPU for each CPU */
94
for (i = 0; i < info->num_cpus; i++) {
95
--
96
2.20.1
97
98
diff view generated by jsdifflib
Deleted patch
1
Move the PPUs into the data-driven device placement framework.
2
We don't implement them, so they are just TYPE_UNIMPLEMENTED stubs.
3
1
4
Because the SSE-200 and the IotKit diverge here (the IoTKit does
5
not have the PPUs) we need to separate out the ARMSSEDeviceInfo
6
for the two variants, and only add the PPUs to the SSE-200.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-30-peter.maydell@linaro.org
12
---
13
include/hw/arm/armsse.h | 10 +-
14
hw/arm/armsse.c | 222 +++++++++++++++++++++++++++++-----------
15
2 files changed, 165 insertions(+), 67 deletions(-)
16
17
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/armsse.h
20
+++ b/include/hw/arm/armsse.h
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
22
23
#define SSE_MAX_CPUS 2
24
25
-/* These define what each PPU in the ppu[] index is for */
26
-#define CPU0CORE_PPU 0
27
-#define CPU1CORE_PPU 1
28
-#define DBG_PPU 2
29
-#define RAM0_PPU 3
30
-#define RAM1_PPU 4
31
-#define RAM2_PPU 5
32
-#define RAM3_PPU 6
33
#define NUM_PPUS 7
34
35
/* Number of CPU IRQs used by the SSE itself */
36
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
37
IoTKitSysCtl sysinfo;
38
39
ARMSSEMHU mhu[2];
40
- UnimplementedDeviceState ppu[NUM_PPUS];
41
+ UnimplementedDeviceState unimp[NUM_PPUS];
42
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
43
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
44
45
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/armsse.c
48
+++ b/hw/arm/armsse.c
49
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSEDeviceInfo {
50
const char *type; /* QOM type name */
51
unsigned int index; /* Which of the N devices of this type is this ? */
52
hwaddr addr;
53
+ hwaddr size; /* only needed for TYPE_UNIMPLEMENTED_DEVICE */
54
int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
55
int ppc_port; /* Port number of this device on the PPC */
56
int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1, or NMI_0 or NMI_1 */
57
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
58
uint32_t iidr;
59
uint32_t cpuwait_rst;
60
bool has_mhus;
61
- bool has_ppus;
62
bool has_cachectrl;
63
bool has_cpusecctrl;
64
bool has_cpuid;
65
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
66
DEFINE_PROP_END_OF_LIST()
67
};
68
69
-static const ARMSSEDeviceInfo sse200_devices[] = {
70
+static const ARMSSEDeviceInfo iotkit_devices[] = {
71
{
72
.name = "timer0",
73
.type = TYPE_CMSDK_APB_TIMER,
74
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
75
}
76
};
77
78
+static const ARMSSEDeviceInfo sse200_devices[] = {
79
+ {
80
+ .name = "timer0",
81
+ .type = TYPE_CMSDK_APB_TIMER,
82
+ .index = 0,
83
+ .addr = 0x40000000,
84
+ .ppc = 0,
85
+ .ppc_port = 0,
86
+ .irq = 3,
87
+ },
88
+ {
89
+ .name = "timer1",
90
+ .type = TYPE_CMSDK_APB_TIMER,
91
+ .index = 1,
92
+ .addr = 0x40001000,
93
+ .ppc = 0,
94
+ .ppc_port = 1,
95
+ .irq = 4,
96
+ },
97
+ {
98
+ .name = "s32ktimer",
99
+ .type = TYPE_CMSDK_APB_TIMER,
100
+ .index = 2,
101
+ .addr = 0x4002f000,
102
+ .ppc = 1,
103
+ .ppc_port = 0,
104
+ .irq = 2,
105
+ .slowclk = true,
106
+ },
107
+ {
108
+ .name = "dualtimer",
109
+ .type = TYPE_CMSDK_APB_DUALTIMER,
110
+ .index = 0,
111
+ .addr = 0x40002000,
112
+ .ppc = 0,
113
+ .ppc_port = 2,
114
+ .irq = 5,
115
+ },
116
+ {
117
+ .name = "s32kwatchdog",
118
+ .type = TYPE_CMSDK_APB_WATCHDOG,
119
+ .index = 0,
120
+ .addr = 0x5002e000,
121
+ .ppc = NO_PPC,
122
+ .irq = NMI_0,
123
+ .slowclk = true,
124
+ },
125
+ {
126
+ .name = "nswatchdog",
127
+ .type = TYPE_CMSDK_APB_WATCHDOG,
128
+ .index = 1,
129
+ .addr = 0x40081000,
130
+ .ppc = NO_PPC,
131
+ .irq = 1,
132
+ },
133
+ {
134
+ .name = "swatchdog",
135
+ .type = TYPE_CMSDK_APB_WATCHDOG,
136
+ .index = 2,
137
+ .addr = 0x50081000,
138
+ .ppc = NO_PPC,
139
+ .irq = NMI_1,
140
+ },
141
+ {
142
+ .name = "armsse-sysinfo",
143
+ .type = TYPE_IOTKIT_SYSINFO,
144
+ .index = 0,
145
+ .addr = 0x40020000,
146
+ .ppc = NO_PPC,
147
+ .irq = NO_IRQ,
148
+ },
149
+ {
150
+ .name = "armsse-sysctl",
151
+ .type = TYPE_IOTKIT_SYSCTL,
152
+ .index = 0,
153
+ .addr = 0x50021000,
154
+ .ppc = NO_PPC,
155
+ .irq = NO_IRQ,
156
+ },
157
+ {
158
+ .name = "CPU0CORE_PPU",
159
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
160
+ .index = 0,
161
+ .addr = 0x50023000,
162
+ .size = 0x1000,
163
+ .ppc = NO_PPC,
164
+ .irq = NO_IRQ,
165
+ },
166
+ {
167
+ .name = "CPU1CORE_PPU",
168
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
169
+ .index = 1,
170
+ .addr = 0x50025000,
171
+ .size = 0x1000,
172
+ .ppc = NO_PPC,
173
+ .irq = NO_IRQ,
174
+ },
175
+ {
176
+ .name = "DBG_PPU",
177
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
178
+ .index = 2,
179
+ .addr = 0x50029000,
180
+ .size = 0x1000,
181
+ .ppc = NO_PPC,
182
+ .irq = NO_IRQ,
183
+ },
184
+ {
185
+ .name = "RAM0_PPU",
186
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
187
+ .index = 3,
188
+ .addr = 0x5002a000,
189
+ .size = 0x1000,
190
+ .ppc = NO_PPC,
191
+ .irq = NO_IRQ,
192
+ },
193
+ {
194
+ .name = "RAM1_PPU",
195
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
196
+ .index = 4,
197
+ .addr = 0x5002b000,
198
+ .size = 0x1000,
199
+ .ppc = NO_PPC,
200
+ .irq = NO_IRQ,
201
+ },
202
+ {
203
+ .name = "RAM2_PPU",
204
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
205
+ .index = 5,
206
+ .addr = 0x5002c000,
207
+ .size = 0x1000,
208
+ .ppc = NO_PPC,
209
+ .irq = NO_IRQ,
210
+ },
211
+ {
212
+ .name = "RAM3_PPU",
213
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
214
+ .index = 6,
215
+ .addr = 0x5002d000,
216
+ .size = 0x1000,
217
+ .ppc = NO_PPC,
218
+ .irq = NO_IRQ,
219
+ },
220
+ {
221
+ .name = NULL,
222
+ }
223
+};
224
+
225
static const ARMSSEInfo armsse_variants[] = {
226
{
227
.name = TYPE_IOTKIT,
228
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
229
.iidr = 0,
230
.cpuwait_rst = 0,
231
.has_mhus = false,
232
- .has_ppus = false,
233
.has_cachectrl = false,
234
.has_cpusecctrl = false,
235
.has_cpuid = false,
236
.props = iotkit_properties,
237
- .devinfo = sse200_devices,
238
+ .devinfo = iotkit_devices,
239
},
240
{
241
.name = TYPE_SSE200,
242
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
243
.iidr = 0,
244
.cpuwait_rst = 2,
245
.has_mhus = true,
246
- .has_ppus = true,
247
.has_cachectrl = true,
248
.has_cpusecctrl = true,
249
.has_cpuid = true,
250
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
251
assert(devinfo->index == 0);
252
object_initialize_child(obj, devinfo->name, &s->sysctl,
253
TYPE_IOTKIT_SYSCTL);
254
+ } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
255
+ assert(devinfo->index < ARRAY_SIZE(s->unimp));
256
+ object_initialize_child(obj, devinfo->name,
257
+ &s->unimp[devinfo->index],
258
+ TYPE_UNIMPLEMENTED_DEVICE);
259
} else {
260
g_assert_not_reached();
261
}
262
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
263
object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
264
object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
265
}
266
- if (info->has_ppus) {
267
- for (i = 0; i < info->num_cpus; i++) {
268
- char *name = g_strdup_printf("CPU%dCORE_PPU", i);
269
- int ppuidx = CPU0CORE_PPU + i;
270
-
271
- object_initialize_child(obj, name, &s->ppu[ppuidx],
272
- TYPE_UNIMPLEMENTED_DEVICE);
273
- g_free(name);
274
- }
275
- object_initialize_child(obj, "DBG_PPU", &s->ppu[DBG_PPU],
276
- TYPE_UNIMPLEMENTED_DEVICE);
277
- for (i = 0; i < info->sram_banks; i++) {
278
- char *name = g_strdup_printf("RAM%d_PPU", i);
279
- int ppuidx = RAM0_PPU + i;
280
-
281
- object_initialize_child(obj, name, &s->ppu[ppuidx],
282
- TYPE_UNIMPLEMENTED_DEVICE);
283
- g_free(name);
284
- }
285
- }
286
if (info->has_cachectrl) {
287
for (i = 0; i < info->num_cpus; i++) {
288
char *name = g_strdup_printf("cachectrl%d", i);
289
@@ -XXX,XX +XXX,XX @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
290
}
291
}
292
293
-static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr)
294
-{
295
- /* Map a PPU unimplemented device stub */
296
- DeviceState *dev = DEVICE(&s->ppu[ppuidx]);
297
-
298
- qdev_prop_set_string(dev, "name", name);
299
- qdev_prop_set_uint64(dev, "size", 0x1000);
300
- sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
301
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
302
-}
303
-
304
static void armsse_realize(DeviceState *dev, Error **errp)
305
{
306
ARMSSE *s = ARM_SSE(dev);
307
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
308
return;
309
}
310
mr = sysbus_mmio_get_region(sbd, 0);
311
+ } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
312
+ sbd = SYS_BUS_DEVICE(&s->unimp[devinfo->index]);
313
+
314
+ qdev_prop_set_string(DEVICE(sbd), "name", devinfo->name);
315
+ qdev_prop_set_uint64(DEVICE(sbd), "size", devinfo->size);
316
+ if (!sysbus_realize(sbd, errp)) {
317
+ return;
318
+ }
319
+ mr = sysbus_mmio_get_region(sbd, 0);
320
} else {
321
g_assert_not_reached();
322
}
323
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
324
memory_region_add_subregion(&s->container, devinfo->addr, mr);
325
}
326
327
- if (info->has_ppus) {
328
- /* CPUnCORE_PPU for each CPU */
329
- for (i = 0; i < info->num_cpus; i++) {
330
- char *name = g_strdup_printf("CPU%dCORE_PPU", i);
331
-
332
- map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
333
- /*
334
- * We don't support CPU debug so don't create the
335
- * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
336
- */
337
- g_free(name);
338
- }
339
- map_ppu(s, DBG_PPU, "DBG_PPU", 0x50029000);
340
-
341
- for (i = 0; i < info->sram_banks; i++) {
342
- char *name = g_strdup_printf("RAM%d_PPU", i);
343
-
344
- map_ppu(s, RAM0_PPU + i, name, 0x5002a000 + i * 0x1000);
345
- g_free(name);
346
- }
347
- }
348
-
349
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
350
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
351
352
--
353
2.20.1
354
355
diff view generated by jsdifflib
Deleted patch
1
We forgot to implement a TYPE_UNIMPLEMENTED_DEVICE stub
2
for the SYS_PPU in the SSE-200, which is at 0x50022000.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-31-peter.maydell@linaro.org
8
---
9
include/hw/arm/armsse.h | 2 +-
10
hw/arm/armsse.c | 9 +++++++++
11
2 files changed, 10 insertions(+), 1 deletion(-)
12
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armsse.h
16
+++ b/include/hw/arm/armsse.h
17
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
18
19
#define SSE_MAX_CPUS 2
20
21
-#define NUM_PPUS 7
22
+#define NUM_PPUS 8
23
24
/* Number of CPU IRQs used by the SSE itself */
25
#define NUM_SSE_IRQS 32
26
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/armsse.c
29
+++ b/hw/arm/armsse.c
30
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
31
.ppc = NO_PPC,
32
.irq = NO_IRQ,
33
},
34
+ {
35
+ .name = "SYS_PPU",
36
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
37
+ .index = 7,
38
+ .addr = 0x50022000,
39
+ .size = 0x1000,
40
+ .ppc = NO_PPC,
41
+ .irq = NO_IRQ,
42
+ },
43
{
44
.name = NULL,
45
}
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a slightly different set of shared-per-CPU interrupts,
2
allow the irq_is_common[] array to be different per SSE variant.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-32-peter.maydell@linaro.org
9
---
10
hw/arm/armsse.c | 39 +++++++++++++++++++++------------------
11
1 file changed, 21 insertions(+), 18 deletions(-)
12
13
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/armsse.c
16
+++ b/hw/arm/armsse.c
17
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
18
bool has_cpuid;
19
Property *props;
20
const ARMSSEDeviceInfo *devinfo;
21
+ const bool *irq_is_common;
22
};
23
24
static Property iotkit_properties[] = {
25
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
26
}
27
};
28
29
+/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
30
+static const bool sse200_irq_is_common[32] = {
31
+ [0 ... 5] = true,
32
+ /* 6, 7: per-CPU MHU interrupts */
33
+ [8 ... 12] = true,
34
+ /* 13: per-CPU icache interrupt */
35
+ /* 14: reserved */
36
+ [15 ... 20] = true,
37
+ /* 21: reserved */
38
+ [22 ... 26] = true,
39
+ /* 27: reserved */
40
+ /* 28, 29: per-CPU CTI interrupts */
41
+ /* 30, 31: reserved */
42
+};
43
+
44
static const ARMSSEInfo armsse_variants[] = {
45
{
46
.name = TYPE_IOTKIT,
47
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
48
.has_cpuid = false,
49
.props = iotkit_properties,
50
.devinfo = iotkit_devices,
51
+ .irq_is_common = sse200_irq_is_common,
52
},
53
{
54
.name = TYPE_SSE200,
55
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
56
.has_cpuid = true,
57
.props = armsse_properties,
58
.devinfo = sse200_devices,
59
+ .irq_is_common = sse200_irq_is_common,
60
},
61
};
62
63
@@ -XXX,XX +XXX,XX @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
64
/* Clock frequency in HZ of the 32KHz "slow clock" */
65
#define S32KCLK (32 * 1000)
66
67
-/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
68
-static bool irq_is_common[32] = {
69
- [0 ... 5] = true,
70
- /* 6, 7: per-CPU MHU interrupts */
71
- [8 ... 12] = true,
72
- /* 13: per-CPU icache interrupt */
73
- /* 14: reserved */
74
- [15 ... 20] = true,
75
- /* 21: reserved */
76
- [22 ... 26] = true,
77
- /* 27: reserved */
78
- /* 28, 29: per-CPU CTI interrupts */
79
- /* 30, 31: reserved */
80
-};
81
-
82
/*
83
* Create an alias region in @container of @size bytes starting at @base
84
* which mirrors the memory starting at @orig.
85
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
86
}
87
if (info->num_cpus > 1) {
88
for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
89
- if (irq_is_common[i]) {
90
+ if (info->irq_is_common[i]) {
91
char *name = g_strdup_printf("cpu-irq-splitter%d", i);
92
SplitIRQ *splitter = &s->cpu_irq_splitter[i];
93
94
@@ -XXX,XX +XXX,XX @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
95
ARMSSEClass *asc = ARM_SSE_GET_CLASS(s);
96
const ARMSSEInfo *info = asc->info;
97
98
- assert(irq_is_common[irqno]);
99
+ assert(info->irq_is_common[irqno]);
100
101
if (info->num_cpus == 1) {
102
/* Only one CPU -- just connect directly to it */
103
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
104
/* Wire up the splitters that connect common IRQs to all CPUs */
105
if (info->num_cpus > 1) {
106
for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
107
- if (irq_is_common[i]) {
108
+ if (info->irq_is_common[i]) {
109
Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
110
DeviceState *devs = DEVICE(splitter);
111
int cpunum;
112
--
113
2.20.1
114
115
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a system counter device; add support for SSE
2
variants having this device.
3
1
4
As with the existing devices like the cache control block, CPUID
5
block, etc, we don't try to make the MMIO addresses configurable. We
6
can do that if and when we need to model a future SSE variant which
7
has the counter in a different location.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-33-peter.maydell@linaro.org
13
---
14
include/hw/arm/armsse.h | 3 +++
15
hw/arm/armsse.c | 27 +++++++++++++++++++++++++++
16
2 files changed, 30 insertions(+)
17
18
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/armsse.h
21
+++ b/include/hw/arm/armsse.h
22
@@ -XXX,XX +XXX,XX @@
23
#include "hw/misc/tz-mpc.h"
24
#include "hw/timer/cmsdk-apb-timer.h"
25
#include "hw/timer/cmsdk-apb-dualtimer.h"
26
+#include "hw/timer/sse-counter.h"
27
#include "hw/watchdog/cmsdk-apb-watchdog.h"
28
#include "hw/misc/iotkit-sysctl.h"
29
#include "hw/misc/iotkit-sysinfo.h"
30
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
31
32
CMSDKAPBWatchdog cmsdk_watchdog[3];
33
34
+ SSECounter sse_counter;
35
+
36
IoTKitSysCtl sysctl;
37
IoTKitSysCtl sysinfo;
38
39
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/armsse.c
42
+++ b/hw/arm/armsse.c
43
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
44
bool has_cachectrl;
45
bool has_cpusecctrl;
46
bool has_cpuid;
47
+ bool has_sse_counter;
48
Property *props;
49
const ARMSSEDeviceInfo *devinfo;
50
const bool *irq_is_common;
51
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
52
.has_cachectrl = false,
53
.has_cpusecctrl = false,
54
.has_cpuid = false,
55
+ .has_sse_counter = false,
56
.props = iotkit_properties,
57
.devinfo = iotkit_devices,
58
.irq_is_common = sse200_irq_is_common,
59
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
60
.has_cachectrl = true,
61
.has_cpusecctrl = true,
62
.has_cpuid = true,
63
+ .has_sse_counter = false,
64
.props = armsse_properties,
65
.devinfo = sse200_devices,
66
.irq_is_common = sse200_irq_is_common,
67
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
68
g_free(name);
69
}
70
}
71
+ if (info->has_sse_counter) {
72
+ object_initialize_child(obj, "sse-counter", &s->sse_counter,
73
+ TYPE_SSE_COUNTER);
74
+ }
75
+
76
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, TYPE_OR_IRQ);
77
object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
78
TYPE_OR_IRQ);
79
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
80
qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
81
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
82
83
+ /* The SSE-300 has a System Counter / System Timestamp Generator */
84
+ if (info->has_sse_counter) {
85
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sse_counter);
86
+
87
+ qdev_connect_clock_in(DEVICE(sbd), "CLK", s->mainclk);
88
+ if (!sysbus_realize(sbd, errp)) {
89
+ return;
90
+ }
91
+ /*
92
+ * The control frame is only in the Secure region;
93
+ * the status frame is in the NS region (and visible in the
94
+ * S region via the alias mapping).
95
+ */
96
+ memory_region_add_subregion(&s->container, 0x58100000,
97
+ sysbus_mmio_get_region(sbd, 0));
98
+ memory_region_add_subregion(&s->container, 0x48101000,
99
+ sysbus_mmio_get_region(sbd, 1));
100
+ }
101
+
102
/* Devices behind APB PPC0:
103
* 0x40000000: timer0
104
* 0x40001000: timer1
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has four timers of type TYPE_SSE_TIMER; add support in
2
the code for having these in an ARMSSEDeviceInfo array.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-34-peter.maydell@linaro.org
9
---
10
include/hw/arm/armsse.h | 2 ++
11
hw/arm/armsse.c | 15 +++++++++++++++
12
2 files changed, 17 insertions(+)
13
14
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armsse.h
17
+++ b/include/hw/arm/armsse.h
18
@@ -XXX,XX +XXX,XX @@
19
#include "hw/timer/cmsdk-apb-timer.h"
20
#include "hw/timer/cmsdk-apb-dualtimer.h"
21
#include "hw/timer/sse-counter.h"
22
+#include "hw/timer/sse-timer.h"
23
#include "hw/watchdog/cmsdk-apb-watchdog.h"
24
#include "hw/misc/iotkit-sysctl.h"
25
#include "hw/misc/iotkit-sysinfo.h"
26
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
27
CMSDKAPBWatchdog cmsdk_watchdog[3];
28
29
SSECounter sse_counter;
30
+ SSETimer sse_timer[4];
31
32
IoTKitSysCtl sysctl;
33
IoTKitSysCtl sysinfo;
34
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/armsse.c
37
+++ b/hw/arm/armsse.c
38
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
39
assert(devinfo->index == 0);
40
object_initialize_child(obj, devinfo->name, &s->dualtimer,
41
TYPE_CMSDK_APB_DUALTIMER);
42
+ } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
43
+ assert(devinfo->index < ARRAY_SIZE(s->sse_timer));
44
+ object_initialize_child(obj, devinfo->name,
45
+ &s->sse_timer[devinfo->index],
46
+ TYPE_SSE_TIMER);
47
} else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
48
assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
49
object_initialize_child(obj, devinfo->name,
50
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
51
return;
52
}
53
mr = sysbus_mmio_get_region(sbd, 0);
54
+ } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
55
+ sbd = SYS_BUS_DEVICE(&s->sse_timer[devinfo->index]);
56
+
57
+ assert(info->has_sse_counter);
58
+ object_property_set_link(OBJECT(sbd), "counter",
59
+ OBJECT(&s->sse_counter), &error_abort);
60
+ if (!sysbus_realize(sbd, errp)) {
61
+ return;
62
+ }
63
+ mr = sysbus_mmio_get_region(sbd, 0);
64
} else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
65
sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
66
67
--
68
2.20.1
69
70
diff view generated by jsdifflib
Deleted patch
1
Support SSE variants like the SSE-300 with an ARMSSE_CPU_PWRCTRL register
2
block. Because this block is per-CPU and does not clash with any of the
3
SSE-200 devices, we handle it with a has_cpu_pwrctrl flag like the
4
existing has_cachectrl, has_cpusectrl and has_cpuid, rather than
5
trying to add per-CPU-device support to the devinfo array handling code.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-35-peter.maydell@linaro.org
11
---
12
include/hw/arm/armsse.h | 3 +++
13
hw/arm/armsse.c | 26 ++++++++++++++++++++++++++
14
2 files changed, 29 insertions(+)
15
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/armsse.h
19
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/misc/iotkit-sysinfo.h"
22
#include "hw/misc/armsse-cpuid.h"
23
#include "hw/misc/armsse-mhu.h"
24
+#include "hw/misc/armsse-cpu-pwrctrl.h"
25
#include "hw/misc/unimp.h"
26
#include "hw/or-irq.h"
27
#include "hw/clock.h"
28
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
29
30
ARMSSECPUID cpuid[SSE_MAX_CPUS];
31
32
+ ARMSSECPUPwrCtrl cpu_pwrctrl[SSE_MAX_CPUS];
33
+
34
/*
35
* 'container' holds all devices seen by all CPUs.
36
* 'cpu_container[i]' is the view that CPU i has: this has the
37
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/armsse.c
40
+++ b/hw/arm/armsse.c
41
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
42
bool has_cachectrl;
43
bool has_cpusecctrl;
44
bool has_cpuid;
45
+ bool has_cpu_pwrctrl;
46
bool has_sse_counter;
47
Property *props;
48
const ARMSSEDeviceInfo *devinfo;
49
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
50
.has_cachectrl = false,
51
.has_cpusecctrl = false,
52
.has_cpuid = false,
53
+ .has_cpu_pwrctrl = false,
54
.has_sse_counter = false,
55
.props = iotkit_properties,
56
.devinfo = iotkit_devices,
57
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
58
.has_cachectrl = true,
59
.has_cpusecctrl = true,
60
.has_cpuid = true,
61
+ .has_cpu_pwrctrl = false,
62
.has_sse_counter = false,
63
.props = armsse_properties,
64
.devinfo = sse200_devices,
65
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
66
g_free(name);
67
}
68
}
69
+ if (info->has_cpu_pwrctrl) {
70
+ for (i = 0; i < info->num_cpus; i++) {
71
+ char *name = g_strdup_printf("cpu_pwrctrl%d", i);
72
+
73
+ object_initialize_child(obj, name, &s->cpu_pwrctrl[i],
74
+ TYPE_ARMSSE_CPU_PWRCTRL);
75
+ g_free(name);
76
+ }
77
+ }
78
if (info->has_sse_counter) {
79
object_initialize_child(obj, "sse-counter", &s->sse_counter,
80
TYPE_SSE_COUNTER);
81
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
82
* 0x50010000: L1 icache control registers
83
* 0x50011000: CPUSECCTRL (CPU local security control registers)
84
* 0x4001f000 and 0x5001f000: CPU_IDENTITY register block
85
+ * The SSE-300 has an extra:
86
+ * 0x40012000 and 0x50012000: CPU_PWRCTRL register block
87
*/
88
if (info->has_cachectrl) {
89
for (i = 0; i < info->num_cpus; i++) {
90
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
91
memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
92
}
93
}
94
+ if (info->has_cpu_pwrctrl) {
95
+ for (i = 0; i < info->num_cpus; i++) {
96
+ MemoryRegion *mr;
97
+
98
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), errp)) {
99
+ return;
100
+ }
101
+
102
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), 0);
103
+ memory_region_add_subregion(&s->cpu_container[i], 0x40012000, mr);
104
+ }
105
+ }
106
107
if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
108
return;
109
--
110
2.20.1
111
112
diff view generated by jsdifflib
Deleted patch
1
Now we have sufficiently parameterised the code, we can add SSE-300
2
support by adding a new entry to the armsse_variants[] array.
3
1
4
Note that the main watchdog (unlike the s32k watchdog) in the SSE-300
5
is a different device from the CMSDK watchdog; we don't have a model
6
of it so we leave it as a TYPE_UNIMPLEMENTED_DEVICE stub.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-36-peter.maydell@linaro.org
12
---
13
include/hw/arm/armsse.h | 1 +
14
hw/arm/armsse.c | 152 ++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 153 insertions(+)
16
17
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/armsse.h
20
+++ b/include/hw/arm/armsse.h
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
22
*/
23
#define TYPE_IOTKIT "iotkit"
24
#define TYPE_SSE200 "sse-200"
25
+#define TYPE_SSE300 "sse-300"
26
27
/* We have an IRQ splitter and an OR gate input for each external PPC
28
* and the 2 internal PPCs
29
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/armsse.c
32
+++ b/hw/arm/armsse.c
33
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
34
}
35
};
36
37
+static const ARMSSEDeviceInfo sse300_devices[] = {
38
+ {
39
+ .name = "timer0",
40
+ .type = TYPE_SSE_TIMER,
41
+ .index = 0,
42
+ .addr = 0x48000000,
43
+ .ppc = 0,
44
+ .ppc_port = 0,
45
+ .irq = 3,
46
+ },
47
+ {
48
+ .name = "timer1",
49
+ .type = TYPE_SSE_TIMER,
50
+ .index = 1,
51
+ .addr = 0x48001000,
52
+ .ppc = 0,
53
+ .ppc_port = 1,
54
+ .irq = 4,
55
+ },
56
+ {
57
+ .name = "timer2",
58
+ .type = TYPE_SSE_TIMER,
59
+ .index = 2,
60
+ .addr = 0x48002000,
61
+ .ppc = 0,
62
+ .ppc_port = 2,
63
+ .irq = 5,
64
+ },
65
+ {
66
+ .name = "timer3",
67
+ .type = TYPE_SSE_TIMER,
68
+ .index = 3,
69
+ .addr = 0x48003000,
70
+ .ppc = 0,
71
+ .ppc_port = 5,
72
+ .irq = 27,
73
+ },
74
+ {
75
+ .name = "s32ktimer",
76
+ .type = TYPE_CMSDK_APB_TIMER,
77
+ .index = 0,
78
+ .addr = 0x4802f000,
79
+ .ppc = 1,
80
+ .ppc_port = 0,
81
+ .irq = 2,
82
+ .slowclk = true,
83
+ },
84
+ {
85
+ .name = "s32kwatchdog",
86
+ .type = TYPE_CMSDK_APB_WATCHDOG,
87
+ .index = 0,
88
+ .addr = 0x4802e000,
89
+ .ppc = NO_PPC,
90
+ .irq = NMI_0,
91
+ .slowclk = true,
92
+ },
93
+ {
94
+ .name = "watchdog",
95
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
96
+ .index = 0,
97
+ .addr = 0x48040000,
98
+ .size = 0x2000,
99
+ .ppc = NO_PPC,
100
+ .irq = NO_IRQ,
101
+ },
102
+ {
103
+ .name = "armsse-sysinfo",
104
+ .type = TYPE_IOTKIT_SYSINFO,
105
+ .index = 0,
106
+ .addr = 0x48020000,
107
+ .ppc = NO_PPC,
108
+ .irq = NO_IRQ,
109
+ },
110
+ {
111
+ .name = "armsse-sysctl",
112
+ .type = TYPE_IOTKIT_SYSCTL,
113
+ .index = 0,
114
+ .addr = 0x58021000,
115
+ .ppc = NO_PPC,
116
+ .irq = NO_IRQ,
117
+ },
118
+ {
119
+ .name = "SYS_PPU",
120
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
121
+ .index = 1,
122
+ .addr = 0x58022000,
123
+ .size = 0x1000,
124
+ .ppc = NO_PPC,
125
+ .irq = NO_IRQ,
126
+ },
127
+ {
128
+ .name = "CPU0CORE_PPU",
129
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
130
+ .index = 2,
131
+ .addr = 0x50023000,
132
+ .size = 0x1000,
133
+ .ppc = NO_PPC,
134
+ .irq = NO_IRQ,
135
+ },
136
+ {
137
+ .name = "MGMT_PPU",
138
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
139
+ .index = 3,
140
+ .addr = 0x50028000,
141
+ .size = 0x1000,
142
+ .ppc = NO_PPC,
143
+ .irq = NO_IRQ,
144
+ },
145
+ {
146
+ .name = "DEBUG_PPU",
147
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
148
+ .index = 4,
149
+ .addr = 0x50029000,
150
+ .size = 0x1000,
151
+ .ppc = NO_PPC,
152
+ .irq = NO_IRQ,
153
+ },
154
+ {
155
+ .name = NULL,
156
+ }
157
+};
158
+
159
/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
160
static const bool sse200_irq_is_common[32] = {
161
[0 ... 5] = true,
162
@@ -XXX,XX +XXX,XX @@ static const bool sse200_irq_is_common[32] = {
163
/* 30, 31: reserved */
164
};
165
166
+static const bool sse300_irq_is_common[32] = {
167
+ [0 ... 5] = true,
168
+ /* 6, 7: per-CPU MHU interrupts */
169
+ [8 ... 12] = true,
170
+ /* 13: reserved */
171
+ [14 ... 16] = true,
172
+ /* 17-25: reserved */
173
+ [26 ... 27] = true,
174
+ /* 28, 29: per-CPU CTI interrupts */
175
+ /* 30, 31: reserved */
176
+};
177
+
178
static const ARMSSEInfo armsse_variants[] = {
179
{
180
.name = TYPE_IOTKIT,
181
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
182
.devinfo = sse200_devices,
183
.irq_is_common = sse200_irq_is_common,
184
},
185
+ {
186
+ .name = TYPE_SSE300,
187
+ .sse_version = ARMSSE_SSE300,
188
+ .sram_banks = 2,
189
+ .num_cpus = 1,
190
+ .sys_version = 0x7e00043b,
191
+ .iidr = 0x74a0043b,
192
+ .cpuwait_rst = 0,
193
+ .has_mhus = false,
194
+ .has_cachectrl = false,
195
+ .has_cpusecctrl = true,
196
+ .has_cpuid = true,
197
+ .has_cpu_pwrctrl = true,
198
+ .has_sse_counter = true,
199
+ .props = armsse_properties,
200
+ .devinfo = sse300_devices,
201
+ .irq_is_common = sse300_irq_is_common,
202
+ },
203
};
204
205
static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
206
--
207
2.20.1
208
209
diff view generated by jsdifflib
Deleted patch
1
The AN547 puts the combined UART overflow IRQ at 48, not 47 like the
2
other images. Make this setting board-specific.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-37-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 6 +++++-
11
1 file changed, 5 insertions(+), 1 deletion(-)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
18
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
19
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
20
int numirq; /* Number of external interrupts */
21
+ int uart_overflow_irq; /* number of the combined UART overflow IRQ */
22
const RAMInfo *raminfo;
23
const char *armsse_type;
24
};
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
26
&error_fatal);
27
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
28
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
29
- get_sse_irq_in(mms, 47));
30
+ get_sse_irq_in(mms, mmc->uart_overflow_irq));
31
32
/* Most of the devices in the FPGA are behind Peripheral Protection
33
* Controllers. The required order for initializing things is:
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
35
mmc->fpgaio_num_leds = 2;
36
mmc->fpgaio_has_switches = false;
37
mmc->numirq = 92;
38
+ mmc->uart_overflow_irq = 47;
39
mmc->raminfo = an505_raminfo;
40
mmc->armsse_type = TYPE_IOTKIT;
41
mps2tz_set_default_ram_info(mmc);
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
43
mmc->fpgaio_num_leds = 2;
44
mmc->fpgaio_has_switches = false;
45
mmc->numirq = 92;
46
+ mmc->uart_overflow_irq = 47;
47
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
48
mmc->armsse_type = TYPE_SSE200;
49
mps2tz_set_default_ram_info(mmc);
50
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
51
mmc->fpgaio_num_leds = 10;
52
mmc->fpgaio_has_switches = true;
53
mmc->numirq = 95;
54
+ mmc->uart_overflow_irq = 47;
55
mmc->raminfo = an524_raminfo;
56
mmc->armsse_type = TYPE_SSE200;
57
mps2tz_set_default_ram_info(mmc);
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
Deleted patch
1
We've already broken migration compatibility for all the MPS
2
boards, so we might as well take advantage of this to simplify
3
the vmstate for the FPGAIO device by folding the counters
4
subsection into the main vmstate description.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-38-peter.maydell@linaro.org
10
---
11
hw/misc/mps2-fpgaio.c | 30 +++++-------------------------
12
1 file changed, 5 insertions(+), 25 deletions(-)
13
14
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/misc/mps2-fpgaio.c
17
+++ b/hw/misc/mps2-fpgaio.c
18
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
19
}
20
}
21
22
-static bool mps2_fpgaio_counters_needed(void *opaque)
23
-{
24
- /* Currently vmstate.c insists all subsections have a 'needed' function */
25
- return true;
26
-}
27
-
28
-static const VMStateDescription mps2_fpgaio_counters_vmstate = {
29
- .name = "mps2-fpgaio/counters",
30
+static const VMStateDescription mps2_fpgaio_vmstate = {
31
+ .name = "mps2-fpgaio",
32
.version_id = 2,
33
.minimum_version_id = 2,
34
- .needed = mps2_fpgaio_counters_needed,
35
.fields = (VMStateField[]) {
36
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
37
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
38
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
39
VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
40
VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
41
VMSTATE_UINT32(counter, MPS2FPGAIO),
42
VMSTATE_UINT32(pscntr, MPS2FPGAIO),
43
VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
44
VMSTATE_END_OF_LIST()
45
- }
46
-};
47
-
48
-static const VMStateDescription mps2_fpgaio_vmstate = {
49
- .name = "mps2-fpgaio",
50
- .version_id = 1,
51
- .minimum_version_id = 1,
52
- .fields = (VMStateField[]) {
53
- VMSTATE_UINT32(led0, MPS2FPGAIO),
54
- VMSTATE_UINT32(prescale, MPS2FPGAIO),
55
- VMSTATE_UINT32(misc, MPS2FPGAIO),
56
- VMSTATE_END_OF_LIST()
57
},
58
- .subsections = (const VMStateDescription*[]) {
59
- &mps2_fpgaio_counters_vmstate,
60
- NULL
61
- }
62
};
63
64
static Property mps2_fpgaio_properties[] = {
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
For the AN547 image, the FPGAIO block has an extra DBGCTRL register,
2
which is used to control the SPNIDEN, SPIDEN, NPIDEN and DBGEN inputs
3
to the CPU. These signals control when the CPU permits use of the
4
external debug interface. Our CPU models don't implement the
5
external debug interface, so we model the register as
6
reads-as-written.
7
1
8
Implement the register, with a property defining whether it is
9
present, and allow mps2-tz boards to specify that it is present.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210219144617.4782-39-peter.maydell@linaro.org
16
---
17
include/hw/misc/mps2-fpgaio.h | 2 ++
18
hw/arm/mps2-tz.c | 5 +++++
19
hw/misc/mps2-fpgaio.c | 22 ++++++++++++++++++++--
20
3 files changed, 27 insertions(+), 2 deletions(-)
21
22
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/misc/mps2-fpgaio.h
25
+++ b/include/hw/misc/mps2-fpgaio.h
26
@@ -XXX,XX +XXX,XX @@ struct MPS2FPGAIO {
27
LEDState *led[MPS2FPGAIO_MAX_LEDS];
28
uint32_t num_leds;
29
bool has_switches;
30
+ bool has_dbgctrl;
31
32
uint32_t led0;
33
uint32_t prescale;
34
uint32_t misc;
35
+ uint32_t dbgctrl;
36
37
/* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
38
int64_t pscntr_sync_ticks;
39
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/mps2-tz.c
42
+++ b/hw/arm/mps2-tz.c
43
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
44
const uint32_t *oscclk;
45
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
46
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
47
+ bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
48
int numirq; /* Number of external interrupts */
49
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
50
const RAMInfo *raminfo;
51
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
52
object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
53
qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
54
qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
55
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-dbgctrl", mmc->fpgaio_has_dbgctrl);
56
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
57
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
58
}
59
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
60
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
61
mmc->fpgaio_num_leds = 2;
62
mmc->fpgaio_has_switches = false;
63
+ mmc->fpgaio_has_dbgctrl = false;
64
mmc->numirq = 92;
65
mmc->uart_overflow_irq = 47;
66
mmc->raminfo = an505_raminfo;
67
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
68
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
69
mmc->fpgaio_num_leds = 2;
70
mmc->fpgaio_has_switches = false;
71
+ mmc->fpgaio_has_dbgctrl = false;
72
mmc->numirq = 92;
73
mmc->uart_overflow_irq = 47;
74
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
75
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
76
mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
77
mmc->fpgaio_num_leds = 10;
78
mmc->fpgaio_has_switches = true;
79
+ mmc->fpgaio_has_dbgctrl = false;
80
mmc->numirq = 95;
81
mmc->uart_overflow_irq = 47;
82
mmc->raminfo = an524_raminfo;
83
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/mps2-fpgaio.c
86
+++ b/hw/misc/mps2-fpgaio.c
87
@@ -XXX,XX +XXX,XX @@
88
#include "qemu/timer.h"
89
90
REG32(LED0, 0)
91
+REG32(DBGCTRL, 4)
92
REG32(BUTTON, 8)
93
REG32(CLK1HZ, 0x10)
94
REG32(CLK100HZ, 0x14)
95
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
96
case A_LED0:
97
r = s->led0;
98
break;
99
+ case A_DBGCTRL:
100
+ if (!s->has_dbgctrl) {
101
+ goto bad_offset;
102
+ }
103
+ r = s->dbgctrl;
104
+ break;
105
case A_BUTTON:
106
/* User-pressable board buttons. We don't model that, so just return
107
* zeroes.
108
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
109
}
110
}
111
break;
112
+ case A_DBGCTRL:
113
+ if (!s->has_dbgctrl) {
114
+ goto bad_offset;
115
+ }
116
+ qemu_log_mask(LOG_UNIMP,
117
+ "MPS2 FPGAIO: DBGCTRL unimplemented\n");
118
+ s->dbgctrl = value;
119
+ break;
120
case A_PRESCALE:
121
resync_counter(s);
122
s->prescale = value;
123
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
124
s->pscntr = value;
125
break;
126
default:
127
+ bad_offset:
128
qemu_log_mask(LOG_GUEST_ERROR,
129
"MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
130
break;
131
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
132
133
static const VMStateDescription mps2_fpgaio_vmstate = {
134
.name = "mps2-fpgaio",
135
- .version_id = 2,
136
- .minimum_version_id = 2,
137
+ .version_id = 3,
138
+ .minimum_version_id = 3,
139
.fields = (VMStateField[]) {
140
VMSTATE_UINT32(led0, MPS2FPGAIO),
141
VMSTATE_UINT32(prescale, MPS2FPGAIO),
142
VMSTATE_UINT32(misc, MPS2FPGAIO),
143
+ VMSTATE_UINT32(dbgctrl, MPS2FPGAIO),
144
VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
145
VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
146
VMSTATE_UINT32(counter, MPS2FPGAIO),
147
@@ -XXX,XX +XXX,XX @@ static Property mps2_fpgaio_properties[] = {
148
/* Number of LEDs controlled by LED0 register */
149
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
150
DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
151
+ DEFINE_PROP_BOOL("has-dbgctrl", MPS2FPGAIO, has_dbgctrl, false),
152
DEFINE_PROP_END_OF_LIST(),
153
};
154
155
--
156
2.20.1
157
158
diff view generated by jsdifflib
Deleted patch
1
Implement the minor changes required to the SCC block for AN547 images:
2
* CFG2 and CFG5 exist (like AN524)
3
* CFG3 is reserved (like AN524)
4
* CFG0 bit 1 is CPU_WAIT; we don't implement it, but note this
5
in the TODO comment
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-40-peter.maydell@linaro.org
11
---
12
hw/misc/mps2-scc.c | 15 +++++++++------
13
1 file changed, 9 insertions(+), 6 deletions(-)
14
15
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/mps2-scc.c
18
+++ b/hw/misc/mps2-scc.c
19
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
20
r = s->cfg1;
21
break;
22
case A_CFG2:
23
- if (scc_partno(s) != 0x524) {
24
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
25
/* CFG2 reserved on other boards */
26
goto bad_offset;
27
}
28
r = s->cfg2;
29
break;
30
case A_CFG3:
31
- if (scc_partno(s) == 0x524) {
32
+ if (scc_partno(s) == 0x524 && scc_partno(s) == 0x547) {
33
/* CFG3 reserved on AN524 */
34
goto bad_offset;
35
}
36
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
37
r = s->cfg4;
38
break;
39
case A_CFG5:
40
- if (scc_partno(s) != 0x524) {
41
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
42
/* CFG5 reserved on other boards */
43
goto bad_offset;
44
}
45
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
46
47
switch (offset) {
48
case A_CFG0:
49
- /* TODO on some boards bit 0 controls RAM remapping */
50
+ /*
51
+ * TODO on some boards bit 0 controls RAM remapping;
52
+ * on others bit 1 is CPU_WAIT.
53
+ */
54
s->cfg0 = value;
55
break;
56
case A_CFG1:
57
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
58
}
59
break;
60
case A_CFG2:
61
- if (scc_partno(s) != 0x524) {
62
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
63
/* CFG2 reserved on other boards */
64
goto bad_offset;
65
}
66
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
67
s->cfg2 = value;
68
break;
69
case A_CFG5:
70
- if (scc_partno(s) != 0x524) {
71
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
72
/* CFG5 reserved on other boards */
73
goto bad_offset;
74
}
75
--
76
2.20.1
77
78
diff view generated by jsdifflib
Deleted patch
1
The AN547 runs the APB peripherals outside the SSE-300 on a different
2
and slightly slower clock than it runs the SSE-300 with. Support
3
making the APB peripheral clock frequency board-specific. (For our
4
implementation only the UARTs actually take a clock.)
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-41-peter.maydell@linaro.org
11
---
12
hw/arm/mps2-tz.c | 6 +++++-
13
1 file changed, 5 insertions(+), 1 deletion(-)
14
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
18
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
20
MPS2TZFPGAType fpga_type;
21
uint32_t scc_id;
22
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
23
+ uint32_t apb_periph_frq; /* APB peripheral frequency in Hz */
24
uint32_t len_oscclk;
25
const uint32_t *oscclk;
26
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
28
29
object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
30
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
31
- qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
32
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->apb_periph_frq);
33
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
34
s = SYS_BUS_DEVICE(uart);
35
sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
36
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
37
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
38
mmc->scc_id = 0x41045050;
39
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
40
+ mmc->apb_periph_frq = mmc->sysclk_frq;
41
mmc->oscclk = an505_oscclk;
42
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
43
mmc->fpgaio_num_leds = 2;
44
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
45
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
46
mmc->scc_id = 0x41045210;
47
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
48
+ mmc->apb_periph_frq = mmc->sysclk_frq;
49
mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
50
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
51
mmc->fpgaio_num_leds = 2;
52
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
53
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
54
mmc->scc_id = 0x41045240;
55
mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
56
+ mmc->apb_periph_frq = mmc->sysclk_frq;
57
mmc->oscclk = an524_oscclk;
58
mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
59
mmc->fpgaio_num_leds = 10;
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
Deleted patch
1
The AN547 configures the SSE-300 with a different initsvtor0
2
setting from its default; make this a board-specific setting.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-42-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 5 +++++
11
1 file changed, 5 insertions(+)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
18
bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
19
int numirq; /* Number of external interrupts */
20
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
21
+ uint32_t init_svtor; /* init-svtor setting for SSE */
22
const RAMInfo *raminfo;
23
const char *armsse_type;
24
};
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
26
object_property_set_link(OBJECT(&mms->iotkit), "memory",
27
OBJECT(system_memory), &error_abort);
28
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
29
+ qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
30
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
31
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
32
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
33
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
34
mmc->fpgaio_has_dbgctrl = false;
35
mmc->numirq = 92;
36
mmc->uart_overflow_irq = 47;
37
+ mmc->init_svtor = 0x10000000;
38
mmc->raminfo = an505_raminfo;
39
mmc->armsse_type = TYPE_IOTKIT;
40
mps2tz_set_default_ram_info(mmc);
41
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
42
mmc->fpgaio_has_dbgctrl = false;
43
mmc->numirq = 92;
44
mmc->uart_overflow_irq = 47;
45
+ mmc->init_svtor = 0x10000000;
46
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
47
mmc->armsse_type = TYPE_SSE200;
48
mps2tz_set_default_ram_info(mmc);
49
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
50
mmc->fpgaio_has_dbgctrl = false;
51
mmc->numirq = 95;
52
mmc->uart_overflow_irq = 47;
53
+ mmc->init_svtor = 0x10000000;
54
mmc->raminfo = an524_raminfo;
55
mmc->armsse_type = TYPE_SSE200;
56
mps2tz_set_default_ram_info(mmc);
57
--
58
2.20.1
59
60
diff view generated by jsdifflib
Deleted patch
1
Add support for the mps3-an547 board; this is an SSE-300 based
2
FPGA image that runs on the MPS3.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-43-peter.maydell@linaro.org
8
---
9
hw/arm/mps2-tz.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++-
10
1 file changed, 144 insertions(+), 2 deletions(-)
11
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
15
+++ b/hw/arm/mps2-tz.c
16
@@ -XXX,XX +XXX,XX @@
17
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
18
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
19
* "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
20
+ * "mps2-an547" -- Single Cortex-M55 as documented in Application Note AN547
21
*
22
* Links to the TRM for the board itself and to the various Application
23
* Notes which document the FPGA images can be found here:
24
@@ -XXX,XX +XXX,XX @@
25
* https://developer.arm.com/documentation/dai0521/latest/
26
* Application Note AN524:
27
* https://developer.arm.com/documentation/dai0524/latest/
28
+ * Application Note AN547:
29
+ * https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/DAI0547B_SSE300_PLUS_U55_FPGA_for_mps3.pdf
30
*
31
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
32
* (ARM ECM0601256) for the details of some of the device layout:
33
@@ -XXX,XX +XXX,XX @@
34
* Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
35
* most of the device layout:
36
* https://developer.arm.com/documentation/101104/latest/
37
+ * and the AN547 uses the SSE-300, whose layout is in the SSE-300 TRM:
38
+ * https://developer.arm.com/documentation/101773/latest/
39
*/
40
41
#include "qemu/osdep.h"
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/qdev-clock.h"
44
#include "qom/object.h"
45
46
-#define MPS2TZ_NUMIRQ_MAX 95
47
-#define MPS2TZ_RAM_MAX 4
48
+#define MPS2TZ_NUMIRQ_MAX 96
49
+#define MPS2TZ_RAM_MAX 5
50
51
typedef enum MPS2TZFPGAType {
52
FPGA_AN505,
53
FPGA_AN521,
54
FPGA_AN524,
55
+ FPGA_AN547,
56
} MPS2TZFPGAType;
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
60
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
61
#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
62
#define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
63
+#define TYPE_MPS3TZ_AN547_MACHINE MACHINE_TYPE_NAME("mps3-an547")
64
65
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
66
67
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an524_raminfo[] = { {
68
},
69
};
70
71
+static const RAMInfo an547_raminfo[] = { {
72
+ .name = "itcm",
73
+ .base = 0x00000000,
74
+ .size = 512 * KiB,
75
+ .mpc = -1,
76
+ .mrindex = 0,
77
+ }, {
78
+ .name = "sram",
79
+ .base = 0x01000000,
80
+ .size = 2 * MiB,
81
+ .mpc = 0,
82
+ .mrindex = 1,
83
+ }, {
84
+ .name = "dtcm",
85
+ .base = 0x20000000,
86
+ .size = 4 * 128 * KiB,
87
+ .mpc = -1,
88
+ .mrindex = 2,
89
+ }, {
90
+ .name = "sram 2",
91
+ .base = 0x21000000,
92
+ .size = 4 * MiB,
93
+ .mpc = -1,
94
+ .mrindex = 3,
95
+ }, {
96
+ /* We don't model QSPI flash yet; for now expose it as simple ROM */
97
+ .name = "QSPI",
98
+ .base = 0x28000000,
99
+ .size = 8 * MiB,
100
+ .mpc = 1,
101
+ .mrindex = 4,
102
+ .flags = IS_ROM,
103
+ }, {
104
+ .name = "DDR",
105
+ .base = 0x60000000,
106
+ .size = MPS3_DDR_SIZE,
107
+ .mpc = 2,
108
+ .mrindex = -1,
109
+ }, {
110
+ .name = NULL,
111
+ },
112
+};
113
+
114
static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
115
{
116
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
117
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
118
},
119
};
120
121
+ const PPCInfo an547_ppcs[] = { {
122
+ .name = "apb_ppcexp0",
123
+ .ports = {
124
+ { "ssram-mpc", make_mpc, &mms->mpc[0], 0x57000000, 0x1000 },
125
+ { "qspi-mpc", make_mpc, &mms->mpc[1], 0x57001000, 0x1000 },
126
+ { "ddr-mpc", make_mpc, &mms->mpc[2], 0x57002000, 0x1000 },
127
+ },
128
+ }, {
129
+ .name = "apb_ppcexp1",
130
+ .ports = {
131
+ { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000 },
132
+ { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000 },
133
+ { "spi0", make_spi, &mms->spi[0], 0x49202000, 0x1000, { 53 } },
134
+ { "spi1", make_spi, &mms->spi[1], 0x49203000, 0x1000, { 54 } },
135
+ { "spi2", make_spi, &mms->spi[2], 0x49204000, 0x1000, { 55 } },
136
+ { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000 },
137
+ { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000 },
138
+ { /* port 7 reserved */ },
139
+ { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000 },
140
+ },
141
+ }, {
142
+ .name = "apb_ppcexp2",
143
+ .ports = {
144
+ { "scc", make_scc, &mms->scc, 0x49300000, 0x1000 },
145
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio, 0x49301000, 0x1000 },
146
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x49302000, 0x1000 },
147
+ { "uart0", make_uart, &mms->uart[0], 0x49303000, 0x1000, { 33, 34, 43 } },
148
+ { "uart1", make_uart, &mms->uart[1], 0x49304000, 0x1000, { 35, 36, 44 } },
149
+ { "uart2", make_uart, &mms->uart[2], 0x49305000, 0x1000, { 37, 38, 45 } },
150
+ { "uart3", make_uart, &mms->uart[3], 0x49306000, 0x1000, { 39, 40, 46 } },
151
+ { "uart4", make_uart, &mms->uart[4], 0x49307000, 0x1000, { 41, 42, 47 } },
152
+ { "uart5", make_uart, &mms->uart[5], 0x49308000, 0x1000, { 125, 126, 127 } },
153
+
154
+ { /* port 9 reserved */ },
155
+ { "clcd", make_unimp_dev, &mms->cldc, 0x4930a000, 0x1000 },
156
+ { "rtc", make_rtc, &mms->rtc, 0x4930b000, 0x1000 },
157
+ },
158
+ }, {
159
+ .name = "ahb_ppcexp0",
160
+ .ports = {
161
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
162
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
163
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
164
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
165
+ { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 49 } },
166
+ },
167
+ },
168
+ };
169
+
170
switch (mmc->fpga_type) {
171
case FPGA_AN505:
172
case FPGA_AN521:
173
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
174
ppcs = an524_ppcs;
175
num_ppcs = ARRAY_SIZE(an524_ppcs);
176
break;
177
+ case FPGA_AN547:
178
+ ppcs = an547_ppcs;
179
+ num_ppcs = ARRAY_SIZE(an547_ppcs);
180
+ break;
181
default:
182
g_assert_not_reached();
183
}
184
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
185
186
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
187
188
+ if (mmc->fpga_type == FPGA_AN547) {
189
+ create_unimplemented_device("U55 timing adapter 0", 0x48102000, 0x1000);
190
+ create_unimplemented_device("U55 timing adapter 1", 0x48103000, 0x1000);
191
+ }
192
+
193
create_non_mpc_ram(mms);
194
195
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
196
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
197
mps2tz_set_default_ram_info(mmc);
198
}
199
200
+static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
201
+{
202
+ MachineClass *mc = MACHINE_CLASS(oc);
203
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
204
+
205
+ mc->desc = "ARM MPS3 with AN547 FPGA image for Cortex-M55";
206
+ mc->default_cpus = 1;
207
+ mc->min_cpus = mc->default_cpus;
208
+ mc->max_cpus = mc->default_cpus;
209
+ mmc->fpga_type = FPGA_AN547;
210
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m55");
211
+ mmc->scc_id = 0x41055470;
212
+ mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
213
+ mmc->apb_periph_frq = 25 * 1000 * 1000; /* 25MHz */
214
+ mmc->oscclk = an524_oscclk; /* same as AN524 */
215
+ mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
216
+ mmc->fpgaio_num_leds = 10;
217
+ mmc->fpgaio_has_switches = true;
218
+ mmc->fpgaio_has_dbgctrl = true;
219
+ mmc->numirq = 96;
220
+ mmc->uart_overflow_irq = 48;
221
+ mmc->init_svtor = 0x00000000;
222
+ mmc->raminfo = an547_raminfo;
223
+ mmc->armsse_type = TYPE_SSE300;
224
+ mps2tz_set_default_ram_info(mmc);
225
+}
226
+
227
static const TypeInfo mps2tz_info = {
228
.name = TYPE_MPS2TZ_MACHINE,
229
.parent = TYPE_MACHINE,
230
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps3tz_an524_info = {
231
.class_init = mps3tz_an524_class_init,
232
};
233
234
+static const TypeInfo mps3tz_an547_info = {
235
+ .name = TYPE_MPS3TZ_AN547_MACHINE,
236
+ .parent = TYPE_MPS2TZ_MACHINE,
237
+ .class_init = mps3tz_an547_class_init,
238
+};
239
+
240
static void mps2tz_machine_init(void)
241
{
242
type_register_static(&mps2tz_info);
243
type_register_static(&mps2tz_an505_info);
244
type_register_static(&mps2tz_an521_info);
245
type_register_static(&mps3tz_an524_info);
246
+ type_register_static(&mps3tz_an547_info);
247
}
248
249
type_init(mps2tz_machine_init);
250
--
251
2.20.1
252
253
diff view generated by jsdifflib
Deleted patch
1
Add brief documentation of the new mps3-an547 board.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210219144617.4782-44-peter.maydell@linaro.org
7
---
8
docs/system/arm/mps2.rst | 6 ++++--
9
1 file changed, 4 insertions(+), 2 deletions(-)
10
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
12
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/system/arm/mps2.rst
14
+++ b/docs/system/arm/mps2.rst
15
@@ -XXX,XX +XXX,XX @@
16
-Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
17
-=========================================================================================================================================
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an547``)
19
+=========================================================================================================================================================
20
21
These board models all use Arm M-profile CPUs.
22
23
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
24
Dual Cortex-M33 as documented in Arm Application Note AN521
25
``mps3-an524``
26
Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
27
+``mps3-an547``
28
+ Cortex-M55 on an MPS3, as documented in Arm Application Note AN547
29
30
Differences between QEMU and real hardware:
31
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
Add a simple qtest to exercise the new system counter device in the
2
SSE-300.
3
1
4
We'll add tests of the system timer device here too, so this includes
5
scaffolding (register definitions, etc) for those.
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210219144617.4782-45-peter.maydell@linaro.org
11
---
12
tests/qtest/sse-timer-test.c | 117 +++++++++++++++++++++++++++++++++++
13
MAINTAINERS | 1 +
14
tests/qtest/meson.build | 1 +
15
3 files changed, 119 insertions(+)
16
create mode 100644 tests/qtest/sse-timer-test.c
17
18
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qtest/sse-timer-test.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QTest testcase for the SSE timer device
26
+ *
27
+ * Copyright (c) 2021 Linaro Limited
28
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
30
+ * under the terms of the GNU General Public License as published by the
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
39
+
40
+#include "qemu/osdep.h"
41
+#include "libqtest-single.h"
42
+
43
+/*
44
+ * SSE-123/SSE-300 timer in the mps3-an547 board, where it is driven
45
+ * at 32MHz, so 31.25ns per tick.
46
+ */
47
+#define TIMER_BASE 0x48000000
48
+
49
+/* PERIPHNSPPC0 register in the SSE-300 Secure Access Configuration block */
50
+#define PERIPHNSPPC0 (0x50080000 + 0x70)
51
+
52
+/* Base of the System Counter control frame */
53
+#define COUNTER_BASE 0x58100000
54
+
55
+/* SSE counter register offsets in the control frame */
56
+#define CNTCR 0
57
+#define CNTSR 0x4
58
+#define CNTCV_LO 0x8
59
+#define CNTCV_HI 0xc
60
+#define CNTSCR 0x10
61
+
62
+/* SSE timer register offsets */
63
+#define CNTPCT_LO 0
64
+#define CNTPCT_HI 4
65
+#define CNTFRQ 0x10
66
+#define CNTP_CVAL_LO 0x20
67
+#define CNTP_CVAL_HI 0x24
68
+#define CNTP_TVAL 0x28
69
+#define CNTP_CTL 0x2c
70
+#define CNTP_AIVAL_LO 0x40
71
+#define CNTP_AIVAL_HI 0x44
72
+#define CNTP_AIVAL_RELOAD 0x48
73
+#define CNTP_AIVAL_CTL 0x4c
74
+
75
+/* 4 ticks in nanoseconds (so we can work in integers) */
76
+#define FOUR_TICKS 125
77
+
78
+static void clock_step_ticks(uint64_t ticks)
79
+{
80
+ /*
81
+ * Advance the qtest clock by however many nanoseconds we
82
+ * need to move the timer forward the specified number of ticks.
83
+ * ticks must be a multiple of 4, so we get a whole number of ns.
84
+ */
85
+ assert(!(ticks & 3));
86
+ clock_step(FOUR_TICKS * (ticks >> 2));
87
+}
88
+
89
+static void reset_counter_and_timer(void)
90
+{
91
+ /*
92
+ * Reset the system counter and the timer between tests. This
93
+ * isn't a full reset, but it's sufficient for what the tests check.
94
+ */
95
+ writel(COUNTER_BASE + CNTCR, 0);
96
+ writel(TIMER_BASE + CNTP_CTL, 0);
97
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 0);
98
+ writel(COUNTER_BASE + CNTCV_LO, 0);
99
+ writel(COUNTER_BASE + CNTCV_HI, 0);
100
+}
101
+
102
+static void test_counter(void)
103
+{
104
+ /* Basic counter functionality test */
105
+
106
+ reset_counter_and_timer();
107
+ /* The counter should start disabled: check that it doesn't move */
108
+ clock_step_ticks(100);
109
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 0);
110
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
111
+ /* Now enable it and check that it does count */
112
+ writel(COUNTER_BASE + CNTCR, 1);
113
+ clock_step_ticks(100);
114
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 100);
115
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
116
+ /* Check the counter scaling functionality */
117
+ writel(COUNTER_BASE + CNTCR, 0);
118
+ writel(COUNTER_BASE + CNTSCR, 0x00100000); /* 1/16th normal speed */
119
+ writel(COUNTER_BASE + CNTCR, 5); /* EN, SCEN */
120
+ clock_step_ticks(160);
121
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 110);
122
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
123
+}
124
+
125
+int main(int argc, char **argv)
126
+{
127
+ int r;
128
+
129
+ g_test_init(&argc, &argv, NULL);
130
+
131
+ qtest_start("-machine mps3-an547");
132
+
133
+ qtest_add_func("/sse-timer/counter", test_counter);
134
+
135
+ r = g_test_run();
136
+
137
+ qtest_end();
138
+
139
+ return r;
140
+}
141
diff --git a/MAINTAINERS b/MAINTAINERS
142
index XXXXXXX..XXXXXXX 100644
143
--- a/MAINTAINERS
144
+++ b/MAINTAINERS
145
@@ -XXX,XX +XXX,XX @@ F: hw/timer/sse-counter.c
146
F: include/hw/timer/sse-counter.h
147
F: hw/timer/sse-timer.c
148
F: include/hw/timer/sse-timer.h
149
+F: tests/qtest/sse-timer-test.c
150
F: docs/system/arm/mps2.rst
151
152
Musca
153
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
154
index XXXXXXX..XXXXXXX 100644
155
--- a/tests/qtest/meson.build
156
+++ b/tests/qtest/meson.build
157
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
158
'npcm7xx_watchdog_timer-test'] + \
159
(slirp.found() ? ['npcm7xx_emc-test'] : [])
160
qtests_arm = \
161
+ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
162
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
163
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
164
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
165
--
166
2.20.1
167
168
diff view generated by jsdifflib
Deleted patch
1
Add a test which tests various parts of the functionality of the
2
SSE system timer.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
---
8
tests/qtest/sse-timer-test.c | 91 ++++++++++++++++++++++++++++++++++++
9
1 file changed, 91 insertions(+)
10
11
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qtest/sse-timer-test.c
14
+++ b/tests/qtest/sse-timer-test.c
15
@@ -XXX,XX +XXX,XX @@ static void test_counter(void)
16
g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
17
}
18
19
+static void test_timer(void)
20
+{
21
+ /* Basic timer functionality test */
22
+
23
+ reset_counter_and_timer();
24
+ /*
25
+ * The timer is behind a Peripheral Protection Controller, and
26
+ * qtest accesses are always non-secure (no memory attributes),
27
+ * so we must program the PPC to accept NS transactions. TIMER0
28
+ * is on port 0 of PPC0, controlled by bit 0 of this register.
29
+ */
30
+ writel(PERIPHNSPPC0, 1);
31
+ /* We must enable the System Counter or the timer won't run. */
32
+ writel(COUNTER_BASE + CNTCR, 1);
33
+
34
+ /* Timer starts disabled and with a counter of 0 */
35
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 0);
36
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 0);
37
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
38
+
39
+ /* Turn it on */
40
+ writel(TIMER_BASE + CNTP_CTL, 1);
41
+
42
+ /* Is the timer ticking? */
43
+ clock_step_ticks(100);
44
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 100);
45
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
46
+
47
+ /* Set the CompareValue to 4000 ticks */
48
+ writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
49
+ writel(TIMER_BASE + CNTP_CVAL_HI, 0);
50
+
51
+ /* Check TVAL view of the counter */
52
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 3900);
53
+
54
+ /* Advance to the CompareValue mark and check ISTATUS is set */
55
+ clock_step_ticks(3900);
56
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 0);
57
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
58
+
59
+ /* Now exercise the auto-reload part of the timer */
60
+ writel(TIMER_BASE + CNTP_AIVAL_RELOAD, 200);
61
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
62
+
63
+ /* Check AIVAL was reloaded and that ISTATUS is now clear */
64
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4200);
65
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
66
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
67
+
68
+ /*
69
+ * Check that when we advance forward to the reload time the interrupt
70
+ * fires and the value reloads
71
+ */
72
+ clock_step_ticks(100);
73
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
74
+ clock_step_ticks(100);
75
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
76
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4400);
77
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
78
+
79
+ clock_step_ticks(100);
80
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
81
+ /* Check that writing 0 to CLR clears the interrupt */
82
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
83
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
84
+ /* Check that when we move forward to the reload time it fires again */
85
+ clock_step_ticks(100);
86
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
87
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4600);
88
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
89
+
90
+ /*
91
+ * Step the clock far enough that we overflow the low half of the
92
+ * CNTPCT and AIVAL registers, and check that their high halves
93
+ * give the right values. We do the forward movement in
94
+ * non-autoinc mode because otherwise it takes forever as the
95
+ * timer has to emulate all the 'reload at t + N, t + 2N, etc'
96
+ * steps.
97
+ */
98
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 0);
99
+ clock_step_ticks(0x42ULL << 32);
100
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 4400);
101
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0x42);
102
+
103
+ /* Turn on the autoinc again to check AIVAL_HI */
104
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
105
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4600);
106
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
107
+}
108
+
109
int main(int argc, char **argv)
110
{
111
int r;
112
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
113
qtest_start("-machine mps3-an547");
114
115
qtest_add_func("/sse-timer/counter", test_counter);
116
+ qtest_add_func("/sse-timer/timer", test_timer);
117
118
r = g_test_run();
119
120
--
121
2.20.1
122
123
diff view generated by jsdifflib
Deleted patch
1
Test that when we change the scaling of the system counter that the
2
system timer responds appropriately.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
---
8
tests/qtest/sse-timer-test.c | 32 ++++++++++++++++++++++++++++++++
9
1 file changed, 32 insertions(+)
10
11
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qtest/sse-timer-test.c
14
+++ b/tests/qtest/sse-timer-test.c
15
@@ -XXX,XX +XXX,XX @@ static void test_timer(void)
16
g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
17
}
18
19
+static void test_timer_scale_change(void)
20
+{
21
+ /*
22
+ * Test that the timer responds correctly to counter
23
+ * scaling changes while it has an active timer.
24
+ */
25
+ reset_counter_and_timer();
26
+ /* Give ourselves access to the timer, and enable the counter and timer */
27
+ writel(PERIPHNSPPC0, 1);
28
+ writel(COUNTER_BASE + CNTCR, 1);
29
+ writel(TIMER_BASE + CNTP_CTL, 1);
30
+ /* Set the CompareValue to 4000 ticks */
31
+ writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
32
+ writel(TIMER_BASE + CNTP_CVAL_HI, 0);
33
+ /* Advance halfway and check ISTATUS is not set */
34
+ clock_step_ticks(2000);
35
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
36
+ /* Reprogram the counter to run at 1/16th speed */
37
+ writel(COUNTER_BASE + CNTCR, 0);
38
+ writel(COUNTER_BASE + CNTSCR, 0x00100000); /* 1/16th normal speed */
39
+ writel(COUNTER_BASE + CNTCR, 5); /* EN, SCEN */
40
+ /* Advance to where the timer would have fired and check it has not */
41
+ clock_step_ticks(2000);
42
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
43
+ /* Advance to where the timer must fire at the new clock rate */
44
+ clock_step_ticks(29996);
45
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
46
+ clock_step_ticks(4);
47
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
48
+}
49
+
50
int main(int argc, char **argv)
51
{
52
int r;
53
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
54
55
qtest_add_func("/sse-timer/counter", test_counter);
56
qtest_add_func("/sse-timer/timer", test_timer);
57
+ qtest_add_func("/sse-timer/timer-scale-change", test_timer_scale_change);
58
59
r = g_test_run();
60
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
KVM requires the target cpu to be at least ARMv8 architecture
4
(support on ARMv7 has been dropped in commit 82bf7ae84ce:
5
"target/arm: Remove KVM support for 32-bit Arm hosts").
6
7
A KVM-only build won't be able to run TCG cpus, move the
8
v7A CPU definitions to cpu_tcg.c.
9
10
Reported-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20210306151801.2388182-1-f4bug@amsat.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/cpu.c | 335 -------------------------------------------
17
target/arm/cpu_tcg.c | 318 ++++++++++++++++++++++++++++++++++++++++
18
2 files changed, 318 insertions(+), 335 deletions(-)
19
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
25
return oc;
26
}
27
28
-/* CPU models. These are not needed for the AArch64 linux-user build. */
29
-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
30
-
31
-static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
32
- { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
33
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
34
- { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
35
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
36
- REGINFO_SENTINEL
37
-};
38
-
39
-static void cortex_a8_initfn(Object *obj)
40
-{
41
- ARMCPU *cpu = ARM_CPU(obj);
42
-
43
- cpu->dtb_compatible = "arm,cortex-a8";
44
- set_feature(&cpu->env, ARM_FEATURE_V7);
45
- set_feature(&cpu->env, ARM_FEATURE_NEON);
46
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
47
- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
48
- set_feature(&cpu->env, ARM_FEATURE_EL3);
49
- cpu->midr = 0x410fc080;
50
- cpu->reset_fpsid = 0x410330c0;
51
- cpu->isar.mvfr0 = 0x11110222;
52
- cpu->isar.mvfr1 = 0x00011111;
53
- cpu->ctr = 0x82048004;
54
- cpu->reset_sctlr = 0x00c50078;
55
- cpu->isar.id_pfr0 = 0x1031;
56
- cpu->isar.id_pfr1 = 0x11;
57
- cpu->isar.id_dfr0 = 0x400;
58
- cpu->id_afr0 = 0;
59
- cpu->isar.id_mmfr0 = 0x31100003;
60
- cpu->isar.id_mmfr1 = 0x20000000;
61
- cpu->isar.id_mmfr2 = 0x01202000;
62
- cpu->isar.id_mmfr3 = 0x11;
63
- cpu->isar.id_isar0 = 0x00101111;
64
- cpu->isar.id_isar1 = 0x12112111;
65
- cpu->isar.id_isar2 = 0x21232031;
66
- cpu->isar.id_isar3 = 0x11112131;
67
- cpu->isar.id_isar4 = 0x00111142;
68
- cpu->isar.dbgdidr = 0x15141000;
69
- cpu->clidr = (1 << 27) | (2 << 24) | 3;
70
- cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
71
- cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
72
- cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
73
- cpu->reset_auxcr = 2;
74
- define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
75
-}
76
-
77
-static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
78
- /*
79
- * power_control should be set to maximum latency. Again,
80
- * default to 0 and set by private hook
81
- */
82
- { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
83
- .access = PL1_RW, .resetvalue = 0,
84
- .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
85
- { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
86
- .access = PL1_RW, .resetvalue = 0,
87
- .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
88
- { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
89
- .access = PL1_RW, .resetvalue = 0,
90
- .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
91
- { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
92
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
93
- /* TLB lockdown control */
94
- { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
95
- .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
96
- { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
97
- .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
98
- { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
99
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
100
- { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
101
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
102
- { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
103
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
104
- REGINFO_SENTINEL
105
-};
106
-
107
-static void cortex_a9_initfn(Object *obj)
108
-{
109
- ARMCPU *cpu = ARM_CPU(obj);
110
-
111
- cpu->dtb_compatible = "arm,cortex-a9";
112
- set_feature(&cpu->env, ARM_FEATURE_V7);
113
- set_feature(&cpu->env, ARM_FEATURE_NEON);
114
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
115
- set_feature(&cpu->env, ARM_FEATURE_EL3);
116
- /*
117
- * Note that A9 supports the MP extensions even for
118
- * A9UP and single-core A9MP (which are both different
119
- * and valid configurations; we don't model A9UP).
120
- */
121
- set_feature(&cpu->env, ARM_FEATURE_V7MP);
122
- set_feature(&cpu->env, ARM_FEATURE_CBAR);
123
- cpu->midr = 0x410fc090;
124
- cpu->reset_fpsid = 0x41033090;
125
- cpu->isar.mvfr0 = 0x11110222;
126
- cpu->isar.mvfr1 = 0x01111111;
127
- cpu->ctr = 0x80038003;
128
- cpu->reset_sctlr = 0x00c50078;
129
- cpu->isar.id_pfr0 = 0x1031;
130
- cpu->isar.id_pfr1 = 0x11;
131
- cpu->isar.id_dfr0 = 0x000;
132
- cpu->id_afr0 = 0;
133
- cpu->isar.id_mmfr0 = 0x00100103;
134
- cpu->isar.id_mmfr1 = 0x20000000;
135
- cpu->isar.id_mmfr2 = 0x01230000;
136
- cpu->isar.id_mmfr3 = 0x00002111;
137
- cpu->isar.id_isar0 = 0x00101111;
138
- cpu->isar.id_isar1 = 0x13112111;
139
- cpu->isar.id_isar2 = 0x21232041;
140
- cpu->isar.id_isar3 = 0x11112131;
141
- cpu->isar.id_isar4 = 0x00111142;
142
- cpu->isar.dbgdidr = 0x35141000;
143
- cpu->clidr = (1 << 27) | (1 << 24) | 3;
144
- cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
145
- cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
146
- define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
147
-}
148
-
149
-#ifndef CONFIG_USER_ONLY
150
-static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
151
-{
152
- MachineState *ms = MACHINE(qdev_get_machine());
153
-
154
- /*
155
- * Linux wants the number of processors from here.
156
- * Might as well set the interrupt-controller bit too.
157
- */
158
- return ((ms->smp.cpus - 1) << 24) | (1 << 23);
159
-}
160
-#endif
161
-
162
-static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
163
-#ifndef CONFIG_USER_ONLY
164
- { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
165
- .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
166
- .writefn = arm_cp_write_ignore, },
167
-#endif
168
- { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
169
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
170
- REGINFO_SENTINEL
171
-};
172
-
173
-static void cortex_a7_initfn(Object *obj)
174
-{
175
- ARMCPU *cpu = ARM_CPU(obj);
176
-
177
- cpu->dtb_compatible = "arm,cortex-a7";
178
- set_feature(&cpu->env, ARM_FEATURE_V7VE);
179
- set_feature(&cpu->env, ARM_FEATURE_NEON);
180
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
181
- set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
182
- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
183
- set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
184
- set_feature(&cpu->env, ARM_FEATURE_EL2);
185
- set_feature(&cpu->env, ARM_FEATURE_EL3);
186
- set_feature(&cpu->env, ARM_FEATURE_PMU);
187
- cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
188
- cpu->midr = 0x410fc075;
189
- cpu->reset_fpsid = 0x41023075;
190
- cpu->isar.mvfr0 = 0x10110222;
191
- cpu->isar.mvfr1 = 0x11111111;
192
- cpu->ctr = 0x84448003;
193
- cpu->reset_sctlr = 0x00c50078;
194
- cpu->isar.id_pfr0 = 0x00001131;
195
- cpu->isar.id_pfr1 = 0x00011011;
196
- cpu->isar.id_dfr0 = 0x02010555;
197
- cpu->id_afr0 = 0x00000000;
198
- cpu->isar.id_mmfr0 = 0x10101105;
199
- cpu->isar.id_mmfr1 = 0x40000000;
200
- cpu->isar.id_mmfr2 = 0x01240000;
201
- cpu->isar.id_mmfr3 = 0x02102211;
202
- /*
203
- * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
204
- * table 4-41 gives 0x02101110, which includes the arm div insns.
205
- */
206
- cpu->isar.id_isar0 = 0x02101110;
207
- cpu->isar.id_isar1 = 0x13112111;
208
- cpu->isar.id_isar2 = 0x21232041;
209
- cpu->isar.id_isar3 = 0x11112131;
210
- cpu->isar.id_isar4 = 0x10011142;
211
- cpu->isar.dbgdidr = 0x3515f005;
212
- cpu->clidr = 0x0a200023;
213
- cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
214
- cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
215
- cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
216
- define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
217
-}
218
-
219
-static void cortex_a15_initfn(Object *obj)
220
-{
221
- ARMCPU *cpu = ARM_CPU(obj);
222
-
223
- cpu->dtb_compatible = "arm,cortex-a15";
224
- set_feature(&cpu->env, ARM_FEATURE_V7VE);
225
- set_feature(&cpu->env, ARM_FEATURE_NEON);
226
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
227
- set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
228
- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
229
- set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
230
- set_feature(&cpu->env, ARM_FEATURE_EL2);
231
- set_feature(&cpu->env, ARM_FEATURE_EL3);
232
- set_feature(&cpu->env, ARM_FEATURE_PMU);
233
- cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
234
- cpu->midr = 0x412fc0f1;
235
- cpu->reset_fpsid = 0x410430f0;
236
- cpu->isar.mvfr0 = 0x10110222;
237
- cpu->isar.mvfr1 = 0x11111111;
238
- cpu->ctr = 0x8444c004;
239
- cpu->reset_sctlr = 0x00c50078;
240
- cpu->isar.id_pfr0 = 0x00001131;
241
- cpu->isar.id_pfr1 = 0x00011011;
242
- cpu->isar.id_dfr0 = 0x02010555;
243
- cpu->id_afr0 = 0x00000000;
244
- cpu->isar.id_mmfr0 = 0x10201105;
245
- cpu->isar.id_mmfr1 = 0x20000000;
246
- cpu->isar.id_mmfr2 = 0x01240000;
247
- cpu->isar.id_mmfr3 = 0x02102211;
248
- cpu->isar.id_isar0 = 0x02101110;
249
- cpu->isar.id_isar1 = 0x13112111;
250
- cpu->isar.id_isar2 = 0x21232041;
251
- cpu->isar.id_isar3 = 0x11112131;
252
- cpu->isar.id_isar4 = 0x10011142;
253
- cpu->isar.dbgdidr = 0x3515f021;
254
- cpu->clidr = 0x0a200023;
255
- cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
256
- cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
257
- cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
258
- define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
259
-}
260
-
261
-#ifndef TARGET_AARCH64
262
-/*
263
- * -cpu max: a CPU with as many features enabled as our emulation supports.
264
- * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
265
- * this only needs to handle 32 bits, and need not care about KVM.
266
- */
267
-static void arm_max_initfn(Object *obj)
268
-{
269
- ARMCPU *cpu = ARM_CPU(obj);
270
-
271
- cortex_a15_initfn(obj);
272
-
273
- /* old-style VFP short-vector support */
274
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
275
-
276
-#ifdef CONFIG_USER_ONLY
277
- /*
278
- * We don't set these in system emulation mode for the moment,
279
- * since we don't correctly set (all of) the ID registers to
280
- * advertise them.
281
- */
282
- set_feature(&cpu->env, ARM_FEATURE_V8);
283
- {
284
- uint32_t t;
285
-
286
- t = cpu->isar.id_isar5;
287
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
288
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
289
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
290
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
291
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
292
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
293
- cpu->isar.id_isar5 = t;
294
-
295
- t = cpu->isar.id_isar6;
296
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
297
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
298
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
299
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
300
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
301
- cpu->isar.id_isar6 = t;
302
-
303
- t = cpu->isar.mvfr1;
304
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
305
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
306
- cpu->isar.mvfr1 = t;
307
-
308
- t = cpu->isar.mvfr2;
309
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
310
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
311
- cpu->isar.mvfr2 = t;
312
-
313
- t = cpu->isar.id_mmfr3;
314
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
315
- cpu->isar.id_mmfr3 = t;
316
-
317
- t = cpu->isar.id_mmfr4;
318
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
319
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
320
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
321
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
322
- cpu->isar.id_mmfr4 = t;
323
-
324
- t = cpu->isar.id_pfr0;
325
- t = FIELD_DP32(t, ID_PFR0, DIT, 1);
326
- cpu->isar.id_pfr0 = t;
327
-
328
- t = cpu->isar.id_pfr2;
329
- t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
330
- cpu->isar.id_pfr2 = t;
331
- }
332
-#endif
333
-}
334
-#endif
335
-
336
-#endif /* !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) */
337
-
338
-static const ARMCPUInfo arm_cpus[] = {
339
-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
340
- { .name = "cortex-a7", .initfn = cortex_a7_initfn },
341
- { .name = "cortex-a8", .initfn = cortex_a8_initfn },
342
- { .name = "cortex-a9", .initfn = cortex_a9_initfn },
343
- { .name = "cortex-a15", .initfn = cortex_a15_initfn },
344
-#ifndef TARGET_AARCH64
345
- { .name = "max", .initfn = arm_max_initfn },
346
-#endif
347
-#ifdef CONFIG_USER_ONLY
348
- { .name = "any", .initfn = arm_max_initfn },
349
-#endif
350
-#endif
351
-};
352
-
353
static Property arm_cpu_properties[] = {
354
DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
355
DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
356
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
357
358
static void arm_cpu_register_types(void)
359
{
360
- const size_t cpu_count = ARRAY_SIZE(arm_cpus);
361
-
362
type_register_static(&arm_cpu_type_info);
363
364
#ifdef CONFIG_KVM
365
type_register_static(&host_arm_cpu_type_info);
366
#endif
367
-
368
- if (cpu_count) {
369
- size_t i;
370
-
371
- for (i = 0; i < cpu_count; ++i) {
372
- arm_cpu_register(&arm_cpus[i]);
373
- }
374
- }
375
}
376
377
type_init(arm_cpu_register_types)
378
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
379
index XXXXXXX..XXXXXXX 100644
380
--- a/target/arm/cpu_tcg.c
381
+++ b/target/arm/cpu_tcg.c
382
@@ -XXX,XX +XXX,XX @@
383
#endif /* CONFIG_TCG */
384
#include "internals.h"
385
#include "target/arm/idau.h"
386
+#if !defined(CONFIG_USER_ONLY)
387
+#include "hw/boards.h"
388
+#endif
389
390
/* CPU models. These are not needed for the AArch64 linux-user build. */
391
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
392
@@ -XXX,XX +XXX,XX @@ static void arm11mpcore_initfn(Object *obj)
393
cpu->reset_auxcr = 1;
394
}
395
396
+static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
397
+ { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
398
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
399
+ { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
400
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
401
+ REGINFO_SENTINEL
402
+};
403
+
404
+static void cortex_a8_initfn(Object *obj)
405
+{
406
+ ARMCPU *cpu = ARM_CPU(obj);
407
+
408
+ cpu->dtb_compatible = "arm,cortex-a8";
409
+ set_feature(&cpu->env, ARM_FEATURE_V7);
410
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
411
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
412
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
413
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
414
+ cpu->midr = 0x410fc080;
415
+ cpu->reset_fpsid = 0x410330c0;
416
+ cpu->isar.mvfr0 = 0x11110222;
417
+ cpu->isar.mvfr1 = 0x00011111;
418
+ cpu->ctr = 0x82048004;
419
+ cpu->reset_sctlr = 0x00c50078;
420
+ cpu->isar.id_pfr0 = 0x1031;
421
+ cpu->isar.id_pfr1 = 0x11;
422
+ cpu->isar.id_dfr0 = 0x400;
423
+ cpu->id_afr0 = 0;
424
+ cpu->isar.id_mmfr0 = 0x31100003;
425
+ cpu->isar.id_mmfr1 = 0x20000000;
426
+ cpu->isar.id_mmfr2 = 0x01202000;
427
+ cpu->isar.id_mmfr3 = 0x11;
428
+ cpu->isar.id_isar0 = 0x00101111;
429
+ cpu->isar.id_isar1 = 0x12112111;
430
+ cpu->isar.id_isar2 = 0x21232031;
431
+ cpu->isar.id_isar3 = 0x11112131;
432
+ cpu->isar.id_isar4 = 0x00111142;
433
+ cpu->isar.dbgdidr = 0x15141000;
434
+ cpu->clidr = (1 << 27) | (2 << 24) | 3;
435
+ cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
436
+ cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
437
+ cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
438
+ cpu->reset_auxcr = 2;
439
+ define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
440
+}
441
+
442
+static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
443
+ /*
444
+ * power_control should be set to maximum latency. Again,
445
+ * default to 0 and set by private hook
446
+ */
447
+ { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
448
+ .access = PL1_RW, .resetvalue = 0,
449
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
450
+ { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
451
+ .access = PL1_RW, .resetvalue = 0,
452
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
453
+ { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
454
+ .access = PL1_RW, .resetvalue = 0,
455
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
456
+ { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
457
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
458
+ /* TLB lockdown control */
459
+ { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
460
+ .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
461
+ { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
462
+ .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
463
+ { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
464
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
465
+ { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
466
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
467
+ { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
468
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
469
+ REGINFO_SENTINEL
470
+};
471
+
472
+static void cortex_a9_initfn(Object *obj)
473
+{
474
+ ARMCPU *cpu = ARM_CPU(obj);
475
+
476
+ cpu->dtb_compatible = "arm,cortex-a9";
477
+ set_feature(&cpu->env, ARM_FEATURE_V7);
478
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
479
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
480
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
481
+ /*
482
+ * Note that A9 supports the MP extensions even for
483
+ * A9UP and single-core A9MP (which are both different
484
+ * and valid configurations; we don't model A9UP).
485
+ */
486
+ set_feature(&cpu->env, ARM_FEATURE_V7MP);
487
+ set_feature(&cpu->env, ARM_FEATURE_CBAR);
488
+ cpu->midr = 0x410fc090;
489
+ cpu->reset_fpsid = 0x41033090;
490
+ cpu->isar.mvfr0 = 0x11110222;
491
+ cpu->isar.mvfr1 = 0x01111111;
492
+ cpu->ctr = 0x80038003;
493
+ cpu->reset_sctlr = 0x00c50078;
494
+ cpu->isar.id_pfr0 = 0x1031;
495
+ cpu->isar.id_pfr1 = 0x11;
496
+ cpu->isar.id_dfr0 = 0x000;
497
+ cpu->id_afr0 = 0;
498
+ cpu->isar.id_mmfr0 = 0x00100103;
499
+ cpu->isar.id_mmfr1 = 0x20000000;
500
+ cpu->isar.id_mmfr2 = 0x01230000;
501
+ cpu->isar.id_mmfr3 = 0x00002111;
502
+ cpu->isar.id_isar0 = 0x00101111;
503
+ cpu->isar.id_isar1 = 0x13112111;
504
+ cpu->isar.id_isar2 = 0x21232041;
505
+ cpu->isar.id_isar3 = 0x11112131;
506
+ cpu->isar.id_isar4 = 0x00111142;
507
+ cpu->isar.dbgdidr = 0x35141000;
508
+ cpu->clidr = (1 << 27) | (1 << 24) | 3;
509
+ cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
510
+ cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
511
+ define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
512
+}
513
+
514
+#ifndef CONFIG_USER_ONLY
515
+static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
516
+{
517
+ MachineState *ms = MACHINE(qdev_get_machine());
518
+
519
+ /*
520
+ * Linux wants the number of processors from here.
521
+ * Might as well set the interrupt-controller bit too.
522
+ */
523
+ return ((ms->smp.cpus - 1) << 24) | (1 << 23);
524
+}
525
+#endif
526
+
527
+static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
528
+#ifndef CONFIG_USER_ONLY
529
+ { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
530
+ .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
531
+ .writefn = arm_cp_write_ignore, },
532
+#endif
533
+ { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
534
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
535
+ REGINFO_SENTINEL
536
+};
537
+
538
+static void cortex_a7_initfn(Object *obj)
539
+{
540
+ ARMCPU *cpu = ARM_CPU(obj);
541
+
542
+ cpu->dtb_compatible = "arm,cortex-a7";
543
+ set_feature(&cpu->env, ARM_FEATURE_V7VE);
544
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
545
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
546
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
547
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
548
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
549
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
550
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
551
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
552
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
553
+ cpu->midr = 0x410fc075;
554
+ cpu->reset_fpsid = 0x41023075;
555
+ cpu->isar.mvfr0 = 0x10110222;
556
+ cpu->isar.mvfr1 = 0x11111111;
557
+ cpu->ctr = 0x84448003;
558
+ cpu->reset_sctlr = 0x00c50078;
559
+ cpu->isar.id_pfr0 = 0x00001131;
560
+ cpu->isar.id_pfr1 = 0x00011011;
561
+ cpu->isar.id_dfr0 = 0x02010555;
562
+ cpu->id_afr0 = 0x00000000;
563
+ cpu->isar.id_mmfr0 = 0x10101105;
564
+ cpu->isar.id_mmfr1 = 0x40000000;
565
+ cpu->isar.id_mmfr2 = 0x01240000;
566
+ cpu->isar.id_mmfr3 = 0x02102211;
567
+ /*
568
+ * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
569
+ * table 4-41 gives 0x02101110, which includes the arm div insns.
570
+ */
571
+ cpu->isar.id_isar0 = 0x02101110;
572
+ cpu->isar.id_isar1 = 0x13112111;
573
+ cpu->isar.id_isar2 = 0x21232041;
574
+ cpu->isar.id_isar3 = 0x11112131;
575
+ cpu->isar.id_isar4 = 0x10011142;
576
+ cpu->isar.dbgdidr = 0x3515f005;
577
+ cpu->clidr = 0x0a200023;
578
+ cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
579
+ cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
580
+ cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
581
+ define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
582
+}
583
+
584
+static void cortex_a15_initfn(Object *obj)
585
+{
586
+ ARMCPU *cpu = ARM_CPU(obj);
587
+
588
+ cpu->dtb_compatible = "arm,cortex-a15";
589
+ set_feature(&cpu->env, ARM_FEATURE_V7VE);
590
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
591
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
592
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
593
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
594
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
595
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
596
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
597
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
598
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
599
+ cpu->midr = 0x412fc0f1;
600
+ cpu->reset_fpsid = 0x410430f0;
601
+ cpu->isar.mvfr0 = 0x10110222;
602
+ cpu->isar.mvfr1 = 0x11111111;
603
+ cpu->ctr = 0x8444c004;
604
+ cpu->reset_sctlr = 0x00c50078;
605
+ cpu->isar.id_pfr0 = 0x00001131;
606
+ cpu->isar.id_pfr1 = 0x00011011;
607
+ cpu->isar.id_dfr0 = 0x02010555;
608
+ cpu->id_afr0 = 0x00000000;
609
+ cpu->isar.id_mmfr0 = 0x10201105;
610
+ cpu->isar.id_mmfr1 = 0x20000000;
611
+ cpu->isar.id_mmfr2 = 0x01240000;
612
+ cpu->isar.id_mmfr3 = 0x02102211;
613
+ cpu->isar.id_isar0 = 0x02101110;
614
+ cpu->isar.id_isar1 = 0x13112111;
615
+ cpu->isar.id_isar2 = 0x21232041;
616
+ cpu->isar.id_isar3 = 0x11112131;
617
+ cpu->isar.id_isar4 = 0x10011142;
618
+ cpu->isar.dbgdidr = 0x3515f021;
619
+ cpu->clidr = 0x0a200023;
620
+ cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
621
+ cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
622
+ cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
623
+ define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
624
+}
625
+
626
static void cortex_m0_initfn(Object *obj)
627
{
628
ARMCPU *cpu = ARM_CPU(obj);
629
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
630
cc->gdb_core_xml_file = "arm-m-profile.xml";
631
}
632
633
+#ifndef TARGET_AARCH64
634
+/*
635
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
636
+ * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
637
+ * this only needs to handle 32 bits, and need not care about KVM.
638
+ */
639
+static void arm_max_initfn(Object *obj)
640
+{
641
+ ARMCPU *cpu = ARM_CPU(obj);
642
+
643
+ cortex_a15_initfn(obj);
644
+
645
+ /* old-style VFP short-vector support */
646
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
647
+
648
+#ifdef CONFIG_USER_ONLY
649
+ /*
650
+ * We don't set these in system emulation mode for the moment,
651
+ * since we don't correctly set (all of) the ID registers to
652
+ * advertise them.
653
+ */
654
+ set_feature(&cpu->env, ARM_FEATURE_V8);
655
+ {
656
+ uint32_t t;
657
+
658
+ t = cpu->isar.id_isar5;
659
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
660
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
661
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
662
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
663
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
664
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
665
+ cpu->isar.id_isar5 = t;
666
+
667
+ t = cpu->isar.id_isar6;
668
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
669
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
670
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
671
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
672
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
673
+ cpu->isar.id_isar6 = t;
674
+
675
+ t = cpu->isar.mvfr1;
676
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
677
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
678
+ cpu->isar.mvfr1 = t;
679
+
680
+ t = cpu->isar.mvfr2;
681
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
682
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
683
+ cpu->isar.mvfr2 = t;
684
+
685
+ t = cpu->isar.id_mmfr3;
686
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
687
+ cpu->isar.id_mmfr3 = t;
688
+
689
+ t = cpu->isar.id_mmfr4;
690
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
691
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
692
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
693
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
694
+ cpu->isar.id_mmfr4 = t;
695
+
696
+ t = cpu->isar.id_pfr0;
697
+ t = FIELD_DP32(t, ID_PFR0, DIT, 1);
698
+ cpu->isar.id_pfr0 = t;
699
+
700
+ t = cpu->isar.id_pfr2;
701
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
702
+ cpu->isar.id_pfr2 = t;
703
+ }
704
+#endif /* CONFIG_USER_ONLY */
705
+}
706
+#endif /* !TARGET_AARCH64 */
707
+
708
static const ARMCPUInfo arm_tcg_cpus[] = {
709
{ .name = "arm926", .initfn = arm926_initfn },
710
{ .name = "arm946", .initfn = arm946_initfn },
711
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
712
{ .name = "arm1136", .initfn = arm1136_initfn },
713
{ .name = "arm1176", .initfn = arm1176_initfn },
714
{ .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
715
+ { .name = "cortex-a7", .initfn = cortex_a7_initfn },
716
+ { .name = "cortex-a8", .initfn = cortex_a8_initfn },
717
+ { .name = "cortex-a9", .initfn = cortex_a9_initfn },
718
+ { .name = "cortex-a15", .initfn = cortex_a15_initfn },
719
{ .name = "cortex-m0", .initfn = cortex_m0_initfn,
720
.class_init = arm_v7m_class_init },
721
{ .name = "cortex-m3", .initfn = cortex_m3_initfn,
722
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
723
{ .name = "pxa270-b1", .initfn = pxa270b1_initfn },
724
{ .name = "pxa270-c0", .initfn = pxa270c0_initfn },
725
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
726
+#ifndef TARGET_AARCH64
727
+ { .name = "max", .initfn = arm_max_initfn },
728
+#endif
729
+#ifdef CONFIG_USER_ONLY
730
+ { .name = "any", .initfn = arm_max_initfn },
731
+#endif
732
};
733
734
static const TypeInfo idau_interface_type_info = {
735
--
736
2.20.1
737
738
diff view generated by jsdifflib
Deleted patch
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
1
3
ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
4
is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
5
crash. This is observed when testing VxWorks 7.
6
7
This adds a Xilinx CSU DMA model and the implementation is based on
8
https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c.
9
The DST part of the model is verified along with ZynqMP GQSPI model.
10
11
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
12
Signed-off-by: Bin Meng <bin.meng@windriver.com>
13
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Message-id: 20210303135254.3970-2-bmeng.cn@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/dma/xlnx_csu_dma.h | 52 +++
19
hw/dma/xlnx_csu_dma.c | 745 ++++++++++++++++++++++++++++++++++
20
hw/dma/Kconfig | 4 +
21
hw/dma/meson.build | 1 +
22
4 files changed, 802 insertions(+)
23
create mode 100644 include/hw/dma/xlnx_csu_dma.h
24
create mode 100644 hw/dma/xlnx_csu_dma.c
25
26
diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h
27
new file mode 100644
28
index XXXXXXX..XXXXXXX
29
--- /dev/null
30
+++ b/include/hw/dma/xlnx_csu_dma.h
31
@@ -XXX,XX +XXX,XX @@
32
+/*
33
+ * Xilinx Platform CSU Stream DMA emulation
34
+ *
35
+ * This implementation is based on
36
+ * https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c
37
+ *
38
+ * This program is free software; you can redistribute it and/or
39
+ * modify it under the terms of the GNU General Public License as
40
+ * published by the Free Software Foundation; either version 2 or
41
+ * (at your option) version 3 of the License.
42
+ *
43
+ * This program is distributed in the hope that it will be useful,
44
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
45
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46
+ * GNU General Public License for more details.
47
+ *
48
+ * You should have received a copy of the GNU General Public License along
49
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
50
+ */
51
+
52
+#ifndef XLNX_CSU_DMA_H
53
+#define XLNX_CSU_DMA_H
54
+
55
+#define TYPE_XLNX_CSU_DMA "xlnx.csu_dma"
56
+
57
+#define XLNX_CSU_DMA_R_MAX (0x2c / 4)
58
+
59
+typedef struct XlnxCSUDMA {
60
+ SysBusDevice busdev;
61
+ MemoryRegion iomem;
62
+ MemTxAttrs attr;
63
+ MemoryRegion *dma_mr;
64
+ AddressSpace *dma_as;
65
+ qemu_irq irq;
66
+ StreamSink *tx_dev; /* Used as generic StreamSink */
67
+ ptimer_state *src_timer;
68
+
69
+ uint16_t width;
70
+ bool is_dst;
71
+ bool r_size_last_word;
72
+
73
+ StreamCanPushNotifyFn notify;
74
+ void *notify_opaque;
75
+
76
+ uint32_t regs[XLNX_CSU_DMA_R_MAX];
77
+ RegisterInfo regs_info[XLNX_CSU_DMA_R_MAX];
78
+} XlnxCSUDMA;
79
+
80
+#define XLNX_CSU_DMA(obj) \
81
+ OBJECT_CHECK(XlnxCSUDMA, (obj), TYPE_XLNX_CSU_DMA)
82
+
83
+#endif
84
diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c
85
new file mode 100644
86
index XXXXXXX..XXXXXXX
87
--- /dev/null
88
+++ b/hw/dma/xlnx_csu_dma.c
89
@@ -XXX,XX +XXX,XX @@
90
+/*
91
+ * Xilinx Platform CSU Stream DMA emulation
92
+ *
93
+ * This implementation is based on
94
+ * https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c
95
+ *
96
+ * This program is free software; you can redistribute it and/or
97
+ * modify it under the terms of the GNU General Public License as
98
+ * published by the Free Software Foundation; either version 2 or
99
+ * (at your option) version 3 of the License.
100
+ *
101
+ * This program is distributed in the hope that it will be useful,
102
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
103
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104
+ * GNU General Public License for more details.
105
+ *
106
+ * You should have received a copy of the GNU General Public License along
107
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
108
+ */
109
+
110
+#include "qemu/osdep.h"
111
+#include "qemu/log.h"
112
+#include "qapi/error.h"
113
+#include "hw/hw.h"
114
+#include "hw/irq.h"
115
+#include "hw/qdev-properties.h"
116
+#include "hw/sysbus.h"
117
+#include "migration/vmstate.h"
118
+#include "sysemu/dma.h"
119
+#include "hw/ptimer.h"
120
+#include "hw/stream.h"
121
+#include "hw/register.h"
122
+#include "hw/dma/xlnx_csu_dma.h"
123
+
124
+/*
125
+ * Ref: UG1087 (v1.7) February 8, 2019
126
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
127
+ * CSUDMA Module section
128
+ */
129
+REG32(ADDR, 0x0)
130
+ FIELD(ADDR, ADDR, 2, 30) /* wo */
131
+REG32(SIZE, 0x4)
132
+ FIELD(SIZE, SIZE, 2, 27) /* wo */
133
+ FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
134
+REG32(STATUS, 0x8)
135
+ FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
136
+ FIELD(STATUS, FIFO_LEVEL, 5, 8) /* ro */
137
+ FIELD(STATUS, OUTSTANDING, 1, 4) /* ro */
138
+ FIELD(STATUS, BUSY, 0, 1) /* ro */
139
+REG32(CTRL, 0xc)
140
+ FIELD(CTRL, FIFOTHRESH, 25, 7) /* rw, only exists in DST, reset 0x40 */
141
+ FIELD(CTRL, APB_ERR_RESP, 24, 1) /* rw */
142
+ FIELD(CTRL, ENDIANNESS, 23, 1) /* rw */
143
+ FIELD(CTRL, AXI_BRST_TYPE, 22, 1) /* rw */
144
+ FIELD(CTRL, TIMEOUT_VAL, 10, 12) /* rw, reset: 0xFFE */
145
+ FIELD(CTRL, FIFO_THRESH, 2, 8) /* rw, reset: 0x80 */
146
+ FIELD(CTRL, PAUSE_STRM, 1, 1) /* rw */
147
+ FIELD(CTRL, PAUSE_MEM, 0, 1) /* rw */
148
+REG32(CRC, 0x10)
149
+REG32(INT_STATUS, 0x14)
150
+ FIELD(INT_STATUS, FIFO_OVERFLOW, 7, 1) /* wtc */
151
+ FIELD(INT_STATUS, INVALID_APB, 6, 1) /* wtc */
152
+ FIELD(INT_STATUS, THRESH_HIT, 5, 1) /* wtc */
153
+ FIELD(INT_STATUS, TIMEOUT_MEM, 4, 1) /* wtc */
154
+ FIELD(INT_STATUS, TIMEOUT_STRM, 3, 1) /* wtc */
155
+ FIELD(INT_STATUS, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
156
+ FIELD(INT_STATUS, DONE, 1, 1) /* wtc */
157
+ FIELD(INT_STATUS, MEM_DONE, 0, 1) /* wtc */
158
+REG32(INT_ENABLE, 0x18)
159
+ FIELD(INT_ENABLE, FIFO_OVERFLOW, 7, 1) /* wtc */
160
+ FIELD(INT_ENABLE, INVALID_APB, 6, 1) /* wtc */
161
+ FIELD(INT_ENABLE, THRESH_HIT, 5, 1) /* wtc */
162
+ FIELD(INT_ENABLE, TIMEOUT_MEM, 4, 1) /* wtc */
163
+ FIELD(INT_ENABLE, TIMEOUT_STRM, 3, 1) /* wtc */
164
+ FIELD(INT_ENABLE, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
165
+ FIELD(INT_ENABLE, DONE, 1, 1) /* wtc */
166
+ FIELD(INT_ENABLE, MEM_DONE, 0, 1) /* wtc */
167
+REG32(INT_DISABLE, 0x1c)
168
+ FIELD(INT_DISABLE, FIFO_OVERFLOW, 7, 1) /* wtc */
169
+ FIELD(INT_DISABLE, INVALID_APB, 6, 1) /* wtc */
170
+ FIELD(INT_DISABLE, THRESH_HIT, 5, 1) /* wtc */
171
+ FIELD(INT_DISABLE, TIMEOUT_MEM, 4, 1) /* wtc */
172
+ FIELD(INT_DISABLE, TIMEOUT_STRM, 3, 1) /* wtc */
173
+ FIELD(INT_DISABLE, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
174
+ FIELD(INT_DISABLE, DONE, 1, 1) /* wtc */
175
+ FIELD(INT_DISABLE, MEM_DONE, 0, 1) /* wtc */
176
+REG32(INT_MASK, 0x20)
177
+ FIELD(INT_MASK, FIFO_OVERFLOW, 7, 1) /* ro, reset: 0x1 */
178
+ FIELD(INT_MASK, INVALID_APB, 6, 1) /* ro, reset: 0x1 */
179
+ FIELD(INT_MASK, THRESH_HIT, 5, 1) /* ro, reset: 0x1 */
180
+ FIELD(INT_MASK, TIMEOUT_MEM, 4, 1) /* ro, reset: 0x1 */
181
+ FIELD(INT_MASK, TIMEOUT_STRM, 3, 1) /* ro, reset: 0x1 */
182
+ FIELD(INT_MASK, AXI_BRESP_ERR, 2, 1) /* ro, reset: 0x1, SRC: AXI_RDERR */
183
+ FIELD(INT_MASK, DONE, 1, 1) /* ro, reset: 0x1 */
184
+ FIELD(INT_MASK, MEM_DONE, 0, 1) /* ro, reset: 0x1 */
185
+REG32(CTRL2, 0x24)
186
+ FIELD(CTRL2, ARCACHE, 24, 3) /* rw */
187
+ FIELD(CTRL2, ROUTE_BIT, 23, 1) /* rw */
188
+ FIELD(CTRL2, TIMEOUT_EN, 22, 1) /* rw */
189
+ FIELD(CTRL2, TIMEOUT_PRE, 4, 12) /* rw, reset: 0xFFF */
190
+ FIELD(CTRL2, MAX_OUTS_CMDS, 0, 4) /* rw, reset: 0x8 */
191
+REG32(ADDR_MSB, 0x28)
192
+ FIELD(ADDR_MSB, ADDR_MSB, 0, 17) /* wo */
193
+
194
+#define R_CTRL_TIMEOUT_VAL_RESET (0xFFE)
195
+#define R_CTRL_FIFO_THRESH_RESET (0x80)
196
+#define R_CTRL_FIFOTHRESH_RESET (0x40)
197
+
198
+#define R_CTRL2_TIMEOUT_PRE_RESET (0xFFF)
199
+#define R_CTRL2_MAX_OUTS_CMDS_RESET (0x8)
200
+
201
+#define XLNX_CSU_DMA_ERR_DEBUG (0)
202
+#define XLNX_CSU_DMA_INT_R_MASK (0xff)
203
+
204
+/* UG1807: Set the prescaler value for the timeout in clk (~2.5ns) cycles */
205
+#define XLNX_CSU_DMA_TIMER_FREQ (400 * 1000 * 1000)
206
+
207
+static bool xlnx_csu_dma_is_paused(XlnxCSUDMA *s)
208
+{
209
+ bool paused;
210
+
211
+ paused = !!(s->regs[R_CTRL] & R_CTRL_PAUSE_STRM_MASK);
212
+ paused |= !!(s->regs[R_CTRL] & R_CTRL_PAUSE_MEM_MASK);
213
+
214
+ return paused;
215
+}
216
+
217
+static bool xlnx_csu_dma_get_eop(XlnxCSUDMA *s)
218
+{
219
+ return s->r_size_last_word;
220
+}
221
+
222
+static bool xlnx_csu_dma_burst_is_fixed(XlnxCSUDMA *s)
223
+{
224
+ return !!(s->regs[R_CTRL] & R_CTRL_AXI_BRST_TYPE_MASK);
225
+}
226
+
227
+static bool xlnx_csu_dma_timeout_enabled(XlnxCSUDMA *s)
228
+{
229
+ return !!(s->regs[R_CTRL2] & R_CTRL2_TIMEOUT_EN_MASK);
230
+}
231
+
232
+static void xlnx_csu_dma_update_done_cnt(XlnxCSUDMA *s, int a)
233
+{
234
+ int cnt;
235
+
236
+ /* Increase DONE_CNT */
237
+ cnt = ARRAY_FIELD_EX32(s->regs, STATUS, DONE_CNT) + a;
238
+ ARRAY_FIELD_DP32(s->regs, STATUS, DONE_CNT, cnt);
239
+}
240
+
241
+static void xlnx_csu_dma_data_process(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
242
+{
243
+ uint32_t bswap;
244
+ uint32_t i;
245
+
246
+ bswap = s->regs[R_CTRL] & R_CTRL_ENDIANNESS_MASK;
247
+ if (s->is_dst && !bswap) {
248
+ /* Fast when ENDIANNESS cleared */
249
+ return;
250
+ }
251
+
252
+ for (i = 0; i < len; i += 4) {
253
+ uint8_t *b = &buf[i];
254
+ union {
255
+ uint8_t u8[4];
256
+ uint32_t u32;
257
+ } v = {
258
+ .u8 = { b[0], b[1], b[2], b[3] }
259
+ };
260
+
261
+ if (!s->is_dst) {
262
+ s->regs[R_CRC] += v.u32;
263
+ }
264
+ if (bswap) {
265
+ /*
266
+ * No point using bswap, we need to writeback
267
+ * into a potentially unaligned pointer.
268
+ */
269
+ b[0] = v.u8[3];
270
+ b[1] = v.u8[2];
271
+ b[2] = v.u8[1];
272
+ b[3] = v.u8[0];
273
+ }
274
+ }
275
+}
276
+
277
+static void xlnx_csu_dma_update_irq(XlnxCSUDMA *s)
278
+{
279
+ qemu_set_irq(s->irq, !!(s->regs[R_INT_STATUS] & ~s->regs[R_INT_MASK]));
280
+}
281
+
282
+/* len is in bytes */
283
+static uint32_t xlnx_csu_dma_read(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
284
+{
285
+ hwaddr addr = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
286
+ MemTxResult result = MEMTX_OK;
287
+
288
+ if (xlnx_csu_dma_burst_is_fixed(s)) {
289
+ uint32_t i;
290
+
291
+ for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
292
+ uint32_t mlen = MIN(len - i, s->width);
293
+
294
+ result = address_space_rw(s->dma_as, addr, s->attr,
295
+ buf + i, mlen, false);
296
+ }
297
+ } else {
298
+ result = address_space_rw(s->dma_as, addr, s->attr, buf, len, false);
299
+ }
300
+
301
+ if (result == MEMTX_OK) {
302
+ xlnx_csu_dma_data_process(s, buf, len);
303
+ } else {
304
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%lx for mem read",
305
+ __func__, addr);
306
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_AXI_BRESP_ERR_MASK;
307
+ xlnx_csu_dma_update_irq(s);
308
+ }
309
+ return len;
310
+}
311
+
312
+/* len is in bytes */
313
+static uint32_t xlnx_csu_dma_write(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
314
+{
315
+ hwaddr addr = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
316
+ MemTxResult result = MEMTX_OK;
317
+
318
+ xlnx_csu_dma_data_process(s, buf, len);
319
+ if (xlnx_csu_dma_burst_is_fixed(s)) {
320
+ uint32_t i;
321
+
322
+ for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
323
+ uint32_t mlen = MIN(len - i, s->width);
324
+
325
+ result = address_space_rw(s->dma_as, addr, s->attr,
326
+ buf, mlen, true);
327
+ buf += mlen;
328
+ }
329
+ } else {
330
+ result = address_space_rw(s->dma_as, addr, s->attr, buf, len, true);
331
+ }
332
+
333
+ if (result != MEMTX_OK) {
334
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%lx for mem write",
335
+ __func__, addr);
336
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_AXI_BRESP_ERR_MASK;
337
+ xlnx_csu_dma_update_irq(s);
338
+ }
339
+ return len;
340
+}
341
+
342
+static void xlnx_csu_dma_done(XlnxCSUDMA *s)
343
+{
344
+ s->regs[R_STATUS] &= ~R_STATUS_BUSY_MASK;
345
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_DONE_MASK;
346
+
347
+ if (!s->is_dst) {
348
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_MEM_DONE_MASK;
349
+ }
350
+
351
+ xlnx_csu_dma_update_done_cnt(s, 1);
352
+}
353
+
354
+static uint32_t xlnx_csu_dma_advance(XlnxCSUDMA *s, uint32_t len)
355
+{
356
+ uint32_t size = s->regs[R_SIZE];
357
+ hwaddr dst = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
358
+
359
+ assert(len <= size);
360
+
361
+ size -= len;
362
+ s->regs[R_SIZE] = size;
363
+
364
+ if (!xlnx_csu_dma_burst_is_fixed(s)) {
365
+ dst += len;
366
+ s->regs[R_ADDR] = (uint32_t) dst;
367
+ s->regs[R_ADDR_MSB] = dst >> 32;
368
+ }
369
+
370
+ if (size == 0) {
371
+ xlnx_csu_dma_done(s);
372
+ }
373
+
374
+ return size;
375
+}
376
+
377
+static void xlnx_csu_dma_src_notify(void *opaque)
378
+{
379
+ XlnxCSUDMA *s = XLNX_CSU_DMA(opaque);
380
+ unsigned char buf[4 * 1024];
381
+ size_t rlen = 0;
382
+
383
+ ptimer_transaction_begin(s->src_timer);
384
+ /* Stop the backpreassure timer */
385
+ ptimer_stop(s->src_timer);
386
+
387
+ while (s->regs[R_SIZE] && !xlnx_csu_dma_is_paused(s) &&
388
+ stream_can_push(s->tx_dev, xlnx_csu_dma_src_notify, s)) {
389
+ uint32_t plen = MIN(s->regs[R_SIZE], sizeof buf);
390
+ bool eop = false;
391
+
392
+ /* Did we fit it all? */
393
+ if (s->regs[R_SIZE] == plen && xlnx_csu_dma_get_eop(s)) {
394
+ eop = true;
395
+ }
396
+
397
+ /* DMA transfer */
398
+ xlnx_csu_dma_read(s, buf, plen);
399
+ rlen = stream_push(s->tx_dev, buf, plen, eop);
400
+ xlnx_csu_dma_advance(s, rlen);
401
+ }
402
+
403
+ if (xlnx_csu_dma_timeout_enabled(s) && s->regs[R_SIZE] &&
404
+ !stream_can_push(s->tx_dev, xlnx_csu_dma_src_notify, s)) {
405
+ uint32_t timeout = ARRAY_FIELD_EX32(s->regs, CTRL, TIMEOUT_VAL);
406
+ uint32_t div = ARRAY_FIELD_EX32(s->regs, CTRL2, TIMEOUT_PRE) + 1;
407
+ uint32_t freq = XLNX_CSU_DMA_TIMER_FREQ;
408
+
409
+ freq /= div;
410
+ ptimer_set_freq(s->src_timer, freq);
411
+ ptimer_set_count(s->src_timer, timeout);
412
+ ptimer_run(s->src_timer, 1);
413
+ }
414
+
415
+ ptimer_transaction_commit(s->src_timer);
416
+ xlnx_csu_dma_update_irq(s);
417
+}
418
+
419
+static uint64_t addr_pre_write(RegisterInfo *reg, uint64_t val)
420
+{
421
+ /* Address is word aligned */
422
+ return val & R_ADDR_ADDR_MASK;
423
+}
424
+
425
+static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
426
+{
427
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
428
+
429
+ if (s->regs[R_SIZE] != 0) {
430
+ qemu_log_mask(LOG_GUEST_ERROR,
431
+ "%s: Starting DMA while already running.\n", __func__);
432
+ }
433
+
434
+ if (!s->is_dst) {
435
+ s->r_size_last_word = !!(val & R_SIZE_LAST_WORD_MASK);
436
+ }
437
+
438
+ /* Size is word aligned */
439
+ return val & R_SIZE_SIZE_MASK;
440
+}
441
+
442
+static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)
443
+{
444
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
445
+
446
+ return val | s->r_size_last_word;
447
+}
448
+
449
+static void size_post_write(RegisterInfo *reg, uint64_t val)
450
+{
451
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
452
+
453
+ s->regs[R_STATUS] |= R_STATUS_BUSY_MASK;
454
+
455
+ /*
456
+ * Note that if SIZE is programmed to 0, and the DMA is started,
457
+ * the interrupts DONE and MEM_DONE will be asserted.
458
+ */
459
+ if (s->regs[R_SIZE] == 0) {
460
+ xlnx_csu_dma_done(s);
461
+ xlnx_csu_dma_update_irq(s);
462
+ return;
463
+ }
464
+
465
+ /* Set SIZE is considered the last step in transfer configuration */
466
+ if (!s->is_dst) {
467
+ xlnx_csu_dma_src_notify(s);
468
+ } else {
469
+ if (s->notify) {
470
+ s->notify(s->notify_opaque);
471
+ }
472
+ }
473
+}
474
+
475
+static uint64_t status_pre_write(RegisterInfo *reg, uint64_t val)
476
+{
477
+ return val & (R_STATUS_DONE_CNT_MASK | R_STATUS_BUSY_MASK);
478
+}
479
+
480
+static void ctrl_post_write(RegisterInfo *reg, uint64_t val)
481
+{
482
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
483
+
484
+ if (!s->is_dst) {
485
+ if (!xlnx_csu_dma_is_paused(s)) {
486
+ xlnx_csu_dma_src_notify(s);
487
+ }
488
+ } else {
489
+ if (!xlnx_csu_dma_is_paused(s) && s->notify) {
490
+ s->notify(s->notify_opaque);
491
+ }
492
+ }
493
+}
494
+
495
+static uint64_t int_status_pre_write(RegisterInfo *reg, uint64_t val)
496
+{
497
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
498
+
499
+ /* DMA counter decrements when flag 'DONE' is cleared */
500
+ if ((val & s->regs[R_INT_STATUS] & R_INT_STATUS_DONE_MASK)) {
501
+ xlnx_csu_dma_update_done_cnt(s, -1);
502
+ }
503
+
504
+ return s->regs[R_INT_STATUS] & ~val;
505
+}
506
+
507
+static void int_status_post_write(RegisterInfo *reg, uint64_t val)
508
+{
509
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
510
+
511
+ xlnx_csu_dma_update_irq(s);
512
+}
513
+
514
+static uint64_t int_enable_pre_write(RegisterInfo *reg, uint64_t val)
515
+{
516
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
517
+ uint32_t v32 = val;
518
+
519
+ /*
520
+ * R_INT_ENABLE doesn't have its own state.
521
+ * It is used to indirectly modify R_INT_MASK.
522
+ *
523
+ * 1: Enable this interrupt field (the mask bit will be cleared to 0)
524
+ * 0: No effect
525
+ */
526
+ s->regs[R_INT_MASK] &= ~v32;
527
+ return 0;
528
+}
529
+
530
+static void int_enable_post_write(RegisterInfo *reg, uint64_t val)
531
+{
532
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
533
+
534
+ xlnx_csu_dma_update_irq(s);
535
+}
536
+
537
+static uint64_t int_disable_pre_write(RegisterInfo *reg, uint64_t val)
538
+{
539
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
540
+ uint32_t v32 = val;
541
+
542
+ /*
543
+ * R_INT_DISABLE doesn't have its own state.
544
+ * It is used to indirectly modify R_INT_MASK.
545
+ *
546
+ * 1: Disable this interrupt field (the mask bit will be set to 1)
547
+ * 0: No effect
548
+ */
549
+ s->regs[R_INT_MASK] |= v32;
550
+ return 0;
551
+}
552
+
553
+static void int_disable_post_write(RegisterInfo *reg, uint64_t val)
554
+{
555
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
556
+
557
+ xlnx_csu_dma_update_irq(s);
558
+}
559
+
560
+static uint64_t addr_msb_pre_write(RegisterInfo *reg, uint64_t val)
561
+{
562
+ return val & R_ADDR_MSB_ADDR_MSB_MASK;
563
+}
564
+
565
+static const RegisterAccessInfo *xlnx_csu_dma_regs_info[] = {
566
+#define DMACH_REGINFO(NAME, snd) \
567
+ (const RegisterAccessInfo []) { \
568
+ { \
569
+ .name = #NAME "_ADDR", \
570
+ .addr = A_ADDR, \
571
+ .pre_write = addr_pre_write \
572
+ }, { \
573
+ .name = #NAME "_SIZE", \
574
+ .addr = A_SIZE, \
575
+ .pre_write = size_pre_write, \
576
+ .post_write = size_post_write, \
577
+ .post_read = size_post_read \
578
+ }, { \
579
+ .name = #NAME "_STATUS", \
580
+ .addr = A_STATUS, \
581
+ .pre_write = status_pre_write, \
582
+ .w1c = R_STATUS_DONE_CNT_MASK, \
583
+ .ro = (R_STATUS_BUSY_MASK \
584
+ | R_STATUS_FIFO_LEVEL_MASK \
585
+ | R_STATUS_OUTSTANDING_MASK) \
586
+ }, { \
587
+ .name = #NAME "_CTRL", \
588
+ .addr = A_CTRL, \
589
+ .post_write = ctrl_post_write, \
590
+ .reset = ((R_CTRL_TIMEOUT_VAL_RESET << R_CTRL_TIMEOUT_VAL_SHIFT) \
591
+ | (R_CTRL_FIFO_THRESH_RESET << R_CTRL_FIFO_THRESH_SHIFT)\
592
+ | (snd ? 0 : R_CTRL_FIFOTHRESH_RESET \
593
+ << R_CTRL_FIFOTHRESH_SHIFT)) \
594
+ }, { \
595
+ .name = #NAME "_CRC", \
596
+ .addr = A_CRC, \
597
+ }, { \
598
+ .name = #NAME "_INT_STATUS", \
599
+ .addr = A_INT_STATUS, \
600
+ .pre_write = int_status_pre_write, \
601
+ .post_write = int_status_post_write \
602
+ }, { \
603
+ .name = #NAME "_INT_ENABLE", \
604
+ .addr = A_INT_ENABLE, \
605
+ .pre_write = int_enable_pre_write, \
606
+ .post_write = int_enable_post_write \
607
+ }, { \
608
+ .name = #NAME "_INT_DISABLE", \
609
+ .addr = A_INT_DISABLE, \
610
+ .pre_write = int_disable_pre_write, \
611
+ .post_write = int_disable_post_write \
612
+ }, { \
613
+ .name = #NAME "_INT_MASK", \
614
+ .addr = A_INT_MASK, \
615
+ .ro = ~0, \
616
+ .reset = XLNX_CSU_DMA_INT_R_MASK \
617
+ }, { \
618
+ .name = #NAME "_CTRL2", \
619
+ .addr = A_CTRL2, \
620
+ .reset = ((R_CTRL2_TIMEOUT_PRE_RESET \
621
+ << R_CTRL2_TIMEOUT_PRE_SHIFT) \
622
+ | (R_CTRL2_MAX_OUTS_CMDS_RESET \
623
+ << R_CTRL2_MAX_OUTS_CMDS_SHIFT)) \
624
+ }, { \
625
+ .name = #NAME "_ADDR_MSB", \
626
+ .addr = A_ADDR_MSB, \
627
+ .pre_write = addr_msb_pre_write \
628
+ } \
629
+ }
630
+
631
+ DMACH_REGINFO(DMA_SRC, true),
632
+ DMACH_REGINFO(DMA_DST, false)
633
+};
634
+
635
+static const MemoryRegionOps xlnx_csu_dma_ops = {
636
+ .read = register_read_memory,
637
+ .write = register_write_memory,
638
+ .endianness = DEVICE_LITTLE_ENDIAN,
639
+ .valid = {
640
+ .min_access_size = 4,
641
+ .max_access_size = 4,
642
+ }
643
+};
644
+
645
+static void xlnx_csu_dma_src_timeout_hit(void *opaque)
646
+{
647
+ XlnxCSUDMA *s = XLNX_CSU_DMA(opaque);
648
+
649
+ /* Ignore if the timeout is masked */
650
+ if (!xlnx_csu_dma_timeout_enabled(s)) {
651
+ return;
652
+ }
653
+
654
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_TIMEOUT_STRM_MASK;
655
+ xlnx_csu_dma_update_irq(s);
656
+}
657
+
658
+static size_t xlnx_csu_dma_stream_push(StreamSink *obj, uint8_t *buf,
659
+ size_t len, bool eop)
660
+{
661
+ XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
662
+ uint32_t size = s->regs[R_SIZE];
663
+ uint32_t mlen = MIN(size, len) & (~3); /* Size is word aligned */
664
+
665
+ /* Be called when it's DST */
666
+ assert(s->is_dst);
667
+
668
+ if (size == 0 || len <= 0) {
669
+ return 0;
670
+ }
671
+
672
+ if (len && (xlnx_csu_dma_is_paused(s) || mlen == 0)) {
673
+ qemu_log_mask(LOG_GUEST_ERROR,
674
+ "csu-dma: DST channel dropping %zd b of data.\n", len);
675
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_FIFO_OVERFLOW_MASK;
676
+ return len;
677
+ }
678
+
679
+ if (xlnx_csu_dma_write(s, buf, mlen) != mlen) {
680
+ return 0;
681
+ }
682
+
683
+ xlnx_csu_dma_advance(s, mlen);
684
+ xlnx_csu_dma_update_irq(s);
685
+
686
+ return mlen;
687
+}
688
+
689
+static bool xlnx_csu_dma_stream_can_push(StreamSink *obj,
690
+ StreamCanPushNotifyFn notify,
691
+ void *notify_opaque)
692
+{
693
+ XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
694
+
695
+ if (s->regs[R_SIZE] != 0) {
696
+ return true;
697
+ } else {
698
+ s->notify = notify;
699
+ s->notify_opaque = notify_opaque;
700
+ return false;
701
+ }
702
+}
703
+
704
+static void xlnx_csu_dma_reset(DeviceState *dev)
705
+{
706
+ XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
707
+ unsigned int i;
708
+
709
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
710
+ register_reset(&s->regs_info[i]);
711
+ }
712
+}
713
+
714
+static void xlnx_csu_dma_realize(DeviceState *dev, Error **errp)
715
+{
716
+ XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
717
+ RegisterInfoArray *reg_array;
718
+
719
+ reg_array =
720
+ register_init_block32(dev, xlnx_csu_dma_regs_info[!!s->is_dst],
721
+ XLNX_CSU_DMA_R_MAX,
722
+ s->regs_info, s->regs,
723
+ &xlnx_csu_dma_ops,
724
+ XLNX_CSU_DMA_ERR_DEBUG,
725
+ XLNX_CSU_DMA_R_MAX * 4);
726
+ memory_region_add_subregion(&s->iomem,
727
+ 0x0,
728
+ &reg_array->mem);
729
+
730
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
731
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
732
+
733
+ if (!s->is_dst && !s->tx_dev) {
734
+ error_setg(errp, "zynqmp.csu-dma: Stream not connected");
735
+ return;
736
+ }
737
+
738
+ s->src_timer = ptimer_init(xlnx_csu_dma_src_timeout_hit,
739
+ s, PTIMER_POLICY_DEFAULT);
740
+
741
+ if (s->dma_mr) {
742
+ s->dma_as = g_malloc0(sizeof(AddressSpace));
743
+ address_space_init(s->dma_as, s->dma_mr, NULL);
744
+ } else {
745
+ s->dma_as = &address_space_memory;
746
+ }
747
+
748
+ s->attr = MEMTXATTRS_UNSPECIFIED;
749
+
750
+ s->r_size_last_word = 0;
751
+}
752
+
753
+static const VMStateDescription vmstate_xlnx_csu_dma = {
754
+ .name = TYPE_XLNX_CSU_DMA,
755
+ .version_id = 0,
756
+ .minimum_version_id = 0,
757
+ .minimum_version_id_old = 0,
758
+ .fields = (VMStateField[]) {
759
+ VMSTATE_PTIMER(src_timer, XlnxCSUDMA),
760
+ VMSTATE_UINT16(width, XlnxCSUDMA),
761
+ VMSTATE_BOOL(is_dst, XlnxCSUDMA),
762
+ VMSTATE_BOOL(r_size_last_word, XlnxCSUDMA),
763
+ VMSTATE_UINT32_ARRAY(regs, XlnxCSUDMA, XLNX_CSU_DMA_R_MAX),
764
+ VMSTATE_END_OF_LIST(),
765
+ }
766
+};
767
+
768
+static Property xlnx_csu_dma_properties[] = {
769
+ /*
770
+ * Ref PG021, Stream Data Width:
771
+ * Data width in bits of the AXI S2MM AXI4-Stream Data bus.
772
+ * This value must be equal or less than the Memory Map Data Width.
773
+ * Valid values are 8, 16, 32, 64, 128, 512 and 1024.
774
+ * "dma-width" is the byte value of the "Stream Data Width".
775
+ */
776
+ DEFINE_PROP_UINT16("dma-width", XlnxCSUDMA, width, 4),
777
+ /*
778
+ * The CSU DMA is a two-channel, simple DMA, allowing separate control of
779
+ * the SRC (read) channel and DST (write) channel. "is-dst" is used to mark
780
+ * which channel the device is connected to.
781
+ */
782
+ DEFINE_PROP_BOOL("is-dst", XlnxCSUDMA, is_dst, true),
783
+ DEFINE_PROP_END_OF_LIST(),
784
+};
785
+
786
+static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data)
787
+{
788
+ DeviceClass *dc = DEVICE_CLASS(klass);
789
+ StreamSinkClass *ssc = STREAM_SINK_CLASS(klass);
790
+
791
+ dc->reset = xlnx_csu_dma_reset;
792
+ dc->realize = xlnx_csu_dma_realize;
793
+ dc->vmsd = &vmstate_xlnx_csu_dma;
794
+ device_class_set_props(dc, xlnx_csu_dma_properties);
795
+
796
+ ssc->push = xlnx_csu_dma_stream_push;
797
+ ssc->can_push = xlnx_csu_dma_stream_can_push;
798
+}
799
+
800
+static void xlnx_csu_dma_init(Object *obj)
801
+{
802
+ XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
803
+
804
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_CSU_DMA,
805
+ XLNX_CSU_DMA_R_MAX * 4);
806
+
807
+ object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SINK,
808
+ (Object **)&s->tx_dev,
809
+ qdev_prop_allow_set_link_before_realize,
810
+ OBJ_PROP_LINK_STRONG);
811
+ object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
812
+ (Object **)&s->dma_mr,
813
+ qdev_prop_allow_set_link_before_realize,
814
+ OBJ_PROP_LINK_STRONG);
815
+}
816
+
817
+static const TypeInfo xlnx_csu_dma_info = {
818
+ .name = TYPE_XLNX_CSU_DMA,
819
+ .parent = TYPE_SYS_BUS_DEVICE,
820
+ .instance_size = sizeof(XlnxCSUDMA),
821
+ .class_init = xlnx_csu_dma_class_init,
822
+ .instance_init = xlnx_csu_dma_init,
823
+ .interfaces = (InterfaceInfo[]) {
824
+ { TYPE_STREAM_SINK },
825
+ { }
826
+ }
827
+};
828
+
829
+static void xlnx_csu_dma_register_types(void)
830
+{
831
+ type_register_static(&xlnx_csu_dma_info);
832
+}
833
+
834
+type_init(xlnx_csu_dma_register_types)
835
diff --git a/hw/dma/Kconfig b/hw/dma/Kconfig
836
index XXXXXXX..XXXXXXX 100644
837
--- a/hw/dma/Kconfig
838
+++ b/hw/dma/Kconfig
839
@@ -XXX,XX +XXX,XX @@ config STP2000
840
841
config SIFIVE_PDMA
842
bool
843
+
844
+config XLNX_CSU_DMA
845
+ bool
846
+ select REGISTER
847
diff --git a/hw/dma/meson.build b/hw/dma/meson.build
848
index XXXXXXX..XXXXXXX 100644
849
--- a/hw/dma/meson.build
850
+++ b/hw/dma/meson.build
851
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_dma.c', 'soc_dma.c'))
852
softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_dma.c'))
853
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_dma.c'))
854
softmmu_ss.add(when: 'CONFIG_SIFIVE_PDMA', if_true: files('sifive_pdma.c'))
855
+softmmu_ss.add(when: 'CONFIG_XLNX_CSU_DMA', if_true: files('xlnx_csu_dma.c'))
856
--
857
2.20.1
858
859
diff view generated by jsdifflib
Deleted patch
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
1
3
There are some coding convention warnings in xlnx-zynqmp.c and
4
xlnx-zynqmp.h, as reported by:
5
6
$ ./scripts/checkpatch.pl include/hw/arm/xlnx-zynqmp.h
7
$ ./scripts/checkpatch.pl hw/arm/xlnx-zynqmp.c
8
9
Let's clean them up.
10
11
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
12
Signed-off-by: Bin Meng <bin.meng@windriver.com>
13
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Message-id: 20210303135254.3970-3-bmeng.cn@gmail.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
include/hw/arm/xlnx-zynqmp.h | 3 ++-
18
hw/arm/xlnx-zynqmp.c | 9 ++++++---
19
2 files changed, 8 insertions(+), 4 deletions(-)
20
21
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/xlnx-zynqmp.h
24
+++ b/include/hw/arm/xlnx-zynqmp.h
25
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
26
27
#define XLNX_ZYNQMP_GIC_REGIONS 6
28
29
-/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
30
+/*
31
+ * ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
32
* and under-decodes the 64k region. This mirrors the 4k regions to every 4k
33
* aligned address in the 64k region. To implement each GIC region needs a
34
* number of memory region aliases.
35
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/xlnx-zynqmp.c
38
+++ b/hw/arm/xlnx-zynqmp.c
39
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
40
41
ram_size = memory_region_size(s->ddr_ram);
42
43
- /* Create the DDR Memory Regions. User friendly checks should happen at
44
+ /*
45
+ * Create the DDR Memory Regions. User friendly checks should happen at
46
* the board level
47
*/
48
if (ram_size > XLNX_ZYNQMP_MAX_LOW_RAM_SIZE) {
49
- /* The RAM size is above the maximum available for the low DDR.
50
+ /*
51
+ * The RAM size is above the maximum available for the low DDR.
52
* Create the high DDR memory region as well.
53
*/
54
assert(ram_size <= XLNX_ZYNQMP_MAX_RAM_SIZE);
55
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
56
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sdhci[i]);
57
Object *sdhci = OBJECT(&s->sdhci[i]);
58
59
- /* Compatible with:
60
+ /*
61
+ * Compatible with:
62
* - SD Host Controller Specification Version 3.00
63
* - SDIO Specification Version 3.0
64
* - eMMC Specification Version 4.51
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
1
3
Add a Xilinx CSU DMA module to ZynqMP SoC, and connent the stream
4
link of GQSPI to CSU DMA.
5
6
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
7
Signed-off-by: Bin Meng <bin.meng@windriver.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Message-id: 20210303135254.3970-4-bmeng.cn@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/xlnx-zynqmp.h | 2 ++
13
hw/arm/xlnx-zynqmp.c | 12 ++++++++++++
14
hw/arm/Kconfig | 1 +
15
3 files changed, 15 insertions(+)
16
17
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/xlnx-zynqmp.h
20
+++ b/include/hw/arm/xlnx-zynqmp.h
21
@@ -XXX,XX +XXX,XX @@
22
#include "target/arm/cpu.h"
23
#include "qom/object.h"
24
#include "net/can_emu.h"
25
+#include "hw/dma/xlnx_csu_dma.h"
26
27
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
28
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
30
XlnxZynqMPRTC rtc;
31
XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH];
32
XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH];
33
+ XlnxCSUDMA qspi_dma;
34
35
char *boot_cpu;
36
ARMCPU *boot_cpu_ptr;
37
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/xlnx-zynqmp.c
40
+++ b/hw/arm/xlnx-zynqmp.c
41
@@ -XXX,XX +XXX,XX @@
42
#define QSPI_ADDR 0xff0f0000
43
#define LQSPI_ADDR 0xc0000000
44
#define QSPI_IRQ 15
45
+#define QSPI_DMA_ADDR 0xff0f0800
46
47
#define DP_ADDR 0xfd4a0000
48
#define DP_IRQ 113
49
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
50
for (i = 0; i < XLNX_ZYNQMP_NUM_ADMA_CH; i++) {
51
object_initialize_child(obj, "adma[*]", &s->adma[i], TYPE_XLNX_ZDMA);
52
}
53
+
54
+ object_initialize_child(obj, "qspi-dma", &s->qspi_dma, TYPE_XLNX_CSU_DMA);
55
}
56
57
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
58
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adma[i]), 0,
60
gic_spi[adma_ch_intr[i]]);
61
}
62
+
63
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->qspi_dma), errp)) {
64
+ return;
65
+ }
66
+
67
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi_dma), 0, QSPI_DMA_ADDR);
68
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0, gic_spi[QSPI_IRQ]);
69
+ object_property_set_link(OBJECT(&s->qspi), "stream-connected-dma",
70
+ OBJECT(&s->qspi_dma), errp);
71
}
72
73
static Property xlnx_zynqmp_props[] = {
74
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
75
index XXXXXXX..XXXXXXX 100644
76
--- a/hw/arm/Kconfig
77
+++ b/hw/arm/Kconfig
78
@@ -XXX,XX +XXX,XX @@ config XLNX_ZYNQMP_ARM
79
select SSI_M25P80
80
select XILINX_AXI
81
select XILINX_SPIPS
82
+ select XLNX_CSU_DMA
83
select XLNX_ZYNQMP
84
select XLNX_ZDMA
85
86
--
87
2.20.1
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
1
3
There are some coding convention warnings in xilinx_spips.c,
4
as reported by:
5
6
$ ./scripts/checkpatch.pl hw/ssi/xilinx_spips.c
7
8
Let's clean them up.
9
10
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
11
Signed-off-by: Bin Meng <bin.meng@windriver.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Message-id: 20210303135254.3970-5-bmeng.cn@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/ssi/xilinx_spips.c | 23 ++++++++++++++---------
19
1 file changed, 14 insertions(+), 9 deletions(-)
20
21
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/ssi/xilinx_spips.c
24
+++ b/hw/ssi/xilinx_spips.c
25
@@ -XXX,XX +XXX,XX @@
26
FIELD(GQSPI_FIFO_CTRL, GENERIC_FIFO_RESET, 0, 1)
27
#define R_GQSPI_GFIFO_THRESH (0x150 / 4)
28
#define R_GQSPI_DATA_STS (0x15c / 4)
29
-/* We use the snapshot register to hold the core state for the currently
30
+/*
31
+ * We use the snapshot register to hold the core state for the currently
32
* or most recently executed command. So the generic fifo format is defined
33
* for the snapshot register
34
*/
35
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
36
xlnx_zynqmp_qspips_update_ixr(s);
37
}
38
39
-/* N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
40
+/*
41
+ * N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
42
* column wise (from element 0 to N-1). num is the length of x, and dir
43
* reverses the direction of the transform. Best illustrated by example:
44
* Each digit in the below array is a single bit (num == 3):
45
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
46
tx_rx[i] = tx;
47
}
48
} else {
49
- /* Extract a dummy byte and generate dummy cycles according to the
50
- * link state */
51
+ /*
52
+ * Extract a dummy byte and generate dummy cycles according to the
53
+ * link state
54
+ */
55
tx = fifo8_pop(&s->tx_fifo);
56
dummy_cycles = 8 / s->link_state;
57
}
58
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
59
}
60
break;
61
case (SNOOP_ADDR):
62
- /* Address has been transmitted, transmit dummy cycles now if
63
- * needed */
64
+ /*
65
+ * Address has been transmitted, transmit dummy cycles now if needed
66
+ */
67
if (s->cmd_dummies < 0) {
68
s->snoop_state = SNOOP_NONE;
69
} else {
70
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
71
}
72
73
static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
74
- unsigned size)
75
+ unsigned size)
76
{
77
XilinxSPIPS *s = opaque;
78
uint32_t mask = ~0;
79
@@ -XXX,XX +XXX,XX @@ static uint64_t xlnx_zynqmp_qspips_read(void *opaque,
80
}
81
82
static void xilinx_spips_write(void *opaque, hwaddr addr,
83
- uint64_t value, unsigned size)
84
+ uint64_t value, unsigned size)
85
{
86
int mask = ~0;
87
XilinxSPIPS *s = opaque;
88
@@ -XXX,XX +XXX,XX @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
89
}
90
91
static void xlnx_zynqmp_qspips_write(void *opaque, hwaddr addr,
92
- uint64_t value, unsigned size)
93
+ uint64_t value, unsigned size)
94
{
95
XlnxZynqMPQSPIPS *s = XLNX_ZYNQMP_QSPIPS(opaque);
96
uint32_t reg = addr / 4;
97
--
98
2.20.1
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
1
3
Now that the Xilinx CSU DMA model is implemented, the existing
4
DMA related dead codes in the ZynqMP QSPI are useless and should
5
be removed. The maximum register number is also updated to only
6
include the QSPI registers.
7
8
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
9
Signed-off-by: Bin Meng <bin.meng@windriver.com>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Message-id: 20210303135254.3970-6-bmeng.cn@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
include/hw/ssi/xilinx_spips.h | 2 +-
15
hw/ssi/xilinx_spips.c | 10 ----------
16
2 files changed, 1 insertion(+), 11 deletions(-)
17
18
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/ssi/xilinx_spips.h
21
+++ b/include/hw/ssi/xilinx_spips.h
22
@@ -XXX,XX +XXX,XX @@
23
typedef struct XilinxSPIPS XilinxSPIPS;
24
25
#define XLNX_SPIPS_R_MAX (0x100 / 4)
26
-#define XLNX_ZYNQMP_SPIPS_R_MAX (0x830 / 4)
27
+#define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
28
29
/* Bite off 4k chunks at a time */
30
#define LQSPI_CACHE_SIZE 1024
31
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/ssi/xilinx_spips.c
34
+++ b/hw/ssi/xilinx_spips.c
35
@@ -XXX,XX +XXX,XX @@
36
#define R_GQSPI_MOD_ID (0x1fc / 4)
37
#define R_GQSPI_MOD_ID_RESET (0x10a0000)
38
39
-#define R_QSPIDMA_DST_CTRL (0x80c / 4)
40
-#define R_QSPIDMA_DST_CTRL_RESET (0x803ffa00)
41
-#define R_QSPIDMA_DST_I_MASK (0x820 / 4)
42
-#define R_QSPIDMA_DST_I_MASK_RESET (0xfe)
43
-#define R_QSPIDMA_DST_CTRL2 (0x824 / 4)
44
-#define R_QSPIDMA_DST_CTRL2_RESET (0x081bfff8)
45
-
46
/* size of TXRX FIFOs */
47
#define RXFF_A (128)
48
#define TXFF_A (128)
49
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
50
s->regs[R_GQSPI_GPIO] = 1;
51
s->regs[R_GQSPI_LPBK_DLY_ADJ] = R_GQSPI_LPBK_DLY_ADJ_RESET;
52
s->regs[R_GQSPI_MOD_ID] = R_GQSPI_MOD_ID_RESET;
53
- s->regs[R_QSPIDMA_DST_CTRL] = R_QSPIDMA_DST_CTRL_RESET;
54
- s->regs[R_QSPIDMA_DST_I_MASK] = R_QSPIDMA_DST_I_MASK_RESET;
55
- s->regs[R_QSPIDMA_DST_CTRL2] = R_QSPIDMA_DST_CTRL2_RESET;
56
s->man_start_com_g = false;
57
s->gqspi_irqline = 0;
58
xlnx_zynqmp_qspips_update_ixr(s);
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
Deleted patch
1
The #defines INTERNAL and CASCADING represent different possible
2
values for the TCCR.CSS register field; prefix them with CSS_ to make
3
this more obvious, before we add more defines to represent the
4
other possible values of the field in the next commit.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210219223241.16344-2-peter.maydell@linaro.org
9
---
10
hw/timer/renesas_tmr.c | 16 ++++++++--------
11
1 file changed, 8 insertions(+), 8 deletions(-)
12
13
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/timer/renesas_tmr.c
16
+++ b/hw/timer/renesas_tmr.c
17
@@ -XXX,XX +XXX,XX @@ REG8(TCCR, 10)
18
FIELD(TCCR, CSS, 3, 2)
19
FIELD(TCCR, TMRIS, 7, 1)
20
21
-#define INTERNAL 0x01
22
-#define CASCADING 0x03
23
+#define CSS_INTERNAL 0x01
24
+#define CSS_CASCADING 0x03
25
#define CCLR_A 0x01
26
#define CCLR_B 0x02
27
28
@@ -XXX,XX +XXX,XX @@ static void update_events(RTMRState *tmr, int ch)
29
/* event not happened */
30
return ;
31
}
32
- if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CASCADING) {
33
+ if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CSS_CASCADING) {
34
/* cascading mode */
35
if (ch == 1) {
36
tmr->next[ch] = none;
37
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
38
if (delta > 0) {
39
tmr->tick = now;
40
41
- if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == INTERNAL) {
42
+ if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_INTERNAL) {
43
/* timer1 count update */
44
elapsed = elapsed_time(tmr, 1, delta);
45
if (elapsed >= 0x100) {
46
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
47
tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff);
48
}
49
switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
50
- case INTERNAL:
51
+ case CSS_INTERNAL:
52
elapsed = elapsed_time(tmr, 0, delta);
53
tcnt[0] = tmr->tcnt[0] + elapsed;
54
break;
55
- case CASCADING:
56
+ case CSS_CASCADING:
57
if (ovf > 0) {
58
tcnt[0] = tmr->tcnt[0] + ovf;
59
}
60
@@ -XXX,XX +XXX,XX @@ static uint16_t issue_event(RTMRState *tmr, int ch, int sz,
61
qemu_irq_pulse(tmr->cmia[ch]);
62
}
63
if (sz == 8 && ch == 0 &&
64
- FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CASCADING) {
65
+ FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_CASCADING) {
66
tmr->tcnt[1]++;
67
timer_events(tmr, 1);
68
}
69
@@ -XXX,XX +XXX,XX @@ static void timer_events(RTMRState *tmr, int ch)
70
uint16_t tcnt;
71
72
tmr->tcnt[ch] = read_tcnt(tmr, 1, ch);
73
- if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CASCADING) {
74
+ if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CSS_CASCADING) {
75
tmr->tcnt[ch] = issue_event(tmr, ch, 8,
76
tmr->tcnt[ch],
77
tmr->tcora[ch],
78
--
79
2.20.1
80
81
diff view generated by jsdifflib
Deleted patch
1
The read_tcnt() function calculates the TCNT register values for the
2
two channels of the timer module; it sets these up in the local
3
tcnt[] array, and eventually returns either one or both of them,
4
depending on whether the access is 8 or 16 bits. However, not all of
5
the code paths through this function set both elements of this array:
6
if the guest has programmed the TCCR.CSS register fields to values
7
which are either documented as not to be used or which QEMU does not
8
implement, then the function will return uninitialized data. (This
9
was spotted by Coverity.)
10
1
11
Add the missing CSS cases to this code, so that we return a
12
consistent value instead of uninitialized data, and so the code
13
structure indicates what's happening.
14
15
Fixes: CID 1429976
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Message-id: 20210219223241.16344-3-peter.maydell@linaro.org
19
---
20
hw/timer/renesas_tmr.c | 19 +++++++++++++++----
21
1 file changed, 15 insertions(+), 4 deletions(-)
22
23
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/timer/renesas_tmr.c
26
+++ b/hw/timer/renesas_tmr.c
27
@@ -XXX,XX +XXX,XX @@ REG8(TCCR, 10)
28
FIELD(TCCR, CSS, 3, 2)
29
FIELD(TCCR, TMRIS, 7, 1)
30
31
+#define CSS_EXTERNAL 0x00
32
#define CSS_INTERNAL 0x01
33
+#define CSS_INVALID 0x02
34
#define CSS_CASCADING 0x03
35
#define CCLR_A 0x01
36
#define CCLR_B 0x02
37
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
38
if (delta > 0) {
39
tmr->tick = now;
40
41
- if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_INTERNAL) {
42
+ switch (FIELD_EX8(tmr->tccr[1], TCCR, CSS)) {
43
+ case CSS_INTERNAL:
44
/* timer1 count update */
45
elapsed = elapsed_time(tmr, 1, delta);
46
if (elapsed >= 0x100) {
47
ovf = elapsed >> 8;
48
}
49
tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff);
50
+ break;
51
+ case CSS_INVALID: /* guest error to have set this */
52
+ case CSS_EXTERNAL: /* QEMU doesn't implement these */
53
+ case CSS_CASCADING:
54
+ tcnt[1] = tmr->tcnt[1];
55
+ break;
56
}
57
switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
58
case CSS_INTERNAL:
59
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
60
tcnt[0] = tmr->tcnt[0] + elapsed;
61
break;
62
case CSS_CASCADING:
63
- if (ovf > 0) {
64
- tcnt[0] = tmr->tcnt[0] + ovf;
65
- }
66
+ tcnt[0] = tmr->tcnt[0] + ovf;
67
+ break;
68
+ case CSS_INVALID: /* guest error to have set this */
69
+ case CSS_EXTERNAL: /* QEMU doesn't implement this */
70
+ tcnt[0] = tmr->tcnt[0];
71
break;
72
}
73
} else {
74
--
75
2.20.1
76
77
diff view generated by jsdifflib