1
Hi; some minor changes for 6.2, which I think can be classified
1
target-arm queue: mostly aspeed changes from Cédric.
2
as bug fixes and are OK for this point in the release cycle.
3
(Wouldn't be the end of the world if they slipped to 7.0.)
4
2
3
thanks
5
-- PMM
4
-- PMM
6
5
7
The following changes since commit 42f6c9179be4401974dd3a75ee72defd16b5092d:
6
The following changes since commit 85182c96de61f0b600bbe834d5a23e713162e892:
8
7
9
Merge tag 'pull-ppc-20211112' of https://github.com/legoater/qemu into staging (2021-11-12 12:28:25 +0100)
8
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20190912a' into staging (2019-09-13 14:37:48 +0100)
10
9
11
are available in the Git repository at:
10
are available in the Git repository at:
12
11
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20211115-1
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190913
14
13
15
for you to fetch changes up to 1adf528ec3bdf62ea3b580b7ad562534a3676ff5:
14
for you to fetch changes up to 27a296fce9821e3608d537756cffa6e43a46df3b:
16
15
17
hw/rtc/pl031: Send RTC_CHANGE QMP event (2021-11-15 18:53:00 +0000)
16
qemu-ga: Convert invocation documentation to rST (2019-09-13 16:05:01 +0100)
18
17
19
----------------------------------------------------------------
18
----------------------------------------------------------------
20
target-arm queue:
19
target-arm queue:
21
* Support multiple redistributor regions for TCG GICv3
20
* aspeed: add a GPIO controller to the SoC
22
* Send RTC_CHANGE QMP event from pl031
21
* aspeed: Various refactorings
22
* aspeed: Improve DMA controller modelling
23
* atomic_template: fix indentation in GEN_ATOMIC_HELPER
24
* qemu-ga: Convert invocation documentation to rST
23
25
24
----------------------------------------------------------------
26
----------------------------------------------------------------
25
Eric Auger (1):
27
Christian Svensson (1):
26
hw/rtc/pl031: Send RTC_CHANGE QMP event
28
aspeed/smc: Calculate checksum on normal DMA
27
29
28
Peter Maydell (3):
30
Cédric Le Goater (7):
29
hw/intc/arm_gicv3: Move checking of redist-region-count to arm_gicv3_common_realize
31
aspeed: Remove unused SoC definitions
30
hw/intc/arm_gicv3: Set GICR_TYPER.Last correctly when nb_redist_regions > 1
32
aspeed: Use consistent typenames
31
hw/intc/arm_gicv3: Support multiple redistributor regions
33
aspeed/smc: Add support for DMAs
34
aspeed/smc: Add DMA calibration settings
35
aspeed/smc: Inject errors in DMA checksum
36
aspeed/scu: Introduce per-SoC SCU types
37
aspeed/scu: Introduce a aspeed_scu_get_apb_freq() routine
32
38
33
include/hw/intc/arm_gicv3_common.h | 14 ++++++++--
39
Emilio G. Cota (1):
34
hw/intc/arm_gicv3.c | 12 +-------
40
atomic_template: fix indentation in GEN_ATOMIC_HELPER
35
hw/intc/arm_gicv3_common.c | 56 ++++++++++++++++++++++++--------------
36
hw/intc/arm_gicv3_kvm.c | 10 ++-----
37
hw/intc/arm_gicv3_redist.c | 40 +++++++++++++++------------
38
hw/rtc/pl031.c | 10 ++++++-
39
hw/rtc/meson.build | 2 +-
40
7 files changed, 83 insertions(+), 61 deletions(-)
41
41
42
Peter Maydell (1):
43
qemu-ga: Convert invocation documentation to rST
44
45
Rashmica Gupta (2):
46
hw/gpio: Add basic Aspeed GPIO model for AST2400 and AST2500
47
aspeed: add a GPIO controller to the SoC
48
49
Makefile | 24 +-
50
hw/gpio/Makefile.objs | 1 +
51
accel/tcg/atomic_template.h | 2 +-
52
include/hw/arm/aspeed_soc.h | 4 +-
53
include/hw/gpio/aspeed_gpio.h | 100 +++++
54
include/hw/misc/aspeed_scu.h | 21 +-
55
include/hw/ssi/aspeed_smc.h | 7 +
56
hw/arm/aspeed.c | 2 +
57
hw/arm/aspeed_soc.c | 63 ++-
58
hw/gpio/aspeed_gpio.c | 884 ++++++++++++++++++++++++++++++++++++++++++
59
hw/misc/aspeed_scu.c | 102 ++---
60
hw/ssi/aspeed_smc.c | 335 +++++++++++++++-
61
hw/timer/aspeed_timer.c | 3 +-
62
MAINTAINERS | 2 +-
63
docs/conf.py | 18 +-
64
docs/interop/conf.py | 7 +
65
docs/interop/index.rst | 1 +
66
docs/interop/qemu-ga.rst | 133 +++++++
67
qemu-doc.texi | 5 -
68
qemu-ga.texi | 137 -------
69
20 files changed, 1585 insertions(+), 266 deletions(-)
70
create mode 100644 include/hw/gpio/aspeed_gpio.h
71
create mode 100644 hw/gpio/aspeed_gpio.c
72
create mode 100644 docs/interop/qemu-ga.rst
73
delete mode 100644 qemu-ga.texi
74
diff view generated by jsdifflib
New patch
1
From: Rashmica Gupta <rashmica.g@gmail.com>
1
2
3
GPIO pins are arranged in groups of 8 pins labeled A,B,..,Y,Z,AA,AB,AC.
4
(Note that the ast2400 controller only goes up to group AB).
5
A set has four groups (except set AC which only has one) and is
6
referred to by the groups it is composed of (eg ABCD,EFGH,...,YZAAAB).
7
Each set is accessed and controlled by a bank of 14 registers.
8
9
These registers operate on a per pin level where each bit in the register
10
corresponds to a pin, except for the command source registers. The command
11
source registers operate on a per group level where bits 24, 16, 8 and 0
12
correspond to each group in the set.
13
14
eg. registers for set ABCD:
15
|D7...D0|C7...C0|B7...B0|A7...A0| <- GPIOs
16
|31...24|23...16|15....8|7.....0| <- bit position
17
18
Note that there are a couple of groups that only have 4 pins.
19
20
There are two ways that this model deviates from the behaviour of the
21
actual controller:
22
(1) The only control source driving the GPIO pins in the model is the ARM
23
model (as there currently aren't models for the LPC or Coprocessor).
24
25
(2) None of the registers in the model are reset tolerant (needs
26
integration with the watchdog).
27
28
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
29
Tested-by: Andrew Jeffery <andrew@aj.id.au>
30
Reviewed-by: Cédric Le Goater <clg@kaod.org>
31
Signed-off-by: Cédric Le Goater <clg@kaod.org>
32
Message-id: 20190904070506.1052-2-clg@kaod.org
33
[clg: fixed missing header files
34
made use of HWADDR_PRIx to fix compilation on windows ]
35
Signed-off-by: Cédric Le Goater <clg@kaod.org>
36
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
---
38
hw/gpio/Makefile.objs | 1 +
39
include/hw/gpio/aspeed_gpio.h | 100 ++++
40
hw/gpio/aspeed_gpio.c | 884 ++++++++++++++++++++++++++++++++++
41
3 files changed, 985 insertions(+)
42
create mode 100644 include/hw/gpio/aspeed_gpio.h
43
create mode 100644 hw/gpio/aspeed_gpio.c
44
45
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/gpio/Makefile.objs
48
+++ b/hw/gpio/Makefile.objs
49
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_gpio.o
50
obj-$(CONFIG_IMX) += imx_gpio.o
51
obj-$(CONFIG_RASPI) += bcm2835_gpio.o
52
obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o
53
+obj-$(CONFIG_ASPEED_SOC) += aspeed_gpio.o
54
diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h
55
new file mode 100644
56
index XXXXXXX..XXXXXXX
57
--- /dev/null
58
+++ b/include/hw/gpio/aspeed_gpio.h
59
@@ -XXX,XX +XXX,XX @@
60
+/*
61
+ * ASPEED GPIO Controller
62
+ *
63
+ * Copyright (C) 2017-2018 IBM Corp.
64
+ *
65
+ * This code is licensed under the GPL version 2 or later. See
66
+ * the COPYING file in the top-level directory.
67
+ */
68
+
69
+#ifndef ASPEED_GPIO_H
70
+#define ASPEED_GPIO_H
71
+
72
+#include "hw/sysbus.h"
73
+
74
+#define TYPE_ASPEED_GPIO "aspeed.gpio"
75
+#define ASPEED_GPIO(obj) OBJECT_CHECK(AspeedGPIOState, (obj), TYPE_ASPEED_GPIO)
76
+#define ASPEED_GPIO_CLASS(klass) \
77
+ OBJECT_CLASS_CHECK(AspeedGPIOClass, (klass), TYPE_ASPEED_GPIO)
78
+#define ASPEED_GPIO_GET_CLASS(obj) \
79
+ OBJECT_GET_CLASS(AspeedGPIOClass, (obj), TYPE_ASPEED_GPIO)
80
+
81
+#define ASPEED_GPIO_MAX_NR_SETS 8
82
+#define ASPEED_REGS_PER_BANK 14
83
+#define ASPEED_GPIO_MAX_NR_REGS (ASPEED_REGS_PER_BANK * ASPEED_GPIO_MAX_NR_SETS)
84
+#define ASPEED_GPIO_NR_PINS 228
85
+#define ASPEED_GROUPS_PER_SET 4
86
+#define ASPEED_GPIO_NR_DEBOUNCE_REGS 3
87
+#define ASPEED_CHARS_PER_GROUP_LABEL 4
88
+
89
+typedef struct GPIOSets GPIOSets;
90
+
91
+typedef struct GPIOSetProperties {
92
+ uint32_t input;
93
+ uint32_t output;
94
+ char group_label[ASPEED_GROUPS_PER_SET][ASPEED_CHARS_PER_GROUP_LABEL];
95
+} GPIOSetProperties;
96
+
97
+enum GPIORegType {
98
+ gpio_not_a_reg,
99
+ gpio_reg_data_value,
100
+ gpio_reg_direction,
101
+ gpio_reg_int_enable,
102
+ gpio_reg_int_sens_0,
103
+ gpio_reg_int_sens_1,
104
+ gpio_reg_int_sens_2,
105
+ gpio_reg_int_status,
106
+ gpio_reg_reset_tolerant,
107
+ gpio_reg_debounce_1,
108
+ gpio_reg_debounce_2,
109
+ gpio_reg_cmd_source_0,
110
+ gpio_reg_cmd_source_1,
111
+ gpio_reg_data_read,
112
+ gpio_reg_input_mask,
113
+};
114
+
115
+typedef struct AspeedGPIOReg {
116
+ uint16_t set_idx;
117
+ enum GPIORegType type;
118
+ } AspeedGPIOReg;
119
+
120
+typedef struct AspeedGPIOClass {
121
+ SysBusDevice parent_obj;
122
+ const GPIOSetProperties *props;
123
+ uint32_t nr_gpio_pins;
124
+ uint32_t nr_gpio_sets;
125
+ uint32_t gap;
126
+ const AspeedGPIOReg *reg_table;
127
+} AspeedGPIOClass;
128
+
129
+typedef struct AspeedGPIOState {
130
+ /* <private> */
131
+ SysBusDevice parent;
132
+
133
+ /*< public >*/
134
+ MemoryRegion iomem;
135
+ int pending;
136
+ qemu_irq irq;
137
+ qemu_irq gpios[ASPEED_GPIO_NR_PINS];
138
+
139
+/* Parallel GPIO Registers */
140
+ uint32_t debounce_regs[ASPEED_GPIO_NR_DEBOUNCE_REGS];
141
+ struct GPIOSets {
142
+ uint32_t data_value; /* Reflects pin values */
143
+ uint32_t data_read; /* Contains last value written to data value */
144
+ uint32_t direction;
145
+ uint32_t int_enable;
146
+ uint32_t int_sens_0;
147
+ uint32_t int_sens_1;
148
+ uint32_t int_sens_2;
149
+ uint32_t int_status;
150
+ uint32_t reset_tol;
151
+ uint32_t cmd_source_0;
152
+ uint32_t cmd_source_1;
153
+ uint32_t debounce_1;
154
+ uint32_t debounce_2;
155
+ uint32_t input_mask;
156
+ } sets[ASPEED_GPIO_MAX_NR_SETS];
157
+} AspeedGPIOState;
158
+
159
+#endif /* _ASPEED_GPIO_H_ */
160
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
161
new file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- /dev/null
164
+++ b/hw/gpio/aspeed_gpio.c
165
@@ -XXX,XX +XXX,XX @@
166
+/*
167
+ * ASPEED GPIO Controller
168
+ *
169
+ * Copyright (C) 2017-2019 IBM Corp.
170
+ *
171
+ * SPDX-License-Identifier: GPL-2.0-or-later
172
+ */
173
+
174
+#include <assert.h>
175
+
176
+#include "qemu/osdep.h"
177
+#include "qemu/host-utils.h"
178
+#include "qemu/log.h"
179
+#include "hw/gpio/aspeed_gpio.h"
180
+#include "include/hw/misc/aspeed_scu.h"
181
+#include "qapi/error.h"
182
+#include "qapi/visitor.h"
183
+#include "hw/irq.h"
184
+#include "migration/vmstate.h"
185
+
186
+#define GPIOS_PER_REG 32
187
+#define GPIOS_PER_SET GPIOS_PER_REG
188
+#define GPIO_PIN_GAP_SIZE 4
189
+#define GPIOS_PER_GROUP 8
190
+#define GPIO_GROUP_SHIFT 3
191
+
192
+/* GPIO Source Types */
193
+#define ASPEED_CMD_SRC_MASK 0x01010101
194
+#define ASPEED_SOURCE_ARM 0
195
+#define ASPEED_SOURCE_LPC 1
196
+#define ASPEED_SOURCE_COPROCESSOR 2
197
+#define ASPEED_SOURCE_RESERVED 3
198
+
199
+/* GPIO Interrupt Triggers */
200
+/*
201
+ * For each set of gpios there are three sensitivity registers that control
202
+ * the interrupt trigger mode.
203
+ *
204
+ * | 2 | 1 | 0 | trigger mode
205
+ * -----------------------------
206
+ * | 0 | 0 | 0 | falling-edge
207
+ * | 0 | 0 | 1 | rising-edge
208
+ * | 0 | 1 | 0 | level-low
209
+ * | 0 | 1 | 1 | level-high
210
+ * | 1 | X | X | dual-edge
211
+ */
212
+#define ASPEED_FALLING_EDGE 0
213
+#define ASPEED_RISING_EDGE 1
214
+#define ASPEED_LEVEL_LOW 2
215
+#define ASPEED_LEVEL_HIGH 3
216
+#define ASPEED_DUAL_EDGE 4
217
+
218
+/* GPIO Register Address Offsets */
219
+#define GPIO_ABCD_DATA_VALUE (0x000 >> 2)
220
+#define GPIO_ABCD_DIRECTION (0x004 >> 2)
221
+#define GPIO_ABCD_INT_ENABLE (0x008 >> 2)
222
+#define GPIO_ABCD_INT_SENS_0 (0x00C >> 2)
223
+#define GPIO_ABCD_INT_SENS_1 (0x010 >> 2)
224
+#define GPIO_ABCD_INT_SENS_2 (0x014 >> 2)
225
+#define GPIO_ABCD_INT_STATUS (0x018 >> 2)
226
+#define GPIO_ABCD_RESET_TOLERANT (0x01C >> 2)
227
+#define GPIO_EFGH_DATA_VALUE (0x020 >> 2)
228
+#define GPIO_EFGH_DIRECTION (0x024 >> 2)
229
+#define GPIO_EFGH_INT_ENABLE (0x028 >> 2)
230
+#define GPIO_EFGH_INT_SENS_0 (0x02C >> 2)
231
+#define GPIO_EFGH_INT_SENS_1 (0x030 >> 2)
232
+#define GPIO_EFGH_INT_SENS_2 (0x034 >> 2)
233
+#define GPIO_EFGH_INT_STATUS (0x038 >> 2)
234
+#define GPIO_EFGH_RESET_TOLERANT (0x03C >> 2)
235
+#define GPIO_ABCD_DEBOUNCE_1 (0x040 >> 2)
236
+#define GPIO_ABCD_DEBOUNCE_2 (0x044 >> 2)
237
+#define GPIO_EFGH_DEBOUNCE_1 (0x048 >> 2)
238
+#define GPIO_EFGH_DEBOUNCE_2 (0x04C >> 2)
239
+#define GPIO_DEBOUNCE_TIME_1 (0x050 >> 2)
240
+#define GPIO_DEBOUNCE_TIME_2 (0x054 >> 2)
241
+#define GPIO_DEBOUNCE_TIME_3 (0x058 >> 2)
242
+#define GPIO_ABCD_COMMAND_SRC_0 (0x060 >> 2)
243
+#define GPIO_ABCD_COMMAND_SRC_1 (0x064 >> 2)
244
+#define GPIO_EFGH_COMMAND_SRC_0 (0x068 >> 2)
245
+#define GPIO_EFGH_COMMAND_SRC_1 (0x06C >> 2)
246
+#define GPIO_IJKL_DATA_VALUE (0x070 >> 2)
247
+#define GPIO_IJKL_DIRECTION (0x074 >> 2)
248
+#define GPIO_MNOP_DATA_VALUE (0x078 >> 2)
249
+#define GPIO_MNOP_DIRECTION (0x07C >> 2)
250
+#define GPIO_QRST_DATA_VALUE (0x080 >> 2)
251
+#define GPIO_QRST_DIRECTION (0x084 >> 2)
252
+#define GPIO_UVWX_DATA_VALUE (0x088 >> 2)
253
+#define GPIO_UVWX_DIRECTION (0x08C >> 2)
254
+#define GPIO_IJKL_COMMAND_SRC_0 (0x090 >> 2)
255
+#define GPIO_IJKL_COMMAND_SRC_1 (0x094 >> 2)
256
+#define GPIO_IJKL_INT_ENABLE (0x098 >> 2)
257
+#define GPIO_IJKL_INT_SENS_0 (0x09C >> 2)
258
+#define GPIO_IJKL_INT_SENS_1 (0x0A0 >> 2)
259
+#define GPIO_IJKL_INT_SENS_2 (0x0A4 >> 2)
260
+#define GPIO_IJKL_INT_STATUS (0x0A8 >> 2)
261
+#define GPIO_IJKL_RESET_TOLERANT (0x0AC >> 2)
262
+#define GPIO_IJKL_DEBOUNCE_1 (0x0B0 >> 2)
263
+#define GPIO_IJKL_DEBOUNCE_2 (0x0B4 >> 2)
264
+#define GPIO_IJKL_INPUT_MASK (0x0B8 >> 2)
265
+#define GPIO_ABCD_DATA_READ (0x0C0 >> 2)
266
+#define GPIO_EFGH_DATA_READ (0x0C4 >> 2)
267
+#define GPIO_IJKL_DATA_READ (0x0C8 >> 2)
268
+#define GPIO_MNOP_DATA_READ (0x0CC >> 2)
269
+#define GPIO_QRST_DATA_READ (0x0D0 >> 2)
270
+#define GPIO_UVWX_DATA_READ (0x0D4 >> 2)
271
+#define GPIO_YZAAAB_DATA_READ (0x0D8 >> 2)
272
+#define GPIO_AC_DATA_READ (0x0DC >> 2)
273
+#define GPIO_MNOP_COMMAND_SRC_0 (0x0E0 >> 2)
274
+#define GPIO_MNOP_COMMAND_SRC_1 (0x0E4 >> 2)
275
+#define GPIO_MNOP_INT_ENABLE (0x0E8 >> 2)
276
+#define GPIO_MNOP_INT_SENS_0 (0x0EC >> 2)
277
+#define GPIO_MNOP_INT_SENS_1 (0x0F0 >> 2)
278
+#define GPIO_MNOP_INT_SENS_2 (0x0F4 >> 2)
279
+#define GPIO_MNOP_INT_STATUS (0x0F8 >> 2)
280
+#define GPIO_MNOP_RESET_TOLERANT (0x0FC >> 2)
281
+#define GPIO_MNOP_DEBOUNCE_1 (0x100 >> 2)
282
+#define GPIO_MNOP_DEBOUNCE_2 (0x104 >> 2)
283
+#define GPIO_MNOP_INPUT_MASK (0x108 >> 2)
284
+#define GPIO_QRST_COMMAND_SRC_0 (0x110 >> 2)
285
+#define GPIO_QRST_COMMAND_SRC_1 (0x114 >> 2)
286
+#define GPIO_QRST_INT_ENABLE (0x118 >> 2)
287
+#define GPIO_QRST_INT_SENS_0 (0x11C >> 2)
288
+#define GPIO_QRST_INT_SENS_1 (0x120 >> 2)
289
+#define GPIO_QRST_INT_SENS_2 (0x124 >> 2)
290
+#define GPIO_QRST_INT_STATUS (0x128 >> 2)
291
+#define GPIO_QRST_RESET_TOLERANT (0x12C >> 2)
292
+#define GPIO_QRST_DEBOUNCE_1 (0x130 >> 2)
293
+#define GPIO_QRST_DEBOUNCE_2 (0x134 >> 2)
294
+#define GPIO_QRST_INPUT_MASK (0x138 >> 2)
295
+#define GPIO_UVWX_COMMAND_SRC_0 (0x140 >> 2)
296
+#define GPIO_UVWX_COMMAND_SRC_1 (0x144 >> 2)
297
+#define GPIO_UVWX_INT_ENABLE (0x148 >> 2)
298
+#define GPIO_UVWX_INT_SENS_0 (0x14C >> 2)
299
+#define GPIO_UVWX_INT_SENS_1 (0x150 >> 2)
300
+#define GPIO_UVWX_INT_SENS_2 (0x154 >> 2)
301
+#define GPIO_UVWX_INT_STATUS (0x158 >> 2)
302
+#define GPIO_UVWX_RESET_TOLERANT (0x15C >> 2)
303
+#define GPIO_UVWX_DEBOUNCE_1 (0x160 >> 2)
304
+#define GPIO_UVWX_DEBOUNCE_2 (0x164 >> 2)
305
+#define GPIO_UVWX_INPUT_MASK (0x168 >> 2)
306
+#define GPIO_YZAAAB_COMMAND_SRC_0 (0x170 >> 2)
307
+#define GPIO_YZAAAB_COMMAND_SRC_1 (0x174 >> 2)
308
+#define GPIO_YZAAAB_INT_ENABLE (0x178 >> 2)
309
+#define GPIO_YZAAAB_INT_SENS_0 (0x17C >> 2)
310
+#define GPIO_YZAAAB_INT_SENS_1 (0x180 >> 2)
311
+#define GPIO_YZAAAB_INT_SENS_2 (0x184 >> 2)
312
+#define GPIO_YZAAAB_INT_STATUS (0x188 >> 2)
313
+#define GPIO_YZAAAB_RESET_TOLERANT (0x18C >> 2)
314
+#define GPIO_YZAAAB_DEBOUNCE_1 (0x190 >> 2)
315
+#define GPIO_YZAAAB_DEBOUNCE_2 (0x194 >> 2)
316
+#define GPIO_YZAAAB_INPUT_MASK (0x198 >> 2)
317
+#define GPIO_AC_COMMAND_SRC_0 (0x1A0 >> 2)
318
+#define GPIO_AC_COMMAND_SRC_1 (0x1A4 >> 2)
319
+#define GPIO_AC_INT_ENABLE (0x1A8 >> 2)
320
+#define GPIO_AC_INT_SENS_0 (0x1AC >> 2)
321
+#define GPIO_AC_INT_SENS_1 (0x1B0 >> 2)
322
+#define GPIO_AC_INT_SENS_2 (0x1B4 >> 2)
323
+#define GPIO_AC_INT_STATUS (0x1B8 >> 2)
324
+#define GPIO_AC_RESET_TOLERANT (0x1BC >> 2)
325
+#define GPIO_AC_DEBOUNCE_1 (0x1C0 >> 2)
326
+#define GPIO_AC_DEBOUNCE_2 (0x1C4 >> 2)
327
+#define GPIO_AC_INPUT_MASK (0x1C8 >> 2)
328
+#define GPIO_ABCD_INPUT_MASK (0x1D0 >> 2)
329
+#define GPIO_EFGH_INPUT_MASK (0x1D4 >> 2)
330
+#define GPIO_YZAAAB_DATA_VALUE (0x1E0 >> 2)
331
+#define GPIO_YZAAAB_DIRECTION (0x1E4 >> 2)
332
+#define GPIO_AC_DATA_VALUE (0x1E8 >> 2)
333
+#define GPIO_AC_DIRECTION (0x1EC >> 2)
334
+#define GPIO_3_6V_MEM_SIZE 0x1F0
335
+#define GPIO_3_6V_REG_ARRAY_SIZE (GPIO_3_6V_MEM_SIZE >> 2)
336
+
337
+static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio)
338
+{
339
+ uint32_t falling_edge = 0, rising_edge = 0;
340
+ uint32_t int_trigger = extract32(regs->int_sens_0, gpio, 1)
341
+ | extract32(regs->int_sens_1, gpio, 1) << 1
342
+ | extract32(regs->int_sens_2, gpio, 1) << 2;
343
+ uint32_t gpio_curr_high = extract32(regs->data_value, gpio, 1);
344
+ uint32_t gpio_int_enabled = extract32(regs->int_enable, gpio, 1);
345
+
346
+ if (!gpio_int_enabled) {
347
+ return 0;
348
+ }
349
+
350
+ /* Detect edges */
351
+ if (gpio_curr_high && !gpio_prev_high) {
352
+ rising_edge = 1;
353
+ } else if (!gpio_curr_high && gpio_prev_high) {
354
+ falling_edge = 1;
355
+ }
356
+
357
+ if (((int_trigger == ASPEED_FALLING_EDGE) && falling_edge) ||
358
+ ((int_trigger == ASPEED_RISING_EDGE) && rising_edge) ||
359
+ ((int_trigger == ASPEED_LEVEL_LOW) && !gpio_curr_high) ||
360
+ ((int_trigger == ASPEED_LEVEL_HIGH) && gpio_curr_high) ||
361
+ ((int_trigger >= ASPEED_DUAL_EDGE) && (rising_edge || falling_edge)))
362
+ {
363
+ regs->int_status = deposit32(regs->int_status, gpio, 1, 1);
364
+ return 1;
365
+ }
366
+ return 0;
367
+}
368
+
369
+#define nested_struct_index(ta, pa, m, tb, pb) \
370
+ (pb - ((tb *)(((char *)pa) + offsetof(ta, m))))
371
+
372
+static ptrdiff_t aspeed_gpio_set_idx(AspeedGPIOState *s, GPIOSets *regs)
373
+{
374
+ return nested_struct_index(AspeedGPIOState, s, sets, GPIOSets, regs);
375
+}
376
+
377
+static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
378
+ uint32_t value)
379
+{
380
+ uint32_t input_mask = regs->input_mask;
381
+ uint32_t direction = regs->direction;
382
+ uint32_t old = regs->data_value;
383
+ uint32_t new = value;
384
+ uint32_t diff;
385
+ int gpio;
386
+
387
+ diff = old ^ new;
388
+ if (diff) {
389
+ for (gpio = 0; gpio < GPIOS_PER_REG; gpio++) {
390
+ uint32_t mask = 1 << gpio;
391
+
392
+ /* If the gpio needs to be updated... */
393
+ if (!(diff & mask)) {
394
+ continue;
395
+ }
396
+
397
+ /* ...and we're output or not input-masked... */
398
+ if (!(direction & mask) && (input_mask & mask)) {
399
+ continue;
400
+ }
401
+
402
+ /* ...then update the state. */
403
+ if (mask & new) {
404
+ regs->data_value |= mask;
405
+ } else {
406
+ regs->data_value &= ~mask;
407
+ }
408
+
409
+ /* If the gpio is set to output... */
410
+ if (direction & mask) {
411
+ /* ...trigger the line-state IRQ */
412
+ ptrdiff_t set = aspeed_gpio_set_idx(s, regs);
413
+ size_t offset = set * GPIOS_PER_SET + gpio;
414
+ qemu_set_irq(s->gpios[offset], !!(new & mask));
415
+ } else {
416
+ /* ...otherwise if we meet the line's current IRQ policy... */
417
+ if (aspeed_evaluate_irq(regs, old & mask, gpio)) {
418
+ /* ...trigger the VIC IRQ */
419
+ s->pending++;
420
+ }
421
+ }
422
+ }
423
+ }
424
+ qemu_set_irq(s->irq, !!(s->pending));
425
+}
426
+
427
+static uint32_t aspeed_adjust_pin(AspeedGPIOState *s, uint32_t pin)
428
+{
429
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
430
+ /*
431
+ * The 2500 has a 4 pin gap in group AB and the 2400 has a 4 pin
432
+ * gap in group Y (and only four pins in AB but this is the last group so
433
+ * it doesn't matter).
434
+ */
435
+ if (agc->gap && pin >= agc->gap) {
436
+ pin += GPIO_PIN_GAP_SIZE;
437
+ }
438
+
439
+ return pin;
440
+}
441
+
442
+static bool aspeed_gpio_get_pin_level(AspeedGPIOState *s, uint32_t set_idx,
443
+ uint32_t pin)
444
+{
445
+ uint32_t reg_val;
446
+ uint32_t pin_mask = 1 << pin;
447
+
448
+ reg_val = s->sets[set_idx].data_value;
449
+
450
+ return !!(reg_val & pin_mask);
451
+}
452
+
453
+static void aspeed_gpio_set_pin_level(AspeedGPIOState *s, uint32_t set_idx,
454
+ uint32_t pin, bool level)
455
+{
456
+ uint32_t value = s->sets[set_idx].data_value;
457
+ uint32_t pin_mask = 1 << pin;
458
+
459
+ if (level) {
460
+ value |= pin_mask;
461
+ } else {
462
+ value &= !pin_mask;
463
+ }
464
+
465
+ aspeed_gpio_update(s, &s->sets[set_idx], value);
466
+}
467
+
468
+/*
469
+ * | src_1 | src_2 | source |
470
+ * |-----------------------------|
471
+ * | 0 | 0 | ARM |
472
+ * | 0 | 1 | LPC |
473
+ * | 1 | 0 | Coprocessor|
474
+ * | 1 | 1 | Reserved |
475
+ *
476
+ * Once the source of a set is programmed, corresponding bits in the
477
+ * data_value, direction, interrupt [enable, sens[0-2]], reset_tol and
478
+ * debounce registers can only be written by the source.
479
+ *
480
+ * Source is ARM by default
481
+ * only bits 24, 16, 8, and 0 can be set
482
+ *
483
+ * we don't currently have a model for the LPC or Coprocessor
484
+ */
485
+static uint32_t update_value_control_source(GPIOSets *regs, uint32_t old_value,
486
+ uint32_t value)
487
+{
488
+ int i;
489
+ int cmd_source;
490
+
491
+ /* assume the source is always ARM for now */
492
+ int source = ASPEED_SOURCE_ARM;
493
+
494
+ uint32_t new_value = 0;
495
+
496
+ /* for each group in set */
497
+ for (i = 0; i < GPIOS_PER_REG; i += GPIOS_PER_GROUP) {
498
+ cmd_source = extract32(regs->cmd_source_0, i, 1)
499
+ | (extract32(regs->cmd_source_1, i, 1) << 1);
500
+
501
+ if (source == cmd_source) {
502
+ new_value |= (0xff << i) & value;
503
+ } else {
504
+ new_value |= (0xff << i) & old_value;
505
+ }
506
+ }
507
+ return new_value;
508
+}
509
+
510
+static const AspeedGPIOReg aspeed_3_6v_gpios[GPIO_3_6V_REG_ARRAY_SIZE] = {
511
+ /* Set ABCD */
512
+ [GPIO_ABCD_DATA_VALUE] = { 0, gpio_reg_data_value },
513
+ [GPIO_ABCD_DIRECTION] = { 0, gpio_reg_direction },
514
+ [GPIO_ABCD_INT_ENABLE] = { 0, gpio_reg_int_enable },
515
+ [GPIO_ABCD_INT_SENS_0] = { 0, gpio_reg_int_sens_0 },
516
+ [GPIO_ABCD_INT_SENS_1] = { 0, gpio_reg_int_sens_1 },
517
+ [GPIO_ABCD_INT_SENS_2] = { 0, gpio_reg_int_sens_2 },
518
+ [GPIO_ABCD_INT_STATUS] = { 0, gpio_reg_int_status },
519
+ [GPIO_ABCD_RESET_TOLERANT] = { 0, gpio_reg_reset_tolerant },
520
+ [GPIO_ABCD_DEBOUNCE_1] = { 0, gpio_reg_debounce_1 },
521
+ [GPIO_ABCD_DEBOUNCE_2] = { 0, gpio_reg_debounce_2 },
522
+ [GPIO_ABCD_COMMAND_SRC_0] = { 0, gpio_reg_cmd_source_0 },
523
+ [GPIO_ABCD_COMMAND_SRC_1] = { 0, gpio_reg_cmd_source_1 },
524
+ [GPIO_ABCD_DATA_READ] = { 0, gpio_reg_data_read },
525
+ [GPIO_ABCD_INPUT_MASK] = { 0, gpio_reg_input_mask },
526
+ /* Set EFGH */
527
+ [GPIO_EFGH_DATA_VALUE] = { 1, gpio_reg_data_value },
528
+ [GPIO_EFGH_DIRECTION] = { 1, gpio_reg_direction },
529
+ [GPIO_EFGH_INT_ENABLE] = { 1, gpio_reg_int_enable },
530
+ [GPIO_EFGH_INT_SENS_0] = { 1, gpio_reg_int_sens_0 },
531
+ [GPIO_EFGH_INT_SENS_1] = { 1, gpio_reg_int_sens_1 },
532
+ [GPIO_EFGH_INT_SENS_2] = { 1, gpio_reg_int_sens_2 },
533
+ [GPIO_EFGH_INT_STATUS] = { 1, gpio_reg_int_status },
534
+ [GPIO_EFGH_RESET_TOLERANT] = { 1, gpio_reg_reset_tolerant },
535
+ [GPIO_EFGH_DEBOUNCE_1] = { 1, gpio_reg_debounce_1 },
536
+ [GPIO_EFGH_DEBOUNCE_2] = { 1, gpio_reg_debounce_2 },
537
+ [GPIO_EFGH_COMMAND_SRC_0] = { 1, gpio_reg_cmd_source_0 },
538
+ [GPIO_EFGH_COMMAND_SRC_1] = { 1, gpio_reg_cmd_source_1 },
539
+ [GPIO_EFGH_DATA_READ] = { 1, gpio_reg_data_read },
540
+ [GPIO_EFGH_INPUT_MASK] = { 1, gpio_reg_input_mask },
541
+ /* Set IJKL */
542
+ [GPIO_IJKL_DATA_VALUE] = { 2, gpio_reg_data_value },
543
+ [GPIO_IJKL_DIRECTION] = { 2, gpio_reg_direction },
544
+ [GPIO_IJKL_INT_ENABLE] = { 2, gpio_reg_int_enable },
545
+ [GPIO_IJKL_INT_SENS_0] = { 2, gpio_reg_int_sens_0 },
546
+ [GPIO_IJKL_INT_SENS_1] = { 2, gpio_reg_int_sens_1 },
547
+ [GPIO_IJKL_INT_SENS_2] = { 2, gpio_reg_int_sens_2 },
548
+ [GPIO_IJKL_INT_STATUS] = { 2, gpio_reg_int_status },
549
+ [GPIO_IJKL_RESET_TOLERANT] = { 2, gpio_reg_reset_tolerant },
550
+ [GPIO_IJKL_DEBOUNCE_1] = { 2, gpio_reg_debounce_1 },
551
+ [GPIO_IJKL_DEBOUNCE_2] = { 2, gpio_reg_debounce_2 },
552
+ [GPIO_IJKL_COMMAND_SRC_0] = { 2, gpio_reg_cmd_source_0 },
553
+ [GPIO_IJKL_COMMAND_SRC_1] = { 2, gpio_reg_cmd_source_1 },
554
+ [GPIO_IJKL_DATA_READ] = { 2, gpio_reg_data_read },
555
+ [GPIO_IJKL_INPUT_MASK] = { 2, gpio_reg_input_mask },
556
+ /* Set MNOP */
557
+ [GPIO_MNOP_DATA_VALUE] = { 3, gpio_reg_data_value },
558
+ [GPIO_MNOP_DIRECTION] = { 3, gpio_reg_direction },
559
+ [GPIO_MNOP_INT_ENABLE] = { 3, gpio_reg_int_enable },
560
+ [GPIO_MNOP_INT_SENS_0] = { 3, gpio_reg_int_sens_0 },
561
+ [GPIO_MNOP_INT_SENS_1] = { 3, gpio_reg_int_sens_1 },
562
+ [GPIO_MNOP_INT_SENS_2] = { 3, gpio_reg_int_sens_2 },
563
+ [GPIO_MNOP_INT_STATUS] = { 3, gpio_reg_int_status },
564
+ [GPIO_MNOP_RESET_TOLERANT] = { 3, gpio_reg_reset_tolerant },
565
+ [GPIO_MNOP_DEBOUNCE_1] = { 3, gpio_reg_debounce_1 },
566
+ [GPIO_MNOP_DEBOUNCE_2] = { 3, gpio_reg_debounce_2 },
567
+ [GPIO_MNOP_COMMAND_SRC_0] = { 3, gpio_reg_cmd_source_0 },
568
+ [GPIO_MNOP_COMMAND_SRC_1] = { 3, gpio_reg_cmd_source_1 },
569
+ [GPIO_MNOP_DATA_READ] = { 3, gpio_reg_data_read },
570
+ [GPIO_MNOP_INPUT_MASK] = { 3, gpio_reg_input_mask },
571
+ /* Set QRST */
572
+ [GPIO_QRST_DATA_VALUE] = { 4, gpio_reg_data_value },
573
+ [GPIO_QRST_DIRECTION] = { 4, gpio_reg_direction },
574
+ [GPIO_QRST_INT_ENABLE] = { 4, gpio_reg_int_enable },
575
+ [GPIO_QRST_INT_SENS_0] = { 4, gpio_reg_int_sens_0 },
576
+ [GPIO_QRST_INT_SENS_1] = { 4, gpio_reg_int_sens_1 },
577
+ [GPIO_QRST_INT_SENS_2] = { 4, gpio_reg_int_sens_2 },
578
+ [GPIO_QRST_INT_STATUS] = { 4, gpio_reg_int_status },
579
+ [GPIO_QRST_RESET_TOLERANT] = { 4, gpio_reg_reset_tolerant },
580
+ [GPIO_QRST_DEBOUNCE_1] = { 4, gpio_reg_debounce_1 },
581
+ [GPIO_QRST_DEBOUNCE_2] = { 4, gpio_reg_debounce_2 },
582
+ [GPIO_QRST_COMMAND_SRC_0] = { 4, gpio_reg_cmd_source_0 },
583
+ [GPIO_QRST_COMMAND_SRC_1] = { 4, gpio_reg_cmd_source_1 },
584
+ [GPIO_QRST_DATA_READ] = { 4, gpio_reg_data_read },
585
+ [GPIO_QRST_INPUT_MASK] = { 4, gpio_reg_input_mask },
586
+ /* Set UVWX */
587
+ [GPIO_UVWX_DATA_VALUE] = { 5, gpio_reg_data_value },
588
+ [GPIO_UVWX_DIRECTION] = { 5, gpio_reg_direction },
589
+ [GPIO_UVWX_INT_ENABLE] = { 5, gpio_reg_int_enable },
590
+ [GPIO_UVWX_INT_SENS_0] = { 5, gpio_reg_int_sens_0 },
591
+ [GPIO_UVWX_INT_SENS_1] = { 5, gpio_reg_int_sens_1 },
592
+ [GPIO_UVWX_INT_SENS_2] = { 5, gpio_reg_int_sens_2 },
593
+ [GPIO_UVWX_INT_STATUS] = { 5, gpio_reg_int_status },
594
+ [GPIO_UVWX_RESET_TOLERANT] = { 5, gpio_reg_reset_tolerant },
595
+ [GPIO_UVWX_DEBOUNCE_1] = { 5, gpio_reg_debounce_1 },
596
+ [GPIO_UVWX_DEBOUNCE_2] = { 5, gpio_reg_debounce_2 },
597
+ [GPIO_UVWX_COMMAND_SRC_0] = { 5, gpio_reg_cmd_source_0 },
598
+ [GPIO_UVWX_COMMAND_SRC_1] = { 5, gpio_reg_cmd_source_1 },
599
+ [GPIO_UVWX_DATA_READ] = { 5, gpio_reg_data_read },
600
+ [GPIO_UVWX_INPUT_MASK] = { 5, gpio_reg_input_mask },
601
+ /* Set YZAAAB */
602
+ [GPIO_YZAAAB_DATA_VALUE] = { 6, gpio_reg_data_value },
603
+ [GPIO_YZAAAB_DIRECTION] = { 6, gpio_reg_direction },
604
+ [GPIO_YZAAAB_INT_ENABLE] = { 6, gpio_reg_int_enable },
605
+ [GPIO_YZAAAB_INT_SENS_0] = { 6, gpio_reg_int_sens_0 },
606
+ [GPIO_YZAAAB_INT_SENS_1] = { 6, gpio_reg_int_sens_1 },
607
+ [GPIO_YZAAAB_INT_SENS_2] = { 6, gpio_reg_int_sens_2 },
608
+ [GPIO_YZAAAB_INT_STATUS] = { 6, gpio_reg_int_status },
609
+ [GPIO_YZAAAB_RESET_TOLERANT] = { 6, gpio_reg_reset_tolerant },
610
+ [GPIO_YZAAAB_DEBOUNCE_1] = { 6, gpio_reg_debounce_1 },
611
+ [GPIO_YZAAAB_DEBOUNCE_2] = { 6, gpio_reg_debounce_2 },
612
+ [GPIO_YZAAAB_COMMAND_SRC_0] = { 6, gpio_reg_cmd_source_0 },
613
+ [GPIO_YZAAAB_COMMAND_SRC_1] = { 6, gpio_reg_cmd_source_1 },
614
+ [GPIO_YZAAAB_DATA_READ] = { 6, gpio_reg_data_read },
615
+ [GPIO_YZAAAB_INPUT_MASK] = { 6, gpio_reg_input_mask },
616
+ /* Set AC (ast2500 only) */
617
+ [GPIO_AC_DATA_VALUE] = { 7, gpio_reg_data_value },
618
+ [GPIO_AC_DIRECTION] = { 7, gpio_reg_direction },
619
+ [GPIO_AC_INT_ENABLE] = { 7, gpio_reg_int_enable },
620
+ [GPIO_AC_INT_SENS_0] = { 7, gpio_reg_int_sens_0 },
621
+ [GPIO_AC_INT_SENS_1] = { 7, gpio_reg_int_sens_1 },
622
+ [GPIO_AC_INT_SENS_2] = { 7, gpio_reg_int_sens_2 },
623
+ [GPIO_AC_INT_STATUS] = { 7, gpio_reg_int_status },
624
+ [GPIO_AC_RESET_TOLERANT] = { 7, gpio_reg_reset_tolerant },
625
+ [GPIO_AC_DEBOUNCE_1] = { 7, gpio_reg_debounce_1 },
626
+ [GPIO_AC_DEBOUNCE_2] = { 7, gpio_reg_debounce_2 },
627
+ [GPIO_AC_COMMAND_SRC_0] = { 7, gpio_reg_cmd_source_0 },
628
+ [GPIO_AC_COMMAND_SRC_1] = { 7, gpio_reg_cmd_source_1 },
629
+ [GPIO_AC_DATA_READ] = { 7, gpio_reg_data_read },
630
+ [GPIO_AC_INPUT_MASK] = { 7, gpio_reg_input_mask },
631
+};
632
+
633
+static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size)
634
+{
635
+ AspeedGPIOState *s = ASPEED_GPIO(opaque);
636
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
637
+ uint64_t idx = -1;
638
+ const AspeedGPIOReg *reg;
639
+ GPIOSets *set;
640
+
641
+ idx = offset >> 2;
642
+ if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) {
643
+ idx -= GPIO_DEBOUNCE_TIME_1;
644
+ return (uint64_t) s->debounce_regs[idx];
645
+ }
646
+
647
+ reg = &agc->reg_table[idx];
648
+ if (reg->set_idx >= agc->nr_gpio_sets) {
649
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
650
+ HWADDR_PRIx"\n", __func__, offset);
651
+ return 0;
652
+ }
653
+
654
+ set = &s->sets[reg->set_idx];
655
+ switch (reg->type) {
656
+ case gpio_reg_data_value:
657
+ return set->data_value;
658
+ case gpio_reg_direction:
659
+ return set->direction;
660
+ case gpio_reg_int_enable:
661
+ return set->int_enable;
662
+ case gpio_reg_int_sens_0:
663
+ return set->int_sens_0;
664
+ case gpio_reg_int_sens_1:
665
+ return set->int_sens_1;
666
+ case gpio_reg_int_sens_2:
667
+ return set->int_sens_2;
668
+ case gpio_reg_int_status:
669
+ return set->int_status;
670
+ case gpio_reg_reset_tolerant:
671
+ return set->reset_tol;
672
+ case gpio_reg_debounce_1:
673
+ return set->debounce_1;
674
+ case gpio_reg_debounce_2:
675
+ return set->debounce_2;
676
+ case gpio_reg_cmd_source_0:
677
+ return set->cmd_source_0;
678
+ case gpio_reg_cmd_source_1:
679
+ return set->cmd_source_1;
680
+ case gpio_reg_data_read:
681
+ return set->data_read;
682
+ case gpio_reg_input_mask:
683
+ return set->input_mask;
684
+ default:
685
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
686
+ HWADDR_PRIx"\n", __func__, offset);
687
+ return 0;
688
+ };
689
+}
690
+
691
+static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data,
692
+ uint32_t size)
693
+{
694
+ AspeedGPIOState *s = ASPEED_GPIO(opaque);
695
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
696
+ const GPIOSetProperties *props;
697
+ uint64_t idx = -1;
698
+ const AspeedGPIOReg *reg;
699
+ GPIOSets *set;
700
+ uint32_t cleared;
701
+
702
+ idx = offset >> 2;
703
+ if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) {
704
+ idx -= GPIO_DEBOUNCE_TIME_1;
705
+ s->debounce_regs[idx] = (uint32_t) data;
706
+ return;
707
+ }
708
+
709
+ reg = &agc->reg_table[idx];
710
+ if (reg->set_idx >= agc->nr_gpio_sets) {
711
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
712
+ HWADDR_PRIx"\n", __func__, offset);
713
+ return;
714
+ }
715
+
716
+ set = &s->sets[reg->set_idx];
717
+ props = &agc->props[reg->set_idx];
718
+
719
+ switch (reg->type) {
720
+ case gpio_reg_data_value:
721
+ data &= props->output;
722
+ data = update_value_control_source(set, set->data_value, data);
723
+ set->data_read = data;
724
+ aspeed_gpio_update(s, set, data);
725
+ return;
726
+ case gpio_reg_direction:
727
+ /*
728
+ * where data is the value attempted to be written to the pin:
729
+ * pin type | input mask | output mask | expected value
730
+ * ------------------------------------------------------------
731
+ * bidirectional | 1 | 1 | data
732
+ * input only | 1 | 0 | 0
733
+ * output only | 0 | 1 | 1
734
+ * no pin / gap | 0 | 0 | 0
735
+ *
736
+ * which is captured by:
737
+ * data = ( data | ~input) & output;
738
+ */
739
+ data = (data | ~props->input) & props->output;
740
+ set->direction = update_value_control_source(set, set->direction, data);
741
+ break;
742
+ case gpio_reg_int_enable:
743
+ set->int_enable = update_value_control_source(set, set->int_enable,
744
+ data);
745
+ break;
746
+ case gpio_reg_int_sens_0:
747
+ set->int_sens_0 = update_value_control_source(set, set->int_sens_0,
748
+ data);
749
+ break;
750
+ case gpio_reg_int_sens_1:
751
+ set->int_sens_1 = update_value_control_source(set, set->int_sens_1,
752
+ data);
753
+ break;
754
+ case gpio_reg_int_sens_2:
755
+ set->int_sens_2 = update_value_control_source(set, set->int_sens_2,
756
+ data);
757
+ break;
758
+ case gpio_reg_int_status:
759
+ cleared = ctpop32(data & set->int_status);
760
+ if (s->pending && cleared) {
761
+ assert(s->pending >= cleared);
762
+ s->pending -= cleared;
763
+ }
764
+ set->int_status &= ~data;
765
+ break;
766
+ case gpio_reg_reset_tolerant:
767
+ set->reset_tol = update_value_control_source(set, set->reset_tol,
768
+ data);
769
+ return;
770
+ case gpio_reg_debounce_1:
771
+ set->debounce_1 = update_value_control_source(set, set->debounce_1,
772
+ data);
773
+ return;
774
+ case gpio_reg_debounce_2:
775
+ set->debounce_2 = update_value_control_source(set, set->debounce_2,
776
+ data);
777
+ return;
778
+ case gpio_reg_cmd_source_0:
779
+ set->cmd_source_0 = data & ASPEED_CMD_SRC_MASK;
780
+ return;
781
+ case gpio_reg_cmd_source_1:
782
+ set->cmd_source_1 = data & ASPEED_CMD_SRC_MASK;
783
+ return;
784
+ case gpio_reg_data_read:
785
+ /* Read only register */
786
+ return;
787
+ case gpio_reg_input_mask:
788
+ /*
789
+ * feeds into interrupt generation
790
+ * 0: read from data value reg will be updated
791
+ * 1: read from data value reg will not be updated
792
+ */
793
+ set->input_mask = data & props->input;
794
+ break;
795
+ default:
796
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
797
+ HWADDR_PRIx"\n", __func__, offset);
798
+ return;
799
+ }
800
+ aspeed_gpio_update(s, set, set->data_value);
801
+ return;
802
+}
803
+
804
+static int get_set_idx(AspeedGPIOState *s, const char *group, int *group_idx)
805
+{
806
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
807
+ int set_idx, g_idx = *group_idx;
808
+
809
+ for (set_idx = 0; set_idx < agc->nr_gpio_sets; set_idx++) {
810
+ const GPIOSetProperties *set_props = &agc->props[set_idx];
811
+ for (g_idx = 0; g_idx < ASPEED_GROUPS_PER_SET; g_idx++) {
812
+ if (!strncmp(group, set_props->group_label[g_idx], strlen(group))) {
813
+ *group_idx = g_idx;
814
+ return set_idx;
815
+ }
816
+ }
817
+ }
818
+ return -1;
819
+}
820
+
821
+static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name,
822
+ void *opaque, Error **errp)
823
+{
824
+ int pin = 0xfff;
825
+ bool level = true;
826
+ char group[3];
827
+ AspeedGPIOState *s = ASPEED_GPIO(obj);
828
+ int set_idx, group_idx = 0;
829
+
830
+ if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
831
+ error_setg(errp, "%s: error reading %s", __func__, name);
832
+ return;
833
+ }
834
+ set_idx = get_set_idx(s, group, &group_idx);
835
+ if (set_idx == -1) {
836
+ error_setg(errp, "%s: invalid group %s", __func__, group);
837
+ return;
838
+ }
839
+ pin = pin + group_idx * GPIOS_PER_GROUP;
840
+ level = aspeed_gpio_get_pin_level(s, set_idx, pin);
841
+ visit_type_bool(v, name, &level, errp);
842
+}
843
+
844
+static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
845
+ void *opaque, Error **errp)
846
+{
847
+ Error *local_err = NULL;
848
+ bool level;
849
+ int pin = 0xfff;
850
+ char group[3];
851
+ AspeedGPIOState *s = ASPEED_GPIO(obj);
852
+ int set_idx, group_idx = 0;
853
+
854
+ visit_type_bool(v, name, &level, &local_err);
855
+ if (local_err) {
856
+ error_propagate(errp, local_err);
857
+ return;
858
+ }
859
+ if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
860
+ error_setg(errp, "%s: error reading %s", __func__, name);
861
+ return;
862
+ }
863
+ set_idx = get_set_idx(s, group, &group_idx);
864
+ if (set_idx == -1) {
865
+ error_setg(errp, "%s: invalid group %s", __func__, group);
866
+ return;
867
+ }
868
+ pin = pin + group_idx * GPIOS_PER_GROUP;
869
+ aspeed_gpio_set_pin_level(s, set_idx, pin, level);
870
+}
871
+
872
+/****************** Setup functions ******************/
873
+static const GPIOSetProperties ast2400_set_props[] = {
874
+ [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} },
875
+ [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} },
876
+ [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} },
877
+ [3] = {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} },
878
+ [4] = {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} },
879
+ [5] = {0xffffffff, 0x0000ffff, {"U", "V", "W", "X"} },
880
+ [6] = {0x0000000f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} },
881
+};
882
+
883
+static const GPIOSetProperties ast2500_set_props[] = {
884
+ [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} },
885
+ [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} },
886
+ [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} },
887
+ [3] = {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} },
888
+ [4] = {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} },
889
+ [5] = {0xffffffff, 0x0000ffff, {"U", "V", "W", "X"} },
890
+ [6] = {0xffffff0f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} },
891
+ [7] = {0x000000ff, 0x000000ff, {"AC"} },
892
+};
893
+
894
+static const MemoryRegionOps aspeed_gpio_ops = {
895
+ .read = aspeed_gpio_read,
896
+ .write = aspeed_gpio_write,
897
+ .endianness = DEVICE_LITTLE_ENDIAN,
898
+ .valid.min_access_size = 4,
899
+ .valid.max_access_size = 4,
900
+};
901
+
902
+static void aspeed_gpio_reset(DeviceState *dev)
903
+{
904
+ AspeedGPIOState *s = ASPEED_GPIO(dev);
905
+
906
+ /* TODO: respect the reset tolerance registers */
907
+ memset(s->sets, 0, sizeof(s->sets));
908
+}
909
+
910
+static void aspeed_gpio_realize(DeviceState *dev, Error **errp)
911
+{
912
+ AspeedGPIOState *s = ASPEED_GPIO(dev);
913
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
914
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
915
+ int pin;
916
+
917
+ /* Interrupt parent line */
918
+ sysbus_init_irq(sbd, &s->irq);
919
+
920
+ /* Individual GPIOs */
921
+ for (pin = 0; pin < agc->nr_gpio_pins; pin++) {
922
+ sysbus_init_irq(sbd, &s->gpios[pin]);
923
+ }
924
+
925
+ memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s,
926
+ TYPE_ASPEED_GPIO, GPIO_3_6V_MEM_SIZE);
927
+
928
+ sysbus_init_mmio(sbd, &s->iomem);
929
+}
930
+
931
+static void aspeed_gpio_init(Object *obj)
932
+{
933
+ AspeedGPIOState *s = ASPEED_GPIO(obj);
934
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
935
+ int pin;
936
+
937
+ for (pin = 0; pin < agc->nr_gpio_pins; pin++) {
938
+ char *name;
939
+ int set_idx = pin / GPIOS_PER_SET;
940
+ int pin_idx = aspeed_adjust_pin(s, pin) - (set_idx * GPIOS_PER_SET);
941
+ int group_idx = pin_idx >> GPIO_GROUP_SHIFT;
942
+ const GPIOSetProperties *props = &agc->props[set_idx];
943
+
944
+ name = g_strdup_printf("gpio%s%d", props->group_label[group_idx],
945
+ pin_idx % GPIOS_PER_GROUP);
946
+ object_property_add(obj, name, "bool", aspeed_gpio_get_pin,
947
+ aspeed_gpio_set_pin, NULL, NULL, NULL);
948
+ }
949
+}
950
+
951
+static const VMStateDescription vmstate_gpio_regs = {
952
+ .name = TYPE_ASPEED_GPIO"/regs",
953
+ .version_id = 1,
954
+ .minimum_version_id = 1,
955
+ .fields = (VMStateField[]) {
956
+ VMSTATE_UINT32(data_value, GPIOSets),
957
+ VMSTATE_UINT32(data_read, GPIOSets),
958
+ VMSTATE_UINT32(direction, GPIOSets),
959
+ VMSTATE_UINT32(int_enable, GPIOSets),
960
+ VMSTATE_UINT32(int_sens_0, GPIOSets),
961
+ VMSTATE_UINT32(int_sens_1, GPIOSets),
962
+ VMSTATE_UINT32(int_sens_2, GPIOSets),
963
+ VMSTATE_UINT32(int_status, GPIOSets),
964
+ VMSTATE_UINT32(reset_tol, GPIOSets),
965
+ VMSTATE_UINT32(cmd_source_0, GPIOSets),
966
+ VMSTATE_UINT32(cmd_source_1, GPIOSets),
967
+ VMSTATE_UINT32(debounce_1, GPIOSets),
968
+ VMSTATE_UINT32(debounce_2, GPIOSets),
969
+ VMSTATE_UINT32(input_mask, GPIOSets),
970
+ VMSTATE_END_OF_LIST(),
971
+ }
972
+};
973
+
974
+static const VMStateDescription vmstate_aspeed_gpio = {
975
+ .name = TYPE_ASPEED_GPIO,
976
+ .version_id = 1,
977
+ .minimum_version_id = 1,
978
+ .fields = (VMStateField[]) {
979
+ VMSTATE_STRUCT_ARRAY(sets, AspeedGPIOState, ASPEED_GPIO_MAX_NR_SETS,
980
+ 1, vmstate_gpio_regs, GPIOSets),
981
+ VMSTATE_UINT32_ARRAY(debounce_regs, AspeedGPIOState,
982
+ ASPEED_GPIO_NR_DEBOUNCE_REGS),
983
+ VMSTATE_END_OF_LIST(),
984
+ }
985
+};
986
+
987
+static void aspeed_gpio_class_init(ObjectClass *klass, void *data)
988
+{
989
+ DeviceClass *dc = DEVICE_CLASS(klass);
990
+
991
+ dc->realize = aspeed_gpio_realize;
992
+ dc->reset = aspeed_gpio_reset;
993
+ dc->desc = "Aspeed GPIO Controller";
994
+ dc->vmsd = &vmstate_aspeed_gpio;
995
+}
996
+
997
+static void aspeed_gpio_ast2400_class_init(ObjectClass *klass, void *data)
998
+{
999
+ AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
1000
+
1001
+ agc->props = ast2400_set_props;
1002
+ agc->nr_gpio_pins = 216;
1003
+ agc->nr_gpio_sets = 7;
1004
+ agc->gap = 196;
1005
+ agc->reg_table = aspeed_3_6v_gpios;
1006
+}
1007
+
1008
+static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data)
1009
+{
1010
+ AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
1011
+
1012
+ agc->props = ast2500_set_props;
1013
+ agc->nr_gpio_pins = 228;
1014
+ agc->nr_gpio_sets = 8;
1015
+ agc->gap = 220;
1016
+ agc->reg_table = aspeed_3_6v_gpios;
1017
+}
1018
+
1019
+static const TypeInfo aspeed_gpio_info = {
1020
+ .name = TYPE_ASPEED_GPIO,
1021
+ .parent = TYPE_SYS_BUS_DEVICE,
1022
+ .instance_size = sizeof(AspeedGPIOState),
1023
+ .class_size = sizeof(AspeedGPIOClass),
1024
+ .class_init = aspeed_gpio_class_init,
1025
+ .abstract = true,
1026
+};
1027
+
1028
+static const TypeInfo aspeed_gpio_ast2400_info = {
1029
+ .name = TYPE_ASPEED_GPIO "-ast2400",
1030
+ .parent = TYPE_ASPEED_GPIO,
1031
+ .class_init = aspeed_gpio_ast2400_class_init,
1032
+ .instance_init = aspeed_gpio_init,
1033
+};
1034
+
1035
+static const TypeInfo aspeed_gpio_ast2500_info = {
1036
+ .name = TYPE_ASPEED_GPIO "-ast2500",
1037
+ .parent = TYPE_ASPEED_GPIO,
1038
+ .class_init = aspeed_gpio_2500_class_init,
1039
+ .instance_init = aspeed_gpio_init,
1040
+};
1041
+
1042
+static void aspeed_gpio_register_types(void)
1043
+{
1044
+ type_register_static(&aspeed_gpio_info);
1045
+ type_register_static(&aspeed_gpio_ast2400_info);
1046
+ type_register_static(&aspeed_gpio_ast2500_info);
1047
+}
1048
+
1049
+type_init(aspeed_gpio_register_types);
1050
--
1051
2.20.1
1052
1053
diff view generated by jsdifflib
New patch
1
From: Rashmica Gupta <rashmica.g@gmail.com>
1
2
3
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
4
Reviewed-by: Cédric Le Goater <clg@kaod.org>
5
Signed-off-by: Cédric Le Goater <clg@kaod.org>
6
Message-id: 20190904070506.1052-3-clg@kaod.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
include/hw/arm/aspeed_soc.h | 3 +++
10
hw/arm/aspeed_soc.c | 17 +++++++++++++++++
11
2 files changed, 20 insertions(+)
12
13
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/aspeed_soc.h
16
+++ b/include/hw/arm/aspeed_soc.h
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/watchdog/wdt_aspeed.h"
19
#include "hw/net/ftgmac100.h"
20
#include "target/arm/cpu.h"
21
+#include "hw/gpio/aspeed_gpio.h"
22
23
#define ASPEED_SPIS_NUM 2
24
#define ASPEED_WDTS_NUM 3
25
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
26
AspeedSDMCState sdmc;
27
AspeedWDTState wdt[ASPEED_WDTS_NUM];
28
FTGMAC100State ftgmac100[ASPEED_MACS_NUM];
29
+ AspeedGPIOState gpio;
30
} AspeedSoCState;
31
32
#define TYPE_ASPEED_SOC "aspeed-soc"
33
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCInfo {
34
int spis_num;
35
const char *fmc_typename;
36
const char **spi_typename;
37
+ const char *gpio_typename;
38
int wdts_num;
39
const int *irqmap;
40
const hwaddr *memmap;
41
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/aspeed_soc.c
44
+++ b/hw/arm/aspeed_soc.c
45
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
46
.spis_num = 1,
47
.fmc_typename = "aspeed.smc.fmc",
48
.spi_typename = aspeed_soc_ast2400_typenames,
49
+ .gpio_typename = "aspeed.gpio-ast2400",
50
.wdts_num = 2,
51
.irqmap = aspeed_soc_ast2400_irqmap,
52
.memmap = aspeed_soc_ast2400_memmap,
53
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
54
.spis_num = 1,
55
.fmc_typename = "aspeed.smc.fmc",
56
.spi_typename = aspeed_soc_ast2400_typenames,
57
+ .gpio_typename = "aspeed.gpio-ast2400",
58
.wdts_num = 2,
59
.irqmap = aspeed_soc_ast2400_irqmap,
60
.memmap = aspeed_soc_ast2400_memmap,
61
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
62
.spis_num = 1,
63
.fmc_typename = "aspeed.smc.fmc",
64
.spi_typename = aspeed_soc_ast2400_typenames,
65
+ .gpio_typename = "aspeed.gpio-ast2400",
66
.wdts_num = 2,
67
.irqmap = aspeed_soc_ast2400_irqmap,
68
.memmap = aspeed_soc_ast2400_memmap,
69
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
70
.spis_num = 2,
71
.fmc_typename = "aspeed.smc.ast2500-fmc",
72
.spi_typename = aspeed_soc_ast2500_typenames,
73
+ .gpio_typename = "aspeed.gpio-ast2500",
74
.wdts_num = 3,
75
.irqmap = aspeed_soc_ast2500_irqmap,
76
.memmap = aspeed_soc_ast2500_memmap,
77
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
78
79
sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma),
80
TYPE_ASPEED_XDMA);
81
+
82
+ sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio),
83
+ sc->info->gpio_typename);
84
}
85
86
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
87
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
88
sc->info->memmap[ASPEED_XDMA]);
89
sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0,
90
aspeed_soc_get_irq(s, ASPEED_XDMA));
91
+
92
+ /* GPIO */
93
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
94
+ if (err) {
95
+ error_propagate(errp, err);
96
+ return;
97
+ }
98
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->info->memmap[ASPEED_GPIO]);
99
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
100
+ aspeed_soc_get_irq(s, ASPEED_GPIO));
101
}
102
static Property aspeed_soc_properties[] = {
103
DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0),
104
--
105
2.20.1
106
107
diff view generated by jsdifflib
New patch
1
From: Cédric Le Goater <clg@kaod.org>
1
2
3
There are no QEMU Aspeed machines using the SoCs "ast2400-a0" or
4
"ast2400".
5
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
7
Message-id: 20190904070506.1052-4-clg@kaod.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/aspeed_soc.c | 26 --------------------------
12
1 file changed, 26 deletions(-)
13
14
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/aspeed_soc.c
17
+++ b/hw/arm/aspeed_soc.c
18
@@ -XXX,XX +XXX,XX @@ static const char *aspeed_soc_ast2500_typenames[] = {
19
20
static const AspeedSoCInfo aspeed_socs[] = {
21
{
22
- .name = "ast2400-a0",
23
- .cpu_type = ARM_CPU_TYPE_NAME("arm926"),
24
- .silicon_rev = AST2400_A0_SILICON_REV,
25
- .sram_size = 0x8000,
26
- .spis_num = 1,
27
- .fmc_typename = "aspeed.smc.fmc",
28
- .spi_typename = aspeed_soc_ast2400_typenames,
29
- .gpio_typename = "aspeed.gpio-ast2400",
30
- .wdts_num = 2,
31
- .irqmap = aspeed_soc_ast2400_irqmap,
32
- .memmap = aspeed_soc_ast2400_memmap,
33
- .num_cpus = 1,
34
- }, {
35
.name = "ast2400-a1",
36
.cpu_type = ARM_CPU_TYPE_NAME("arm926"),
37
.silicon_rev = AST2400_A1_SILICON_REV,
38
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
39
.irqmap = aspeed_soc_ast2400_irqmap,
40
.memmap = aspeed_soc_ast2400_memmap,
41
.num_cpus = 1,
42
- }, {
43
- .name = "ast2400",
44
- .cpu_type = ARM_CPU_TYPE_NAME("arm926"),
45
- .silicon_rev = AST2400_A0_SILICON_REV,
46
- .sram_size = 0x8000,
47
- .spis_num = 1,
48
- .fmc_typename = "aspeed.smc.fmc",
49
- .spi_typename = aspeed_soc_ast2400_typenames,
50
- .gpio_typename = "aspeed.gpio-ast2400",
51
- .wdts_num = 2,
52
- .irqmap = aspeed_soc_ast2400_irqmap,
53
- .memmap = aspeed_soc_ast2400_memmap,
54
- .num_cpus = 1,
55
}, {
56
.name = "ast2500-a1",
57
.cpu_type = ARM_CPU_TYPE_NAME("arm1176"),
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
New patch
1
From: Cédric Le Goater <clg@kaod.org>
1
2
3
Improve the naming of the different controller models to ease their
4
generation when initializing the SoC. The rename of the SMC types is
5
breaking migration compatibility.
6
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Message-id: 20190904070506.1052-5-clg@kaod.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/aspeed_soc.h | 3 ---
13
hw/arm/aspeed_soc.c | 25 ++++++++++++-------------
14
hw/ssi/aspeed_smc.c | 12 ++++++------
15
3 files changed, 18 insertions(+), 22 deletions(-)
16
17
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/aspeed_soc.h
20
+++ b/include/hw/arm/aspeed_soc.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCInfo {
22
uint32_t silicon_rev;
23
uint64_t sram_size;
24
int spis_num;
25
- const char *fmc_typename;
26
- const char **spi_typename;
27
- const char *gpio_typename;
28
int wdts_num;
29
const int *irqmap;
30
const hwaddr *memmap;
31
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/aspeed_soc.c
34
+++ b/hw/arm/aspeed_soc.c
35
@@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2400_irqmap[] = {
36
37
#define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap
38
39
-static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" };
40
-static const char *aspeed_soc_ast2500_typenames[] = {
41
- "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
42
-
43
static const AspeedSoCInfo aspeed_socs[] = {
44
{
45
.name = "ast2400-a1",
46
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
47
.silicon_rev = AST2400_A1_SILICON_REV,
48
.sram_size = 0x8000,
49
.spis_num = 1,
50
- .fmc_typename = "aspeed.smc.fmc",
51
- .spi_typename = aspeed_soc_ast2400_typenames,
52
- .gpio_typename = "aspeed.gpio-ast2400",
53
.wdts_num = 2,
54
.irqmap = aspeed_soc_ast2400_irqmap,
55
.memmap = aspeed_soc_ast2400_memmap,
56
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
57
.silicon_rev = AST2500_A1_SILICON_REV,
58
.sram_size = 0x9000,
59
.spis_num = 2,
60
- .fmc_typename = "aspeed.smc.ast2500-fmc",
61
- .spi_typename = aspeed_soc_ast2500_typenames,
62
- .gpio_typename = "aspeed.gpio-ast2500",
63
.wdts_num = 3,
64
.irqmap = aspeed_soc_ast2500_irqmap,
65
.memmap = aspeed_soc_ast2500_memmap,
66
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
67
AspeedSoCState *s = ASPEED_SOC(obj);
68
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
69
int i;
70
+ char socname[8];
71
+ char typename[64];
72
+
73
+ if (sscanf(sc->info->name, "%7s", socname) != 1) {
74
+ g_assert_not_reached();
75
+ }
76
77
for (i = 0; i < sc->info->num_cpus; i++) {
78
object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]),
79
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
80
sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c),
81
TYPE_ASPEED_I2C);
82
83
+ snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
84
sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc),
85
- sc->info->fmc_typename);
86
+ typename);
87
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
88
&error_abort);
89
90
for (i = 0; i < sc->info->spis_num; i++) {
91
+ snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
92
sysbus_init_child_obj(obj, "spi[*]", OBJECT(&s->spi[i]),
93
- sizeof(s->spi[i]), sc->info->spi_typename[i]);
94
+ sizeof(s->spi[i]), typename);
95
}
96
97
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
98
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
99
sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma),
100
TYPE_ASPEED_XDMA);
101
102
+ snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
103
sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio),
104
- sc->info->gpio_typename);
105
+ typename);
106
}
107
108
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
109
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/hw/ssi/aspeed_smc.c
112
+++ b/hw/ssi/aspeed_smc.c
113
@@ -XXX,XX +XXX,XX @@ static const AspeedSegments aspeed_segments_ast2500_spi2[] = {
114
115
static const AspeedSMCController controllers[] = {
116
{
117
- .name = "aspeed.smc.smc",
118
+ .name = "aspeed.smc-ast2400",
119
.r_conf = R_CONF,
120
.r_ce_ctrl = R_CE_CTRL,
121
.r_ctrl0 = R_CTRL0,
122
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
123
.has_dma = false,
124
.nregs = ASPEED_SMC_R_SMC_MAX,
125
}, {
126
- .name = "aspeed.smc.fmc",
127
+ .name = "aspeed.fmc-ast2400",
128
.r_conf = R_CONF,
129
.r_ce_ctrl = R_CE_CTRL,
130
.r_ctrl0 = R_CTRL0,
131
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
132
.has_dma = true,
133
.nregs = ASPEED_SMC_R_MAX,
134
}, {
135
- .name = "aspeed.smc.spi",
136
+ .name = "aspeed.spi1-ast2400",
137
.r_conf = R_SPI_CONF,
138
.r_ce_ctrl = 0xff,
139
.r_ctrl0 = R_SPI_CTRL0,
140
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
141
.has_dma = false,
142
.nregs = ASPEED_SMC_R_SPI_MAX,
143
}, {
144
- .name = "aspeed.smc.ast2500-fmc",
145
+ .name = "aspeed.fmc-ast2500",
146
.r_conf = R_CONF,
147
.r_ce_ctrl = R_CE_CTRL,
148
.r_ctrl0 = R_CTRL0,
149
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
150
.has_dma = true,
151
.nregs = ASPEED_SMC_R_MAX,
152
}, {
153
- .name = "aspeed.smc.ast2500-spi1",
154
+ .name = "aspeed.spi1-ast2500",
155
.r_conf = R_CONF,
156
.r_ce_ctrl = R_CE_CTRL,
157
.r_ctrl0 = R_CTRL0,
158
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
159
.has_dma = false,
160
.nregs = ASPEED_SMC_R_MAX,
161
}, {
162
- .name = "aspeed.smc.ast2500-spi2",
163
+ .name = "aspeed.spi2-ast2500",
164
.r_conf = R_CONF,
165
.r_ce_ctrl = R_CE_CTRL,
166
.r_ctrl0 = R_CTRL0,
167
--
168
2.20.1
169
170
diff view generated by jsdifflib
New patch
1
1
From: Cédric Le Goater <clg@kaod.org>
2
3
The FMC controller on the Aspeed SoCs support DMA to access the flash
4
modules. It can operate in a normal mode, to copy to or from the flash
5
module mapping window, or in a checksum calculation mode, to evaluate
6
the best clock settings for reads.
7
8
The model introduces two custom address spaces for DMAs: one for the
9
AHB window of the FMC flash devices and one for the DRAM. The latter
10
is populated using a "dram" link set from the machine with the RAM
11
container region.
12
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Acked-by: Joel Stanley <joel@jms.id.au>
15
Message-id: 20190904070506.1052-6-clg@kaod.org
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
include/hw/ssi/aspeed_smc.h | 6 +
20
hw/arm/aspeed.c | 2 +
21
hw/arm/aspeed_soc.c | 2 +
22
hw/ssi/aspeed_smc.c | 222 +++++++++++++++++++++++++++++++++++-
23
4 files changed, 226 insertions(+), 6 deletions(-)
24
25
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/ssi/aspeed_smc.h
28
+++ b/include/hw/ssi/aspeed_smc.h
29
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCController {
30
hwaddr flash_window_base;
31
uint32_t flash_window_size;
32
bool has_dma;
33
+ hwaddr dma_flash_mask;
34
+ hwaddr dma_dram_mask;
35
uint32_t nregs;
36
} AspeedSMCController;
37
38
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCState {
39
/* for DMA support */
40
uint64_t sdram_base;
41
42
+ AddressSpace flash_as;
43
+ MemoryRegion *dram_mr;
44
+ AddressSpace dram_as;
45
+
46
AspeedSMCFlash *flashes;
47
48
uint8_t snoop_index;
49
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/aspeed.c
52
+++ b/hw/arm/aspeed.c
53
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
54
&error_abort);
55
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
56
&error_abort);
57
+ object_property_set_link(OBJECT(&bmc->soc), OBJECT(&bmc->ram_container),
58
+ "dram", &error_abort);
59
if (machine->kernel_filename) {
60
/*
61
* When booting with a -kernel command line there is no u-boot
62
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/hw/arm/aspeed_soc.c
65
+++ b/hw/arm/aspeed_soc.c
66
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
67
typename);
68
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
69
&error_abort);
70
+ object_property_add_alias(obj, "dram", OBJECT(&s->fmc), "dram",
71
+ &error_abort);
72
73
for (i = 0; i < sc->info->spis_num; i++) {
74
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
75
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/ssi/aspeed_smc.c
78
+++ b/hw/ssi/aspeed_smc.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "qemu/log.h"
81
#include "qemu/module.h"
82
#include "qemu/error-report.h"
83
+#include "qapi/error.h"
84
+#include "exec/address-spaces.h"
85
86
#include "hw/irq.h"
87
#include "hw/qdev-properties.h"
88
@@ -XXX,XX +XXX,XX @@
89
#define DMA_CTRL_FREQ_SHIFT 4
90
#define DMA_CTRL_MODE (1 << 3)
91
#define DMA_CTRL_CKSUM (1 << 2)
92
-#define DMA_CTRL_DIR (1 << 1)
93
-#define DMA_CTRL_EN (1 << 0)
94
+#define DMA_CTRL_WRITE (1 << 1)
95
+#define DMA_CTRL_ENABLE (1 << 0)
96
97
/* DMA Flash Side Address */
98
#define R_DMA_FLASH_ADDR (0x84 / 4)
99
@@ -XXX,XX +XXX,XX @@
100
#define ASPEED_SOC_SPI_FLASH_BASE 0x30000000
101
#define ASPEED_SOC_SPI2_FLASH_BASE 0x38000000
102
103
+/*
104
+ * DMA DRAM addresses should be 4 bytes aligned and the valid address
105
+ * range is 0x40000000 - 0x5FFFFFFF (AST2400)
106
+ * 0x80000000 - 0xBFFFFFFF (AST2500)
107
+ *
108
+ * DMA flash addresses should be 4 bytes aligned and the valid address
109
+ * range is 0x20000000 - 0x2FFFFFFF.
110
+ *
111
+ * DMA length is from 4 bytes to 32MB
112
+ * 0: 4 bytes
113
+ * 0x7FFFFF: 32M bytes
114
+ */
115
+#define DMA_DRAM_ADDR(s, val) ((s)->sdram_base | \
116
+ ((val) & (s)->ctrl->dma_dram_mask))
117
+#define DMA_FLASH_ADDR(s, val) ((s)->ctrl->flash_window_base | \
118
+ ((val) & (s)->ctrl->dma_flash_mask))
119
+#define DMA_LENGTH(val) ((val) & 0x01FFFFFC)
120
+
121
/* Flash opcodes. */
122
#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
123
124
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
125
.flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
126
.flash_window_size = 0x10000000,
127
.has_dma = true,
128
+ .dma_flash_mask = 0x0FFFFFFC,
129
+ .dma_dram_mask = 0x1FFFFFFC,
130
.nregs = ASPEED_SMC_R_MAX,
131
}, {
132
.name = "aspeed.spi1-ast2400",
133
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
134
.flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
135
.flash_window_size = 0x10000000,
136
.has_dma = true,
137
+ .dma_flash_mask = 0x0FFFFFFC,
138
+ .dma_dram_mask = 0x3FFFFFFC,
139
.nregs = ASPEED_SMC_R_MAX,
140
}, {
141
.name = "aspeed.spi1-ast2500",
142
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_reset(DeviceState *d)
143
144
memset(s->regs, 0, sizeof s->regs);
145
146
- /* Pretend DMA is done (u-boot initialization) */
147
- s->regs[R_INTR_CTRL] = INTR_CTRL_DMA_STATUS;
148
-
149
/* Unselect all slaves */
150
for (i = 0; i < s->num_cs; ++i) {
151
s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
152
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
153
addr == s->r_ce_ctrl ||
154
addr == R_INTR_CTRL ||
155
addr == R_DUMMY_DATA ||
156
+ (s->ctrl->has_dma && addr == R_DMA_CTRL) ||
157
+ (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) ||
158
+ (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) ||
159
+ (s->ctrl->has_dma && addr == R_DMA_LEN) ||
160
+ (s->ctrl->has_dma && addr == R_DMA_CHECKSUM) ||
161
(addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
162
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) {
163
return s->regs[addr];
164
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
165
}
166
}
167
168
+/*
169
+ * Accumulate the result of the reads to provide a checksum that will
170
+ * be used to validate the read timing settings.
171
+ */
172
+static void aspeed_smc_dma_checksum(AspeedSMCState *s)
173
+{
174
+ MemTxResult result;
175
+ uint32_t data;
176
+
177
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
178
+ qemu_log_mask(LOG_GUEST_ERROR,
179
+ "%s: invalid direction for DMA checksum\n", __func__);
180
+ return;
181
+ }
182
+
183
+ while (s->regs[R_DMA_LEN]) {
184
+ data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
185
+ MEMTXATTRS_UNSPECIFIED, &result);
186
+ if (result != MEMTX_OK) {
187
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash read failed @%08x\n",
188
+ __func__, s->regs[R_DMA_FLASH_ADDR]);
189
+ return;
190
+ }
191
+
192
+ /*
193
+ * When the DMA is on-going, the DMA registers are updated
194
+ * with the current working addresses and length.
195
+ */
196
+ s->regs[R_DMA_CHECKSUM] += data;
197
+ s->regs[R_DMA_FLASH_ADDR] += 4;
198
+ s->regs[R_DMA_LEN] -= 4;
199
+ }
200
+}
201
+
202
+static void aspeed_smc_dma_rw(AspeedSMCState *s)
203
+{
204
+ MemTxResult result;
205
+ uint32_t data;
206
+
207
+ while (s->regs[R_DMA_LEN]) {
208
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
209
+ data = address_space_ldl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
210
+ MEMTXATTRS_UNSPECIFIED, &result);
211
+ if (result != MEMTX_OK) {
212
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM read failed @%08x\n",
213
+ __func__, s->regs[R_DMA_DRAM_ADDR]);
214
+ return;
215
+ }
216
+
217
+ address_space_stl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
218
+ data, MEMTXATTRS_UNSPECIFIED, &result);
219
+ if (result != MEMTX_OK) {
220
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash write failed @%08x\n",
221
+ __func__, s->regs[R_DMA_FLASH_ADDR]);
222
+ return;
223
+ }
224
+ } else {
225
+ data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
226
+ MEMTXATTRS_UNSPECIFIED, &result);
227
+ if (result != MEMTX_OK) {
228
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash read failed @%08x\n",
229
+ __func__, s->regs[R_DMA_FLASH_ADDR]);
230
+ return;
231
+ }
232
+
233
+ address_space_stl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
234
+ data, MEMTXATTRS_UNSPECIFIED, &result);
235
+ if (result != MEMTX_OK) {
236
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM write failed @%08x\n",
237
+ __func__, s->regs[R_DMA_DRAM_ADDR]);
238
+ return;
239
+ }
240
+ }
241
+
242
+ /*
243
+ * When the DMA is on-going, the DMA registers are updated
244
+ * with the current working addresses and length.
245
+ */
246
+ s->regs[R_DMA_FLASH_ADDR] += 4;
247
+ s->regs[R_DMA_DRAM_ADDR] += 4;
248
+ s->regs[R_DMA_LEN] -= 4;
249
+ }
250
+}
251
+
252
+static void aspeed_smc_dma_stop(AspeedSMCState *s)
253
+{
254
+ /*
255
+ * When the DMA is disabled, INTR_CTRL_DMA_STATUS=0 means the
256
+ * engine is idle
257
+ */
258
+ s->regs[R_INTR_CTRL] &= ~INTR_CTRL_DMA_STATUS;
259
+ s->regs[R_DMA_CHECKSUM] = 0;
260
+
261
+ /*
262
+ * Lower the DMA irq in any case. The IRQ control register could
263
+ * have been cleared before disabling the DMA.
264
+ */
265
+ qemu_irq_lower(s->irq);
266
+}
267
+
268
+/*
269
+ * When INTR_CTRL_DMA_STATUS=1, the DMA has completed and a new DMA
270
+ * can start even if the result of the previous was not collected.
271
+ */
272
+static bool aspeed_smc_dma_in_progress(AspeedSMCState *s)
273
+{
274
+ return s->regs[R_DMA_CTRL] & DMA_CTRL_ENABLE &&
275
+ !(s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_STATUS);
276
+}
277
+
278
+static void aspeed_smc_dma_done(AspeedSMCState *s)
279
+{
280
+ s->regs[R_INTR_CTRL] |= INTR_CTRL_DMA_STATUS;
281
+ if (s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_EN) {
282
+ qemu_irq_raise(s->irq);
283
+ }
284
+}
285
+
286
+static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint64_t dma_ctrl)
287
+{
288
+ if (!(dma_ctrl & DMA_CTRL_ENABLE)) {
289
+ s->regs[R_DMA_CTRL] = dma_ctrl;
290
+
291
+ aspeed_smc_dma_stop(s);
292
+ return;
293
+ }
294
+
295
+ if (aspeed_smc_dma_in_progress(s)) {
296
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA in progress\n", __func__);
297
+ return;
298
+ }
299
+
300
+ s->regs[R_DMA_CTRL] = dma_ctrl;
301
+
302
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_CKSUM) {
303
+ aspeed_smc_dma_checksum(s);
304
+ } else {
305
+ aspeed_smc_dma_rw(s);
306
+ }
307
+
308
+ aspeed_smc_dma_done(s);
309
+}
310
+
311
static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
312
unsigned int size)
313
{
314
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
315
}
316
} else if (addr == R_DUMMY_DATA) {
317
s->regs[addr] = value & 0xff;
318
+ } else if (addr == R_INTR_CTRL) {
319
+ s->regs[addr] = value;
320
+ } else if (s->ctrl->has_dma && addr == R_DMA_CTRL) {
321
+ aspeed_smc_dma_ctrl(s, value);
322
+ } else if (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) {
323
+ s->regs[addr] = DMA_DRAM_ADDR(s, value);
324
+ } else if (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) {
325
+ s->regs[addr] = DMA_FLASH_ADDR(s, value);
326
+ } else if (s->ctrl->has_dma && addr == R_DMA_LEN) {
327
+ s->regs[addr] = DMA_LENGTH(value);
328
} else {
329
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
330
__func__, addr);
331
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_smc_ops = {
332
.valid.unaligned = true,
333
};
334
335
+
336
+/*
337
+ * Initialize the custom address spaces for DMAs
338
+ */
339
+static void aspeed_smc_dma_setup(AspeedSMCState *s, Error **errp)
340
+{
341
+ char *name;
342
+
343
+ if (!s->dram_mr) {
344
+ error_setg(errp, TYPE_ASPEED_SMC ": 'dram' link not set");
345
+ return;
346
+ }
347
+
348
+ name = g_strdup_printf("%s-dma-flash", s->ctrl->name);
349
+ address_space_init(&s->flash_as, &s->mmio_flash, name);
350
+ g_free(name);
351
+
352
+ name = g_strdup_printf("%s-dma-dram", s->ctrl->name);
353
+ address_space_init(&s->dram_as, s->dram_mr, name);
354
+ g_free(name);
355
+}
356
+
357
static void aspeed_smc_realize(DeviceState *dev, Error **errp)
358
{
359
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
360
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
361
s->num_cs = s->ctrl->max_slaves;
362
}
363
364
+ /* DMA irq. Keep it first for the initialization in the SoC */
365
+ sysbus_init_irq(sbd, &s->irq);
366
+
367
s->spi = ssi_create_bus(dev, "spi");
368
369
/* Setup cs_lines for slaves */
370
- sysbus_init_irq(sbd, &s->irq);
371
s->cs_lines = g_new0(qemu_irq, s->num_cs);
372
ssi_auto_connect_slaves(dev, s->cs_lines, s->spi);
373
374
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
375
memory_region_add_subregion(&s->mmio_flash, offset, &fl->mmio);
376
offset += fl->size;
377
}
378
+
379
+ /* DMA support */
380
+ if (s->ctrl->has_dma) {
381
+ aspeed_smc_dma_setup(s, errp);
382
+ }
383
}
384
385
static const VMStateDescription vmstate_aspeed_smc = {
386
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_smc = {
387
static Property aspeed_smc_properties[] = {
388
DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
389
DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0),
390
+ DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr,
391
+ TYPE_MEMORY_REGION, MemoryRegion *),
392
DEFINE_PROP_END_OF_LIST(),
393
};
394
395
--
396
2.20.1
397
398
diff view generated by jsdifflib
1
The GICv3 devices have an array property redist-region-count.
1
From: Cédric Le Goater <clg@kaod.org>
2
Currently we check this for errors (bad values) in
3
gicv3_init_irqs_and_mmio(), just before we use it. Move this error
4
checking to the arm_gicv3_common_realize() function, where we
5
sanity-check all of the other base-class properties. (This will
6
always be before gicv3_init_irqs_and_mmio() is called, because
7
that function is called in the subclass realize methods, after
8
they have called the parent-class realize.)
9
2
10
The motivation for this refactor is:
3
When doing calibration, the SPI clock rate in the CE0 Control Register
11
* we would like to use the redist_region_count[] values in
4
and the read delay cycles in the Read Timing Compensation Register are
12
arm_gicv3_common_realize() in a subsequent patch, so we need
5
set using bit[11:4] of the DMA Control Register.
13
to have already done the sanity-checking first
14
* this removes the only use of the Error** argument to
15
gicv3_init_irqs_and_mmio(), so we can remove some error-handling
16
boilerplate
17
6
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Acked-by: Joel Stanley <joel@jms.id.au>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20190904070506.1052-7-clg@kaod.org
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
---
12
---
21
include/hw/intc/arm_gicv3_common.h | 2 +-
13
hw/ssi/aspeed_smc.c | 64 ++++++++++++++++++++++++++++++++++++++++++++-
22
hw/intc/arm_gicv3.c | 6 +-----
14
1 file changed, 63 insertions(+), 1 deletion(-)
23
hw/intc/arm_gicv3_common.c | 26 +++++++++++++-------------
24
hw/intc/arm_gicv3_kvm.c | 6 +-----
25
4 files changed, 16 insertions(+), 24 deletions(-)
26
15
27
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
16
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/intc/arm_gicv3_common.h
18
--- a/hw/ssi/aspeed_smc.c
30
+++ b/include/hw/intc/arm_gicv3_common.h
19
+++ b/hw/ssi/aspeed_smc.c
31
@@ -XXX,XX +XXX,XX @@ struct ARMGICv3CommonClass {
20
@@ -XXX,XX +XXX,XX @@
32
};
21
#define CTRL_CMD_MASK 0xff
33
22
#define CTRL_DUMMY_HIGH_SHIFT 14
34
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
23
#define CTRL_AST2400_SPI_4BYTE (1 << 13)
35
- const MemoryRegionOps *ops, Error **errp);
24
+#define CE_CTRL_CLOCK_FREQ_SHIFT 8
36
+ const MemoryRegionOps *ops);
25
+#define CE_CTRL_CLOCK_FREQ_MASK 0xf
37
26
+#define CE_CTRL_CLOCK_FREQ(div) \
38
#endif
27
+ (((div) & CE_CTRL_CLOCK_FREQ_MASK) << CE_CTRL_CLOCK_FREQ_SHIFT)
39
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
28
#define CTRL_DUMMY_LOW_SHIFT 6 /* 2 bits [7:6] */
40
index XXXXXXX..XXXXXXX 100644
29
#define CTRL_CE_STOP_ACTIVE (1 << 2)
41
--- a/hw/intc/arm_gicv3.c
30
#define CTRL_CMD_MODE_MASK 0x3
42
+++ b/hw/intc/arm_gicv3.c
31
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
32
#define DMA_CTRL_DELAY_SHIFT 8
33
#define DMA_CTRL_FREQ_MASK 0xf
34
#define DMA_CTRL_FREQ_SHIFT 4
35
-#define DMA_CTRL_MODE (1 << 3)
36
+#define DMA_CTRL_CALIB (1 << 3)
37
#define DMA_CTRL_CKSUM (1 << 2)
38
#define DMA_CTRL_WRITE (1 << 1)
39
#define DMA_CTRL_ENABLE (1 << 0)
40
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
41
}
42
}
43
44
+static uint8_t aspeed_smc_hclk_divisor(uint8_t hclk_mask)
45
+{
46
+ /* HCLK/1 .. HCLK/16 */
47
+ const uint8_t hclk_divisors[] = {
48
+ 15, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0
49
+ };
50
+ int i;
51
+
52
+ for (i = 0; i < ARRAY_SIZE(hclk_divisors); i++) {
53
+ if (hclk_mask == hclk_divisors[i]) {
54
+ return i + 1;
55
+ }
56
+ }
57
+
58
+ qemu_log_mask(LOG_GUEST_ERROR, "invalid HCLK mask %x", hclk_mask);
59
+ return 0;
60
+}
61
+
62
+/*
63
+ * When doing calibration, the SPI clock rate in the CE0 Control
64
+ * Register and the read delay cycles in the Read Timing Compensation
65
+ * Register are set using bit[11:4] of the DMA Control Register.
66
+ */
67
+static void aspeed_smc_dma_calibration(AspeedSMCState *s)
68
+{
69
+ uint8_t delay =
70
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_DELAY_SHIFT) & DMA_CTRL_DELAY_MASK;
71
+ uint8_t hclk_mask =
72
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_FREQ_SHIFT) & DMA_CTRL_FREQ_MASK;
73
+ uint8_t hclk_div = aspeed_smc_hclk_divisor(hclk_mask);
74
+ uint32_t hclk_shift = (hclk_div - 1) << 2;
75
+ uint8_t cs;
76
+
77
+ /*
78
+ * The Read Timing Compensation Register values apply to all CS on
79
+ * the SPI bus and only HCLK/1 - HCLK/5 can have tunable delays
80
+ */
81
+ if (hclk_div && hclk_div < 6) {
82
+ s->regs[s->r_timings] &= ~(0xf << hclk_shift);
83
+ s->regs[s->r_timings] |= delay << hclk_shift;
84
+ }
85
+
86
+ /*
87
+ * TODO: compute the CS from the DMA address and the segment
88
+ * registers. This is not really a problem for now because the
89
+ * Timing Register values apply to all CS and software uses CS0 to
90
+ * do calibration.
91
+ */
92
+ cs = 0;
93
+ s->regs[s->r_ctrl0 + cs] &=
94
+ ~(CE_CTRL_CLOCK_FREQ_MASK << CE_CTRL_CLOCK_FREQ_SHIFT);
95
+ s->regs[s->r_ctrl0 + cs] |= CE_CTRL_CLOCK_FREQ(hclk_div);
96
+}
97
+
98
/*
99
* Accumulate the result of the reads to provide a checksum that will
100
* be used to validate the read timing settings.
101
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
44
return;
102
return;
45
}
103
}
46
104
47
- gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops, &local_err);
105
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_CALIB) {
48
- if (local_err) {
106
+ aspeed_smc_dma_calibration(s);
49
- error_propagate(errp, local_err);
50
- return;
51
- }
52
+ gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops);
53
54
gicv3_init_cpuif(s);
55
}
56
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/intc/arm_gicv3_common.c
59
+++ b/hw/intc/arm_gicv3_common.c
60
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3 = {
61
};
62
63
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
64
- const MemoryRegionOps *ops, Error **errp)
65
+ const MemoryRegionOps *ops)
66
{
67
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
68
- int rdist_capacity = 0;
69
int i;
70
71
- for (i = 0; i < s->nb_redist_regions; i++) {
72
- rdist_capacity += s->redist_region_count[i];
73
- }
74
- if (rdist_capacity < s->num_cpu) {
75
- error_setg(errp, "Capacity of the redist regions(%d) "
76
- "is less than number of vcpus(%d)",
77
- rdist_capacity, s->num_cpu);
78
- return;
79
- }
80
-
81
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
82
* GPIO array layout is thus:
83
* [0..N-1] spi
84
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
85
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
86
{
87
GICv3State *s = ARM_GICV3_COMMON(dev);
88
- int i;
89
+ int i, rdist_capacity;
90
91
/* revision property is actually reserved and currently used only in order
92
* to keep the interface compatible with GICv2 code, avoiding extra
93
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
94
return;
95
}
96
97
+ rdist_capacity = 0;
98
+ for (i = 0; i < s->nb_redist_regions; i++) {
99
+ rdist_capacity += s->redist_region_count[i];
100
+ }
101
+ if (rdist_capacity < s->num_cpu) {
102
+ error_setg(errp, "Capacity of the redist regions(%d) "
103
+ "is less than number of vcpus(%d)",
104
+ rdist_capacity, s->num_cpu);
105
+ return;
106
+ }
107
+ }
107
+
108
+
108
s->cpu = g_new0(GICv3CPUState, s->num_cpu);
109
while (s->regs[R_DMA_LEN]) {
109
110
data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
110
for (i = 0; i < s->num_cpu; i++) {
111
MEMTXATTRS_UNSPECIFIED, &result);
111
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/hw/intc/arm_gicv3_kvm.c
114
+++ b/hw/intc/arm_gicv3_kvm.c
115
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
116
return;
117
}
118
119
- gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL, &local_err);
120
- if (local_err) {
121
- error_propagate(errp, local_err);
122
- return;
123
- }
124
+ gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
125
126
for (i = 0; i < s->num_cpu; i++) {
127
ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
128
--
112
--
129
2.25.1
113
2.20.1
130
114
131
115
diff view generated by jsdifflib
1
The 'Last' bit in the GICR_TYPER GICv3 redistributor register is
1
From: Cédric Le Goater <clg@kaod.org>
2
supposed to be set to 1 if this is the last redistributor in a series
3
of contiguous redistributor pages. Currently we set Last only for
4
the redistributor for CPU (num_cpu - 1). This only works if there is
5
a single redistributor region; if there are multiple redistributor
6
regions then we need to set the Last bit for the last redistributor
7
in each region.
8
2
9
This doesn't cause any problems currently because only the KVM GICv3
3
Emulate read errors in the DMA Checksum Register for high frequencies
10
supports multiple redistributor regions, and it ignores the value in
4
and optimistic settings of the Read Timing Compensation Register. This
11
GICv3State::gicr_typer. But we need to fix this before we can enable
5
will help in tuning the SPI timing calibration algorithm. Errors are
12
support for multiple regions in the emulated GICv3.
6
only injected when the property "inject_failure" is set to true as
7
suggested by Philippe.
13
8
9
The values below are those to expect from the first flash device of
10
the FMC controller of a palmetto-bmc machine.
11
12
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Reviewed-by: Joel Stanley <joel@jms.id.au>
15
Message-id: 20190904070506.1052-8-clg@kaod.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
17
---
17
hw/intc/arm_gicv3_common.c | 17 ++++++++++++-----
18
include/hw/ssi/aspeed_smc.h | 1 +
18
1 file changed, 12 insertions(+), 5 deletions(-)
19
hw/ssi/aspeed_smc.c | 36 ++++++++++++++++++++++++++++++++++++
20
2 files changed, 37 insertions(+)
19
21
20
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
22
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
21
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/arm_gicv3_common.c
24
--- a/include/hw/ssi/aspeed_smc.h
23
+++ b/hw/intc/arm_gicv3_common.c
25
+++ b/include/hw/ssi/aspeed_smc.h
24
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
26
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCState {
25
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
27
26
{
28
uint32_t num_cs;
27
GICv3State *s = ARM_GICV3_COMMON(dev);
29
qemu_irq *cs_lines;
28
- int i, rdist_capacity;
30
+ bool inject_failure;
29
+ int i, rdist_capacity, cpuidx;
31
30
32
SSIBus *spi;
31
/* revision property is actually reserved and currently used only in order
33
32
* to keep the interface compatible with GICv2 code, avoiding extra
34
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
33
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
35
index XXXXXXX..XXXXXXX 100644
34
for (i = 0; i < s->num_cpu; i++) {
36
--- a/hw/ssi/aspeed_smc.c
35
CPUState *cpu = qemu_get_cpu(i);
37
+++ b/hw/ssi/aspeed_smc.c
36
uint64_t cpu_affid;
38
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_calibration(AspeedSMCState *s)
37
- int last;
39
s->regs[s->r_ctrl0 + cs] |= CE_CTRL_CLOCK_FREQ(hclk_div);
38
40
}
39
s->cpu[i].cpu = cpu;
41
40
s->cpu[i].gic = s;
42
+/*
41
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
43
+ * Emulate read errors in the DMA Checksum Register for high
42
* PLPIS == 0 (physical LPIs not supported)
44
+ * frequencies and optimistic settings of the Read Timing Compensation
43
*/
45
+ * Register. This will help in tuning the SPI timing calibration
44
cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL);
46
+ * algorithm.
45
- last = (i == s->num_cpu - 1);
47
+ */
46
48
+static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
47
/* The CPU mp-affinity property is in MPIDR register format; squash
49
+{
48
* the affinity bytes into 32 bits as the GICR_TYPER has them.
50
+ uint8_t delay =
49
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
51
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_DELAY_SHIFT) & DMA_CTRL_DELAY_MASK;
50
(cpu_affid & 0xFFFFFF);
52
+ uint8_t hclk_mask =
51
s->cpu[i].gicr_typer = (cpu_affid << 32) |
53
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_FREQ_SHIFT) & DMA_CTRL_FREQ_MASK;
52
(1 << 24) |
54
+
53
- (i << 8) |
55
+ /*
54
- (last << 4);
56
+ * Typical values of a palmetto-bmc machine.
55
+ (i << 8);
57
+ */
56
58
+ switch (aspeed_smc_hclk_divisor(hclk_mask)) {
57
if (s->lpi_enable) {
59
+ case 4 ... 16:
58
s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
60
+ return false;
59
}
61
+ case 3: /* at least one HCLK cycle delay */
62
+ return (delay & 0x7) < 1;
63
+ case 2: /* at least two HCLK cycle delay */
64
+ return (delay & 0x7) < 2;
65
+ case 1: /* (> 100MHz) is above the max freq of the controller */
66
+ return true;
67
+ default:
68
+ g_assert_not_reached();
69
+ }
70
+}
71
+
72
/*
73
* Accumulate the result of the reads to provide a checksum that will
74
* be used to validate the read timing settings.
75
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
76
s->regs[R_DMA_FLASH_ADDR] += 4;
77
s->regs[R_DMA_LEN] -= 4;
60
}
78
}
61
+
79
+
62
+ /*
80
+ if (s->inject_failure && aspeed_smc_inject_read_failure(s)) {
63
+ * Now go through and set GICR_TYPER.Last for the final
81
+ s->regs[R_DMA_CHECKSUM] = 0xbadc0de;
64
+ * redistributor in each region.
65
+ */
66
+ cpuidx = 0;
67
+ for (i = 0; i < s->nb_redist_regions; i++) {
68
+ cpuidx += s->redist_region_count[i];
69
+ s->cpu[cpuidx - 1].gicr_typer |= GICR_TYPER_LAST;
70
+ }
82
+ }
83
+
71
}
84
}
72
85
73
static void arm_gicv3_finalize(Object *obj)
86
static void aspeed_smc_dma_rw(AspeedSMCState *s)
87
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_smc = {
88
89
static Property aspeed_smc_properties[] = {
90
DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
91
+ DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false),
92
DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0),
93
DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr,
94
TYPE_MEMORY_REGION, MemoryRegion *),
74
--
95
--
75
2.25.1
96
2.20.1
76
97
77
98
diff view generated by jsdifflib
1
Our GICv3 QOM interface includes an array property
1
From: Christian Svensson <bluecmd@google.com>
2
redist-region-count which allows board models to specify that the
3
registributor registers are not in a single contiguous range, but
4
split into multiple pieces. We implemented this for KVM, but
5
currently the TCG GICv3 model insists that there is only one region.
6
You can see the limit being hit with a setup like:
7
qemu-system-aarch64 -machine virt,gic-version=3 -smp 124
8
2
9
Add support for split regions to the TCG GICv3. To do this we switch
3
This patch adds the missing checksum calculation on normal DMA transfer.
10
from allocating a simple array of MemoryRegions to an array of
4
According to the datasheet this is how the SMC should behave.
11
GICv3RedistRegion structs so that we can use the GICv3RedistRegion as
12
the opaque pointer in the MemoryRegion read/write callbacks. Each
13
GICv3RedistRegion contains the MemoryRegion, a backpointer allowing
14
the read/write callback to get hold of the GICv3State, and an index
15
which allows us to calculate which CPU's redistributor is being
16
accessed.
17
5
18
Note that arm_gicv3_kvm always passes in NULL as the ops argument
6
Verified on AST1250 that the hardware matches the behaviour.
19
to gicv3_init_irqs_and_mmio(), so the only MemoryRegion read/write
20
callbacks we need to update to handle this new scheme are the
21
gicv3_redist_read/write functions used by the emulated GICv3.
22
7
8
Signed-off-by: Christian Svensson <bluecmd@google.com>
9
Reviewed-by: Joel Stanley <joel@jms.id.au>
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Message-id: 20190904070506.1052-9-clg@kaod.org
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
---
13
---
26
include/hw/intc/arm_gicv3_common.h | 12 ++++++++-
14
hw/ssi/aspeed_smc.c | 1 +
27
hw/intc/arm_gicv3.c | 6 -----
15
1 file changed, 1 insertion(+)
28
hw/intc/arm_gicv3_common.c | 15 ++++++++---
29
hw/intc/arm_gicv3_kvm.c | 4 +--
30
hw/intc/arm_gicv3_redist.c | 40 ++++++++++++++++--------------
31
5 files changed, 46 insertions(+), 31 deletions(-)
32
16
33
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
17
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
34
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
35
--- a/include/hw/intc/arm_gicv3_common.h
19
--- a/hw/ssi/aspeed_smc.c
36
+++ b/include/hw/intc/arm_gicv3_common.h
20
+++ b/hw/ssi/aspeed_smc.c
37
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
21
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
38
bool seenbetter;
22
s->regs[R_DMA_FLASH_ADDR] += 4;
39
};
23
s->regs[R_DMA_DRAM_ADDR] += 4;
40
24
s->regs[R_DMA_LEN] -= 4;
41
+/*
25
+ s->regs[R_DMA_CHECKSUM] += data;
42
+ * The redistributor pages might be split into more than one region
43
+ * on some machine types if there are many CPUs.
44
+ */
45
+typedef struct GICv3RedistRegion {
46
+ GICv3State *gic;
47
+ MemoryRegion iomem;
48
+ uint32_t cpuidx; /* index of first CPU this region covers */
49
+} GICv3RedistRegion;
50
+
51
struct GICv3State {
52
/*< private >*/
53
SysBusDevice parent_obj;
54
/*< public >*/
55
56
MemoryRegion iomem_dist; /* Distributor */
57
- MemoryRegion *iomem_redist; /* Redistributor Regions */
58
+ GICv3RedistRegion *redist_regions; /* Redistributor Regions */
59
uint32_t *redist_region_count; /* redistributor count within each region */
60
uint32_t nb_redist_regions; /* number of redist regions */
61
62
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/hw/intc/arm_gicv3.c
65
+++ b/hw/intc/arm_gicv3.c
66
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
67
return;
68
}
69
70
- if (s->nb_redist_regions != 1) {
71
- error_setg(errp, "VGICv3 redist region number(%d) not equal to 1",
72
- s->nb_redist_regions);
73
- return;
74
- }
75
-
76
gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops);
77
78
gicv3_init_cpuif(s);
79
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/intc/arm_gicv3_common.c
82
+++ b/hw/intc/arm_gicv3_common.c
83
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
84
{
85
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
86
int i;
87
+ int cpuidx;
88
89
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
90
* GPIO array layout is thus:
91
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
92
"gicv3_dist", 0x10000);
93
sysbus_init_mmio(sbd, &s->iomem_dist);
94
95
- s->iomem_redist = g_new0(MemoryRegion, s->nb_redist_regions);
96
+ s->redist_regions = g_new0(GICv3RedistRegion, s->nb_redist_regions);
97
+ cpuidx = 0;
98
for (i = 0; i < s->nb_redist_regions; i++) {
99
char *name = g_strdup_printf("gicv3_redist_region[%d]", i);
100
+ GICv3RedistRegion *region = &s->redist_regions[i];
101
102
- memory_region_init_io(&s->iomem_redist[i], OBJECT(s),
103
- ops ? &ops[1] : NULL, s, name,
104
+ region->gic = s;
105
+ region->cpuidx = cpuidx;
106
+ cpuidx += s->redist_region_count[i];
107
+
108
+ memory_region_init_io(&region->iomem, OBJECT(s),
109
+ ops ? &ops[1] : NULL, region, name,
110
s->redist_region_count[i] * GICV3_REDIST_SIZE);
111
- sysbus_init_mmio(sbd, &s->iomem_redist[i]);
112
+ sysbus_init_mmio(sbd, &region->iomem);
113
g_free(name);
114
}
26
}
115
}
27
}
116
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/intc/arm_gicv3_kvm.c
119
+++ b/hw/intc/arm_gicv3_kvm.c
120
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
121
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
122
123
if (!multiple_redist_region_allowed) {
124
- kvm_arm_register_device(&s->iomem_redist[0], -1,
125
+ kvm_arm_register_device(&s->redist_regions[0].iomem, -1,
126
KVM_DEV_ARM_VGIC_GRP_ADDR,
127
KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
128
} else {
129
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
130
uint64_t addr_ormask =
131
i | ((uint64_t)s->redist_region_count[i] << 52);
132
133
- kvm_arm_register_device(&s->iomem_redist[i], -1,
134
+ kvm_arm_register_device(&s->redist_regions[i].iomem, -1,
135
KVM_DEV_ARM_VGIC_GRP_ADDR,
136
KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION,
137
s->dev_fd, addr_ormask);
138
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/hw/intc/arm_gicv3_redist.c
141
+++ b/hw/intc/arm_gicv3_redist.c
142
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writell(GICv3CPUState *cs, hwaddr offset,
143
MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
144
unsigned size, MemTxAttrs attrs)
145
{
146
- GICv3State *s = opaque;
147
+ GICv3RedistRegion *region = opaque;
148
+ GICv3State *s = region->gic;
149
GICv3CPUState *cs;
150
MemTxResult r;
151
int cpuidx;
152
153
assert((offset & (size - 1)) == 0);
154
155
- /* This region covers all the redistributor pages; there are
156
- * (for GICv3) two 64K pages per CPU. At the moment they are
157
- * all contiguous (ie in this one region), though we might later
158
- * want to allow splitting of redistributor pages into several
159
- * blocks so we can support more CPUs.
160
+ /*
161
+ * There are (for GICv3) two 64K redistributor pages per CPU.
162
+ * In some cases the redistributor pages for all CPUs are not
163
+ * contiguous (eg on the virt board they are split into two
164
+ * parts if there are too many CPUs to all fit in the same place
165
+ * in the memory map); if so then the GIC has multiple MemoryRegions
166
+ * for the redistributors.
167
*/
168
- cpuidx = offset / 0x20000;
169
- offset %= 0x20000;
170
- assert(cpuidx < s->num_cpu);
171
+ cpuidx = region->cpuidx + offset / GICV3_REDIST_SIZE;
172
+ offset %= GICV3_REDIST_SIZE;
173
174
cs = &s->cpu[cpuidx];
175
176
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
177
MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
178
unsigned size, MemTxAttrs attrs)
179
{
180
- GICv3State *s = opaque;
181
+ GICv3RedistRegion *region = opaque;
182
+ GICv3State *s = region->gic;
183
GICv3CPUState *cs;
184
MemTxResult r;
185
int cpuidx;
186
187
assert((offset & (size - 1)) == 0);
188
189
- /* This region covers all the redistributor pages; there are
190
- * (for GICv3) two 64K pages per CPU. At the moment they are
191
- * all contiguous (ie in this one region), though we might later
192
- * want to allow splitting of redistributor pages into several
193
- * blocks so we can support more CPUs.
194
+ /*
195
+ * There are (for GICv3) two 64K redistributor pages per CPU.
196
+ * In some cases the redistributor pages for all CPUs are not
197
+ * contiguous (eg on the virt board they are split into two
198
+ * parts if there are too many CPUs to all fit in the same place
199
+ * in the memory map); if so then the GIC has multiple MemoryRegions
200
+ * for the redistributors.
201
*/
202
- cpuidx = offset / 0x20000;
203
- offset %= 0x20000;
204
- assert(cpuidx < s->num_cpu);
205
+ cpuidx = region->cpuidx + offset / GICV3_REDIST_SIZE;
206
+ offset %= GICV3_REDIST_SIZE;
207
208
cs = &s->cpu[cpuidx];
209
28
210
--
29
--
211
2.25.1
30
2.20.1
212
31
213
32
diff view generated by jsdifflib
New patch
1
1
From: Cédric Le Goater <clg@kaod.org>
2
3
and use a class AspeedSCUClass to define each SoC characteristics.
4
5
Signed-off-by: Cédric Le Goater <clg@kaod.org>
6
Message-id: 20190904070506.1052-10-clg@kaod.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/misc/aspeed_scu.h | 15 +++++++
11
hw/arm/aspeed_soc.c | 3 +-
12
hw/misc/aspeed_scu.c | 83 ++++++++++++++++++++----------------
13
3 files changed, 64 insertions(+), 37 deletions(-)
14
15
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/aspeed_scu.h
18
+++ b/include/hw/misc/aspeed_scu.h
19
@@ -XXX,XX +XXX,XX @@
20
21
#define TYPE_ASPEED_SCU "aspeed.scu"
22
#define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU)
23
+#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
24
+#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
25
26
#define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
27
28
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUState {
29
30
extern bool is_supported_silicon_rev(uint32_t silicon_rev);
31
32
+#define ASPEED_SCU_CLASS(klass) \
33
+ OBJECT_CLASS_CHECK(AspeedSCUClass, (klass), TYPE_ASPEED_SCU)
34
+#define ASPEED_SCU_GET_CLASS(obj) \
35
+ OBJECT_GET_CLASS(AspeedSCUClass, (obj), TYPE_ASPEED_SCU)
36
+
37
+typedef struct AspeedSCUClass {
38
+ SysBusDeviceClass parent_class;
39
+
40
+ const uint32_t *resets;
41
+ uint32_t (*calc_hpll)(AspeedSCUState *s);
42
+ uint32_t apb_divider;
43
+} AspeedSCUClass;
44
+
45
#define ASPEED_SCU_PROT_KEY 0x1688A8A8
46
47
/*
48
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/aspeed_soc.c
51
+++ b/hw/arm/aspeed_soc.c
52
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
53
&error_abort, NULL);
54
}
55
56
+ snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
57
sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu),
58
- TYPE_ASPEED_SCU);
59
+ typename);
60
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
61
sc->info->silicon_rev);
62
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
63
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/misc/aspeed_scu.c
66
+++ b/hw/misc/aspeed_scu.c
67
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_get_random(void)
68
69
static void aspeed_scu_set_apb_freq(AspeedSCUState *s)
70
{
71
- uint32_t apb_divider;
72
-
73
- switch (s->silicon_rev) {
74
- case AST2400_A0_SILICON_REV:
75
- case AST2400_A1_SILICON_REV:
76
- apb_divider = 2;
77
- break;
78
- case AST2500_A0_SILICON_REV:
79
- case AST2500_A1_SILICON_REV:
80
- apb_divider = 4;
81
- break;
82
- default:
83
- g_assert_not_reached();
84
- }
85
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
86
87
s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
88
- / apb_divider;
89
+ / asc->apb_divider;
90
}
91
92
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
93
@@ -XXX,XX +XXX,XX @@ static const uint32_t hpll_ast2400_freqs[][4] = {
94
{ 400, 375, 350, 425 }, /* 25MHz */
95
};
96
97
-static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s)
98
+static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
99
{
100
uint32_t hpll_reg = s->regs[HPLL_PARAM];
101
uint8_t freq_select;
102
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s)
103
return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
104
}
105
106
-static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s)
107
+static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s)
108
{
109
uint32_t hpll_reg = s->regs[HPLL_PARAM];
110
uint32_t multiplier = 1;
111
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s)
112
static void aspeed_scu_reset(DeviceState *dev)
113
{
114
AspeedSCUState *s = ASPEED_SCU(dev);
115
- const uint32_t *reset;
116
- uint32_t (*calc_hpll)(AspeedSCUState *s);
117
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
118
119
- switch (s->silicon_rev) {
120
- case AST2400_A0_SILICON_REV:
121
- case AST2400_A1_SILICON_REV:
122
- reset = ast2400_a0_resets;
123
- calc_hpll = aspeed_scu_calc_hpll_ast2400;
124
- break;
125
- case AST2500_A0_SILICON_REV:
126
- case AST2500_A1_SILICON_REV:
127
- reset = ast2500_a1_resets;
128
- calc_hpll = aspeed_scu_calc_hpll_ast2500;
129
- break;
130
- default:
131
- g_assert_not_reached();
132
- }
133
-
134
- memcpy(s->regs, reset, sizeof(s->regs));
135
+ memcpy(s->regs, asc->resets, sizeof(s->regs));
136
s->regs[SILICON_REV] = s->silicon_rev;
137
s->regs[HW_STRAP1] = s->hw_strap1;
138
s->regs[HW_STRAP2] = s->hw_strap2;
139
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_reset(DeviceState *dev)
140
* All registers are set. Now compute the frequencies of the main clocks
141
*/
142
s->clkin = aspeed_scu_get_clkin(s);
143
- s->hpll = calc_hpll(s);
144
+ s->hpll = asc->calc_hpll(s);
145
aspeed_scu_set_apb_freq(s);
146
}
147
148
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_scu_info = {
149
.parent = TYPE_SYS_BUS_DEVICE,
150
.instance_size = sizeof(AspeedSCUState),
151
.class_init = aspeed_scu_class_init,
152
+ .class_size = sizeof(AspeedSCUClass),
153
+ .abstract = true,
154
+};
155
+
156
+static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
157
+{
158
+ DeviceClass *dc = DEVICE_CLASS(klass);
159
+ AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
160
+
161
+ dc->desc = "ASPEED 2400 System Control Unit";
162
+ asc->resets = ast2400_a0_resets;
163
+ asc->calc_hpll = aspeed_2400_scu_calc_hpll;
164
+ asc->apb_divider = 2;
165
+}
166
+
167
+static const TypeInfo aspeed_2400_scu_info = {
168
+ .name = TYPE_ASPEED_2400_SCU,
169
+ .parent = TYPE_ASPEED_SCU,
170
+ .instance_size = sizeof(AspeedSCUState),
171
+ .class_init = aspeed_2400_scu_class_init,
172
+};
173
+
174
+static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
175
+{
176
+ DeviceClass *dc = DEVICE_CLASS(klass);
177
+ AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
178
+
179
+ dc->desc = "ASPEED 2500 System Control Unit";
180
+ asc->resets = ast2500_a1_resets;
181
+ asc->calc_hpll = aspeed_2500_scu_calc_hpll;
182
+ asc->apb_divider = 4;
183
+}
184
+
185
+static const TypeInfo aspeed_2500_scu_info = {
186
+ .name = TYPE_ASPEED_2500_SCU,
187
+ .parent = TYPE_ASPEED_SCU,
188
+ .instance_size = sizeof(AspeedSCUState),
189
+ .class_init = aspeed_2500_scu_class_init,
190
};
191
192
static void aspeed_scu_register_types(void)
193
{
194
type_register_static(&aspeed_scu_info);
195
+ type_register_static(&aspeed_2400_scu_info);
196
+ type_register_static(&aspeed_2500_scu_info);
197
}
198
199
type_init(aspeed_scu_register_types);
200
--
201
2.20.1
202
203
diff view generated by jsdifflib
New patch
1
From: Cédric Le Goater <clg@kaod.org>
1
2
3
The APB frequency can be calculated directly when needed from the
4
HPLL_PARAM and CLK_SEL register values. This removes useless state in
5
the model.
6
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Message-id: 20190904070506.1052-11-clg@kaod.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/misc/aspeed_scu.h | 8 +++-----
13
hw/misc/aspeed_scu.c | 25 +++++++++----------------
14
hw/timer/aspeed_timer.c | 3 ++-
15
3 files changed, 14 insertions(+), 22 deletions(-)
16
17
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/misc/aspeed_scu.h
20
+++ b/include/hw/misc/aspeed_scu.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUState {
22
uint32_t hw_strap1;
23
uint32_t hw_strap2;
24
uint32_t hw_prot_key;
25
-
26
- uint32_t clkin;
27
- uint32_t hpll;
28
- uint32_t apb_freq;
29
} AspeedSCUState;
30
31
#define AST2400_A0_SILICON_REV 0x02000303U
32
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUClass {
33
SysBusDeviceClass parent_class;
34
35
const uint32_t *resets;
36
- uint32_t (*calc_hpll)(AspeedSCUState *s);
37
+ uint32_t (*calc_hpll)(AspeedSCUState *s, uint32_t hpll_reg);
38
uint32_t apb_divider;
39
} AspeedSCUClass;
40
41
#define ASPEED_SCU_PROT_KEY 0x1688A8A8
42
43
+uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
44
+
45
/*
46
* Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
47
* were added.
48
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/misc/aspeed_scu.c
51
+++ b/hw/misc/aspeed_scu.c
52
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_get_random(void)
53
return num;
54
}
55
56
-static void aspeed_scu_set_apb_freq(AspeedSCUState *s)
57
+uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
58
{
59
AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
60
+ uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]);
61
62
- s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
63
+ return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
64
/ asc->apb_divider;
65
}
66
67
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
68
return;
69
case CLK_SEL:
70
s->regs[reg] = data;
71
- aspeed_scu_set_apb_freq(s);
72
break;
73
case HW_STRAP1:
74
if (ASPEED_IS_AST2500(s->regs[SILICON_REV])) {
75
@@ -XXX,XX +XXX,XX @@ static const uint32_t hpll_ast2400_freqs[][4] = {
76
{ 400, 375, 350, 425 }, /* 25MHz */
77
};
78
79
-static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
80
+static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
81
{
82
- uint32_t hpll_reg = s->regs[HPLL_PARAM];
83
uint8_t freq_select;
84
bool clk_25m_in;
85
+ uint32_t clkin = aspeed_scu_get_clkin(s);
86
87
if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
90
multiplier = (2 - od) * ((n + 2) / (d + 1));
91
}
92
93
- return s->clkin * multiplier;
94
+ return clkin * multiplier;
95
}
96
97
/* HW strapping */
98
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
99
return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
100
}
101
102
-static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s)
103
+static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
104
{
105
- uint32_t hpll_reg = s->regs[HPLL_PARAM];
106
uint32_t multiplier = 1;
107
+ uint32_t clkin = aspeed_scu_get_clkin(s);
108
109
if (hpll_reg & SCU_H_PLL_OFF) {
110
return 0;
111
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s)
112
multiplier = ((m + 1) / (n + 1)) / (p + 1);
113
}
114
115
- return s->clkin * multiplier;
116
+ return clkin * multiplier;
117
}
118
119
static void aspeed_scu_reset(DeviceState *dev)
120
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_reset(DeviceState *dev)
121
s->regs[HW_STRAP1] = s->hw_strap1;
122
s->regs[HW_STRAP2] = s->hw_strap2;
123
s->regs[PROT_KEY] = s->hw_prot_key;
124
-
125
- /*
126
- * All registers are set. Now compute the frequencies of the main clocks
127
- */
128
- s->clkin = aspeed_scu_get_clkin(s);
129
- s->hpll = asc->calc_hpll(s);
130
- aspeed_scu_set_apb_freq(s);
131
}
132
133
static uint32_t aspeed_silicon_revs[] = {
134
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/hw/timer/aspeed_timer.c
137
+++ b/hw/timer/aspeed_timer.c
138
@@ -XXX,XX +XXX,XX @@ static inline uint32_t calculate_rate(struct AspeedTimer *t)
139
{
140
AspeedTimerCtrlState *s = timer_to_ctrl(t);
141
142
- return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq;
143
+ return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ :
144
+ aspeed_scu_get_apb_freq(s->scu);
145
}
146
147
static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns)
148
--
149
2.20.1
150
151
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: "Emilio G. Cota" <cota@braap.org>
2
2
3
The PL031 currently is not able to report guest RTC change to the QMP
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
monitor as opposed to mc146818 or spapr RTCs. This patch adds the call
4
Signed-off-by: Emilio G. Cota <cota@braap.org>
5
to qapi_event_send_rtc_change() when the Load Register is written. The
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
value which is reported corresponds to the difference between the guest
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
reference time and the reference time kept in softmmu/rtc.c.
8
9
For instance adding 20s to the guest RTC value will report 20. Adding
10
an extra 20s to the guest RTC value will report 20 + 20 = 40.
11
12
The inclusion of qapi/qapi-types-misc-target.h in hw/rtl/pl031.c
13
require to compile the PL031 with specific_ss.add() to avoid
14
./qapi/qapi-types-misc-target.h:18:13: error: attempt to use poisoned
15
"TARGET_<ARCH>".
16
17
Signed-off-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Message-id: 20210920122535.269988-1-eric.auger@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
8
---
22
hw/rtc/pl031.c | 10 +++++++++-
9
accel/tcg/atomic_template.h | 2 +-
23
hw/rtc/meson.build | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
24
2 files changed, 10 insertions(+), 2 deletions(-)
25
11
26
diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c
12
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/rtc/pl031.c
14
--- a/accel/tcg/atomic_template.h
29
+++ b/hw/rtc/pl031.c
15
+++ b/accel/tcg/atomic_template.h
30
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
31
#include "qemu/log.h"
17
32
#include "qemu/module.h"
18
#define GEN_ATOMIC_HELPER(X) \
33
#include "trace.h"
19
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
34
+#include "qapi/qapi-events-misc-target.h"
20
- ABI_TYPE val EXTRA_ARGS) \
35
21
+ ABI_TYPE val EXTRA_ARGS) \
36
#define RTC_DR 0x00 /* Data read register */
22
{ \
37
#define RTC_MR 0x04 /* Match register */
23
ATOMIC_MMU_DECLS; \
38
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
24
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
39
trace_pl031_write(offset, value);
40
41
switch (offset) {
42
- case RTC_LR:
43
+ case RTC_LR: {
44
+ struct tm tm;
45
+
46
s->tick_offset += value - pl031_get_count(s);
47
+
48
+ qemu_get_timedate(&tm, s->tick_offset);
49
+ qapi_event_send_rtc_change(qemu_timedate_diff(&tm));
50
+
51
pl031_set_alarm(s);
52
break;
53
+ }
54
case RTC_MR:
55
s->mr = value;
56
pl031_set_alarm(s);
57
diff --git a/hw/rtc/meson.build b/hw/rtc/meson.build
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/rtc/meson.build
60
+++ b/hw/rtc/meson.build
61
@@ -XXX,XX +XXX,XX @@
62
softmmu_ss.add(when: 'CONFIG_DS1338', if_true: files('ds1338.c'))
63
softmmu_ss.add(when: 'CONFIG_M41T80', if_true: files('m41t80.c'))
64
softmmu_ss.add(when: 'CONFIG_M48T59', if_true: files('m48t59.c'))
65
-softmmu_ss.add(when: 'CONFIG_PL031', if_true: files('pl031.c'))
66
+specific_ss.add(when: 'CONFIG_PL031', if_true: files('pl031.c'))
67
softmmu_ss.add(when: 'CONFIG_TWL92230', if_true: files('twl92230.c'))
68
softmmu_ss.add(when: ['CONFIG_ISA_BUS', 'CONFIG_M48T59'], if_true: files('m48t59-isa.c'))
69
softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-rtc.c'))
70
--
25
--
71
2.25.1
26
2.20.1
72
27
73
28
diff view generated by jsdifflib
New patch
1
The qemu-ga documentation is currently in qemu-ga.texi in
2
Texinfo format, which we present to the user as:
3
* a qemu-ga manpage
4
* a section of the main qemu-doc HTML documentation
1
5
6
Convert the documentation to rST format, and present it to
7
the user as:
8
* a qemu-ga manpage
9
* part of the interop/ Sphinx manual
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
13
Tested-by: Michael Roth <mdroth@linux.vnet.ibm.com>
14
Message-id: 20190905131040.8350-1-peter.maydell@linaro.org
15
---
16
Makefile | 24 ++++---
17
MAINTAINERS | 2 +-
18
docs/conf.py | 18 ++---
19
docs/interop/conf.py | 7 ++
20
docs/interop/index.rst | 1 +
21
docs/interop/qemu-ga.rst | 133 +++++++++++++++++++++++++++++++++++++
22
qemu-doc.texi | 5 --
23
qemu-ga.texi | 137 ---------------------------------------
24
8 files changed, 166 insertions(+), 161 deletions(-)
25
create mode 100644 docs/interop/qemu-ga.rst
26
delete mode 100644 qemu-ga.texi
27
28
diff --git a/Makefile b/Makefile
29
index XXXXXXX..XXXXXXX 100644
30
--- a/Makefile
31
+++ b/Makefile
32
@@ -XXX,XX +XXX,XX @@ endif
33
endif
34
35
ifdef BUILD_DOCS
36
-DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
37
+DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 docs/interop/qemu-ga.8
38
DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7
39
DOCS+=docs/interop/qemu-ga-ref.html docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7
40
DOCS+=docs/qemu-block-drivers.7
41
@@ -XXX,XX +XXX,XX @@ DESCS=
42
endif
43
44
# Note that we manually filter-out the non-Sphinx documentation which
45
-# is currently built into the docs/interop directory in the build tree.
46
+# is currently built into the docs/interop directory in the build tree,
47
+# and also any sphinx-built manpages.
48
define install-manual =
49
for d in $$(cd $(MANUAL_BUILDDIR) && find $1 -type d); do $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)/$$d"; done
50
-for f in $$(cd $(MANUAL_BUILDDIR) && find $1 -type f -a '!' '(' -name 'qemu-*-qapi.*' -o -name 'qemu-*-ref.*' ')' ); do $(INSTALL_DATA) "$(MANUAL_BUILDDIR)/$$f" "$(DESTDIR)$(qemu_docdir)/$$f"; done
51
+for f in $$(cd $(MANUAL_BUILDDIR) && find $1 -type f -a '!' '(' -name '*.[0-9]' -o -name 'qemu-*-qapi.*' -o -name 'qemu-*-ref.*' ')' ); do $(INSTALL_DATA) "$(MANUAL_BUILDDIR)/$$f" "$(DESTDIR)$(qemu_docdir)/$$f"; done
52
endef
53
54
# Note that we deliberately do not install the "devel" manual: it is
55
@@ -XXX,XX +XXX,XX @@ ifdef CONFIG_TRACE_SYSTEMTAP
56
    $(INSTALL_DATA) scripts/qemu-trace-stap.1 "$(DESTDIR)$(mandir)/man1"
57
endif
58
ifneq (,$(findstring qemu-ga,$(TOOLS)))
59
-    $(INSTALL_DATA) qemu-ga.8 "$(DESTDIR)$(mandir)/man8"
60
+    $(INSTALL_DATA) docs/interop/qemu-ga.8 "$(DESTDIR)$(mandir)/man8"
61
    $(INSTALL_DATA) docs/interop/qemu-ga-ref.html "$(DESTDIR)$(qemu_docdir)"
62
    $(INSTALL_DATA) docs/interop/qemu-ga-ref.txt "$(DESTDIR)$(qemu_docdir)"
63
    $(INSTALL_DATA) docs/interop/qemu-ga-ref.7 "$(DESTDIR)$(mandir)/man7"
64
@@ -XXX,XX +XXX,XX @@ docs/version.texi: $(SRC_PATH)/VERSION config-host.mak
65
sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html $(MANUAL_BUILDDIR)/interop/index.html $(MANUAL_BUILDDIR)/specs/index.html
66
67
# Canned command to build a single manual
68
-build-manual = $(call quiet-command,sphinx-build $(if $(V),,-q) -W -n -b html -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1")
69
+# Arguments: $1 = manual name, $2 = Sphinx builder ('html' or 'man')
70
+build-manual = $(call quiet-command,CONFDIR="$(qemu_confdir)" sphinx-build $(if $(V),,-q) -W -n -b $2 -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1")
71
# We assume all RST files in the manual's directory are used in it
72
manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py
73
74
$(MANUAL_BUILDDIR)/devel/index.html: $(call manual-deps,devel)
75
-    $(call build-manual,devel)
76
+    $(call build-manual,devel,html)
77
78
$(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop)
79
-    $(call build-manual,interop)
80
+    $(call build-manual,interop,html)
81
82
$(MANUAL_BUILDDIR)/specs/index.html: $(call manual-deps,specs)
83
-    $(call build-manual,specs)
84
+    $(call build-manual,specs,html)
85
+
86
+$(MANUAL_BUILDDIR)/interop/qemu-ga.8: $(call manual-deps,interop)
87
+    $(call build-manual,interop,man)
88
89
qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
90
    $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
91
@@ -XXX,XX +XXX,XX @@ qemu.1: qemu-option-trace.texi
92
qemu-img.1: qemu-img.texi qemu-option-trace.texi qemu-img-cmds.texi
93
fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
94
qemu-nbd.8: qemu-nbd.texi qemu-option-trace.texi
95
-qemu-ga.8: qemu-ga.texi
96
docs/qemu-block-drivers.7: docs/qemu-block-drivers.texi
97
docs/qemu-cpu-models.7: docs/qemu-cpu-models.texi
98
scripts/qemu-trace-stap.1: scripts/qemu-trace-stap.texi
99
@@ -XXX,XX +XXX,XX @@ txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt
100
qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \
101
    qemu-img.texi qemu-nbd.texi qemu-options.texi \
102
    qemu-tech.texi qemu-option-trace.texi \
103
-    qemu-deprecated.texi qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
104
+    qemu-deprecated.texi qemu-monitor.texi qemu-img-cmds.texi \
105
    qemu-monitor-info.texi docs/qemu-block-drivers.texi \
106
    docs/qemu-cpu-models.texi docs/security.texi
107
108
diff --git a/MAINTAINERS b/MAINTAINERS
109
index XXXXXXX..XXXXXXX 100644
110
--- a/MAINTAINERS
111
+++ b/MAINTAINERS
112
@@ -XXX,XX +XXX,XX @@ QEMU Guest Agent
113
M: Michael Roth <mdroth@linux.vnet.ibm.com>
114
S: Maintained
115
F: qga/
116
-F: qemu-ga.texi
117
+F: docs/interop/qemu-ga.rst
118
F: scripts/qemu-guest-agent/
119
F: tests/test-qga.c
120
F: docs/interop/qemu-ga-ref.texi
121
diff --git a/docs/conf.py b/docs/conf.py
122
index XXXXXXX..XXXXXXX 100644
123
--- a/docs/conf.py
124
+++ b/docs/conf.py
125
@@ -XXX,XX +XXX,XX @@ todo_include_todos = False
126
# with "option::" in the document being processed. Turn that off.
127
suppress_warnings = ["ref.option"]
128
129
+# The rst_epilog fragment is effectively included in every rST file.
130
+# We use it to define substitutions based on build config that
131
+# can then be used in the documentation. The fallback if the
132
+# environment variable is not set is for the benefit of readthedocs
133
+# style document building; our Makefile always sets the variable.
134
+confdir = os.getenv('CONFDIR', "/etc/qemu")
135
+rst_epilog = ".. |CONFDIR| replace:: ``" + confdir + "``\n"
136
+
137
# -- Options for HTML output ----------------------------------------------
138
139
# The theme to use for HTML and HTML Help pages. See the documentation for
140
@@ -XXX,XX +XXX,XX @@ latex_documents = [
141
142
143
# -- Options for manual page output ---------------------------------------
144
-
145
-# One entry per manual page. List of tuples
146
-# (source start file, name, description, authors, manual section).
147
-man_pages = [
148
- (master_doc, 'qemu', u'QEMU Documentation',
149
- [author], 1)
150
-]
151
-
152
+# Individual manual/conf.py can override this to create man pages
153
+man_pages = []
154
155
# -- Options for Texinfo output -------------------------------------------
156
157
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
158
index XXXXXXX..XXXXXXX 100644
159
--- a/docs/interop/conf.py
160
+++ b/docs/interop/conf.py
161
@@ -XXX,XX +XXX,XX @@ exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
162
# This slightly misuses the 'description', but is the best way to get
163
# the manual title to appear in the sidebar.
164
html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
165
+
166
+# One entry per manual page. List of tuples
167
+# (source start file, name, description, authors, manual section).
168
+man_pages = [
169
+ ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
170
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8)
171
+]
172
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
173
index XXXXXXX..XXXXXXX 100644
174
--- a/docs/interop/index.rst
175
+++ b/docs/interop/index.rst
176
@@ -XXX,XX +XXX,XX @@ Contents:
177
bitmaps
178
live-block-operations
179
pr-helper
180
+ qemu-ga
181
vhost-user
182
vhost-user-gpu
183
diff --git a/docs/interop/qemu-ga.rst b/docs/interop/qemu-ga.rst
184
new file mode 100644
185
index XXXXXXX..XXXXXXX
186
--- /dev/null
187
+++ b/docs/interop/qemu-ga.rst
188
@@ -XXX,XX +XXX,XX @@
189
+QEMU Guest Agent
190
+================
191
+
192
+Synopsis
193
+--------
194
+
195
+**qemu-ga** [*OPTIONS*]
196
+
197
+Description
198
+-----------
199
+
200
+The QEMU Guest Agent is a daemon intended to be run within virtual
201
+machines. It allows the hypervisor host to perform various operations
202
+in the guest, such as:
203
+
204
+- get information from the guest
205
+- set the guest's system time
206
+- read/write a file
207
+- sync and freeze the filesystems
208
+- suspend the guest
209
+- reconfigure guest local processors
210
+- set user's password
211
+- ...
212
+
213
+qemu-ga will read a system configuration file on startup (located at
214
+|CONFDIR|\ ``/qemu-ga.conf`` by default), then parse remaining
215
+configuration options on the command line. For the same key, the last
216
+option wins, but the lists accumulate (see below for configuration
217
+file format).
218
+
219
+Options
220
+-------
221
+
222
+.. program:: qemu-ga
223
+
224
+.. option:: -m, --method=METHOD
225
+
226
+ Transport method: one of ``unix-listen``, ``virtio-serial``, or
227
+ ``isa-serial`` (``virtio-serial`` is the default).
228
+
229
+.. option:: -p, --path=PATH
230
+
231
+ Device/socket path (the default for virtio-serial is
232
+ ``/dev/virtio-ports/org.qemu.guest_agent.0``,
233
+ the default for isa-serial is ``/dev/ttyS0``)
234
+
235
+.. option:: -l, --logfile=PATH
236
+
237
+ Set log file path (default is stderr).
238
+
239
+.. option:: -f, --pidfile=PATH
240
+
241
+ Specify pid file (default is ``/var/run/qemu-ga.pid``).
242
+
243
+.. option:: -F, --fsfreeze-hook=PATH
244
+
245
+ Enable fsfreeze hook. Accepts an optional argument that specifies
246
+ script to run on freeze/thaw. Script will be called with
247
+ 'freeze'/'thaw' arguments accordingly (default is
248
+ |CONFDIR|\ ``/fsfreeze-hook``). If using -F with an argument, do
249
+ not follow -F with a space (for example:
250
+ ``-F/var/run/fsfreezehook.sh``).
251
+
252
+.. option:: -t, --statedir=PATH
253
+
254
+ Specify the directory to store state information (absolute paths only,
255
+ default is ``/var/run``).
256
+
257
+.. option:: -v, --verbose
258
+
259
+ Log extra debugging information.
260
+
261
+.. option:: -V, --version
262
+
263
+ Print version information and exit.
264
+
265
+.. option:: -d, --daemon
266
+
267
+ Daemonize after startup (detach from terminal).
268
+
269
+.. option:: -b, --blacklist=LIST
270
+
271
+ Comma-separated list of RPCs to disable (no spaces, ``?`` to list
272
+ available RPCs).
273
+
274
+.. option:: -D, --dump-conf
275
+
276
+ Dump the configuration in a format compatible with ``qemu-ga.conf``
277
+ and exit.
278
+
279
+.. option:: -h, --help
280
+
281
+ Display this help and exit.
282
+
283
+Files
284
+-----
285
+
286
+
287
+The syntax of the ``qemu-ga.conf`` configuration file follows the
288
+Desktop Entry Specification, here is a quick summary: it consists of
289
+groups of key-value pairs, interspersed with comments.
290
+
291
+::
292
+
293
+ # qemu-ga configuration sample
294
+ [general]
295
+ daemonize = 0
296
+ pidfile = /var/run/qemu-ga.pid
297
+ verbose = 0
298
+ method = virtio-serial
299
+ path = /dev/virtio-ports/org.qemu.guest_agent.0
300
+ statedir = /var/run
301
+
302
+The list of keys follows the command line options:
303
+
304
+============= ===========
305
+Key Key type
306
+============= ===========
307
+daemon boolean
308
+method string
309
+path string
310
+logfile string
311
+pidfile string
312
+fsfreeze-hook string
313
+statedir string
314
+verbose boolean
315
+blacklist string list
316
+============= ===========
317
+
318
+See also
319
+--------
320
+
321
+:manpage:`qemu(1)`
322
diff --git a/qemu-doc.texi b/qemu-doc.texi
323
index XXXXXXX..XXXXXXX 100644
324
--- a/qemu-doc.texi
325
+++ b/qemu-doc.texi
326
@@ -XXX,XX +XXX,XX @@ so should only be used with trusted guest OS.
327
328
@c man end
329
330
-@node QEMU Guest Agent
331
-@chapter QEMU Guest Agent invocation
332
-
333
-@include qemu-ga.texi
334
-
335
@node QEMU User space emulator
336
@chapter QEMU User space emulator
337
338
diff --git a/qemu-ga.texi b/qemu-ga.texi
339
deleted file mode 100644
340
index XXXXXXX..XXXXXXX
341
--- a/qemu-ga.texi
342
+++ /dev/null
343
@@ -XXX,XX +XXX,XX @@
344
-@example
345
-@c man begin SYNOPSIS
346
-@command{qemu-ga} [@var{OPTIONS}]
347
-@c man end
348
-@end example
349
-
350
-@c man begin DESCRIPTION
351
-
352
-The QEMU Guest Agent is a daemon intended to be run within virtual
353
-machines. It allows the hypervisor host to perform various operations
354
-in the guest, such as:
355
-
356
-@itemize
357
-@item
358
-get information from the guest
359
-@item
360
-set the guest's system time
361
-@item
362
-read/write a file
363
-@item
364
-sync and freeze the filesystems
365
-@item
366
-suspend the guest
367
-@item
368
-reconfigure guest local processors
369
-@item
370
-set user's password
371
-@item
372
-...
373
-@end itemize
374
-
375
-qemu-ga will read a system configuration file on startup (located at
376
-@file{@value{CONFDIR}/qemu-ga.conf} by default), then parse remaining
377
-configuration options on the command line. For the same key, the last
378
-option wins, but the lists accumulate (see below for configuration
379
-file format).
380
-
381
-@c man end
382
-
383
-@c man begin OPTIONS
384
-@table @option
385
-@item -m, --method=@var{method}
386
- Transport method: one of @samp{unix-listen}, @samp{virtio-serial}, or
387
- @samp{isa-serial} (@samp{virtio-serial} is the default).
388
-
389
-@item -p, --path=@var{path}
390
- Device/socket path (the default for virtio-serial is
391
- @samp{/dev/virtio-ports/org.qemu.guest_agent.0},
392
- the default for isa-serial is @samp{/dev/ttyS0})
393
-
394
-@item -l, --logfile=@var{path}
395
- Set log file path (default is stderr).
396
-
397
-@item -f, --pidfile=@var{path}
398
- Specify pid file (default is @samp{/var/run/qemu-ga.pid}).
399
-
400
-@item -F, --fsfreeze-hook=@var{path}
401
- Enable fsfreeze hook. Accepts an optional argument that specifies
402
- script to run on freeze/thaw. Script will be called with
403
- 'freeze'/'thaw' arguments accordingly (default is
404
- @samp{@value{CONFDIR}/fsfreeze-hook}). If using -F with an argument, do
405
- not follow -F with a space (for example:
406
- @samp{-F/var/run/fsfreezehook.sh}).
407
-
408
-@item -t, --statedir=@var{path}
409
- Specify the directory to store state information (absolute paths only,
410
- default is @samp{/var/run}).
411
-
412
-@item -v, --verbose
413
- Log extra debugging information.
414
-
415
-@item -V, --version
416
- Print version information and exit.
417
-
418
-@item -d, --daemon
419
- Daemonize after startup (detach from terminal).
420
-
421
-@item -b, --blacklist=@var{list}
422
- Comma-separated list of RPCs to disable (no spaces, @samp{?} to list
423
- available RPCs).
424
-
425
-@item -D, --dump-conf
426
- Dump the configuration in a format compatible with @file{qemu-ga.conf}
427
- and exit.
428
-
429
-@item -h, --help
430
- Display this help and exit.
431
-@end table
432
-
433
-@c man end
434
-
435
-@c man begin FILES
436
-
437
-The syntax of the @file{qemu-ga.conf} configuration file follows the
438
-Desktop Entry Specification, here is a quick summary: it consists of
439
-groups of key-value pairs, interspersed with comments.
440
-
441
-@example
442
-# qemu-ga configuration sample
443
-[general]
444
-daemonize = 0
445
-pidfile = /var/run/qemu-ga.pid
446
-verbose = 0
447
-method = virtio-serial
448
-path = /dev/virtio-ports/org.qemu.guest_agent.0
449
-statedir = /var/run
450
-@end example
451
-
452
-The list of keys follows the command line options:
453
-@table @option
454
-@item daemon= boolean
455
-@item method= string
456
-@item path= string
457
-@item logfile= string
458
-@item pidfile= string
459
-@item fsfreeze-hook= string
460
-@item statedir= string
461
-@item verbose= boolean
462
-@item blacklist= string list
463
-@end table
464
-
465
-@c man end
466
-
467
-@ignore
468
-
469
-@setfilename qemu-ga
470
-@settitle QEMU Guest Agent
471
-
472
-@c man begin AUTHOR
473
-Michael Roth <mdroth@linux.vnet.ibm.com>
474
-@c man end
475
-
476
-@c man begin SEEALSO
477
-qemu(1)
478
-@c man end
479
-
480
-@end ignore
481
--
482
2.20.1
483
484
diff view generated by jsdifflib