1
Arm changes for before softfreeze: mostly my PL061/GPIO patches,
1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
2
but also a new M-profile board and various other things.
2
removal.
3
4
I have enough stuff in my to-review queue that I expect to do another
5
pullreq early next week, but 31 patches is enough to not hang on to.
3
6
4
thanks
7
thanks
5
-- PMM
8
-- PMM
6
9
7
The following changes since commit 05de778b5b8ab0b402996769117b88c7ea5c7c61:
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
8
11
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2021-07-09 14:30:01 +0100)
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
10
13
11
are available in the Git repository at:
14
are available in the Git repository at:
12
15
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210709
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
14
17
15
for you to fetch changes up to 05449abb1d4c5f0c69ceb3d8d03cbc75de39b646:
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
16
19
17
hw/intc: Improve formatting of MEMTX_ERROR guest error message (2021-07-09 16:09:12 +0100)
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
18
21
19
----------------------------------------------------------------
22
----------------------------------------------------------------
20
target-arm queue:
23
target-arm queue:
21
* New machine type: stm32vldiscovery
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
22
* hw/intc/arm_gicv3_cpuif: Fix virtual irq number check in icv_[dir|eoir]_write
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
23
* hw/gpio/pl061: Honour Luminary PL061 PUR and PDR registers
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
24
* virt: Fix implementation of GPIO-based powerdown/shutdown mechanism
27
* xlnx-zynqmp: Connect 4 TTC timers
25
* Correct the encoding of MDCCSR_EL0 and DBGDSCRint
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
26
* hw/intc: Improve formatting of MEMTX_ERROR guest error message
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
31
* hw/core/irq: remove unused 'qemu_irq_split' function
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
33
* virt: document impact of gic-version on max CPUs
27
34
28
----------------------------------------------------------------
35
----------------------------------------------------------------
29
Alexandre Iooss (4):
36
Edgar E. Iglesias (6):
30
stm32f100: Add the stm32f100 SoC
37
timer: cadence_ttc: Break out header file to allow embedding
31
stm32vldiscovery: Add the STM32VLDISCOVERY Machine
38
hw/arm/xlnx-zynqmp: Connect 4 TTC timers
32
docs/system: arm: Add stm32 boards description
39
hw/arm: versal: Create an APU CPU Cluster
33
tests/boot-serial-test: Add STM32VLDISCOVERY board testcase
40
hw/arm: versal: Add the Cortex-R5Fs
41
hw/misc: Add a model of the Xilinx Versal CRL
42
hw/arm: versal: Connect the CRL
34
43
35
Peter Maydell (10):
44
Hao Wu (2):
36
hw/gpio/pl061: Convert DPRINTF to tracepoints
45
hw/misc: Add PWRON STRAP bit fields in GCR module
37
hw/gpio/pl061: Clean up read/write offset handling logic
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
38
hw/gpio/pl061: Add tracepoints for register read and write
39
hw/gpio/pl061: Document the interface of this device
40
hw/gpio/pl061: Honour Luminary PL061 PUR and PDR registers
41
hw/gpio/pl061: Make pullup/pulldown of outputs configurable
42
hw/arm/virt: Make PL061 GPIO lines pulled low, not high
43
hw/gpio/pl061: Convert to 3-phase reset and assert GPIO lines correctly on reset
44
hw/gpio/pl061: Document a shortcoming in our implementation
45
hw/arm/stellaris: Expand comment about handling of OLED chipselect
46
47
47
Rebecca Cran (1):
48
Heinrich Schuchardt (1):
48
hw/intc: Improve formatting of MEMTX_ERROR guest error message
49
hw/arm/virt: impact of gic-version on max CPUs
49
50
50
Ricardo Koller (1):
51
Peter Maydell (19):
51
hw/intc/arm_gicv3_cpuif: Fix virtual irq number check in icv_[dir|eoir]_write
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
53
hw/arm/exynos4210: Use TYPE_OR_IRQ instead of custom OR-gate device
54
hw/intc/exynos4210_gic: Remove unused TYPE_EXYNOS4210_IRQ_GATE
55
hw/arm/exynos4210: Put a9mpcore device into state struct
56
hw/arm/exynos4210: Drop int_gic_irq[] from Exynos4210Irq struct
57
hw/arm/exynos4210: Coalesce board_irqs and irq_table
58
hw/arm/exynos4210: Fix code style nit in combiner_grp_to_gic_id[]
59
hw/arm/exynos4210: Move exynos4210_init_board_irqs() into exynos4210.c
60
hw/arm/exynos4210: Put external GIC into state struct
61
hw/arm/exynos4210: Drop ext_gic_irq[] from Exynos4210Irq struct
62
hw/arm/exynos4210: Move exynos4210_combiner_get_gpioin() into exynos4210.c
63
hw/arm/exynos4210: Delete unused macro definitions
64
hw/arm/exynos4210: Use TYPE_SPLIT_IRQ in exynos4210_init_board_irqs()
65
hw/arm/exynos4210: Fill in irq_table[] for internal-combiner-only IRQ lines
66
hw/arm/exynos4210: Connect MCT_G0 and MCT_G1 to both combiners
67
hw/arm/exynos4210: Don't connect multiple lines to external GIC inputs
68
hw/arm/exynos4210: Fold combiner splits into exynos4210_init_board_irqs()
69
hw/arm/exynos4210: Put combiners into state struct
70
hw/arm/exynos4210: Drop Exynos4210Irq struct
52
71
53
hnick@vmware.com (1):
72
Zongyuan Li (3):
54
target/arm: Correct the encoding of MDCCSR_EL0 and DBGDSCRint
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
75
hw/core/irq: remove unused 'qemu_irq_split' function
55
76
56
docs/system/arm/stm32.rst | 66 +++++++
77
docs/system/arm/virt.rst | 4 +-
57
docs/system/target-arm.rst | 1 +
78
include/hw/arm/exynos4210.h | 50 ++--
58
default-configs/devices/arm-softmmu.mak | 1 +
79
include/hw/arm/xlnx-versal.h | 16 ++
59
include/hw/arm/stm32f100_soc.h | 57 ++++++
80
include/hw/arm/xlnx-zynqmp.h | 4 +
60
hw/arm/stellaris.c | 56 +++++-
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
61
hw/arm/stm32f100_soc.c | 182 +++++++++++++++++
82
include/hw/intc/exynos4210_gic.h | 43 ++++
62
hw/arm/stm32vldiscovery.c | 66 +++++++
83
include/hw/irq.h | 5 -
63
hw/arm/virt.c | 3 +
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
64
hw/gpio/pl061.c | 341 +++++++++++++++++++++++++-------
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
65
hw/intc/arm_gicv3_cpuif.c | 4 +-
86
include/hw/timer/cadence_ttc.h | 54 +++++
66
hw/intc/arm_gicv3_redist.c | 4 +-
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
67
target/arm/helper.c | 16 +-
88
hw/arm/npcm7xx_boards.c | 24 +-
68
tests/qtest/boot-serial-test.c | 37 ++++
89
hw/arm/realview.c | 33 ++-
69
MAINTAINERS | 13 ++
90
hw/arm/stellaris.c | 15 +-
70
hw/arm/Kconfig | 10 +
91
hw/arm/virt.c | 7 +
71
hw/arm/meson.build | 2 +
92
hw/arm/xlnx-versal-virt.c | 6 +-
72
hw/gpio/trace-events | 9 +
93
hw/arm/xlnx-versal.c | 99 +++++++-
73
17 files changed, 790 insertions(+), 78 deletions(-)
94
hw/arm/xlnx-zynqmp.c | 22 ++
74
create mode 100644 docs/system/arm/stm32.rst
95
hw/core/irq.c | 15 --
75
create mode 100644 include/hw/arm/stm32f100_soc.h
96
hw/intc/exynos4210_combiner.c | 108 +--------
76
create mode 100644 hw/arm/stm32f100_soc.c
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
77
create mode 100644 hw/arm/stm32vldiscovery.c
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
78
99
hw/timer/cadence_ttc.c | 32 +--
100
MAINTAINERS | 2 +-
101
hw/misc/meson.build | 1 +
102
25 files changed, 1457 insertions(+), 600 deletions(-)
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
104
create mode 100644 include/hw/intc/exynos4210_gic.h
105
create mode 100644 include/hw/misc/xlnx-versal-crl.h
106
create mode 100644 include/hw/timer/cadence_ttc.h
107
create mode 100644 hw/misc/xlnx-versal-crl.c
diff view generated by jsdifflib
1
For the virt board we have two PL061 devices -- one for NonSecure which
1
It's not possible to provide the guest with the Security extensions
2
is inputs only, and one for Secure which is outputs only. For the former,
2
(TrustZone) when using KVM or HVF, because the hardware
3
we don't care whether its outputs are pulled low or high when the line is
3
virtualization extensions don't permit running EL3 guest code.
4
configured as an input, because we don't connect them. For the latter,
4
However, we weren't checking for this combination, with the result
5
we do care, because we wire the lines up to the gpio-pwr device, which
5
that QEMU would assert if you tried it:
6
assumes that level 1 means "do the action" and 1 means "do nothing".
7
For consistency in case we add more outputs in future, configure both
8
PL061s to pull GPIO lines down to 0.
9
6
10
Reported-by: Maxim Uvarov <maxim.uvarov@linaro.org>
7
$ qemu-system-aarch64 -enable-kvm -machine virt,secure=on -cpu host -display none
8
Unexpected error in object_property_find_err() at ../../qom/object.c:1304:
9
qemu-system-aarch64: Property 'host-arm-cpu.secure-memory' not found
10
Aborted
11
12
Check for this combination of options and report an error, in the
13
same way we already do for attempts to give a KVM or HVF guest the
14
Virtualization or MTE extensions. Now we will report:
15
16
qemu-system-aarch64: mach-virt: KVM does not support providing Security extensions (TrustZone) to the guest CPU
17
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/961
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20220404155301.566542-1-peter.maydell@linaro.org
13
---
22
---
14
hw/arm/virt.c | 3 +++
23
hw/arm/virt.c | 7 +++++++
15
1 file changed, 3 insertions(+)
24
1 file changed, 7 insertions(+)
16
25
17
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
18
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/virt.c
28
--- a/hw/arm/virt.c
20
+++ b/hw/arm/virt.c
29
+++ b/hw/arm/virt.c
21
@@ -XXX,XX +XXX,XX @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
22
MachineState *ms = MACHINE(vms);
31
exit(1);
23
32
}
24
pl061_dev = qdev_new("pl061");
33
25
+ /* Pull lines down to 0 if not driven by the PL061 */
34
+ if (vms->secure && (kvm_enabled() || hvf_enabled())) {
26
+ qdev_prop_set_uint32(pl061_dev, "pullups", 0);
35
+ error_report("mach-virt: %s does not support providing "
27
+ qdev_prop_set_uint32(pl061_dev, "pulldowns", 0xff);
36
+ "Security extensions (TrustZone) to the guest CPU",
28
s = SYS_BUS_DEVICE(pl061_dev);
37
+ kvm_enabled() ? "KVM" : "HVF");
29
sysbus_realize_and_unref(s, &error_fatal);
38
+ exit(1);
30
memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
39
+ }
40
+
41
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
42
error_report("mach-virt: %s does not support providing "
43
"Virtualization extensions to the guest CPU",
31
--
44
--
32
2.20.1
45
2.25.1
33
34
diff view generated by jsdifflib
1
From: Alexandre Iooss <erdnaxe@crans.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
This adds the target guide for Netduino 2, Netduino Plus 2 and STM32VLDISCOVERY.
3
Break out header file to allow embedding of the the TTC.
4
4
5
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Message-id: 20210617165647.2575955-4-erdnaxe@crans.org
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-2-edgar.iglesias@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
docs/system/arm/stm32.rst | 66 ++++++++++++++++++++++++++++++++++++++
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
11
docs/system/target-arm.rst | 1 +
13
hw/timer/cadence_ttc.c | 32 ++------------------
12
MAINTAINERS | 1 +
14
2 files changed, 56 insertions(+), 30 deletions(-)
13
3 files changed, 68 insertions(+)
15
create mode 100644 include/hw/timer/cadence_ttc.h
14
create mode 100644 docs/system/arm/stm32.rst
15
16
16
diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
17
new file mode 100644
18
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
--- /dev/null
20
+++ b/docs/system/arm/stm32.rst
21
+++ b/include/hw/timer/cadence_ttc.h
21
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
22
+STMicroelectronics STM32 boards (``netduino2``, ``netduinoplus2``, ``stm32vldiscovery``)
23
+/*
23
+========================================================================================
24
+ * Xilinx Zynq cadence TTC model
25
+ *
26
+ * Copyright (c) 2011 Xilinx Inc.
27
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
28
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
29
+ * Written By Haibing Ma
30
+ * M. Habib
31
+ *
32
+ * This program is free software; you can redistribute it and/or
33
+ * modify it under the terms of the GNU General Public License
34
+ * as published by the Free Software Foundation; either version
35
+ * 2 of the License, or (at your option) any later version.
36
+ *
37
+ * You should have received a copy of the GNU General Public License along
38
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
39
+ */
40
+#ifndef HW_TIMER_CADENCE_TTC_H
41
+#define HW_TIMER_CADENCE_TTC_H
24
+
42
+
25
+The `STM32`_ chips are a family of 32-bit ARM-based microcontroller by
43
+#include "hw/sysbus.h"
26
+STMicroelectronics.
44
+#include "qemu/timer.h"
27
+
45
+
28
+.. _STM32: https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html
46
+typedef struct {
47
+ QEMUTimer *timer;
48
+ int freq;
29
+
49
+
30
+The STM32F1 series is based on ARM Cortex-M3 core. The following machines are
50
+ uint32_t reg_clock;
31
+based on this chip :
51
+ uint32_t reg_count;
52
+ uint32_t reg_value;
53
+ uint16_t reg_interval;
54
+ uint16_t reg_match[3];
55
+ uint32_t reg_intr;
56
+ uint32_t reg_intr_en;
57
+ uint32_t reg_event_ctrl;
58
+ uint32_t reg_event;
32
+
59
+
33
+- ``stm32vldiscovery`` STM32VLDISCOVERY board with STM32F100RBT6 microcontroller
60
+ uint64_t cpu_time;
61
+ unsigned int cpu_time_valid;
34
+
62
+
35
+The STM32F2 series is based on ARM Cortex-M3 core. The following machines are
63
+ qemu_irq irq;
36
+based on this chip :
64
+} CadenceTimerState;
37
+
65
+
38
+- ``netduino2`` Netduino 2 board with STM32F205RFT6 microcontroller
66
+#define TYPE_CADENCE_TTC "cadence_ttc"
67
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
39
+
68
+
40
+The STM32F4 series is based on ARM Cortex-M4F core. This series is pin-to-pin
69
+struct CadenceTTCState {
41
+compatible with STM32F2 series. The following machines are based on this chip :
70
+ SysBusDevice parent_obj;
42
+
71
+
43
+- ``netduinoplus2`` Netduino Plus 2 board with STM32F405RGT6 microcontroller
72
+ MemoryRegion iomem;
73
+ CadenceTimerState timer[3];
74
+};
44
+
75
+
45
+There are many other STM32 series that are currently not supported by QEMU.
76
+#endif
77
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/timer/cadence_ttc.c
80
+++ b/hw/timer/cadence_ttc.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qemu/timer.h"
83
#include "qom/object.h"
84
85
+#include "hw/timer/cadence_ttc.h"
46
+
86
+
47
+Supported devices
87
#ifdef CADENCE_TTC_ERR_DEBUG
48
+-----------------
88
#define DB_PRINT(...) do { \
49
+
89
fprintf(stderr, ": %s: ", __func__); \
50
+ * ARM Cortex-M3, Cortex M4F
90
@@ -XXX,XX +XXX,XX @@
51
+ * Analog to Digital Converter (ADC)
91
#define CLOCK_CTRL_PS_EN 0x00000001
52
+ * EXTI interrupt
92
#define CLOCK_CTRL_PS_V 0x0000001e
53
+ * Serial ports (USART)
93
54
+ * SPI controller
94
-typedef struct {
55
+ * System configuration (SYSCFG)
95
- QEMUTimer *timer;
56
+ * Timer controller (TIMER)
96
- int freq;
57
+
97
-
58
+Missing devices
98
- uint32_t reg_clock;
59
+---------------
99
- uint32_t reg_count;
60
+
100
- uint32_t reg_value;
61
+ * Camera interface (DCMI)
101
- uint16_t reg_interval;
62
+ * Controller Area Network (CAN)
102
- uint16_t reg_match[3];
63
+ * Cycle Redundancy Check (CRC) calculation unit
103
- uint32_t reg_intr;
64
+ * Digital to Analog Converter (DAC)
104
- uint32_t reg_intr_en;
65
+ * DMA controller
105
- uint32_t reg_event_ctrl;
66
+ * Ethernet controller
106
- uint32_t reg_event;
67
+ * Flash Interface Unit
107
-
68
+ * GPIO controller
108
- uint64_t cpu_time;
69
+ * I2C controller
109
- unsigned int cpu_time_valid;
70
+ * Inter-Integrated Sound (I2S) controller
110
-
71
+ * Power supply configuration (PWR)
111
- qemu_irq irq;
72
+ * Random Number Generator (RNG)
112
-} CadenceTimerState;
73
+ * Real-Time Clock (RTC) controller
113
-
74
+ * Reset and Clock Controller (RCC)
114
-#define TYPE_CADENCE_TTC "cadence_ttc"
75
+ * Secure Digital Input/Output (SDIO) interface
115
-OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
76
+ * USB OTG
116
-
77
+ * Watchdog controller (IWDG, WWDG)
117
-struct CadenceTTCState {
78
+
118
- SysBusDevice parent_obj;
79
+Boot options
119
-
80
+------------
120
- MemoryRegion iomem;
81
+
121
- CadenceTimerState timer[3];
82
+The STM32 machines can be started using the ``-kernel`` option to load a
122
-};
83
+firmware. Example:
123
-
84
+
124
static void cadence_timer_update(CadenceTimerState *s)
85
+.. code-block:: bash
125
{
86
+
126
qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
87
+ $ qemu-system-arm -M stm32vldiscovery -kernel firmware.bin
88
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
89
index XXXXXXX..XXXXXXX 100644
90
--- a/docs/system/target-arm.rst
91
+++ b/docs/system/target-arm.rst
92
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
93
arm/collie
94
arm/sx1
95
arm/stellaris
96
+ arm/stm32
97
arm/virt
98
arm/xlnx-versal-virt
99
100
diff --git a/MAINTAINERS b/MAINTAINERS
101
index XXXXXXX..XXXXXXX 100644
102
--- a/MAINTAINERS
103
+++ b/MAINTAINERS
104
@@ -XXX,XX +XXX,XX @@ M: Alexandre Iooss <erdnaxe@crans.org>
105
L: qemu-arm@nongnu.org
106
S: Maintained
107
F: hw/arm/stm32vldiscovery.c
108
+F: docs/system/arm/stm32.rst
109
110
Versatile Express
111
M: Peter Maydell <peter.maydell@linaro.org>
112
--
127
--
113
2.20.1
128
2.25.1
114
115
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Connect the 4 TTC timers on the ZynqMP.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
14
2 files changed, 26 insertions(+)
15
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/or-irq.h"
22
#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
23
#include "hw/misc/xlnx-zynqmp-crf.h"
24
+#include "hw/timer/cadence_ttc.h"
25
26
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
27
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
30
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
31
32
+#define XLNX_ZYNQMP_NUM_TTC 4
33
+
34
/*
35
* Unimplemented mmio regions needed to boot some images.
36
*/
37
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
38
qemu_or_irq qspi_irq_orgate;
39
XlnxZynqMPAPUCtrl apu_ctrl;
40
XlnxZynqMPCRF crf;
41
+ CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC];
42
43
char *boot_cpu;
44
ARMCPU *boot_cpu_ptr;
45
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/xlnx-zynqmp.c
48
+++ b/hw/arm/xlnx-zynqmp.c
49
@@ -XXX,XX +XXX,XX @@
50
#define APU_ADDR 0xfd5c0000
51
#define APU_IRQ 153
52
53
+#define TTC0_ADDR 0xFF110000
54
+#define TTC0_IRQ 36
55
+
56
#define IPI_ADDR 0xFF300000
57
#define IPI_IRQ 64
58
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_crf(XlnxZynqMPState *s, qemu_irq *gic)
60
sysbus_connect_irq(sbd, 0, gic[CRF_IRQ]);
61
}
62
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
64
+{
65
+ SysBusDevice *sbd;
66
+ int i, irq;
67
+
68
+ for (i = 0; i < XLNX_ZYNQMP_NUM_TTC; i++) {
69
+ object_initialize_child(OBJECT(s), "ttc[*]", &s->ttc[i],
70
+ TYPE_CADENCE_TTC);
71
+ sbd = SYS_BUS_DEVICE(&s->ttc[i]);
72
+
73
+ sysbus_realize(sbd, &error_fatal);
74
+ sysbus_mmio_map(sbd, 0, TTC0_ADDR + i * 0x10000);
75
+ for (irq = 0; irq < 3; irq++) {
76
+ sysbus_connect_irq(sbd, irq, gic[TTC0_IRQ + i * 3 + irq]);
77
+ }
78
+ }
79
+}
80
+
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
82
{
83
static const struct UnimpInfo {
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
85
xlnx_zynqmp_create_efuse(s, gic_spi);
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
87
xlnx_zynqmp_create_crf(s, gic_spi);
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
89
xlnx_zynqmp_create_unimp_mmio(s);
90
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
92
--
93
2.25.1
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Create an APU CPU Cluster. This is in preparation to add the RPU.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Message-id: 20220406174303.2022038-2-edgar.iglesias@xilinx.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/arm/xlnx-versal.h | 2 ++
11
hw/arm/xlnx-versal.c | 9 ++++++++-
12
2 files changed, 10 insertions(+), 1 deletion(-)
13
14
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/xlnx-versal.h
17
+++ b/include/hw/arm/xlnx-versal.h
18
@@ -XXX,XX +XXX,XX @@
19
20
#include "hw/sysbus.h"
21
#include "hw/arm/boot.h"
22
+#include "hw/cpu/cluster.h"
23
#include "hw/or-irq.h"
24
#include "hw/sd/sdhci.h"
25
#include "hw/intc/arm_gicv3.h"
26
@@ -XXX,XX +XXX,XX @@ struct Versal {
27
struct {
28
struct {
29
MemoryRegion mr;
30
+ CPUClusterState cluster;
31
ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
32
GICv3State gic;
33
} apu;
34
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/xlnx-versal.c
37
+++ b/hw/arm/xlnx-versal.c
38
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
39
{
40
int i;
41
42
+ object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
43
+ TYPE_CPU_CLUSTER);
44
+ qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
45
+
46
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
47
Object *obj;
48
49
- object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
50
+ object_initialize_child(OBJECT(&s->fpd.apu.cluster),
51
+ "apu-cpu[*]", &s->fpd.apu.cpu[i],
52
XLNX_VERSAL_ACPU_TYPE);
53
obj = OBJECT(&s->fpd.apu.cpu[i]);
54
if (i) {
55
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
56
&error_abort);
57
qdev_realize(DEVICE(obj), NULL, &error_fatal);
58
}
59
+
60
+ qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
61
}
62
63
static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
64
--
65
2.25.1
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
4
subsystem.
5
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
12
hw/arm/xlnx-versal-virt.c | 6 +++---
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
14
3 files changed, 49 insertions(+), 3 deletions(-)
15
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-versal.h
19
+++ b/include/hw/arm/xlnx-versal.h
20
@@ -XXX,XX +XXX,XX @@
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
22
23
#define XLNX_VERSAL_NR_ACPUS 2
24
+#define XLNX_VERSAL_NR_RCPUS 2
25
#define XLNX_VERSAL_NR_UARTS 2
26
#define XLNX_VERSAL_NR_GEMS 2
27
#define XLNX_VERSAL_NR_ADMAS 8
28
@@ -XXX,XX +XXX,XX @@ struct Versal {
29
VersalUsb2 usb;
30
} iou;
31
32
+ /* Real-time Processing Unit. */
33
+ struct {
34
+ MemoryRegion mr;
35
+ MemoryRegion mr_ps_alias;
36
+
37
+ CPUClusterState cluster;
38
+ ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
39
+ } rpu;
40
+
41
struct {
42
qemu_or_irq irq_orgate;
43
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
44
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal-virt.c
47
+++ b/hw/arm/xlnx-versal-virt.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
49
50
mc->desc = "Xilinx Versal Virtual development board";
51
mc->init = versal_virt_init;
52
- mc->min_cpus = XLNX_VERSAL_NR_ACPUS;
53
- mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
54
- mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
55
+ mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
56
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
57
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
58
mc->no_cdrom = true;
59
mc->default_ram_id = "ddr";
60
}
61
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/xlnx-versal.c
64
+++ b/hw/arm/xlnx-versal.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/sysbus.h"
67
68
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
69
+#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
70
#define GEM_REVISION 0x40070106
71
72
#define VERSAL_NUM_PMC_APB_IRQS 3
73
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
74
}
75
}
76
77
+static void versal_create_rpu_cpus(Versal *s)
78
+{
79
+ int i;
80
+
81
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
82
+ TYPE_CPU_CLUSTER);
83
+ qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
84
+
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
86
+ Object *obj;
87
+
88
+ object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
89
+ "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
90
+ XLNX_VERSAL_RCPU_TYPE);
91
+ obj = OBJECT(&s->lpd.rpu.cpu[i]);
92
+ object_property_set_bool(obj, "start-powered-off", true,
93
+ &error_abort);
94
+
95
+ object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
96
+ object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
97
+ &error_abort);
98
+ object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
99
+ &error_abort);
100
+ qdev_realize(DEVICE(obj), NULL, &error_fatal);
101
+ }
102
+
103
+ qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
104
+}
105
+
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
107
{
108
int i;
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
110
111
versal_create_apu_cpus(s);
112
versal_create_apu_gic(s, pic);
113
+ versal_create_rpu_cpus(s);
114
versal_create_uarts(s, pic);
115
versal_create_usbs(s, pic);
116
versal_create_gems(s, pic);
117
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
118
119
memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
120
memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
121
+ memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
122
+ &s->lpd.rpu.mr_ps_alias, 0);
123
}
124
125
static void versal_init(Object *obj)
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
127
Versal *s = XLNX_VERSAL(obj);
128
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
134
}
135
136
static Property versal_properties[] = {
137
--
138
2.25.1
diff view generated by jsdifflib
1
From: Alexandre Iooss <erdnaxe@crans.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
This SoC is similar to stm32f205 SoC.
3
Add a model of the Xilinx Versal CRL.
4
This will be used by the STM32VLDISCOVERY to create a machine.
5
4
6
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
8
Message-id: 20210617165647.2575955-2-erdnaxe@crans.org
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
include/hw/arm/stm32f100_soc.h | 57 +++++++++++
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
12
hw/arm/stm32f100_soc.c | 182 +++++++++++++++++++++++++++++++++
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
13
MAINTAINERS | 6 ++
13
hw/misc/meson.build | 1 +
14
hw/arm/Kconfig | 6 ++
14
3 files changed, 657 insertions(+)
15
hw/arm/meson.build | 1 +
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
16
5 files changed, 252 insertions(+)
16
create mode 100644 hw/misc/xlnx-versal-crl.c
17
create mode 100644 include/hw/arm/stm32f100_soc.h
18
create mode 100644 hw/arm/stm32f100_soc.c
19
17
20
diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
21
new file mode 100644
19
new file mode 100644
22
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
23
--- /dev/null
21
--- /dev/null
24
+++ b/include/hw/arm/stm32f100_soc.h
22
+++ b/include/hw/misc/xlnx-versal-crl.h
25
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
26
+/*
24
+/*
27
+ * STM32F100 SoC
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
28
+ *
26
+ *
29
+ * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
27
+ * Copyright (c) 2022 Xilinx Inc.
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
30
+ *
29
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
48
+ */
31
+ */
49
+
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
50
+#ifndef HW_ARM_STM32F100_SOC_H
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
51
+#define HW_ARM_STM32F100_SOC_H
34
+
52
+
35
+#include "hw/sysbus.h"
53
+#include "hw/char/stm32f2xx_usart.h"
36
+#include "hw/register.h"
54
+#include "hw/ssi/stm32f2xx_spi.h"
37
+#include "target/arm/cpu.h"
55
+#include "hw/arm/armv7m.h"
38
+
56
+#include "qom/object.h"
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
57
+
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
58
+#define TYPE_STM32F100_SOC "stm32f100-soc"
41
+
59
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC)
42
+REG32(ERR_CTRL, 0x0)
60
+
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
61
+#define STM_NUM_USARTS 3
44
+REG32(IR_STATUS, 0x4)
62
+#define STM_NUM_SPIS 2
45
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
63
+
46
+REG32(IR_MASK, 0x8)
64
+#define FLASH_BASE_ADDRESS 0x08000000
47
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
65
+#define FLASH_SIZE (128 * 1024)
48
+REG32(IR_ENABLE, 0xc)
66
+#define SRAM_BASE_ADDRESS 0x20000000
49
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
67
+#define SRAM_SIZE (8 * 1024)
50
+REG32(IR_DISABLE, 0x10)
68
+
51
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
69
+struct STM32F100State {
52
+REG32(WPROT, 0x1c)
70
+ /*< private >*/
53
+ FIELD(WPROT, ACTIVE, 0, 1)
54
+REG32(PLL_CLK_OTHER_DMN, 0x20)
55
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
56
+REG32(RPLL_CTRL, 0x40)
57
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
58
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
59
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
60
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
61
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
62
+ FIELD(RPLL_CTRL, RESET, 0, 1)
63
+REG32(RPLL_CFG, 0x44)
64
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
65
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
66
+ FIELD(RPLL_CFG, LFHF, 10, 2)
67
+ FIELD(RPLL_CFG, CP, 5, 4)
68
+ FIELD(RPLL_CFG, RES, 0, 4)
69
+REG32(RPLL_FRAC_CFG, 0x48)
70
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
71
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
72
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
73
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
74
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
75
+REG32(PLL_STATUS, 0x50)
76
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
77
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
78
+REG32(RPLL_TO_XPD_CTRL, 0x100)
79
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
80
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
81
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
82
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
83
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
84
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
85
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
86
+REG32(LPD_LSBUS_CTRL, 0x108)
87
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
88
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
89
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
90
+REG32(CPU_R5_CTRL, 0x10c)
91
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
92
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
93
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
94
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
95
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
96
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
97
+REG32(IOU_SWITCH_CTRL, 0x114)
98
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
99
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
100
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
101
+REG32(GEM0_REF_CTRL, 0x118)
102
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
103
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
104
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
105
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
106
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
107
+REG32(GEM1_REF_CTRL, 0x11c)
108
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
109
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
110
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
111
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
112
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
113
+REG32(GEM_TSU_REF_CTRL, 0x120)
114
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
115
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
116
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
117
+REG32(USB0_BUS_REF_CTRL, 0x124)
118
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
119
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
120
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
121
+REG32(UART0_REF_CTRL, 0x128)
122
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
123
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
124
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
125
+REG32(UART1_REF_CTRL, 0x12c)
126
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
127
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
128
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
129
+REG32(SPI0_REF_CTRL, 0x130)
130
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
131
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
132
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
133
+REG32(SPI1_REF_CTRL, 0x134)
134
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
135
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
136
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
137
+REG32(CAN0_REF_CTRL, 0x138)
138
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
139
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
140
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
141
+REG32(CAN1_REF_CTRL, 0x13c)
142
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
143
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
144
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
145
+REG32(I2C0_REF_CTRL, 0x140)
146
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
147
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
148
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
149
+REG32(I2C1_REF_CTRL, 0x144)
150
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
151
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
152
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
153
+REG32(DBG_LPD_CTRL, 0x148)
154
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
155
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
156
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
157
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
158
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
159
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
160
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
161
+REG32(CRL_SAFETY_CHK, 0x150)
162
+REG32(PSM_REF_CTRL, 0x154)
163
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
164
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
165
+REG32(DBG_TSTMP_CTRL, 0x158)
166
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
167
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
168
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
169
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
170
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
171
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
172
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
173
+REG32(USB3_DUAL_REF_CTRL, 0x160)
174
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
175
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
176
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
177
+REG32(RST_CPU_R5, 0x300)
178
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
179
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
180
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
181
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
182
+REG32(RST_ADMA, 0x304)
183
+ FIELD(RST_ADMA, RESET, 0, 1)
184
+REG32(RST_GEM0, 0x308)
185
+ FIELD(RST_GEM0, RESET, 0, 1)
186
+REG32(RST_GEM1, 0x30c)
187
+ FIELD(RST_GEM1, RESET, 0, 1)
188
+REG32(RST_SPARE, 0x310)
189
+ FIELD(RST_SPARE, RESET, 0, 1)
190
+REG32(RST_USB0, 0x314)
191
+ FIELD(RST_USB0, RESET, 0, 1)
192
+REG32(RST_UART0, 0x318)
193
+ FIELD(RST_UART0, RESET, 0, 1)
194
+REG32(RST_UART1, 0x31c)
195
+ FIELD(RST_UART1, RESET, 0, 1)
196
+REG32(RST_SPI0, 0x320)
197
+ FIELD(RST_SPI0, RESET, 0, 1)
198
+REG32(RST_SPI1, 0x324)
199
+ FIELD(RST_SPI1, RESET, 0, 1)
200
+REG32(RST_CAN0, 0x328)
201
+ FIELD(RST_CAN0, RESET, 0, 1)
202
+REG32(RST_CAN1, 0x32c)
203
+ FIELD(RST_CAN1, RESET, 0, 1)
204
+REG32(RST_I2C0, 0x330)
205
+ FIELD(RST_I2C0, RESET, 0, 1)
206
+REG32(RST_I2C1, 0x334)
207
+ FIELD(RST_I2C1, RESET, 0, 1)
208
+REG32(RST_DBG_LPD, 0x338)
209
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
210
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
211
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
212
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
213
+REG32(RST_GPIO, 0x33c)
214
+ FIELD(RST_GPIO, RESET, 0, 1)
215
+REG32(RST_TTC, 0x344)
216
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
217
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
218
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
219
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
220
+REG32(RST_TIMESTAMP, 0x348)
221
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
222
+REG32(RST_SWDT, 0x34c)
223
+ FIELD(RST_SWDT, RESET, 0, 1)
224
+REG32(RST_OCM, 0x350)
225
+ FIELD(RST_OCM, RESET, 0, 1)
226
+REG32(RST_IPI, 0x354)
227
+ FIELD(RST_IPI, RESET, 0, 1)
228
+REG32(RST_SYSMON, 0x358)
229
+ FIELD(RST_SYSMON, SEQ_RST, 1, 1)
230
+ FIELD(RST_SYSMON, CFG_RST, 0, 1)
231
+REG32(RST_FPD, 0x360)
232
+ FIELD(RST_FPD, SRST, 1, 1)
233
+ FIELD(RST_FPD, POR, 0, 1)
234
+REG32(PSM_RST_MODE, 0x370)
235
+ FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
236
+ FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
237
+
238
+#define CRL_R_MAX (R_PSM_RST_MODE + 1)
239
+
240
+#define RPU_MAX_CPU 2
241
+
242
+struct XlnxVersalCRL {
71
+ SysBusDevice parent_obj;
243
+ SysBusDevice parent_obj;
72
+
244
+ qemu_irq irq;
73
+ /*< public >*/
245
+
74
+ char *cpu_type;
246
+ struct {
75
+
247
+ ARMCPU *cpu_r5[RPU_MAX_CPU];
76
+ ARMv7MState armv7m;
248
+ DeviceState *adma[8];
77
+
249
+ DeviceState *uart[2];
78
+ STM32F2XXUsartState usart[STM_NUM_USARTS];
250
+ DeviceState *gem[2];
79
+ STM32F2XXSPIState spi[STM_NUM_SPIS];
251
+ DeviceState *usb;
252
+ } cfg;
253
+
254
+ RegisterInfoArray *reg_array;
255
+ uint32_t regs[CRL_R_MAX];
256
+ RegisterInfo regs_info[CRL_R_MAX];
80
+};
257
+};
81
+
82
+#endif
258
+#endif
83
diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c
259
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
84
new file mode 100644
260
new file mode 100644
85
index XXXXXXX..XXXXXXX
261
index XXXXXXX..XXXXXXX
86
--- /dev/null
262
--- /dev/null
87
+++ b/hw/arm/stm32f100_soc.c
263
+++ b/hw/misc/xlnx-versal-crl.c
88
@@ -XXX,XX +XXX,XX @@
264
@@ -XXX,XX +XXX,XX @@
89
+/*
265
+/*
90
+ * STM32F100 SoC
266
+ * QEMU model of the Clock-Reset-LPD (CRL).
91
+ *
267
+ *
92
+ * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
268
+ * Copyright (c) 2022 Advanced Micro Devices, Inc.
93
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
269
+ * SPDX-License-Identifier: GPL-2.0-or-later
94
+ *
270
+ *
95
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
271
+ * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
96
+ * of this software and associated documentation files (the "Software"), to deal
97
+ * in the Software without restriction, including without limitation the rights
98
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99
+ * copies of the Software, and to permit persons to whom the Software is
100
+ * furnished to do so, subject to the following conditions:
101
+ *
102
+ * The above copyright notice and this permission notice shall be included in
103
+ * all copies or substantial portions of the Software.
104
+ *
105
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
106
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
107
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
108
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
109
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
110
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
111
+ * THE SOFTWARE.
112
+ */
272
+ */
113
+
273
+
114
+#include "qemu/osdep.h"
274
+#include "qemu/osdep.h"
115
+#include "qapi/error.h"
275
+#include "qapi/error.h"
116
+#include "qemu/module.h"
276
+#include "qemu/log.h"
117
+#include "hw/arm/boot.h"
277
+#include "qemu/bitops.h"
118
+#include "exec/address-spaces.h"
278
+#include "migration/vmstate.h"
119
+#include "hw/arm/stm32f100_soc.h"
120
+#include "hw/qdev-properties.h"
279
+#include "hw/qdev-properties.h"
121
+#include "hw/misc/unimp.h"
280
+#include "hw/sysbus.h"
122
+#include "sysemu/sysemu.h"
281
+#include "hw/irq.h"
123
+
282
+#include "hw/register.h"
124
+/* stm32f100_soc implementation is derived from stm32f205_soc */
283
+#include "hw/resettable.h"
125
+
284
+
126
+static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40013800, 0x40004400,
285
+#include "target/arm/arm-powerctl.h"
127
+ 0x40004800 };
286
+#include "hw/misc/xlnx-versal-crl.h"
128
+static const uint32_t spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800 };
287
+
129
+
288
+#ifndef XLNX_VERSAL_CRL_ERR_DEBUG
130
+static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39};
289
+#define XLNX_VERSAL_CRL_ERR_DEBUG 0
131
+static const int spi_irq[STM_NUM_SPIS] = {35, 36};
290
+#endif
132
+
291
+
133
+static void stm32f100_soc_initfn(Object *obj)
292
+static void crl_update_irq(XlnxVersalCRL *s)
134
+{
293
+{
135
+ STM32F100State *s = STM32F100_SOC(obj);
294
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
295
+ qemu_set_irq(s->irq, pending);
296
+}
297
+
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
299
+{
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
301
+ crl_update_irq(s);
302
+}
303
+
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
305
+{
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
307
+ uint32_t val = val64;
308
+
309
+ s->regs[R_IR_MASK] &= ~val;
310
+ crl_update_irq(s);
311
+ return 0;
312
+}
313
+
314
+static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
315
+{
316
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
317
+ uint32_t val = val64;
318
+
319
+ s->regs[R_IR_MASK] |= val;
320
+ crl_update_irq(s);
321
+ return 0;
322
+}
323
+
324
+static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
325
+ bool rst_old, bool rst_new)
326
+{
327
+ device_cold_reset(dev);
328
+}
329
+
330
+static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
331
+ bool rst_old, bool rst_new)
332
+{
333
+ if (rst_new) {
334
+ arm_set_cpu_off(armcpu->mp_affinity);
335
+ } else {
336
+ arm_set_cpu_on_and_reset(armcpu->mp_affinity);
337
+ }
338
+}
339
+
340
+#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \
341
+ bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \
342
+ bool new_f = FIELD_EX32(new_val, reg, f); \
343
+ \
344
+ /* Detect edges. */ \
345
+ if (dev && old_f != new_f) { \
346
+ crl_reset_ ## type(s, dev, old_f, new_f); \
347
+ } \
348
+}
349
+
350
+static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
351
+{
352
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
353
+
354
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
355
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
356
+ return val64;
357
+}
358
+
359
+static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
360
+{
361
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
136
+ int i;
362
+ int i;
137
+
363
+
138
+ object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M);
364
+ /* A single register fans out to all ADMA reset inputs. */
139
+
365
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
140
+ for (i = 0; i < STM_NUM_USARTS; i++) {
366
+ REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
141
+ object_initialize_child(obj, "usart[*]", &s->usart[i],
367
+ }
142
+ TYPE_STM32F2XX_USART);
368
+ return val64;
143
+ }
369
+}
144
+
370
+
145
+ for (i = 0; i < STM_NUM_SPIS; i++) {
371
+static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
146
+ object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI);
372
+{
147
+ }
373
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
148
+}
374
+
149
+
375
+ REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
150
+static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
376
+ return val64;
151
+{
377
+}
152
+ STM32F100State *s = STM32F100_SOC(dev_soc);
378
+
153
+ DeviceState *dev, *armv7m;
379
+static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
154
+ SysBusDevice *busdev;
380
+{
381
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
382
+
383
+ REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
384
+ return val64;
385
+}
386
+
387
+static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
388
+{
389
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
390
+
391
+ REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
392
+ return val64;
393
+}
394
+
395
+static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
396
+{
397
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
398
+
399
+ REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
400
+ return val64;
401
+}
402
+
403
+static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
404
+{
405
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
406
+
407
+ REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
408
+ return val64;
409
+}
410
+
411
+static const RegisterAccessInfo crl_regs_info[] = {
412
+ { .name = "ERR_CTRL", .addr = A_ERR_CTRL,
413
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
414
+ .w1c = 0x1,
415
+ .post_write = crl_status_postw,
416
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
417
+ .reset = 0x1,
418
+ .ro = 0x1,
419
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
420
+ .pre_write = crl_enable_prew,
421
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
422
+ .pre_write = crl_disable_prew,
423
+ },{ .name = "WPROT", .addr = A_WPROT,
424
+ },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN,
425
+ .reset = 0x1,
426
+ .rsvd = 0xe,
427
+ },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL,
428
+ .reset = 0x24809,
429
+ .rsvd = 0xf88c00f6,
430
+ },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG,
431
+ .reset = 0x2000000,
432
+ .rsvd = 0x1801210,
433
+ },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG,
434
+ .rsvd = 0x7e330000,
435
+ },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS,
436
+ .reset = R_PLL_STATUS_RPLL_STABLE_MASK |
437
+ R_PLL_STATUS_RPLL_LOCK_MASK,
438
+ .rsvd = 0xfa,
439
+ .ro = 0x5,
440
+ },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL,
441
+ .reset = 0x2000100,
442
+ .rsvd = 0xfdfc00ff,
443
+ },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL,
444
+ .reset = 0x6000300,
445
+ .rsvd = 0xf9fc00f8,
446
+ },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL,
447
+ .reset = 0x2000800,
448
+ .rsvd = 0xfdfc00f8,
449
+ },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL,
450
+ .reset = 0xe000300,
451
+ .rsvd = 0xe1fc00f8,
452
+ },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL,
453
+ .reset = 0x2000500,
454
+ .rsvd = 0xfdfc00f8,
455
+ },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL,
456
+ .reset = 0xe000a00,
457
+ .rsvd = 0xf1fc00f8,
458
+ },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL,
459
+ .reset = 0xe000a00,
460
+ .rsvd = 0xf1fc00f8,
461
+ },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL,
462
+ .reset = 0x300,
463
+ .rsvd = 0xfdfc00f8,
464
+ },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL,
465
+ .reset = 0x2001900,
466
+ .rsvd = 0xfdfc00f8,
467
+ },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL,
468
+ .reset = 0xc00,
469
+ .rsvd = 0xfdfc00f8,
470
+ },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL,
471
+ .reset = 0xc00,
472
+ .rsvd = 0xfdfc00f8,
473
+ },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL,
474
+ .reset = 0x600,
475
+ .rsvd = 0xfdfc00f8,
476
+ },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL,
477
+ .reset = 0x600,
478
+ .rsvd = 0xfdfc00f8,
479
+ },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL,
480
+ .reset = 0xc00,
481
+ .rsvd = 0xfdfc00f8,
482
+ },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL,
483
+ .reset = 0xc00,
484
+ .rsvd = 0xfdfc00f8,
485
+ },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL,
486
+ .reset = 0xc00,
487
+ .rsvd = 0xfdfc00f8,
488
+ },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL,
489
+ .reset = 0xc00,
490
+ .rsvd = 0xfdfc00f8,
491
+ },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL,
492
+ .reset = 0x300,
493
+ .rsvd = 0xfdfc00f8,
494
+ },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL,
495
+ .reset = 0x2000c00,
496
+ .rsvd = 0xfdfc00f8,
497
+ },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK,
498
+ },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL,
499
+ .reset = 0xf04,
500
+ .rsvd = 0xfffc00f8,
501
+ },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL,
502
+ .reset = 0x300,
503
+ .rsvd = 0xfdfc00f8,
504
+ },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL,
505
+ .reset = 0x300,
506
+ .rsvd = 0xfdfc00f8,
507
+ },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL,
508
+ .reset = 0x3c00,
509
+ .rsvd = 0xfdfc00f8,
510
+ },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5,
511
+ .reset = 0x17,
512
+ .rsvd = 0x8,
513
+ .pre_write = crl_rst_r5_prew,
514
+ },{ .name = "RST_ADMA", .addr = A_RST_ADMA,
515
+ .reset = 0x1,
516
+ .pre_write = crl_rst_adma_prew,
517
+ },{ .name = "RST_GEM0", .addr = A_RST_GEM0,
518
+ .reset = 0x1,
519
+ .pre_write = crl_rst_gem0_prew,
520
+ },{ .name = "RST_GEM1", .addr = A_RST_GEM1,
521
+ .reset = 0x1,
522
+ .pre_write = crl_rst_gem1_prew,
523
+ },{ .name = "RST_SPARE", .addr = A_RST_SPARE,
524
+ .reset = 0x1,
525
+ },{ .name = "RST_USB0", .addr = A_RST_USB0,
526
+ .reset = 0x1,
527
+ .pre_write = crl_rst_usb_prew,
528
+ },{ .name = "RST_UART0", .addr = A_RST_UART0,
529
+ .reset = 0x1,
530
+ .pre_write = crl_rst_uart0_prew,
531
+ },{ .name = "RST_UART1", .addr = A_RST_UART1,
532
+ .reset = 0x1,
533
+ .pre_write = crl_rst_uart1_prew,
534
+ },{ .name = "RST_SPI0", .addr = A_RST_SPI0,
535
+ .reset = 0x1,
536
+ },{ .name = "RST_SPI1", .addr = A_RST_SPI1,
537
+ .reset = 0x1,
538
+ },{ .name = "RST_CAN0", .addr = A_RST_CAN0,
539
+ .reset = 0x1,
540
+ },{ .name = "RST_CAN1", .addr = A_RST_CAN1,
541
+ .reset = 0x1,
542
+ },{ .name = "RST_I2C0", .addr = A_RST_I2C0,
543
+ .reset = 0x1,
544
+ },{ .name = "RST_I2C1", .addr = A_RST_I2C1,
545
+ .reset = 0x1,
546
+ },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD,
547
+ .reset = 0x33,
548
+ .rsvd = 0xcc,
549
+ },{ .name = "RST_GPIO", .addr = A_RST_GPIO,
550
+ .reset = 0x1,
551
+ },{ .name = "RST_TTC", .addr = A_RST_TTC,
552
+ .reset = 0xf,
553
+ },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP,
554
+ .reset = 0x1,
555
+ },{ .name = "RST_SWDT", .addr = A_RST_SWDT,
556
+ .reset = 0x1,
557
+ },{ .name = "RST_OCM", .addr = A_RST_OCM,
558
+ },{ .name = "RST_IPI", .addr = A_RST_IPI,
559
+ },{ .name = "RST_FPD", .addr = A_RST_FPD,
560
+ .reset = 0x3,
561
+ },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE,
562
+ .reset = 0x1,
563
+ .rsvd = 0xf8,
564
+ }
565
+};
566
+
567
+static void crl_reset_enter(Object *obj, ResetType type)
568
+{
569
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
570
+ unsigned int i;
571
+
572
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
573
+ register_reset(&s->regs_info[i]);
574
+ }
575
+}
576
+
577
+static void crl_reset_hold(Object *obj)
578
+{
579
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
580
+
581
+ crl_update_irq(s);
582
+}
583
+
584
+static const MemoryRegionOps crl_ops = {
585
+ .read = register_read_memory,
586
+ .write = register_write_memory,
587
+ .endianness = DEVICE_LITTLE_ENDIAN,
588
+ .valid = {
589
+ .min_access_size = 4,
590
+ .max_access_size = 4,
591
+ },
592
+};
593
+
594
+static void crl_init(Object *obj)
595
+{
596
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
597
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
155
+ int i;
598
+ int i;
156
+
599
+
157
+ MemoryRegion *system_memory = get_system_memory();
600
+ s->reg_array =
158
+ MemoryRegion *sram = g_new(MemoryRegion, 1);
601
+ register_init_block32(DEVICE(obj), crl_regs_info,
159
+ MemoryRegion *flash = g_new(MemoryRegion, 1);
602
+ ARRAY_SIZE(crl_regs_info),
160
+ MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
603
+ s->regs_info, s->regs,
161
+
604
+ &crl_ops,
162
+ /*
605
+ XLNX_VERSAL_CRL_ERR_DEBUG,
163
+ * Init flash region
606
+ CRL_R_MAX * 4);
164
+ * Flash starts at 0x08000000 and then is aliased to boot memory at 0x0
607
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
165
+ */
608
+ sysbus_init_irq(sbd, &s->irq);
166
+ memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F100.flash",
609
+
167
+ FLASH_SIZE, &error_fatal);
610
+ for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
168
+ memory_region_init_alias(flash_alias, OBJECT(dev_soc),
611
+ object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
169
+ "STM32F100.flash.alias", flash, 0, FLASH_SIZE);
612
+ (Object **)&s->cfg.cpu_r5[i],
170
+ memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
613
+ qdev_prop_allow_set_link_before_realize,
171
+ memory_region_add_subregion(system_memory, 0, flash_alias);
614
+ OBJ_PROP_LINK_STRONG);
172
+
615
+ }
173
+ /* Init SRAM region */
616
+
174
+ memory_region_init_ram(sram, NULL, "STM32F100.sram", SRAM_SIZE,
617
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
175
+ &error_fatal);
618
+ object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
176
+ memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
619
+ (Object **)&s->cfg.adma[i],
177
+
620
+ qdev_prop_allow_set_link_before_realize,
178
+ /* Init ARMv7m */
621
+ OBJ_PROP_LINK_STRONG);
179
+ armv7m = DEVICE(&s->armv7m);
622
+ }
180
+ qdev_prop_set_uint32(armv7m, "num-irq", 61);
623
+
181
+ qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
624
+ for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
182
+ qdev_prop_set_bit(armv7m, "enable-bitband", true);
625
+ object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
183
+ object_property_set_link(OBJECT(&s->armv7m), "memory",
626
+ (Object **)&s->cfg.uart[i],
184
+ OBJECT(get_system_memory()), &error_abort);
627
+ qdev_prop_allow_set_link_before_realize,
185
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
628
+ OBJ_PROP_LINK_STRONG);
186
+ return;
629
+ }
187
+ }
630
+
188
+
631
+ for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
189
+ /* Attach UART (uses USART registers) and USART controllers */
632
+ object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
190
+ for (i = 0; i < STM_NUM_USARTS; i++) {
633
+ (Object **)&s->cfg.gem[i],
191
+ dev = DEVICE(&(s->usart[i]));
634
+ qdev_prop_allow_set_link_before_realize,
192
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
635
+ OBJ_PROP_LINK_STRONG);
193
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usart[i]), errp)) {
636
+ }
194
+ return;
637
+
195
+ }
638
+ object_property_add_link(obj, "usb", TYPE_DEVICE,
196
+ busdev = SYS_BUS_DEVICE(dev);
639
+ (Object **)&s->cfg.gem[i],
197
+ sysbus_mmio_map(busdev, 0, usart_addr[i]);
640
+ qdev_prop_allow_set_link_before_realize,
198
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
641
+ OBJ_PROP_LINK_STRONG);
199
+ }
642
+}
200
+
643
+
201
+ /* SPI 1 and 2 */
644
+static void crl_finalize(Object *obj)
202
+ for (i = 0; i < STM_NUM_SPIS; i++) {
645
+{
203
+ dev = DEVICE(&(s->spi[i]));
646
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
204
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
647
+ register_finalize_block(s->reg_array);
205
+ return;
648
+}
206
+ }
649
+
207
+ busdev = SYS_BUS_DEVICE(dev);
650
+static const VMStateDescription vmstate_crl = {
208
+ sysbus_mmio_map(busdev, 0, spi_addr[i]);
651
+ .name = TYPE_XLNX_VERSAL_CRL,
209
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
652
+ .version_id = 1,
210
+ }
653
+ .minimum_version_id = 1,
211
+
654
+ .fields = (VMStateField[]) {
212
+ create_unimplemented_device("timer[2]", 0x40000000, 0x400);
655
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
213
+ create_unimplemented_device("timer[3]", 0x40000400, 0x400);
656
+ VMSTATE_END_OF_LIST(),
214
+ create_unimplemented_device("timer[4]", 0x40000800, 0x400);
657
+ }
215
+ create_unimplemented_device("timer[6]", 0x40001000, 0x400);
216
+ create_unimplemented_device("timer[7]", 0x40001400, 0x400);
217
+ create_unimplemented_device("RTC", 0x40002800, 0x400);
218
+ create_unimplemented_device("WWDG", 0x40002C00, 0x400);
219
+ create_unimplemented_device("IWDG", 0x40003000, 0x400);
220
+ create_unimplemented_device("I2C1", 0x40005400, 0x400);
221
+ create_unimplemented_device("I2C2", 0x40005800, 0x400);
222
+ create_unimplemented_device("BKP", 0x40006C00, 0x400);
223
+ create_unimplemented_device("PWR", 0x40007000, 0x400);
224
+ create_unimplemented_device("DAC", 0x40007400, 0x400);
225
+ create_unimplemented_device("CEC", 0x40007800, 0x400);
226
+ create_unimplemented_device("AFIO", 0x40010000, 0x400);
227
+ create_unimplemented_device("EXTI", 0x40010400, 0x400);
228
+ create_unimplemented_device("GPIOA", 0x40010800, 0x400);
229
+ create_unimplemented_device("GPIOB", 0x40010C00, 0x400);
230
+ create_unimplemented_device("GPIOC", 0x40011000, 0x400);
231
+ create_unimplemented_device("GPIOD", 0x40011400, 0x400);
232
+ create_unimplemented_device("GPIOE", 0x40011800, 0x400);
233
+ create_unimplemented_device("ADC1", 0x40012400, 0x400);
234
+ create_unimplemented_device("timer[1]", 0x40012C00, 0x400);
235
+ create_unimplemented_device("timer[15]", 0x40014000, 0x400);
236
+ create_unimplemented_device("timer[16]", 0x40014400, 0x400);
237
+ create_unimplemented_device("timer[17]", 0x40014800, 0x400);
238
+ create_unimplemented_device("DMA", 0x40020000, 0x400);
239
+ create_unimplemented_device("RCC", 0x40021000, 0x400);
240
+ create_unimplemented_device("Flash Int", 0x40022000, 0x400);
241
+ create_unimplemented_device("CRC", 0x40023000, 0x400);
242
+}
243
+
244
+static Property stm32f100_soc_properties[] = {
245
+ DEFINE_PROP_STRING("cpu-type", STM32F100State, cpu_type),
246
+ DEFINE_PROP_END_OF_LIST(),
247
+};
658
+};
248
+
659
+
249
+static void stm32f100_soc_class_init(ObjectClass *klass, void *data)
660
+static void crl_class_init(ObjectClass *klass, void *data)
250
+{
661
+{
662
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
251
+ DeviceClass *dc = DEVICE_CLASS(klass);
663
+ DeviceClass *dc = DEVICE_CLASS(klass);
252
+
664
+
253
+ dc->realize = stm32f100_soc_realize;
665
+ dc->vmsd = &vmstate_crl;
254
+ device_class_set_props(dc, stm32f100_soc_properties);
666
+
255
+}
667
+ rc->phases.enter = crl_reset_enter;
256
+
668
+ rc->phases.hold = crl_reset_hold;
257
+static const TypeInfo stm32f100_soc_info = {
669
+}
258
+ .name = TYPE_STM32F100_SOC,
670
+
671
+static const TypeInfo crl_info = {
672
+ .name = TYPE_XLNX_VERSAL_CRL,
259
+ .parent = TYPE_SYS_BUS_DEVICE,
673
+ .parent = TYPE_SYS_BUS_DEVICE,
260
+ .instance_size = sizeof(STM32F100State),
674
+ .instance_size = sizeof(XlnxVersalCRL),
261
+ .instance_init = stm32f100_soc_initfn,
675
+ .class_init = crl_class_init,
262
+ .class_init = stm32f100_soc_class_init,
676
+ .instance_init = crl_init,
677
+ .instance_finalize = crl_finalize,
263
+};
678
+};
264
+
679
+
265
+static void stm32f100_soc_types(void)
680
+static void crl_register_types(void)
266
+{
681
+{
267
+ type_register_static(&stm32f100_soc_info);
682
+ type_register_static(&crl_info);
268
+}
683
+}
269
+
684
+
270
+type_init(stm32f100_soc_types)
685
+type_init(crl_register_types)
271
diff --git a/MAINTAINERS b/MAINTAINERS
686
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
272
index XXXXXXX..XXXXXXX 100644
687
index XXXXXXX..XXXXXXX 100644
273
--- a/MAINTAINERS
688
--- a/hw/misc/meson.build
274
+++ b/MAINTAINERS
689
+++ b/hw/misc/meson.build
275
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
276
S: Maintained
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
277
F: hw/arm/virt-acpi-build.c
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
278
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
279
+STM32F100
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
280
+M: Alexandre Iooss <erdnaxe@crans.org>
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
281
+L: qemu-arm@nongnu.org
696
'xlnx-versal-xramc.c',
282
+S: Maintained
697
'xlnx-versal-pmc-iou-slcr.c',
283
+F: hw/arm/stm32f100_soc.c
284
+
285
STM32F205
286
M: Alistair Francis <alistair@alistair23.me>
287
M: Peter Maydell <peter.maydell@linaro.org>
288
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
289
index XXXXXXX..XXXXXXX 100644
290
--- a/hw/arm/Kconfig
291
+++ b/hw/arm/Kconfig
292
@@ -XXX,XX +XXX,XX @@ config RASPI
293
select SDHCI
294
select USB_DWC2
295
296
+config STM32F100_SOC
297
+ bool
298
+ select ARM_V7M
299
+ select STM32F2XX_USART
300
+ select STM32F2XX_SPI
301
+
302
config STM32F205_SOC
303
bool
304
select ARM_V7M
305
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
306
index XXXXXXX..XXXXXXX 100644
307
--- a/hw/arm/meson.build
308
+++ b/hw/arm/meson.build
309
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
310
arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
311
arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
312
arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c', 'bcm2836.c', 'raspi.c'))
313
+arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
314
arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
315
arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
316
arm_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp.c', 'xlnx-zcu102.c'))
317
--
698
--
318
2.20.1
699
2.25.1
319
320
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/xlnx-versal.h | 4 +++
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
13
2 files changed, 56 insertions(+), 2 deletions(-)
14
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/xlnx-versal.h
18
+++ b/include/hw/arm/xlnx-versal.h
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/nvram/xlnx-versal-efuse.h"
21
#include "hw/ssi/xlnx-versal-ospi.h"
22
#include "hw/dma/xlnx_csu_dma.h"
23
+#include "hw/misc/xlnx-versal-crl.h"
24
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
25
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
27
@@ -XXX,XX +XXX,XX @@ struct Versal {
28
qemu_or_irq irq_orgate;
29
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
30
} xram;
31
+
32
+ XlnxVersalCRL crl;
33
} lpd;
34
35
/* The Platform Management Controller subsystem. */
36
@@ -XXX,XX +XXX,XX @@ struct Versal {
37
#define VERSAL_TIMER_NS_EL1_IRQ 14
38
#define VERSAL_TIMER_NS_EL2_IRQ 10
39
40
+#define VERSAL_CRL_IRQ 10
41
#define VERSAL_UART0_IRQ_0 18
42
#define VERSAL_UART1_IRQ_0 19
43
#define VERSAL_USB0_IRQ_0 22
44
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal.c
47
+++ b/hw/arm/xlnx-versal.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
49
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
50
}
51
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
53
+{
54
+ SysBusDevice *sbd;
55
+ int i;
56
+
57
+ object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
58
+ TYPE_XLNX_VERSAL_CRL);
59
+ sbd = SYS_BUS_DEVICE(&s->lpd.crl);
60
+
61
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
62
+ g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
63
+
64
+ object_property_set_link(OBJECT(&s->lpd.crl),
65
+ name, OBJECT(&s->lpd.rpu.cpu[i]),
66
+ &error_abort);
67
+ }
68
+
69
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
70
+ g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
71
+
72
+ object_property_set_link(OBJECT(&s->lpd.crl),
73
+ name, OBJECT(&s->lpd.iou.gem[i]),
74
+ &error_abort);
75
+ }
76
+
77
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
78
+ g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
79
+
80
+ object_property_set_link(OBJECT(&s->lpd.crl),
81
+ name, OBJECT(&s->lpd.iou.adma[i]),
82
+ &error_abort);
83
+ }
84
+
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
86
+ g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
87
+
88
+ object_property_set_link(OBJECT(&s->lpd.crl),
89
+ name, OBJECT(&s->lpd.iou.uart[i]),
90
+ &error_abort);
91
+ }
92
+
93
+ object_property_set_link(OBJECT(&s->lpd.crl),
94
+ "usb", OBJECT(&s->lpd.iou.usb),
95
+ &error_abort);
96
+
97
+ sysbus_realize(sbd, &error_fatal);
98
+ memory_region_add_subregion(&s->mr_ps, MM_CRL,
99
+ sysbus_mmio_get_region(sbd, 0));
100
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
101
+}
102
+
103
/* This takes the board allocated linear DDR memory and creates aliases
104
* for each split DDR range/aperture on the Versal address map.
105
*/
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
107
108
versal_unimp_area(s, "psm", &s->mr_ps,
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
110
- versal_unimp_area(s, "crl", &s->mr_ps,
111
- MM_CRL, MM_CRL_SIZE);
112
versal_unimp_area(s, "crf", &s->mr_ps,
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
114
versal_unimp_area(s, "apu", &s->mr_ps,
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
116
versal_create_efuse(s, pic);
117
versal_create_pmc_iou_slcr(s, pic);
118
versal_create_ospi(s, pic);
119
+ versal_create_crl(s, pic);
120
versal_map_ddr(s);
121
versal_unimp(s);
122
123
--
124
2.25.1
diff view generated by jsdifflib
New patch
1
The Exynos4210 SoC device currently uses a custom device
2
"exynos4210.irq_gate" to model the OR gate that feeds each CPU's IRQ
3
line. We have a standard TYPE_OR_IRQ device for this now, so use
4
that instead.
1
5
6
(This is a migration compatibility break, but that is OK for this
7
machine type.)
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-2-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 1 +
14
hw/arm/exynos4210.c | 31 ++++++++++++++++---------------
15
2 files changed, 17 insertions(+), 15 deletions(-)
16
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/exynos4210.h
20
+++ b/include/hw/arm/exynos4210.h
21
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
22
MemoryRegion bootreg_mem;
23
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
24
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
25
+ qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
26
};
27
28
#define TYPE_EXYNOS4210_SOC "exynos4210"
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
34
{
35
Exynos4210State *s = EXYNOS4210_SOC(socdev);
36
MemoryRegion *system_mem = get_system_memory();
37
- qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
38
SysBusDevice *busdev;
39
DeviceState *dev, *uart[4], *pl330[3];
40
int i, n;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
42
43
/* IRQ Gate */
44
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
45
- dev = qdev_new("exynos4210.irq_gate");
46
- qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
47
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
48
- /* Get IRQ Gate input in gate_irq */
49
- for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
50
- gate_irq[i][n] = qdev_get_gpio_in(dev, n);
51
- }
52
- busdev = SYS_BUS_DEVICE(dev);
53
-
54
- /* Connect IRQ Gate output to CPU's IRQ line */
55
- sysbus_connect_irq(busdev, 0,
56
- qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
57
+ DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
58
+ object_property_set_int(OBJECT(orgate), "num-lines",
59
+ EXYNOS4210_IRQ_GATE_NINPUTS,
60
+ &error_abort);
61
+ qdev_realize(orgate, NULL, &error_abort);
62
+ qdev_connect_gpio_out(orgate, 0,
63
+ qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
64
}
65
66
/* Private memory region and Internal GIC */
67
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
68
sysbus_realize_and_unref(busdev, &error_fatal);
69
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
70
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
71
- sysbus_connect_irq(busdev, n, gate_irq[n][0]);
72
+ sysbus_connect_irq(busdev, n,
73
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
74
}
75
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
76
s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
77
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
78
/* Map Distributer interface */
79
sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
80
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
81
- sysbus_connect_irq(busdev, n, gate_irq[n][1]);
82
+ sysbus_connect_irq(busdev, n,
83
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
84
}
85
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
86
s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
87
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
88
object_initialize_child(obj, name, orgate, TYPE_OR_IRQ);
89
g_free(name);
90
}
91
+
92
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_orgate); i++) {
93
+ g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
94
+ object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
95
+ }
96
}
97
98
static void exynos4210_class_init(ObjectClass *klass, void *data)
99
--
100
2.25.1
diff view generated by jsdifflib
New patch
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
2
delete the device entirely.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
6
Message-id: 20220404154658.565020-3-peter.maydell@linaro.org
7
---
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
9
1 file changed, 107 deletions(-)
10
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/exynos4210_gic.c
14
+++ b/hw/intc/exynos4210_gic.c
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
16
}
17
18
type_init(exynos4210_gic_register_types)
19
-
20
-/* IRQ OR Gate struct.
21
- *
22
- * This device models an OR gate. There are n_in input qdev gpio lines and one
23
- * output sysbus IRQ line. The output IRQ level is formed as OR between all
24
- * gpio inputs.
25
- */
26
-
27
-#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
28
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE)
29
-
30
-struct Exynos4210IRQGateState {
31
- SysBusDevice parent_obj;
32
-
33
- uint32_t n_in; /* inputs amount */
34
- uint32_t *level; /* input levels */
35
- qemu_irq out; /* output IRQ */
36
-};
37
-
38
-static Property exynos4210_irq_gate_properties[] = {
39
- DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
40
- DEFINE_PROP_END_OF_LIST(),
41
-};
42
-
43
-static const VMStateDescription vmstate_exynos4210_irq_gate = {
44
- .name = "exynos4210.irq_gate",
45
- .version_id = 2,
46
- .minimum_version_id = 2,
47
- .fields = (VMStateField[]) {
48
- VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in),
49
- VMSTATE_END_OF_LIST()
50
- }
51
-};
52
-
53
-/* Process a change in IRQ input. */
54
-static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
55
-{
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
57
- uint32_t i;
58
-
59
- assert(irq < s->n_in);
60
-
61
- s->level[irq] = level;
62
-
63
- for (i = 0; i < s->n_in; i++) {
64
- if (s->level[i] >= 1) {
65
- qemu_irq_raise(s->out);
66
- return;
67
- }
68
- }
69
-
70
- qemu_irq_lower(s->out);
71
-}
72
-
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
74
-{
75
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
76
-
77
- memset(s->level, 0, s->n_in * sizeof(*s->level));
78
-}
79
-
80
-/*
81
- * IRQ Gate initialization.
82
- */
83
-static void exynos4210_irq_gate_init(Object *obj)
84
-{
85
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
86
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
87
-
88
- sysbus_init_irq(sbd, &s->out);
89
-}
90
-
91
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
92
-{
93
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
94
-
95
- /* Allocate general purpose input signals and connect a handler to each of
96
- * them */
97
- qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
98
-
99
- s->level = g_malloc0(s->n_in * sizeof(*s->level));
100
-}
101
-
102
-static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
103
-{
104
- DeviceClass *dc = DEVICE_CLASS(klass);
105
-
106
- dc->reset = exynos4210_irq_gate_reset;
107
- dc->vmsd = &vmstate_exynos4210_irq_gate;
108
- device_class_set_props(dc, exynos4210_irq_gate_properties);
109
- dc->realize = exynos4210_irq_gate_realize;
110
-}
111
-
112
-static const TypeInfo exynos4210_irq_gate_info = {
113
- .name = TYPE_EXYNOS4210_IRQ_GATE,
114
- .parent = TYPE_SYS_BUS_DEVICE,
115
- .instance_size = sizeof(Exynos4210IRQGateState),
116
- .instance_init = exynos4210_irq_gate_init,
117
- .class_init = exynos4210_irq_gate_class_init,
118
-};
119
-
120
-static void exynos4210_irq_gate_register_types(void)
121
-{
122
- type_register_static(&exynos4210_irq_gate_info);
123
-}
124
-
125
-type_init(exynos4210_irq_gate_register_types)
126
--
127
2.25.1
diff view generated by jsdifflib
1
The PL061 comes out of reset with all its lines configured as input,
1
The exynos4210 SoC mostly creates its child devices as if it were
2
which means they might need to be pulled to 0 or 1 depending on the
2
board code. This includes the a9mpcore object. Switch that to a
3
'pullups' and 'pulldowns' properties. Currently we do not assert
3
new-style "embedded in the state struct" creation, because in the
4
these lines on reset; they will only be set whenever the guest first
4
next commit we're going to want to refer to the object again further
5
touches a register that triggers a call to pl061_update().
5
down in the exynos4210_realize() function.
6
7
Convert the device to three-phase reset so we have a place where we
8
can safely call qemu_set_irq() to set the floating lines to their
9
correct values.
10
6
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220404154658.565020-4-peter.maydell@linaro.org
14
---
10
---
15
hw/gpio/pl061.c | 29 +++++++++++++++++++++++++----
11
include/hw/arm/exynos4210.h | 2 ++
16
hw/gpio/trace-events | 1 +
12
hw/arm/exynos4210.c | 11 ++++++-----
17
2 files changed, 26 insertions(+), 4 deletions(-)
13
2 files changed, 8 insertions(+), 5 deletions(-)
18
14
19
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
15
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/gpio/pl061.c
17
--- a/include/hw/arm/exynos4210.h
22
+++ b/hw/gpio/pl061.c
18
+++ b/include/hw/arm/exynos4210.h
23
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
19
@@ -XXX,XX +XXX,XX @@
24
return;
20
21
#include "hw/or-irq.h"
22
#include "hw/sysbus.h"
23
+#include "hw/cpu/a9mpcore.h"
24
#include "target/arm/cpu-qom.h"
25
#include "qom/object.h"
26
27
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
28
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
29
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
30
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
31
+ A9MPPrivState a9mpcore;
32
};
33
34
#define TYPE_EXYNOS4210_SOC "exynos4210"
35
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/exynos4210.c
38
+++ b/hw/arm/exynos4210.c
39
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
40
}
41
42
/* Private memory region and Internal GIC */
43
- dev = qdev_new(TYPE_A9MPCORE_PRIV);
44
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
45
- busdev = SYS_BUS_DEVICE(dev);
46
- sysbus_realize_and_unref(busdev, &error_fatal);
47
+ qdev_prop_set_uint32(DEVICE(&s->a9mpcore), "num-cpu", EXYNOS4210_NCPUS);
48
+ busdev = SYS_BUS_DEVICE(&s->a9mpcore);
49
+ sysbus_realize(busdev, &error_fatal);
50
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
51
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
52
sysbus_connect_irq(busdev, n,
53
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
54
}
55
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
56
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
57
+ s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
58
}
59
60
/* Cache controller */
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
62
g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
63
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
64
}
65
+
66
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
25
}
67
}
26
68
27
-static void pl061_reset(DeviceState *dev)
69
static void exynos4210_class_init(ObjectClass *klass, void *data)
28
+static void pl061_enter_reset(Object *obj, ResetType type)
29
{
30
- PL061State *s = PL061(dev);
31
+ PL061State *s = PL061(obj);
32
+
33
+ trace_pl061_reset(DEVICE(s)->canonical_path);
34
35
/* reset values from PL061 TRM, Stellaris LM3S5P31 & LM3S8962 Data Sheet */
36
s->data = 0;
37
- s->old_out_data = 0;
38
s->old_in_data = 0;
39
s->dir = 0;
40
s->isense = 0;
41
@@ -XXX,XX +XXX,XX @@ static void pl061_reset(DeviceState *dev)
42
s->amsel = 0;
43
}
44
45
+static void pl061_hold_reset(Object *obj)
46
+{
47
+ PL061State *s = PL061(obj);
48
+ int i, level;
49
+ uint8_t floating = pl061_floating(s);
50
+ uint8_t pullups = pl061_pullups(s);
51
+
52
+ for (i = 0; i < N_GPIOS; i++) {
53
+ if (extract32(floating, i, 1)) {
54
+ continue;
55
+ }
56
+ level = extract32(pullups, i, 1);
57
+ trace_pl061_set_output(DEVICE(s)->canonical_path, i, level);
58
+ qemu_set_irq(s->out[i], level);
59
+ }
60
+ s->old_out_data = pullups;
61
+}
62
+
63
static void pl061_set_irq(void * opaque, int irq, int level)
64
{
65
PL061State *s = (PL061State *)opaque;
66
@@ -XXX,XX +XXX,XX @@ static Property pl061_props[] = {
67
static void pl061_class_init(ObjectClass *klass, void *data)
68
{
69
DeviceClass *dc = DEVICE_CLASS(klass);
70
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
71
72
dc->vmsd = &vmstate_pl061;
73
- dc->reset = &pl061_reset;
74
dc->realize = pl061_realize;
75
device_class_set_props(dc, pl061_props);
76
+ rc->phases.enter = pl061_enter_reset;
77
+ rc->phases.hold = pl061_hold_reset;
78
}
79
80
static const TypeInfo pl061_info = {
81
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/gpio/trace-events
84
+++ b/hw/gpio/trace-events
85
@@ -XXX,XX +XXX,XX @@ pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to
86
pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
87
pl061_read(const char *id, uint64_t offset, uint64_t r) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
88
pl061_write(const char *id, uint64_t offset, uint64_t value) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
89
+pl061_reset(const char *id) "%s reset"
90
91
# sifive_gpio.c
92
sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
93
--
70
--
94
2.20.1
71
2.25.1
95
96
diff view generated by jsdifflib
New patch
1
The only time we use the int_gic_irq[] array in the Exynos4210Irq
2
struct is in the exynos4210_realize() function: we initialize it with
3
the GPIO inputs of the a9mpcore device, and then a bit later on we
4
connect those to the outputs of the internal combiner. Now that the
5
a9mpcore object is easily accessible as s->a9mpcore we can make the
6
connection directly from one device to the other without going via
7
this array.
1
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-5-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 1 -
14
hw/arm/exynos4210.c | 6 ++----
15
2 files changed, 2 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/exynos4210.h
20
+++ b/include/hw/arm/exynos4210.h
21
@@ -XXX,XX +XXX,XX @@
22
typedef struct Exynos4210Irq {
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
25
- qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ];
26
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
27
qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
28
} Exynos4210Irq;
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
34
sysbus_connect_irq(busdev, n,
35
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
36
}
37
- for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
38
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
39
- }
40
41
/* Cache controller */
42
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
43
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
44
busdev = SYS_BUS_DEVICE(dev);
45
sysbus_realize_and_unref(busdev, &error_fatal);
46
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
47
- sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
48
+ sysbus_connect_irq(busdev, n,
49
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
50
}
51
exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
52
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
53
--
54
2.25.1
diff view generated by jsdifflib
New patch
1
The exynos4210 code currently has two very similar arrays of IRQs:
1
2
3
* board_irqs is a field of the Exynos4210Irq struct which is filled
4
in by exynos4210_init_board_irqs() with the appropriate qemu_irqs
5
for each IRQ the board/SoC can assert
6
* irq_table is a set of qemu_irqs pointed to from the
7
Exynos4210State struct. It's allocated in exynos4210_init_irq,
8
and the only behaviour these irqs have is that they pass on the
9
level to the equivalent board_irqs[] irq
10
11
The extra indirection through irq_table is unnecessary, so coalesce
12
these into a single irq_table[] array as a direct field in
13
Exynos4210State which exynos4210_init_board_irqs() fills in.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220404154658.565020-6-peter.maydell@linaro.org
18
---
19
include/hw/arm/exynos4210.h | 8 ++------
20
hw/arm/exynos4210.c | 6 +-----
21
hw/intc/exynos4210_gic.c | 32 ++++++++------------------------
22
3 files changed, 11 insertions(+), 35 deletions(-)
23
24
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/exynos4210.h
27
+++ b/include/hw/arm/exynos4210.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
29
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
30
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
31
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
32
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
33
} Exynos4210Irq;
34
35
struct Exynos4210State {
36
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
Exynos4210Irq irqs;
40
- qemu_irq *irq_table;
41
+ qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
42
43
MemoryRegion chipid_mem;
44
MemoryRegion iram_mem;
45
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
46
void exynos4210_write_secondary(ARMCPU *cpu,
47
const struct arm_boot_info *info);
48
49
-/* Initialize exynos4210 IRQ subsystem stub */
50
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
51
-
52
/* Initialize board IRQs.
53
* These IRQs contain splitted Int/External Combiner and External Gic IRQs */
54
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
55
+void exynos4210_init_board_irqs(Exynos4210State *s);
56
57
/* Get IRQ number from exynos4210 IRQ subsystem stub.
58
* To identify IRQ source use internal combiner group and bit number
59
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/exynos4210.c
62
+++ b/hw/arm/exynos4210.c
63
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
64
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
65
}
66
67
- /*** IRQs ***/
68
-
69
- s->irq_table = exynos4210_init_irq(&s->irqs);
70
-
71
/* IRQ Gate */
72
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
73
DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
74
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
75
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
76
77
/* Initialize board IRQs. */
78
- exynos4210_init_board_irqs(&s->irqs);
79
+ exynos4210_init_board_irqs(s);
80
81
/*** Memory ***/
82
83
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/intc/exynos4210_gic.c
86
+++ b/hw/intc/exynos4210_gic.c
87
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
88
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
89
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
90
91
-static void exynos4210_irq_handler(void *opaque, int irq, int level)
92
-{
93
- Exynos4210Irq *s = (Exynos4210Irq *)opaque;
94
-
95
- /* Bypass */
96
- qemu_set_irq(s->board_irqs[irq], level);
97
-}
98
-
99
-/*
100
- * Initialize exynos4210 IRQ subsystem stub.
101
- */
102
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *s)
103
-{
104
- return qemu_allocate_irqs(exynos4210_irq_handler, s,
105
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ);
106
-}
107
-
108
/*
109
* Initialize board IRQs.
110
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
111
*/
112
-void exynos4210_init_board_irqs(Exynos4210Irq *s)
113
+void exynos4210_init_board_irqs(Exynos4210State *s)
114
{
115
uint32_t grp, bit, irq_id, n;
116
+ Exynos4210Irq *is = &s->irqs;
117
118
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
119
irq_id = 0;
120
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
121
irq_id = EXT_GIC_ID_MCT_G1;
122
}
123
if (irq_id) {
124
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
125
- s->ext_gic_irq[irq_id-32]);
126
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
127
+ is->ext_gic_irq[irq_id - 32]);
128
} else {
129
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
130
- s->ext_combiner_irq[n]);
131
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
132
+ is->ext_combiner_irq[n]);
133
}
134
}
135
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
136
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
137
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
138
139
if (irq_id) {
140
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
141
- s->ext_gic_irq[irq_id-32]);
142
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
143
+ is->ext_gic_irq[irq_id - 32]);
144
}
145
}
146
}
147
--
148
2.25.1
diff view generated by jsdifflib
1
Add a comment documenting the "QEMU interface" of this device:
1
Fix a missing set of spaces around '-' in the definition of
2
which MMIO regions, IRQ lines, GPIO lines, etc it exposes.
2
combiner_grp_to_gic_id[]. We're about to move this code, so
3
fix the style issue first to keep checkpatch happy with the
4
code-motion patch.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220404154658.565020-7-peter.maydell@linaro.org
6
---
9
---
7
hw/gpio/pl061.c | 7 +++++++
10
hw/intc/exynos4210_gic.c | 2 +-
8
1 file changed, 7 insertions(+)
11
1 file changed, 1 insertion(+), 1 deletion(-)
9
12
10
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
11
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/gpio/pl061.c
15
--- a/hw/intc/exynos4210_gic.c
13
+++ b/hw/gpio/pl061.c
16
+++ b/hw/intc/exynos4210_gic.c
14
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
15
* Written by Paul Brook
16
*
17
* This code is licensed under the GPL.
18
+ *
19
+ * QEMU interface:
20
+ * + sysbus MMIO region 0: the device registers
21
+ * + sysbus IRQ: the GPIOINTR interrupt line
22
+ * + unnamed GPIO inputs 0..7: inputs to connect to the emulated GPIO lines
23
+ * + unnamed GPIO outputs 0..7: the emulated GPIO lines, considered as
24
+ * outputs
25
*/
18
*/
26
19
27
#include "qemu/osdep.h"
20
static const uint32_t
21
-combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
22
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
23
/* int combiner groups 16-19 */
24
{ }, { }, { }, { },
25
/* int combiner group 20 */
28
--
26
--
29
2.20.1
27
2.25.1
30
31
diff view generated by jsdifflib
1
The Luminary variant of the PL061 has registers GPIOPUR and GPIOPDR
1
The function exynos4210_init_board_irqs() currently lives in
2
which lets the guest configure whether the GPIO lines are pull-up,
2
exynos4210_gic.c, but it isn't really part of the exynos4210.gic
3
pull-down, or truly floating. Instead of assuming all lines are pulled
3
device -- it is a function that implements (some of) the wiring up of
4
high, honour the PUR and PDR registers.
4
interrupts between the SoC's GIC and combiner components. This means
5
5
it fits better in exynos4210.c, which is the SoC-level code. Move it
6
For the plain PL061, continue to assume that lines have an external
6
there. Similarly, exynos4210_git_irq() is used almost only in the
7
pull-up resistor, as we did before.
7
SoC-level code, so move it too.
8
9
The stellaris board actually relies on this behaviour -- the CD line
10
of the ssd0323 display device is connected to GPIO output C7, and it
11
is only because of a different bug which we're about to fix that we
12
weren't incorrectly driving this line high on reset and putting the
13
ssd0323 into data mode.
14
8
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-8-peter.maydell@linaro.org
17
---
12
---
18
hw/gpio/pl061.c | 58 +++++++++++++++++++++++++++++++++++++++++---
13
include/hw/arm/exynos4210.h | 4 -
19
hw/gpio/trace-events | 2 +-
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
20
2 files changed, 55 insertions(+), 5 deletions(-)
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
16
3 files changed, 202 insertions(+), 208 deletions(-)
21
17
22
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/gpio/pl061.c
20
--- a/include/hw/arm/exynos4210.h
25
+++ b/hw/gpio/pl061.c
21
+++ b/include/hw/arm/exynos4210.h
26
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl061 = {
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
27
}
23
void exynos4210_write_secondary(ARMCPU *cpu,
28
};
24
const struct arm_boot_info *info);
29
25
30
+static uint8_t pl061_floating(PL061State *s)
26
-/* Initialize board IRQs.
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
29
-
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
31
* To identify IRQ source use internal combiner group and bit number
32
* grp - group number
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/exynos4210.c
36
+++ b/hw/arm/exynos4210.c
37
@@ -XXX,XX +XXX,XX @@
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
40
41
+enum ExtGicId {
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
43
+ EXT_GIC_ID_PDMA0,
44
+ EXT_GIC_ID_PDMA1,
45
+ EXT_GIC_ID_TIMER0,
46
+ EXT_GIC_ID_TIMER1,
47
+ EXT_GIC_ID_TIMER2,
48
+ EXT_GIC_ID_TIMER3,
49
+ EXT_GIC_ID_TIMER4,
50
+ EXT_GIC_ID_MCT_L0,
51
+ EXT_GIC_ID_WDT,
52
+ EXT_GIC_ID_RTC_ALARM,
53
+ EXT_GIC_ID_RTC_TIC,
54
+ EXT_GIC_ID_GPIO_XB,
55
+ EXT_GIC_ID_GPIO_XA,
56
+ EXT_GIC_ID_MCT_L1,
57
+ EXT_GIC_ID_IEM_APC,
58
+ EXT_GIC_ID_IEM_IEC,
59
+ EXT_GIC_ID_NFC,
60
+ EXT_GIC_ID_UART0,
61
+ EXT_GIC_ID_UART1,
62
+ EXT_GIC_ID_UART2,
63
+ EXT_GIC_ID_UART3,
64
+ EXT_GIC_ID_UART4,
65
+ EXT_GIC_ID_MCT_G0,
66
+ EXT_GIC_ID_I2C0,
67
+ EXT_GIC_ID_I2C1,
68
+ EXT_GIC_ID_I2C2,
69
+ EXT_GIC_ID_I2C3,
70
+ EXT_GIC_ID_I2C4,
71
+ EXT_GIC_ID_I2C5,
72
+ EXT_GIC_ID_I2C6,
73
+ EXT_GIC_ID_I2C7,
74
+ EXT_GIC_ID_SPI0,
75
+ EXT_GIC_ID_SPI1,
76
+ EXT_GIC_ID_SPI2,
77
+ EXT_GIC_ID_MCT_G1,
78
+ EXT_GIC_ID_USB_HOST,
79
+ EXT_GIC_ID_USB_DEVICE,
80
+ EXT_GIC_ID_MODEMIF,
81
+ EXT_GIC_ID_HSMMC0,
82
+ EXT_GIC_ID_HSMMC1,
83
+ EXT_GIC_ID_HSMMC2,
84
+ EXT_GIC_ID_HSMMC3,
85
+ EXT_GIC_ID_SDMMC,
86
+ EXT_GIC_ID_MIPI_CSI_4LANE,
87
+ EXT_GIC_ID_MIPI_DSI_4LANE,
88
+ EXT_GIC_ID_MIPI_CSI_2LANE,
89
+ EXT_GIC_ID_MIPI_DSI_2LANE,
90
+ EXT_GIC_ID_ONENAND_AUDI,
91
+ EXT_GIC_ID_ROTATOR,
92
+ EXT_GIC_ID_FIMC0,
93
+ EXT_GIC_ID_FIMC1,
94
+ EXT_GIC_ID_FIMC2,
95
+ EXT_GIC_ID_FIMC3,
96
+ EXT_GIC_ID_JPEG,
97
+ EXT_GIC_ID_2D,
98
+ EXT_GIC_ID_PCIe,
99
+ EXT_GIC_ID_MIXER,
100
+ EXT_GIC_ID_HDMI,
101
+ EXT_GIC_ID_HDMI_I2C,
102
+ EXT_GIC_ID_MFC,
103
+ EXT_GIC_ID_TVENC,
104
+};
105
+
106
+enum ExtInt {
107
+ EXT_GIC_ID_EXTINT0 = 48,
108
+ EXT_GIC_ID_EXTINT1,
109
+ EXT_GIC_ID_EXTINT2,
110
+ EXT_GIC_ID_EXTINT3,
111
+ EXT_GIC_ID_EXTINT4,
112
+ EXT_GIC_ID_EXTINT5,
113
+ EXT_GIC_ID_EXTINT6,
114
+ EXT_GIC_ID_EXTINT7,
115
+ EXT_GIC_ID_EXTINT8,
116
+ EXT_GIC_ID_EXTINT9,
117
+ EXT_GIC_ID_EXTINT10,
118
+ EXT_GIC_ID_EXTINT11,
119
+ EXT_GIC_ID_EXTINT12,
120
+ EXT_GIC_ID_EXTINT13,
121
+ EXT_GIC_ID_EXTINT14,
122
+ EXT_GIC_ID_EXTINT15
123
+};
124
+
125
+/*
126
+ * External GIC sources which are not from External Interrupt Combiner or
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
128
+ * which is INTG16 in Internal Interrupt Combiner.
129
+ */
130
+
131
+static const uint32_t
132
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
133
+ /* int combiner groups 16-19 */
134
+ { }, { }, { }, { },
135
+ /* int combiner group 20 */
136
+ { 0, EXT_GIC_ID_MDMA_LCD0 },
137
+ /* int combiner group 21 */
138
+ { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
139
+ /* int combiner group 22 */
140
+ { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
141
+ EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
142
+ /* int combiner group 23 */
143
+ { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
144
+ /* int combiner group 24 */
145
+ { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
146
+ /* int combiner group 25 */
147
+ { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
148
+ /* int combiner group 26 */
149
+ { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
150
+ EXT_GIC_ID_UART4 },
151
+ /* int combiner group 27 */
152
+ { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
153
+ EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
154
+ EXT_GIC_ID_I2C7 },
155
+ /* int combiner group 28 */
156
+ { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
157
+ /* int combiner group 29 */
158
+ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
159
+ EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
160
+ /* int combiner group 30 */
161
+ { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
162
+ /* int combiner group 31 */
163
+ { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
164
+ /* int combiner group 32 */
165
+ { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
166
+ /* int combiner group 33 */
167
+ { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
168
+ /* int combiner group 34 */
169
+ { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
170
+ /* int combiner group 35 */
171
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
172
+ /* int combiner group 36 */
173
+ { EXT_GIC_ID_MIXER },
174
+ /* int combiner group 37 */
175
+ { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
176
+ EXT_GIC_ID_EXTINT7 },
177
+ /* groups 38-50 */
178
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
179
+ /* int combiner group 51 */
180
+ { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
181
+ /* group 52 */
182
+ { },
183
+ /* int combiner group 53 */
184
+ { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
185
+ /* groups 54-63 */
186
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
187
+};
188
+
189
+/*
190
+ * Initialize board IRQs.
191
+ * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
192
+ */
193
+static void exynos4210_init_board_irqs(Exynos4210State *s)
31
+{
194
+{
32
+ /*
195
+ uint32_t grp, bit, irq_id, n;
33
+ * Return mask of bits which correspond to pins configured as inputs
196
+ Exynos4210Irq *is = &s->irqs;
34
+ * and which are floating (neither pulled up to 1 nor down to 0).
197
+
35
+ */
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
36
+ uint8_t floating;
199
+ irq_id = 0;
37
+
200
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
38
+ if (s->id == pl061_id_luminary) {
201
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
39
+ /*
202
+ /* MCT_G0 is passed to External GIC */
40
+ * If both PUR and PDR bits are clear, there is neither a pullup
203
+ irq_id = EXT_GIC_ID_MCT_G0;
41
+ * nor a pulldown in place, and the output truly floats.
204
+ }
42
+ */
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
43
+ floating = ~(s->pur | s->pdr);
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
44
+ } else {
207
+ /* MCT_G1 is passed to External and GIC */
45
+ /* Assume outputs are pulled high. FIXME: this is board dependent. */
208
+ irq_id = EXT_GIC_ID_MCT_G1;
46
+ floating = 0;
209
+ }
210
+ if (irq_id) {
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
212
+ is->ext_gic_irq[irq_id - 32]);
213
+ } else {
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
215
+ is->ext_combiner_irq[n]);
216
+ }
47
+ }
217
+ }
48
+ return floating & ~s->dir;
218
+ for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
219
+ /* these IDs are passed to Internal Combiner and External GIC */
220
+ grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
221
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
222
+ irq_id = combiner_grp_to_gic_id[grp -
223
+ EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
224
+
225
+ if (irq_id) {
226
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
227
+ is->ext_gic_irq[irq_id - 32]);
228
+ }
229
+ }
49
+}
230
+}
50
+
231
+
51
+static uint8_t pl061_pullups(PL061State *s)
232
+/*
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
234
+ * To identify IRQ source use internal combiner group and bit number
235
+ * grp - group number
236
+ * bit - bit number inside group
237
+ */
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
52
+{
239
+{
53
+ /*
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
54
+ * Return mask of bits which correspond to pins configured as inputs
55
+ * and which are pulled up to 1.
56
+ */
57
+ uint8_t pullups;
58
+
59
+ if (s->id == pl061_id_luminary) {
60
+ /*
61
+ * The Luminary variant of the PL061 has an extra registers which
62
+ * the guest can use to configure whether lines should be pullup
63
+ * or pulldown.
64
+ */
65
+ pullups = s->pur;
66
+ } else {
67
+ /* Assume outputs are pulled high. FIXME: this is board dependent. */
68
+ pullups = 0xff;
69
+ }
70
+ return pullups & ~s->dir;
71
+}
241
+}
72
+
242
+
73
static void pl061_update(PL061State *s)
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
74
{
244
0x09, 0x00, 0x00, 0x00 };
75
uint8_t changed;
245
76
uint8_t mask;
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
77
uint8_t out;
78
int i;
79
+ uint8_t pullups = pl061_pullups(s);
80
+ uint8_t floating = pl061_floating(s);
81
82
- trace_pl061_update(DEVICE(s)->canonical_path, s->dir, s->data);
83
+ trace_pl061_update(DEVICE(s)->canonical_path, s->dir, s->data,
84
+ pullups, floating);
85
86
- /* Outputs float high. */
87
- /* FIXME: This is board dependent. */
88
- out = (s->data & s->dir) | ~s->dir;
89
+ /*
90
+ * Pins configured as output are driven from the data register;
91
+ * otherwise if they're pulled up they're 1, and if they're floating
92
+ * then we give them the same value they had previously, so we don't
93
+ * report any change to the other end.
94
+ */
95
+ out = (s->data & s->dir) | pullups | (s->old_out_data & floating);
96
changed = s->old_out_data ^ out;
97
if (changed) {
98
s->old_out_data = out;
99
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
100
index XXXXXXX..XXXXXXX 100644
247
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/gpio/trace-events
248
--- a/hw/intc/exynos4210_gic.c
102
+++ b/hw/gpio/trace-events
249
+++ b/hw/intc/exynos4210_gic.c
103
@@ -XXX,XX +XXX,XX @@ nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
250
@@ -XXX,XX +XXX,XX @@
104
nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
251
#include "hw/arm/exynos4210.h"
105
252
#include "qom/object.h"
106
# pl061.c
253
107
-pl061_update(const char *id, uint32_t dir, uint32_t data) "%s GPIODIR 0x%x GPIODATA 0x%x"
254
-enum ExtGicId {
108
+pl061_update(const char *id, uint32_t dir, uint32_t data, uint32_t pullups, uint32_t floating) "%s GPIODIR 0x%x GPIODATA 0x%x pullups 0x%x floating 0x%x"
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
109
pl061_set_output(const char *id, int gpio, int level) "%s setting output %d to %d"
256
- EXT_GIC_ID_PDMA0,
110
pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to %d"
257
- EXT_GIC_ID_PDMA1,
111
pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
258
- EXT_GIC_ID_TIMER0,
259
- EXT_GIC_ID_TIMER1,
260
- EXT_GIC_ID_TIMER2,
261
- EXT_GIC_ID_TIMER3,
262
- EXT_GIC_ID_TIMER4,
263
- EXT_GIC_ID_MCT_L0,
264
- EXT_GIC_ID_WDT,
265
- EXT_GIC_ID_RTC_ALARM,
266
- EXT_GIC_ID_RTC_TIC,
267
- EXT_GIC_ID_GPIO_XB,
268
- EXT_GIC_ID_GPIO_XA,
269
- EXT_GIC_ID_MCT_L1,
270
- EXT_GIC_ID_IEM_APC,
271
- EXT_GIC_ID_IEM_IEC,
272
- EXT_GIC_ID_NFC,
273
- EXT_GIC_ID_UART0,
274
- EXT_GIC_ID_UART1,
275
- EXT_GIC_ID_UART2,
276
- EXT_GIC_ID_UART3,
277
- EXT_GIC_ID_UART4,
278
- EXT_GIC_ID_MCT_G0,
279
- EXT_GIC_ID_I2C0,
280
- EXT_GIC_ID_I2C1,
281
- EXT_GIC_ID_I2C2,
282
- EXT_GIC_ID_I2C3,
283
- EXT_GIC_ID_I2C4,
284
- EXT_GIC_ID_I2C5,
285
- EXT_GIC_ID_I2C6,
286
- EXT_GIC_ID_I2C7,
287
- EXT_GIC_ID_SPI0,
288
- EXT_GIC_ID_SPI1,
289
- EXT_GIC_ID_SPI2,
290
- EXT_GIC_ID_MCT_G1,
291
- EXT_GIC_ID_USB_HOST,
292
- EXT_GIC_ID_USB_DEVICE,
293
- EXT_GIC_ID_MODEMIF,
294
- EXT_GIC_ID_HSMMC0,
295
- EXT_GIC_ID_HSMMC1,
296
- EXT_GIC_ID_HSMMC2,
297
- EXT_GIC_ID_HSMMC3,
298
- EXT_GIC_ID_SDMMC,
299
- EXT_GIC_ID_MIPI_CSI_4LANE,
300
- EXT_GIC_ID_MIPI_DSI_4LANE,
301
- EXT_GIC_ID_MIPI_CSI_2LANE,
302
- EXT_GIC_ID_MIPI_DSI_2LANE,
303
- EXT_GIC_ID_ONENAND_AUDI,
304
- EXT_GIC_ID_ROTATOR,
305
- EXT_GIC_ID_FIMC0,
306
- EXT_GIC_ID_FIMC1,
307
- EXT_GIC_ID_FIMC2,
308
- EXT_GIC_ID_FIMC3,
309
- EXT_GIC_ID_JPEG,
310
- EXT_GIC_ID_2D,
311
- EXT_GIC_ID_PCIe,
312
- EXT_GIC_ID_MIXER,
313
- EXT_GIC_ID_HDMI,
314
- EXT_GIC_ID_HDMI_I2C,
315
- EXT_GIC_ID_MFC,
316
- EXT_GIC_ID_TVENC,
317
-};
318
-
319
-enum ExtInt {
320
- EXT_GIC_ID_EXTINT0 = 48,
321
- EXT_GIC_ID_EXTINT1,
322
- EXT_GIC_ID_EXTINT2,
323
- EXT_GIC_ID_EXTINT3,
324
- EXT_GIC_ID_EXTINT4,
325
- EXT_GIC_ID_EXTINT5,
326
- EXT_GIC_ID_EXTINT6,
327
- EXT_GIC_ID_EXTINT7,
328
- EXT_GIC_ID_EXTINT8,
329
- EXT_GIC_ID_EXTINT9,
330
- EXT_GIC_ID_EXTINT10,
331
- EXT_GIC_ID_EXTINT11,
332
- EXT_GIC_ID_EXTINT12,
333
- EXT_GIC_ID_EXTINT13,
334
- EXT_GIC_ID_EXTINT14,
335
- EXT_GIC_ID_EXTINT15
336
-};
337
-
338
-/*
339
- * External GIC sources which are not from External Interrupt Combiner or
340
- * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
341
- * which is INTG16 in Internal Interrupt Combiner.
342
- */
343
-
344
-static const uint32_t
345
-combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
346
- /* int combiner groups 16-19 */
347
- { }, { }, { }, { },
348
- /* int combiner group 20 */
349
- { 0, EXT_GIC_ID_MDMA_LCD0 },
350
- /* int combiner group 21 */
351
- { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
352
- /* int combiner group 22 */
353
- { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
354
- EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
355
- /* int combiner group 23 */
356
- { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
357
- /* int combiner group 24 */
358
- { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
359
- /* int combiner group 25 */
360
- { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
361
- /* int combiner group 26 */
362
- { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
363
- EXT_GIC_ID_UART4 },
364
- /* int combiner group 27 */
365
- { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
366
- EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
367
- EXT_GIC_ID_I2C7 },
368
- /* int combiner group 28 */
369
- { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
370
- /* int combiner group 29 */
371
- { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
372
- EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
373
- /* int combiner group 30 */
374
- { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
375
- /* int combiner group 31 */
376
- { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
377
- /* int combiner group 32 */
378
- { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
379
- /* int combiner group 33 */
380
- { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
381
- /* int combiner group 34 */
382
- { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
383
- /* int combiner group 35 */
384
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
385
- /* int combiner group 36 */
386
- { EXT_GIC_ID_MIXER },
387
- /* int combiner group 37 */
388
- { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
389
- EXT_GIC_ID_EXTINT7 },
390
- /* groups 38-50 */
391
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
392
- /* int combiner group 51 */
393
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
394
- /* group 52 */
395
- { },
396
- /* int combiner group 53 */
397
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
398
- /* groups 54-63 */
399
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
400
-};
401
-
402
#define EXYNOS4210_GIC_NIRQ 160
403
404
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
405
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
406
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
407
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
408
409
-/*
410
- * Initialize board IRQs.
411
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
412
- */
413
-void exynos4210_init_board_irqs(Exynos4210State *s)
414
-{
415
- uint32_t grp, bit, irq_id, n;
416
- Exynos4210Irq *is = &s->irqs;
417
-
418
- for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
419
- irq_id = 0;
420
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
421
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
422
- /* MCT_G0 is passed to External GIC */
423
- irq_id = EXT_GIC_ID_MCT_G0;
424
- }
425
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
426
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
427
- /* MCT_G1 is passed to External and GIC */
428
- irq_id = EXT_GIC_ID_MCT_G1;
429
- }
430
- if (irq_id) {
431
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
432
- is->ext_gic_irq[irq_id - 32]);
433
- } else {
434
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
435
- is->ext_combiner_irq[n]);
436
- }
437
- }
438
- for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
439
- /* these IDs are passed to Internal Combiner and External GIC */
440
- grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
441
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
442
- irq_id = combiner_grp_to_gic_id[grp -
443
- EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
444
-
445
- if (irq_id) {
446
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
447
- is->ext_gic_irq[irq_id - 32]);
448
- }
449
- }
450
-}
451
-
452
-/*
453
- * Get IRQ number from exynos4210 IRQ subsystem stub.
454
- * To identify IRQ source use internal combiner group and bit number
455
- * grp - group number
456
- * bit - bit number inside group
457
- */
458
-uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
459
-{
460
- return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
461
-}
462
-
463
-/********* GIC part *********/
464
-
465
#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
466
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
467
112
--
468
--
113
2.20.1
469
2.25.1
114
115
diff view generated by jsdifflib
1
From: Alexandre Iooss <erdnaxe@crans.org>
1
Switch the creation of the external GIC to the new-style "embedded in
2
state struct" approach, so we can easily refer to the object
3
elsewhere during realize.
2
4
3
This is a Cortex-M3 based machine. Information can be found at:
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
https://www.st.com/en/evaluation-tools/stm32vldiscovery.html
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
8
---
9
include/hw/arm/exynos4210.h | 2 ++
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 10 ++++----
12
hw/intc/exynos4210_gic.c | 17 ++-----------
13
MAINTAINERS | 2 +-
14
5 files changed, 53 insertions(+), 21 deletions(-)
15
create mode 100644 include/hw/intc/exynos4210_gic.h
5
16
6
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210617165647.2575955-3-erdnaxe@crans.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
default-configs/devices/arm-softmmu.mak | 1 +
12
hw/arm/stm32vldiscovery.c | 66 +++++++++++++++++++++++++
13
MAINTAINERS | 6 +++
14
hw/arm/Kconfig | 4 ++
15
hw/arm/meson.build | 1 +
16
5 files changed, 78 insertions(+)
17
create mode 100644 hw/arm/stm32vldiscovery.c
18
19
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/default-configs/devices/arm-softmmu.mak
19
--- a/include/hw/arm/exynos4210.h
22
+++ b/default-configs/devices/arm-softmmu.mak
20
+++ b/include/hw/arm/exynos4210.h
23
@@ -XXX,XX +XXX,XX @@ CONFIG_CHEETAH=y
21
@@ -XXX,XX +XXX,XX @@
24
CONFIG_SX1=y
22
#include "hw/or-irq.h"
25
CONFIG_NSERIES=y
23
#include "hw/sysbus.h"
26
CONFIG_STELLARIS=y
24
#include "hw/cpu/a9mpcore.h"
27
+CONFIG_STM32VLDISCOVERY=y
25
+#include "hw/intc/exynos4210_gic.h"
28
CONFIG_REALVIEW=y
26
#include "target/arm/cpu-qom.h"
29
CONFIG_VERSATILE=y
27
#include "qom/object.h"
30
CONFIG_VEXPRESS=y
28
31
diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c
29
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
30
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
31
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
32
A9MPPrivState a9mpcore;
33
+ Exynos4210GicState ext_gic;
34
};
35
36
#define TYPE_EXYNOS4210_SOC "exynos4210"
37
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
32
new file mode 100644
38
new file mode 100644
33
index XXXXXXX..XXXXXXX
39
index XXXXXXX..XXXXXXX
34
--- /dev/null
40
--- /dev/null
35
+++ b/hw/arm/stm32vldiscovery.c
41
+++ b/include/hw/intc/exynos4210_gic.h
36
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
37
+/*
43
+/*
38
+ * ST STM32VLDISCOVERY machine
44
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
39
+ *
45
+ *
40
+ * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
41
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
47
+ * All rights reserved.
42
+ *
48
+ *
43
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
44
+ * of this software and associated documentation files (the "Software"), to deal
45
+ * in the Software without restriction, including without limitation the rights
46
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
47
+ * copies of the Software, and to permit persons to whom the Software is
48
+ * furnished to do so, subject to the following conditions:
49
+ *
50
+ *
50
+ * The above copyright notice and this permission notice shall be included in
51
+ * This program is free software; you can redistribute it and/or modify it
51
+ * all copies or substantial portions of the Software.
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
52
+ *
55
+ *
53
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56
+ * This program is distributed in the hope that it will be useful,
54
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
55
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
56
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59
+ * See the GNU General Public License for more details.
57
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60
+ *
58
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
61
+ * You should have received a copy of the GNU General Public License along
59
+ * THE SOFTWARE.
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
60
+ */
63
+ */
64
+#ifndef HW_INTC_EXYNOS4210_GIC_H
65
+#define HW_INTC_EXYNOS4210_GIC_H
61
+
66
+
62
+#include "qemu/osdep.h"
67
+#include "hw/sysbus.h"
63
+#include "qapi/error.h"
64
+#include "hw/boards.h"
65
+#include "hw/qdev-properties.h"
66
+#include "qemu/error-report.h"
67
+#include "hw/arm/stm32f100_soc.h"
68
+#include "hw/arm/boot.h"
69
+
68
+
70
+/* stm32vldiscovery implementation is derived from netduinoplus2 */
69
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
70
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
71
+
71
+
72
+/* Main SYSCLK frequency in Hz (24MHz) */
72
+#define EXYNOS4210_GIC_NCPUS 2
73
+#define SYSCLK_FRQ 24000000ULL
74
+
73
+
75
+static void stm32vldiscovery_init(MachineState *machine)
74
+struct Exynos4210GicState {
76
+{
75
+ SysBusDevice parent_obj;
77
+ DeviceState *dev;
78
+
76
+
79
+ /*
77
+ MemoryRegion cpu_container;
80
+ * TODO: ideally we would model the SoC RCC and let it handle
78
+ MemoryRegion dist_container;
81
+ * system_clock_scale, including its ability to define different
79
+ MemoryRegion cpu_alias[EXYNOS4210_GIC_NCPUS];
82
+ * possible SYSCLK sources.
80
+ MemoryRegion dist_alias[EXYNOS4210_GIC_NCPUS];
83
+ */
81
+ uint32_t num_cpu;
84
+ system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
82
+ DeviceState *gic;
83
+};
85
+
84
+
86
+ dev = qdev_new(TYPE_STM32F100_SOC);
85
+#endif
87
+ qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
86
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
88
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
87
index XXXXXXX..XXXXXXX 100644
89
+
88
--- a/hw/arm/exynos4210.c
90
+ armv7m_load_kernel(ARM_CPU(first_cpu),
89
+++ b/hw/arm/exynos4210.c
91
+ machine->kernel_filename,
90
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
92
+ FLASH_SIZE);
91
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
93
+}
92
94
+
93
/* External GIC */
95
+static void stm32vldiscovery_machine_init(MachineClass *mc)
94
- dev = qdev_new("exynos4210.gic");
96
+{
95
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
97
+ mc->desc = "ST STM32VLDISCOVERY (Cortex-M3)";
96
- busdev = SYS_BUS_DEVICE(dev);
98
+ mc->init = stm32vldiscovery_init;
97
- sysbus_realize_and_unref(busdev, &error_fatal);
99
+}
98
+ qdev_prop_set_uint32(DEVICE(&s->ext_gic), "num-cpu", EXYNOS4210_NCPUS);
100
+
99
+ busdev = SYS_BUS_DEVICE(&s->ext_gic);
101
+DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
100
+ sysbus_realize(busdev, &error_fatal);
102
+
101
/* Map CPU interface */
102
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
103
/* Map Distributer interface */
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
105
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
106
}
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
110
}
111
112
/* Internal Interrupt Combiner */
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
114
}
115
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
118
}
119
120
static void exynos4210_class_init(ObjectClass *klass, void *data)
121
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/intc/exynos4210_gic.c
124
+++ b/hw/intc/exynos4210_gic.c
125
@@ -XXX,XX +XXX,XX @@
126
#include "qemu/module.h"
127
#include "hw/irq.h"
128
#include "hw/qdev-properties.h"
129
+#include "hw/intc/exynos4210_gic.h"
130
#include "hw/arm/exynos4210.h"
131
#include "qom/object.h"
132
133
@@ -XXX,XX +XXX,XX @@
134
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
135
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
136
137
-#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
138
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
139
-
140
-struct Exynos4210GicState {
141
- SysBusDevice parent_obj;
142
-
143
- MemoryRegion cpu_container;
144
- MemoryRegion dist_container;
145
- MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
146
- MemoryRegion dist_alias[EXYNOS4210_NCPUS];
147
- uint32_t num_cpu;
148
- DeviceState *gic;
149
-};
150
-
151
static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
152
{
153
Exynos4210GicState *s = (Exynos4210GicState *)opaque;
154
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
155
* enough room for the cpu numbers. gcc 9.2.1 on 32-bit x86
156
* doesn't figure this out, otherwise and gives spurious warnings.
157
*/
158
- assert(n <= EXYNOS4210_NCPUS);
159
+ assert(n <= EXYNOS4210_GIC_NCPUS);
160
for (i = 0; i < n; i++) {
161
/* Map CPU interface per SMP Core */
162
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
103
diff --git a/MAINTAINERS b/MAINTAINERS
163
diff --git a/MAINTAINERS b/MAINTAINERS
104
index XXXXXXX..XXXXXXX 100644
164
index XXXXXXX..XXXXXXX 100644
105
--- a/MAINTAINERS
165
--- a/MAINTAINERS
106
+++ b/MAINTAINERS
166
+++ b/MAINTAINERS
107
@@ -XXX,XX +XXX,XX @@ F: hw/*/stellaris*
167
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
108
F: include/hw/input/gamepad.h
109
F: docs/system/arm/stellaris.rst
110
111
+STM32VLDISCOVERY
112
+M: Alexandre Iooss <erdnaxe@crans.org>
113
+L: qemu-arm@nongnu.org
114
+S: Maintained
115
+F: hw/arm/stm32vldiscovery.c
116
+
117
Versatile Express
118
M: Peter Maydell <peter.maydell@linaro.org>
119
L: qemu-arm@nongnu.org
168
L: qemu-arm@nongnu.org
120
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
169
S: Odd Fixes
121
index XXXXXXX..XXXXXXX 100644
170
F: hw/*/exynos*
122
--- a/hw/arm/Kconfig
171
-F: include/hw/arm/exynos4210.h
123
+++ b/hw/arm/Kconfig
172
+F: include/hw/*/exynos*
124
@@ -XXX,XX +XXX,XX @@ config STELLARIS
173
125
select STELLARIS_ENET # ethernet
174
Calxeda Highbank
126
select UNIMP
175
M: Rob Herring <robh@kernel.org>
127
128
+config STM32VLDISCOVERY
129
+ bool
130
+ select STM32F100_SOC
131
+
132
config STRONGARM
133
bool
134
select PXA2XX
135
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/arm/meson.build
138
+++ b/hw/arm/meson.build
139
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_Z2', if_true: files('z2.c'))
140
arm_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview.c'))
141
arm_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa-ref.c'))
142
arm_ss.add(when: 'CONFIG_STELLARIS', if_true: files('stellaris.c'))
143
+arm_ss.add(when: 'CONFIG_STM32VLDISCOVERY', if_true: files('stm32vldiscovery.c'))
144
arm_ss.add(when: 'CONFIG_COLLIE', if_true: files('collie.c'))
145
arm_ss.add(when: 'CONFIG_VERSATILE', if_true: files('versatilepb.c'))
146
arm_ss.add(when: 'CONFIG_VEXPRESS', if_true: files('vexpress.c'))
147
--
176
--
148
2.20.1
177
2.25.1
149
150
diff view generated by jsdifflib
New patch
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
2
struct is during realize of the SoC -- we initialize it with the
3
input IRQs of the external GIC device, and then connect those to
4
outputs of other devices further on in realize (including in the
5
exynos4210_init_board_irqs() function). Now that the ext_gic object
6
is easily accessible as s->ext_gic we can make the connections
7
directly from one device to the other without going via this array.
1
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-10-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 1 -
14
hw/arm/exynos4210.c | 12 ++++++------
15
2 files changed, 6 insertions(+), 7 deletions(-)
16
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/exynos4210.h
20
+++ b/include/hw/arm/exynos4210.h
21
@@ -XXX,XX +XXX,XX @@
22
typedef struct Exynos4210Irq {
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
25
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
26
} Exynos4210Irq;
27
28
struct Exynos4210State {
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
34
{
35
uint32_t grp, bit, irq_id, n;
36
Exynos4210Irq *is = &s->irqs;
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
38
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
40
irq_id = 0;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
42
}
43
if (irq_id) {
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
45
- is->ext_gic_irq[irq_id - 32]);
46
+ qdev_get_gpio_in(extgicdev,
47
+ irq_id - 32));
48
} else {
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
50
is->ext_combiner_irq[n]);
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
52
53
if (irq_id) {
54
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
55
- is->ext_gic_irq[irq_id - 32]);
56
+ qdev_get_gpio_in(extgicdev,
57
+ irq_id - 32));
58
}
59
}
60
}
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
62
sysbus_connect_irq(busdev, n,
63
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
64
}
65
- for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
66
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
67
- }
68
69
/* Internal Interrupt Combiner */
70
dev = qdev_new("exynos4210.combiner");
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
72
busdev = SYS_BUS_DEVICE(dev);
73
sysbus_realize_and_unref(busdev, &error_fatal);
74
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
75
- sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
76
+ sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
77
}
78
exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
79
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
80
--
81
2.25.1
diff view generated by jsdifflib
1
The Luminary PL061s in the Stellaris LM3S9695 don't all have the same
1
The function exynos4210_combiner_get_gpioin() currently lives in
2
reset value for GPIOPUR. We can get away with not letting the board
2
exynos4210_combiner.c, but it isn't really part of the combiner
3
configure the PUR reset value because we don't actually wire anything
3
device itself -- it is a function that implements the wiring up of
4
up to the lines which should reset to pull-up. Add a comment noting
4
some interrupt sources to multiple combiner inputs. Move it to live
5
this omission.
5
with the other SoC-level code in exynos4210.c, along with a few
6
macros previously defined in exynos4210.h which are now used only
7
in exynos4210.c.
6
8
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
9
---
12
---
10
hw/gpio/pl061.c | 9 +++++++++
13
include/hw/arm/exynos4210.h | 11 -----
11
1 file changed, 9 insertions(+)
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
16
3 files changed, 82 insertions(+), 88 deletions(-)
12
17
13
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/gpio/pl061.c
20
--- a/include/hw/arm/exynos4210.h
16
+++ b/hw/gpio/pl061.c
21
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ static void pl061_enter_reset(Object *obj, ResetType type)
22
@@ -XXX,XX +XXX,XX @@
18
trace_pl061_reset(DEVICE(s)->canonical_path);
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
19
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
20
/* reset values from PL061 TRM, Stellaris LM3S5P31 & LM3S8962 Data Sheet */
25
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
30
-
31
/* IRQs number for external and internal GIC */
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
33
#define EXYNOS4210_INT_GIC_NIRQ 64
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
35
* bit - bit number inside group */
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
37
38
-/*
39
- * Get Combiner input GPIO into irqs structure
40
- */
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
42
- int ext);
43
-
44
/*
45
* exynos4210 UART
46
*/
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/exynos4210.c
50
+++ b/hw/arm/exynos4210.c
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
53
};
54
55
+#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp) * 8 + (bit))
56
+#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
57
+#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
58
+ ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
59
+
60
/*
61
* Initialize board IRQs.
62
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
63
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
64
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
65
}
66
67
+/*
68
+ * Get Combiner input GPIO into irqs structure
69
+ */
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
71
+ DeviceState *dev, int ext)
72
+{
73
+ int n;
74
+ int bit;
75
+ int max;
76
+ qemu_irq *irq;
77
+
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
21
+
81
+
22
+ /*
82
+ /*
23
+ * FIXME: For the LM3S6965, not all of the PL061 instances have the
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
24
+ * same reset values for GPIOPUR, GPIOAFSEL and GPIODEN, so in theory
84
+ * so let split them.
25
+ * we should allow the board to configure these via properties.
26
+ * In practice, we don't wire anything up to the affected GPIO lines
27
+ * (PB7, PC0, PC1, PC2, PC3 -- they're used for JTAG), so we can
28
+ * get away with this inaccuracy.
29
+ */
85
+ */
30
s->data = 0;
86
+ for (n = 0; n < max; n++) {
31
s->old_in_data = 0;
87
+
32
s->dir = 0;
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
89
+
90
+ switch (n) {
91
+ /* MDNIE_LCD1 INTG1 */
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
96
+ continue;
97
+
98
+ /* TMU INTG3 */
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
102
+ continue;
103
+
104
+ /* LCD1 INTG12 */
105
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
106
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
107
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
108
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
109
+ continue;
110
+
111
+ /* Multi-Core Timer INTG12 */
112
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
113
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
114
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
116
+ continue;
117
+
118
+ /* Multi-Core Timer INTG35 */
119
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
120
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
121
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
122
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
123
+ continue;
124
+
125
+ /* Multi-Core Timer INTG51 */
126
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
127
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
128
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
129
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
130
+ continue;
131
+
132
+ /* Multi-Core Timer INTG53 */
133
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
134
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
135
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
136
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
137
+ continue;
138
+ }
139
+
140
+ irq[n] = qdev_get_gpio_in(dev, n);
141
+ }
142
+}
143
+
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
145
0x09, 0x00, 0x00, 0x00 };
146
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/hw/intc/exynos4210_combiner.c
150
+++ b/hw/intc/exynos4210_combiner.c
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
152
}
153
};
154
155
-/*
156
- * Get Combiner input GPIO into irqs structure
157
- */
158
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
159
- int ext)
160
-{
161
- int n;
162
- int bit;
163
- int max;
164
- qemu_irq *irq;
165
-
166
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
167
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
168
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
169
-
170
- /*
171
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
172
- * so let split them.
173
- */
174
- for (n = 0; n < max; n++) {
175
-
176
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
177
-
178
- switch (n) {
179
- /* MDNIE_LCD1 INTG1 */
180
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
181
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
182
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
183
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
184
- continue;
185
-
186
- /* TMU INTG3 */
187
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
188
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
189
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
190
- continue;
191
-
192
- /* LCD1 INTG12 */
193
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
194
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
195
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
196
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
197
- continue;
198
-
199
- /* Multi-Core Timer INTG12 */
200
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
201
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
202
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
203
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
204
- continue;
205
-
206
- /* Multi-Core Timer INTG35 */
207
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
208
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
209
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
210
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
211
- continue;
212
-
213
- /* Multi-Core Timer INTG51 */
214
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
215
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
216
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
217
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
218
- continue;
219
-
220
- /* Multi-Core Timer INTG53 */
221
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
222
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
223
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
224
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
225
- continue;
226
- }
227
-
228
- irq[n] = qdev_get_gpio_in(dev, n);
229
- }
230
-}
231
-
232
static uint64_t
233
exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
234
{
33
--
235
--
34
2.20.1
236
2.25.1
35
36
diff view generated by jsdifflib
New patch
1
Delete a couple of #defines which are never used.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
6
---
7
include/hw/arm/exynos4210.h | 4 ----
8
1 file changed, 4 deletions(-)
9
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/hw/arm/exynos4210.h
13
+++ b/include/hw/arm/exynos4210.h
14
@@ -XXX,XX +XXX,XX @@
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
17
18
-/* IRQs number for external and internal GIC */
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
21
-
22
#define EXYNOS4210_I2C_NUMBER 9
23
24
#define EXYNOS4210_NUM_DMA 3
25
--
26
2.25.1
diff view generated by jsdifflib
1
Currently the pl061_read() and pl061_write() functions handle offsets
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
2
using a combination of three if() statements and a switch(). Clean
2
instead of qemu_irq_split().
3
this up to use just a switch, using case ranges.
4
5
This requires that instead of catching accesses to the luminary-only
6
registers on a stock PL061 via a check on s->rsvd_start we use
7
an "is this luminary?" check in the cases for each luminary-only
8
register.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
12
---
7
---
13
hw/gpio/pl061.c | 104 ++++++++++++++++++++++++++++++++++++------------
8
include/hw/arm/exynos4210.h | 9 ++++++++
14
1 file changed, 79 insertions(+), 25 deletions(-)
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
10
2 files changed, 42 insertions(+), 8 deletions(-)
15
11
16
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/gpio/pl061.c
14
--- a/include/hw/arm/exynos4210.h
19
+++ b/hw/gpio/pl061.c
15
+++ b/include/hw/arm/exynos4210.h
20
@@ -XXX,XX +XXX,XX @@ struct PL061State {
16
@@ -XXX,XX +XXX,XX @@
21
qemu_irq irq;
17
#include "hw/sysbus.h"
22
qemu_irq out[N_GPIOS];
18
#include "hw/cpu/a9mpcore.h"
23
const unsigned char *id;
19
#include "hw/intc/exynos4210_gic.h"
24
- uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */
20
+#include "hw/core/split-irq.h"
21
#include "target/arm/cpu-qom.h"
22
#include "qom/object.h"
23
24
@@ -XXX,XX +XXX,XX @@
25
26
#define EXYNOS4210_NUM_DMA 3
27
28
+/*
29
+ * We need one splitter for every external combiner input, plus
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
32
+ */
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
34
+
35
typedef struct Exynos4210Irq {
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
40
A9MPPrivState a9mpcore;
41
Exynos4210GicState ext_gic;
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
25
};
43
};
26
44
27
static const VMStateDescription vmstate_pl061 = {
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
28
@@ -XXX,XX +XXX,XX @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
29
{
47
index XXXXXXX..XXXXXXX 100644
30
PL061State *s = (PL061State *)opaque;
48
--- a/hw/arm/exynos4210.c
31
49
+++ b/hw/arm/exynos4210.c
32
- if (offset < 0x400) {
50
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
33
- return s->data & (offset >> 2);
51
uint32_t grp, bit, irq_id, n;
34
- }
52
Exynos4210Irq *is = &s->irqs;
35
- if (offset >= s->rsvd_start && offset <= 0xfcc) {
53
DeviceState *extgicdev = DEVICE(&s->ext_gic);
36
- goto err_out;
54
+ int splitcount = 0;
37
- }
55
+ DeviceState *splitter;
38
- if (offset >= 0xfd0 && offset < 0x1000) {
56
39
- return s->id[(offset - 0xfd0) >> 2];
57
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
40
- }
58
irq_id = 0;
41
switch (offset) {
59
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
42
+ case 0x0 ... 0x3ff: /* Data */
60
/* MCT_G1 is passed to External and GIC */
43
+ return s->data & (offset >> 2);
61
irq_id = EXT_GIC_ID_MCT_G1;
44
case 0x400: /* Direction */
62
}
45
return s->dir;
63
+
46
case 0x404: /* Interrupt sense */
64
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
47
@@ -XXX,XX +XXX,XX @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
65
+ splitter = DEVICE(&s->splitter[splitcount]);
48
case 0x420: /* Alternate function select */
66
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
49
return s->afsel;
67
+ qdev_realize(splitter, NULL, &error_abort);
50
case 0x500: /* 2mA drive */
68
+ splitcount++;
51
+ if (s->id != pl061_id_luminary) {
69
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
52
+ goto bad_offset;
70
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
53
+ }
71
if (irq_id) {
54
return s->dr2r;
72
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
55
case 0x504: /* 4mA drive */
73
- qdev_get_gpio_in(extgicdev,
56
+ if (s->id != pl061_id_luminary) {
74
- irq_id - 32));
57
+ goto bad_offset;
75
+ qdev_connect_gpio_out(splitter, 1,
58
+ }
76
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
59
return s->dr4r;
77
} else {
60
case 0x508: /* 8mA drive */
78
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
61
+ if (s->id != pl061_id_luminary) {
79
- is->ext_combiner_irq[n]);
62
+ goto bad_offset;
80
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
63
+ }
81
}
64
return s->dr8r;
65
case 0x50c: /* Open drain */
66
+ if (s->id != pl061_id_luminary) {
67
+ goto bad_offset;
68
+ }
69
return s->odr;
70
case 0x510: /* Pull-up */
71
+ if (s->id != pl061_id_luminary) {
72
+ goto bad_offset;
73
+ }
74
return s->pur;
75
case 0x514: /* Pull-down */
76
+ if (s->id != pl061_id_luminary) {
77
+ goto bad_offset;
78
+ }
79
return s->pdr;
80
case 0x518: /* Slew rate control */
81
+ if (s->id != pl061_id_luminary) {
82
+ goto bad_offset;
83
+ }
84
return s->slr;
85
case 0x51c: /* Digital enable */
86
+ if (s->id != pl061_id_luminary) {
87
+ goto bad_offset;
88
+ }
89
return s->den;
90
case 0x520: /* Lock */
91
+ if (s->id != pl061_id_luminary) {
92
+ goto bad_offset;
93
+ }
94
return s->locked;
95
case 0x524: /* Commit */
96
+ if (s->id != pl061_id_luminary) {
97
+ goto bad_offset;
98
+ }
99
return s->cr;
100
case 0x528: /* Analog mode select */
101
+ if (s->id != pl061_id_luminary) {
102
+ goto bad_offset;
103
+ }
104
return s->amsel;
105
+ case 0xfd0 ... 0xfff: /* ID registers */
106
+ return s->id[(offset - 0xfd0) >> 2];
107
default:
108
+ bad_offset:
109
+ qemu_log_mask(LOG_GUEST_ERROR,
110
+ "pl061_read: Bad offset %x\n", (int)offset);
111
break;
112
}
82
}
113
-err_out:
83
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
114
- qemu_log_mask(LOG_GUEST_ERROR,
84
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
115
- "pl061_read: Bad offset %x\n", (int)offset);
85
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
116
return 0;
86
87
if (irq_id) {
88
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
89
- qdev_get_gpio_in(extgicdev,
90
- irq_id - 32));
91
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
92
+ splitter = DEVICE(&s->splitter[splitcount]);
93
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
94
+ qdev_realize(splitter, NULL, &error_abort);
95
+ splitcount++;
96
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
97
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
98
+ qdev_connect_gpio_out(splitter, 1,
99
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
100
}
101
}
102
+ /*
103
+ * We check this here to avoid a more obscure assert later when
104
+ * qdev_assert_realized_properly() checks that we realized every
105
+ * child object we initialized.
106
+ */
107
+ assert(splitcount == EXYNOS4210_NUM_SPLITTERS);
117
}
108
}
118
109
119
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
110
/*
120
PL061State *s = (PL061State *)opaque;
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
121
uint8_t mask;
112
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
122
123
- if (offset < 0x400) {
124
+ switch (offset) {
125
+ case 0 ... 0x3ff:
126
mask = (offset >> 2) & s->dir;
127
s->data = (s->data & ~mask) | (value & mask);
128
pl061_update(s);
129
return;
130
- }
131
- if (offset >= s->rsvd_start) {
132
- goto err_out;
133
- }
134
- switch (offset) {
135
case 0x400: /* Direction */
136
s->dir = value & 0xff;
137
break;
138
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
139
s->afsel = (s->afsel & ~mask) | (value & mask);
140
break;
141
case 0x500: /* 2mA drive */
142
+ if (s->id != pl061_id_luminary) {
143
+ goto bad_offset;
144
+ }
145
s->dr2r = value & 0xff;
146
break;
147
case 0x504: /* 4mA drive */
148
+ if (s->id != pl061_id_luminary) {
149
+ goto bad_offset;
150
+ }
151
s->dr4r = value & 0xff;
152
break;
153
case 0x508: /* 8mA drive */
154
+ if (s->id != pl061_id_luminary) {
155
+ goto bad_offset;
156
+ }
157
s->dr8r = value & 0xff;
158
break;
159
case 0x50c: /* Open drain */
160
+ if (s->id != pl061_id_luminary) {
161
+ goto bad_offset;
162
+ }
163
s->odr = value & 0xff;
164
break;
165
case 0x510: /* Pull-up */
166
+ if (s->id != pl061_id_luminary) {
167
+ goto bad_offset;
168
+ }
169
s->pur = value & 0xff;
170
break;
171
case 0x514: /* Pull-down */
172
+ if (s->id != pl061_id_luminary) {
173
+ goto bad_offset;
174
+ }
175
s->pdr = value & 0xff;
176
break;
177
case 0x518: /* Slew rate control */
178
+ if (s->id != pl061_id_luminary) {
179
+ goto bad_offset;
180
+ }
181
s->slr = value & 0xff;
182
break;
183
case 0x51c: /* Digital enable */
184
+ if (s->id != pl061_id_luminary) {
185
+ goto bad_offset;
186
+ }
187
s->den = value & 0xff;
188
break;
189
case 0x520: /* Lock */
190
+ if (s->id != pl061_id_luminary) {
191
+ goto bad_offset;
192
+ }
193
s->locked = (value != 0xacce551);
194
break;
195
case 0x524: /* Commit */
196
+ if (s->id != pl061_id_luminary) {
197
+ goto bad_offset;
198
+ }
199
if (!s->locked)
200
s->cr = value & 0xff;
201
break;
202
case 0x528:
203
+ if (s->id != pl061_id_luminary) {
204
+ goto bad_offset;
205
+ }
206
s->amsel = value & 0xff;
207
break;
208
default:
209
- goto err_out;
210
+ bad_offset:
211
+ qemu_log_mask(LOG_GUEST_ERROR,
212
+ "pl061_write: Bad offset %x\n", (int)offset);
213
+ return;
214
}
113
}
215
pl061_update(s);
114
216
return;
115
+ for (i = 0; i < ARRAY_SIZE(s->splitter); i++) {
217
-err_out:
116
+ g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
218
- qemu_log_mask(LOG_GUEST_ERROR,
117
+ object_initialize_child(obj, name, &s->splitter[i], TYPE_SPLIT_IRQ);
219
- "pl061_write: Bad offset %x\n", (int)offset);
118
+ }
119
+
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
220
}
122
}
221
222
static void pl061_reset(DeviceState *dev)
223
@@ -XXX,XX +XXX,XX @@ static void pl061_luminary_init(Object *obj)
224
PL061State *s = PL061(obj);
225
226
s->id = pl061_id_luminary;
227
- s->rsvd_start = 0x52c;
228
}
229
230
static void pl061_init(Object *obj)
231
@@ -XXX,XX +XXX,XX @@ static void pl061_init(Object *obj)
232
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
233
234
s->id = pl061_id;
235
- s->rsvd_start = 0x424;
236
237
memory_region_init_io(&s->iomem, obj, &pl061_ops, s, "pl061", 0x1000);
238
sysbus_init_mmio(sbd, &s->iomem);
239
--
123
--
240
2.20.1
124
2.25.1
241
242
diff view generated by jsdifflib
New patch
1
In exynos4210_init_board_irqs(), the loop that handles IRQ lines that
2
are in a range that applies to the internal combiner only creates a
3
splitter for those interrupts which go to both the internal combiner
4
and to the external GIC, but it does nothing at all for the
5
interrupts which don't go to the external GIC, leaving the
6
irq_table[] array element empty for those. (This will result in
7
those interrupts simply being lost, not in a QEMU crash.)
1
8
9
I don't have a reliable datasheet for this SoC, but since we do wire
10
up one interrupt line in this category (the HDMI I2C device on
11
interrupt 16,1), this seems like it must be a bug in the existing
12
QEMU code. Fill in the irq_table[] entries where we're not splitting
13
the IRQ to both the internal combiner and the external GIC with the
14
IRQ line of the internal combiner. (That is, these IRQ lines go to
15
just one device, not multiple.)
16
17
This bug didn't have any visible guest effects because the only
18
implemented device that was affected was the HDMI I2C controller,
19
and we never connect any I2C devices to that bus.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20220404154658.565020-14-peter.maydell@linaro.org
24
---
25
hw/arm/exynos4210.c | 2 ++
26
1 file changed, 2 insertions(+)
27
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/exynos4210.c
31
+++ b/hw/arm/exynos4210.c
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
34
qdev_connect_gpio_out(splitter, 1,
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
36
+ } else {
37
+ s->irq_table[n] = is->int_combiner_irq[n];
38
}
39
}
40
/*
41
--
42
2.25.1
diff view generated by jsdifflib
New patch
1
Currently for the interrupts MCT_G0 and MCT_G1 which are
2
the only ones in the input range of the external combiner
3
and which are also wired to the external GIC, we connect
4
them only to the internal combiner and the external GIC.
5
This seems likely to be a bug, as all other interrupts
6
which are in the input range of both combiners are
7
connected to both combiners. (The fact that the code in
8
exynos4210_combiner_get_gpioin() is also trying to wire
9
up these inputs on both combiners also suggests this.)
1
10
11
Wire these interrupts up to both combiners, like the rest.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-15-peter.maydell@linaro.org
16
---
17
hw/arm/exynos4210.c | 7 +++----
18
1 file changed, 3 insertions(+), 4 deletions(-)
19
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/exynos4210.c
23
+++ b/hw/arm/exynos4210.c
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
25
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
27
splitter = DEVICE(&s->splitter[splitcount]);
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
30
qdev_realize(splitter, NULL, &error_abort);
31
splitcount++;
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
35
if (irq_id) {
36
- qdev_connect_gpio_out(splitter, 1,
37
+ qdev_connect_gpio_out(splitter, 2,
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
39
- } else {
40
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
41
}
42
}
43
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
44
--
45
2.25.1
diff view generated by jsdifflib
New patch
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
3
connect multiple IRQs up to the same external GIC input, which
4
is not permitted. We do the same thing in the code in
5
exynos4210_init_board_irqs() because the conditionals selecting
6
an irq_id in the first loop match multiple interrupt IDs.
1
7
8
Overall we do this for interrupt IDs
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
10
and
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
12
13
These correspond to the cases for the multi-core timer that we are
14
wiring up to multiple inputs on the combiner in
15
exynos4210_combiner_get_gpioin(). That code already deals with all
16
these interrupt IDs being the same input source, so we don't need to
17
connect the external GIC interrupt for any of them except the first
18
(1, 4) and (1, 5). Remove the array entries and conditionals which
19
were incorrectly causing us to wire up extra lines.
20
21
This bug didn't cause any visible effects, because we only connect
22
up a device to the "primary" ID values (1, 4) and (1, 5), so the
23
extra lines would never be set to a level.
24
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20220404154658.565020-16-peter.maydell@linaro.org
28
---
29
include/hw/arm/exynos4210.h | 2 +-
30
hw/arm/exynos4210.c | 12 +++++-------
31
2 files changed, 6 insertions(+), 8 deletions(-)
32
33
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/hw/arm/exynos4210.h
36
+++ b/include/hw/arm/exynos4210.h
37
@@ -XXX,XX +XXX,XX @@
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
40
*/
41
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
42
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
43
44
typedef struct Exynos4210Irq {
45
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/exynos4210.c
49
+++ b/hw/arm/exynos4210.c
50
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
51
/* int combiner group 34 */
52
{ EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
53
/* int combiner group 35 */
54
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
55
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1 },
56
/* int combiner group 36 */
57
{ EXT_GIC_ID_MIXER },
58
/* int combiner group 37 */
59
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
60
/* groups 38-50 */
61
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
62
/* int combiner group 51 */
63
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
64
+ { EXT_GIC_ID_MCT_L0 },
65
/* group 52 */
66
{ },
67
/* int combiner group 53 */
68
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
69
+ { EXT_GIC_ID_WDT },
70
/* groups 54-63 */
71
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
72
};
73
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
74
75
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
76
irq_id = 0;
77
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
78
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
79
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4)) {
80
/* MCT_G0 is passed to External GIC */
81
irq_id = EXT_GIC_ID_MCT_G0;
82
}
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
86
/* MCT_G1 is passed to External and GIC */
87
irq_id = EXT_GIC_ID_MCT_G1;
88
}
89
--
90
2.25.1
diff view generated by jsdifflib
1
Convert the use of the DPRINTF debug macro in the PL061 model to
1
At this point, the function exynos4210_init_board_irqs() splits input
2
use tracepoints.
2
IRQ lines to connect them to the input combiner, output combiner and
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
4
some of the combiner input lines further to connect them to multiple
5
different inputs on the combiner.
6
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
8
configurable number of outputs, we can do all this in one place, by
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
10
device when it must be connected to more than one input on each
11
combiner.
12
13
We do this with a new data structure, the combinermap, which is an
14
array each of whose elements is a list of the interrupt IDs on the
15
combiner which must be tied together. As we loop through each
16
interrupt ID, if we find that it is the first one in one of these
17
lists, we configure the splitter device with eonugh extra outputs and
18
wire them up to the other interrupt IDs in the list.
19
20
Conveniently, for all the cases where this is necessary, the
21
lowest-numbered interrupt ID in each group is in the range of the
22
external combiner, so we only need to code for this in the first of
23
the two loops in exynos4210_init_board_irqs().
24
25
The old code in exynos4210_combiner_get_gpioin() which is being
26
deleted here had several problems which don't exist in the new code
27
in its handling of the multi-core timer interrupts:
28
(1) the case labels specified bits 4 ... 8, but bit '8' doesn't
29
exist; these should have been 4 ... 7
30
(2) it used the input irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]
31
multiple times as the input of several different splitters,
32
which isn't allowed
33
(3) in an apparent cut-and-paste error, the cases for all the
34
multi-core timer inputs used "bit + 4" even though the
35
bit range for the case was (intended to be) 4 ... 7, which
36
meant it was looking at non-existent bits 8 ... 11.
37
None of these exist in the new code.
3
38
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
7
---
42
---
8
hw/gpio/pl061.c | 27 +++++++++------------------
43
include/hw/arm/exynos4210.h | 6 +-
9
hw/gpio/trace-events | 6 ++++++
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
10
2 files changed, 15 insertions(+), 18 deletions(-)
45
2 files changed, 119 insertions(+), 65 deletions(-)
11
46
12
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/gpio/pl061.c
49
--- a/include/hw/arm/exynos4210.h
15
+++ b/hw/gpio/pl061.c
50
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@
17
#include "qemu/log.h"
52
18
#include "qemu/module.h"
53
/*
19
#include "qom/object.h"
54
* We need one splitter for every external combiner input, plus
20
-
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
21
-//#define DEBUG_PL061 1
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
22
-
57
+ * minus one for every external combiner ID in second or later
23
-#ifdef DEBUG_PL061
58
+ * places in a combinermap[] line.
24
-#define DPRINTF(fmt, ...) \
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
25
-do { printf("pl061: " fmt , ## __VA_ARGS__); } while (0)
60
*/
26
-#define BADF(fmt, ...) \
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
27
-do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
28
-#else
63
29
-#define DPRINTF(fmt, ...) do {} while(0)
64
typedef struct Exynos4210Irq {
30
-#define BADF(fmt, ...) \
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
31
-do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__);} while (0)
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
32
-#endif
67
index XXXXXXX..XXXXXXX 100644
33
+#include "trace.h"
68
--- a/hw/arm/exynos4210.c
34
69
+++ b/hw/arm/exynos4210.c
35
static const uint8_t pl061_id[12] =
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
36
{ 0x00, 0x00, 0x00, 0x00, 0x61, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
37
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
38
uint8_t out;
73
39
int i;
74
+/*
40
75
+ * Some interrupt lines go to multiple combiner inputs.
41
- DPRINTF("dir = %d, data = %d\n", s->dir, s->data);
76
+ * This data structure defines those: each array element is
42
+ trace_pl061_update(DEVICE(s)->canonical_path, s->dir, s->data);
77
+ * a list of combiner inputs which are connected together;
43
78
+ * the one with the smallest interrupt ID value must be first.
44
/* Outputs float high. */
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
45
/* FIXME: This is board dependent. */
80
+ * wired to anything so we can use 0 as a terminator.
46
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
81
+ */
47
for (i = 0; i < N_GPIOS; i++) {
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
48
mask = 1 << i;
83
+#define IRQNONE 0
49
if (changed & mask) {
84
+
50
- DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
85
+#define COMBINERMAP_SIZE 16
51
- qemu_set_irq(s->out[i], (out & mask) != 0);
86
+
52
+ int level = (out & mask) != 0;
87
+static const int combinermap[COMBINERMAP_SIZE][6] = {
53
+ trace_pl061_set_output(DEVICE(s)->canonical_path, i, level);
88
+ /* MDNIE_LCD1 */
54
+ qemu_set_irq(s->out[i], level);
89
+ { IRQNO(0, 4), IRQNO(1, 0), IRQNONE },
55
}
90
+ { IRQNO(0, 5), IRQNO(1, 1), IRQNONE },
91
+ { IRQNO(0, 6), IRQNO(1, 2), IRQNONE },
92
+ { IRQNO(0, 7), IRQNO(1, 3), IRQNONE },
93
+ /* TMU */
94
+ { IRQNO(2, 4), IRQNO(3, 4), IRQNONE },
95
+ { IRQNO(2, 5), IRQNO(3, 5), IRQNONE },
96
+ { IRQNO(2, 6), IRQNO(3, 6), IRQNONE },
97
+ { IRQNO(2, 7), IRQNO(3, 7), IRQNONE },
98
+ /* LCD1 */
99
+ { IRQNO(11, 4), IRQNO(12, 0), IRQNONE },
100
+ { IRQNO(11, 5), IRQNO(12, 1), IRQNONE },
101
+ { IRQNO(11, 6), IRQNO(12, 2), IRQNONE },
102
+ { IRQNO(11, 7), IRQNO(12, 3), IRQNONE },
103
+ /* Multi-core timer */
104
+ { IRQNO(1, 4), IRQNO(12, 4), IRQNO(35, 4), IRQNO(51, 4), IRQNO(53, 4), IRQNONE },
105
+ { IRQNO(1, 5), IRQNO(12, 5), IRQNO(35, 5), IRQNO(51, 5), IRQNO(53, 5), IRQNONE },
106
+ { IRQNO(1, 6), IRQNO(12, 6), IRQNO(35, 6), IRQNO(51, 6), IRQNO(53, 6), IRQNONE },
107
+ { IRQNO(1, 7), IRQNO(12, 7), IRQNO(35, 7), IRQNO(51, 7), IRQNO(53, 7), IRQNONE },
108
+};
109
+
110
+#undef IRQNO
111
+
112
+static const int *combinermap_entry(int irq)
113
+{
114
+ /*
115
+ * If the interrupt number passed in is the first entry in some
116
+ * line of the combinermap, return a pointer to that line;
117
+ * otherwise return NULL.
118
+ */
119
+ int i;
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
121
+ if (combinermap[i][0] == irq) {
122
+ return combinermap[i];
123
+ }
124
+ }
125
+ return NULL;
126
+}
127
+
128
+static int mapline_size(const int *mapline)
129
+{
130
+ /* Return number of entries in this mapline in total */
131
+ int i = 0;
132
+
133
+ if (!mapline) {
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
135
+ return 1;
136
+ }
137
+ while (*mapline != IRQNONE) {
138
+ mapline++;
139
+ i++;
140
+ }
141
+ return i;
142
+}
143
+
144
/*
145
* Initialize board IRQs.
146
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
147
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
148
DeviceState *extgicdev = DEVICE(&s->ext_gic);
149
int splitcount = 0;
150
DeviceState *splitter;
151
+ const int *mapline;
152
+ int numlines, splitin, in;
153
154
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
155
irq_id = 0;
156
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
157
irq_id = EXT_GIC_ID_MCT_G1;
158
}
159
160
+ if (s->irq_table[n]) {
161
+ /*
162
+ * This must be some non-first entry in a combinermap line,
163
+ * and we've already filled it in.
164
+ */
165
+ continue;
166
+ }
167
+ mapline = combinermap_entry(n);
168
+ /*
169
+ * We need to connect the IRQ to multiple inputs on both combiners
170
+ * and possibly also to the external GIC.
171
+ */
172
+ numlines = 2 * mapline_size(mapline);
173
+ if (irq_id) {
174
+ numlines++;
175
+ }
176
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
177
splitter = DEVICE(&s->splitter[splitcount]);
178
- qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
179
+ qdev_prop_set_uint16(splitter, "num-lines", numlines);
180
qdev_realize(splitter, NULL, &error_abort);
181
splitcount++;
182
- s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
183
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
184
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
185
+
186
+ in = n;
187
+ splitin = 0;
188
+ for (;;) {
189
+ s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
190
+ qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
191
+ qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
192
+ splitin += 2;
193
+ if (!mapline) {
194
+ break;
195
+ }
196
+ mapline++;
197
+ in = *mapline;
198
+ if (in == IRQNONE) {
199
+ break;
200
+ }
201
+ }
202
if (irq_id) {
203
- qdev_connect_gpio_out(splitter, 2,
204
+ qdev_connect_gpio_out(splitter, splitin,
205
qdev_get_gpio_in(extgicdev, irq_id - 32));
56
}
206
}
57
}
207
}
58
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
59
for (i = 0; i < N_GPIOS; i++) {
209
irq_id = combiner_grp_to_gic_id[grp -
60
mask = 1 << i;
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
61
if (changed & mask) {
211
62
- DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0);
212
+ if (s->irq_table[n]) {
63
+ trace_pl061_input_change(DEVICE(s)->canonical_path, i,
213
+ /*
64
+ (s->data & mask) != 0);
214
+ * This must be some non-first entry in a combinermap line,
65
215
+ * and we've already filled it in.
66
if (!(s->isense & mask)) {
216
+ */
67
/* Edge interrupt */
217
+ continue;
68
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
218
+ }
69
/* Level interrupt */
219
+
70
s->istate |= ~(s->data ^ s->iev) & s->isense;
220
if (irq_id) {
71
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
72
- DPRINTF("istate = %02X\n", s->istate);
222
splitter = DEVICE(&s->splitter[splitcount]);
73
+ trace_pl061_update_istate(DEVICE(s)->canonical_path,
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
74
+ s->istate, s->im, (s->istate & s->im) != 0);
224
DeviceState *dev, int ext)
75
225
{
76
qemu_set_irq(s->irq, (s->istate & s->im) != 0);
226
int n;
227
- int bit;
228
int max;
229
qemu_irq *irq;
230
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
234
235
- /*
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
237
- * so let split them.
238
- */
239
for (n = 0; n < max; n++) {
240
-
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
242
-
243
- switch (n) {
244
- /* MDNIE_LCD1 INTG1 */
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
249
- continue;
250
-
251
- /* TMU INTG3 */
252
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
253
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
254
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
255
- continue;
256
-
257
- /* LCD1 INTG12 */
258
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
259
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
260
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
261
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
262
- continue;
263
-
264
- /* Multi-Core Timer INTG12 */
265
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
266
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
267
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
268
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
269
- continue;
270
-
271
- /* Multi-Core Timer INTG35 */
272
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
273
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
274
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
275
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
276
- continue;
277
-
278
- /* Multi-Core Timer INTG51 */
279
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
280
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
281
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
282
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
283
- continue;
284
-
285
- /* Multi-Core Timer INTG53 */
286
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
287
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
288
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
289
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
290
- continue;
291
- }
292
-
293
irq[n] = qdev_get_gpio_in(dev, n);
294
}
77
}
295
}
78
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/gpio/trace-events
81
+++ b/hw/gpio/trace-events
82
@@ -XXX,XX +XXX,XX @@ nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x
83
nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
84
nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
85
86
+# pl061.c
87
+pl061_update(const char *id, uint32_t dir, uint32_t data) "%s GPIODIR 0x%x GPIODATA 0x%x"
88
+pl061_set_output(const char *id, int gpio, int level) "%s setting output %d to %d"
89
+pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to %d"
90
+pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
91
+
92
# sifive_gpio.c
93
sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
94
sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
95
--
296
--
96
2.20.1
297
2.25.1
97
98
diff view generated by jsdifflib
1
The PL061 GPIO does not itself include pullup or pulldown resistors
1
Switch the creation of the combiner devices to the new-style
2
to set the value of a GPIO line treated as an output when it is
2
"embedded in state struct" approach, so we can easily refer
3
configured as an input (ie when the PL061 itself is not driving it).
3
to the object elsewhere during realize.
4
In real hardware it is up to the board to add suitable pullups or
5
pulldowns. Currently our implementation hardwires this to "outputs
6
pulled high", which is correct for some boards (eg the realview ones:
7
see figure 3-29 in the "RealView Platform Baseboard for ARM926EJ-S
8
User Guide" DUI0224I), but wrong for others.
9
10
In particular, the wiring in the 'virt' board and the gpio-pwr device
11
assumes that wires should be pulled low, because otherwise the
12
pull-to-high will trigger a shutdown or reset action. (The only
13
reason this doesn't happen immediately on startup is due to another
14
bug in the PL061, where we don't assert the GPIOs to the correct
15
value on reset, but will do so as soon as the guest touches a
16
register and pl061_update() gets called.)
17
18
Add properties to the pl061 so the board can configure whether it
19
wants GPIO lines to have pullup, pulldown, or neither.
20
4
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
23
---
8
---
24
hw/gpio/pl061.c | 51 +++++++++++++++++++++++++++++++++++++++++++++----
9
include/hw/arm/exynos4210.h | 3 ++
25
1 file changed, 47 insertions(+), 4 deletions(-)
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 20 +++++-----
12
hw/intc/exynos4210_combiner.c | 31 +--------------
13
4 files changed, 72 insertions(+), 39 deletions(-)
14
create mode 100644 include/hw/intc/exynos4210_combiner.h
26
15
27
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/gpio/pl061.c
18
--- a/include/hw/arm/exynos4210.h
30
+++ b/hw/gpio/pl061.c
19
+++ b/include/hw/arm/exynos4210.h
31
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
32
* + unnamed GPIO inputs 0..7: inputs to connect to the emulated GPIO lines
33
* + unnamed GPIO outputs 0..7: the emulated GPIO lines, considered as
34
* outputs
35
+ * + QOM property "pullups": an integer defining whether non-floating lines
36
+ * configured as inputs should be pulled up to logical 1 (ie whether in
37
+ * real hardware they have a pullup resistor on the line out of the PL061).
38
+ * This should be an 8-bit value, where bit 0 is 1 if GPIO line 0 should
39
+ * be pulled high, bit 1 configures line 1, and so on. The default is 0xff,
40
+ * indicating that all GPIO lines are pulled up to logical 1.
41
+ * + QOM property "pulldowns": an integer defining whether non-floating lines
42
+ * configured as inputs should be pulled down to logical 0 (ie whether in
43
+ * real hardware they have a pulldown resistor on the line out of the PL061).
44
+ * This should be an 8-bit value, where bit 0 is 1 if GPIO line 0 should
45
+ * be pulled low, bit 1 configures line 1, and so on. The default is 0x0.
46
+ * It is an error to set a bit in both "pullups" and "pulldowns". If a bit
47
+ * is 0 in both, then the line is considered to be floating, and it will
48
+ * not have qemu_set_irq() called on it when it is configured as an input.
49
*/
50
51
#include "qemu/osdep.h"
52
#include "hw/irq.h"
53
#include "hw/sysbus.h"
21
#include "hw/sysbus.h"
54
+#include "hw/qdev-properties.h"
22
#include "hw/cpu/a9mpcore.h"
55
#include "migration/vmstate.h"
23
#include "hw/intc/exynos4210_gic.h"
56
+#include "qapi/error.h"
24
+#include "hw/intc/exynos4210_combiner.h"
57
#include "qemu/log.h"
25
#include "hw/core/split-irq.h"
58
#include "qemu/module.h"
26
#include "target/arm/cpu-qom.h"
59
#include "qom/object.h"
27
#include "qom/object.h"
60
@@ -XXX,XX +XXX,XX @@ struct PL061State {
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
61
qemu_irq irq;
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
62
qemu_irq out[N_GPIOS];
30
A9MPPrivState a9mpcore;
63
const unsigned char *id;
31
Exynos4210GicState ext_gic;
64
+ /* Properties, for non-Luminary PL061 */
32
+ Exynos4210CombinerState int_combiner;
65
+ uint32_t pullups;
33
+ Exynos4210CombinerState ext_combiner;
66
+ uint32_t pulldowns;
34
SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
67
};
35
};
68
36
69
static const VMStateDescription vmstate_pl061 = {
37
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
70
@@ -XXX,XX +XXX,XX @@ static uint8_t pl061_floating(PL061State *s)
38
new file mode 100644
71
*/
39
index XXXXXXX..XXXXXXX
72
floating = ~(s->pur | s->pdr);
40
--- /dev/null
73
} else {
41
+++ b/include/hw/intc/exynos4210_combiner.h
74
- /* Assume outputs are pulled high. FIXME: this is board dependent. */
42
@@ -XXX,XX +XXX,XX @@
75
- floating = 0;
43
+/*
76
+ floating = ~(s->pullups | s->pulldowns);
44
+ * Samsung exynos4210 Interrupt Combiner
77
}
45
+ *
78
return floating & ~s->dir;
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
79
}
47
+ * All rights reserved.
80
@@ -XXX,XX +XXX,XX @@ static uint8_t pl061_pullups(PL061State *s)
48
+ *
81
*/
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
82
pullups = s->pur;
50
+ *
83
} else {
51
+ * This program is free software; you can redistribute it and/or modify it
84
- /* Assume outputs are pulled high. FIXME: this is board dependent. */
52
+ * under the terms of the GNU General Public License as published by the
85
- pullups = 0xff;
53
+ * Free Software Foundation; either version 2 of the License, or (at your
86
+ pullups = s->pullups;
54
+ * option) any later version.
87
}
55
+ *
88
return pullups & ~s->dir;
56
+ * This program is distributed in the hope that it will be useful,
89
}
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
90
@@ -XXX,XX +XXX,XX @@ static void pl061_init(Object *obj)
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
91
qdev_init_gpio_out(dev, s->out, N_GPIOS);
59
+ * See the GNU General Public License for more details.
92
}
60
+ *
93
61
+ * You should have received a copy of the GNU General Public License along
94
+static void pl061_realize(DeviceState *dev, Error **errp)
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
95
+{
63
+ */
96
+ PL061State *s = PL061(dev);
97
+
64
+
98
+ if (s->pullups > 0xff) {
65
+#ifndef HW_INTC_EXYNOS4210_COMBINER
99
+ error_setg(errp, "pullups property must be between 0 and 0xff");
66
+#define HW_INTC_EXYNOS4210_COMBINER
100
+ return;
101
+ }
102
+ if (s->pulldowns > 0xff) {
103
+ error_setg(errp, "pulldowns property must be between 0 and 0xff");
104
+ return;
105
+ }
106
+ if (s->pullups & s->pulldowns) {
107
+ error_setg(errp, "no bit may be set both in pullups and pulldowns");
108
+ return;
109
+ }
110
+}
111
+
67
+
112
+static Property pl061_props[] = {
68
+#include "hw/sysbus.h"
113
+ DEFINE_PROP_UINT32("pullups", PL061State, pullups, 0xff),
69
+
114
+ DEFINE_PROP_UINT32("pulldowns", PL061State, pulldowns, 0x0),
70
+/*
115
+ DEFINE_PROP_END_OF_LIST()
71
+ * State for each output signal of internal combiner
72
+ */
73
+typedef struct CombinerGroupState {
74
+ uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
75
+ uint8_t src_pending; /* Pending source interrupts before masking */
76
+} CombinerGroupState;
77
+
78
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
79
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
80
+
81
+/* Number of groups and total number of interrupts for the internal combiner */
82
+#define IIC_NGRP 64
83
+#define IIC_NIRQ (IIC_NGRP * 8)
84
+#define IIC_REGSET_SIZE 0x41
85
+
86
+struct Exynos4210CombinerState {
87
+ SysBusDevice parent_obj;
88
+
89
+ MemoryRegion iomem;
90
+
91
+ struct CombinerGroupState group[IIC_NGRP];
92
+ uint32_t reg_set[IIC_REGSET_SIZE];
93
+ uint32_t icipsr[2];
94
+ uint32_t external; /* 1 means that this combiner is external */
95
+
96
+ qemu_irq output_irq[IIC_NGRP];
116
+};
97
+};
117
+
98
+
118
static void pl061_class_init(ObjectClass *klass, void *data)
99
+#endif
119
{
100
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
120
DeviceClass *dc = DEVICE_CLASS(klass);
101
index XXXXXXX..XXXXXXX 100644
121
102
--- a/hw/arm/exynos4210.c
122
dc->vmsd = &vmstate_pl061;
103
+++ b/hw/arm/exynos4210.c
123
dc->reset = &pl061_reset;
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
124
+ dc->realize = pl061_realize;
105
}
125
+ device_class_set_props(dc, pl061_props);
106
107
/* Internal Interrupt Combiner */
108
- dev = qdev_new("exynos4210.combiner");
109
- busdev = SYS_BUS_DEVICE(dev);
110
- sysbus_realize_and_unref(busdev, &error_fatal);
111
+ busdev = SYS_BUS_DEVICE(&s->int_combiner);
112
+ sysbus_realize(busdev, &error_fatal);
113
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
114
sysbus_connect_irq(busdev, n,
115
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
116
}
117
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
118
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
119
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
120
121
/* External Interrupt Combiner */
122
- dev = qdev_new("exynos4210.combiner");
123
- qdev_prop_set_uint32(dev, "external", 1);
124
- busdev = SYS_BUS_DEVICE(dev);
125
- sysbus_realize_and_unref(busdev, &error_fatal);
126
+ qdev_prop_set_uint32(DEVICE(&s->ext_combiner), "external", 1);
127
+ busdev = SYS_BUS_DEVICE(&s->ext_combiner);
128
+ sysbus_realize(busdev, &error_fatal);
129
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
130
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
131
}
132
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
133
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
134
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
135
136
/* Initialize board IRQs. */
137
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
138
139
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
140
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
141
+ object_initialize_child(obj, "int-combiner", &s->int_combiner,
142
+ TYPE_EXYNOS4210_COMBINER);
143
+ object_initialize_child(obj, "ext-combiner", &s->ext_combiner,
144
+ TYPE_EXYNOS4210_COMBINER);
126
}
145
}
127
146
128
static const TypeInfo pl061_info = {
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/intc/exynos4210_combiner.c
151
+++ b/hw/intc/exynos4210_combiner.c
152
@@ -XXX,XX +XXX,XX @@
153
#include "hw/sysbus.h"
154
#include "migration/vmstate.h"
155
#include "qemu/module.h"
156
-
157
+#include "hw/intc/exynos4210_combiner.h"
158
#include "hw/arm/exynos4210.h"
159
#include "hw/hw.h"
160
#include "hw/irq.h"
161
@@ -XXX,XX +XXX,XX @@
162
#define DPRINTF(fmt, ...) do {} while (0)
163
#endif
164
165
-#define IIC_NGRP 64 /* Internal Interrupt Combiner
166
- Groups number */
167
-#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner
168
- Interrupts number */
169
#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */
170
-#define IIC_REGSET_SIZE 0x41
171
-
172
-/*
173
- * State for each output signal of internal combiner
174
- */
175
-typedef struct CombinerGroupState {
176
- uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
177
- uint8_t src_pending; /* Pending source interrupts before masking */
178
-} CombinerGroupState;
179
-
180
-#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
181
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
182
-
183
-struct Exynos4210CombinerState {
184
- SysBusDevice parent_obj;
185
-
186
- MemoryRegion iomem;
187
-
188
- struct CombinerGroupState group[IIC_NGRP];
189
- uint32_t reg_set[IIC_REGSET_SIZE];
190
- uint32_t icipsr[2];
191
- uint32_t external; /* 1 means that this combiner is external */
192
-
193
- qemu_irq output_irq[IIC_NGRP];
194
-};
195
196
static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
197
.name = "exynos4210.combiner.groupstate",
129
--
198
--
130
2.20.1
199
2.25.1
131
132
diff view generated by jsdifflib
1
Add tracepoints for reads and writes to the PL061 registers. This requires
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
2
restructuring pl061_read() to only return after the tracepoint, rather
2
arrays in the Exynos4210Irq struct is during realize of the SoC -- we
3
than having lots of early-returns.
3
initialize them with the input IRQs of the combiner devices, and then
4
connect those to outputs of other devices in
5
exynos4210_init_board_irqs(). Now that the combiner objects are
6
easily accessible as s->int_combiner and s->ext_combiner we can make
7
the connections directly from one device to the other without going
8
via these arrays.
9
10
Since these are the only two remaining elements of Exynos4210Irq,
11
we can remove that struct entirely.
4
12
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
8
---
16
---
9
hw/gpio/pl061.c | 70 ++++++++++++++++++++++++++++++--------------
17
include/hw/arm/exynos4210.h | 6 ------
10
hw/gpio/trace-events | 2 ++
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
11
2 files changed, 50 insertions(+), 22 deletions(-)
19
2 files changed, 8 insertions(+), 32 deletions(-)
12
20
13
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/gpio/pl061.c
23
--- a/include/hw/arm/exynos4210.h
16
+++ b/hw/gpio/pl061.c
24
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
25
@@ -XXX,XX +XXX,XX @@
18
unsigned size)
26
*/
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
28
29
-typedef struct Exynos4210Irq {
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
32
-} Exynos4210Irq;
33
-
34
struct Exynos4210State {
35
/*< private >*/
36
SysBusDevice parent_obj;
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
- Exynos4210Irq irqs;
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
41
42
MemoryRegion chipid_mem;
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
48
static void exynos4210_init_board_irqs(Exynos4210State *s)
19
{
49
{
20
PL061State *s = (PL061State *)opaque;
50
uint32_t grp, bit, irq_id, n;
21
+ uint64_t r = 0;
51
- Exynos4210Irq *is = &s->irqs;
22
52
DeviceState *extgicdev = DEVICE(&s->ext_gic);
23
switch (offset) {
53
+ DeviceState *intcdev = DEVICE(&s->int_combiner);
24
case 0x0 ... 0x3ff: /* Data */
54
+ DeviceState *extcdev = DEVICE(&s->ext_combiner);
25
- return s->data & (offset >> 2);
55
int splitcount = 0;
26
+ r = s->data & (offset >> 2);
56
DeviceState *splitter;
27
+ break;
57
const int *mapline;
28
case 0x400: /* Direction */
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
29
- return s->dir;
59
splitin = 0;
30
+ r = s->dir;
60
for (;;) {
31
+ break;
61
s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
32
case 0x404: /* Interrupt sense */
62
- qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
33
- return s->isense;
63
- qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
34
+ r = s->isense;
64
+ qdev_connect_gpio_out(splitter, splitin,
35
+ break;
65
+ qdev_get_gpio_in(intcdev, in));
36
case 0x408: /* Interrupt both edges */
66
+ qdev_connect_gpio_out(splitter, splitin + 1,
37
- return s->ibe;
67
+ qdev_get_gpio_in(extcdev, in));
38
+ r = s->ibe;
68
splitin += 2;
39
+ break;
69
if (!mapline) {
40
case 0x40c: /* Interrupt event */
70
break;
41
- return s->iev;
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
42
+ r = s->iev;
72
qdev_realize(splitter, NULL, &error_abort);
43
+ break;
73
splitcount++;
44
case 0x410: /* Interrupt mask */
74
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
45
- return s->im;
75
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
46
+ r = s->im;
76
+ qdev_connect_gpio_out(splitter, 0, qdev_get_gpio_in(intcdev, n));
47
+ break;
77
qdev_connect_gpio_out(splitter, 1,
48
case 0x414: /* Raw interrupt status */
78
qdev_get_gpio_in(extgicdev, irq_id - 32));
49
- return s->istate;
79
} else {
50
+ r = s->istate;
80
- s->irq_table[n] = is->int_combiner_irq[n];
51
+ break;
81
+ s->irq_table[n] = qdev_get_gpio_in(intcdev, n);
52
case 0x418: /* Masked interrupt status */
53
- return s->istate & s->im;
54
+ r = s->istate & s->im;
55
+ break;
56
case 0x420: /* Alternate function select */
57
- return s->afsel;
58
+ r = s->afsel;
59
+ break;
60
case 0x500: /* 2mA drive */
61
if (s->id != pl061_id_luminary) {
62
goto bad_offset;
63
}
82
}
64
- return s->dr2r;
65
+ r = s->dr2r;
66
+ break;
67
case 0x504: /* 4mA drive */
68
if (s->id != pl061_id_luminary) {
69
goto bad_offset;
70
}
71
- return s->dr4r;
72
+ r = s->dr4r;
73
+ break;
74
case 0x508: /* 8mA drive */
75
if (s->id != pl061_id_luminary) {
76
goto bad_offset;
77
}
78
- return s->dr8r;
79
+ r = s->dr8r;
80
+ break;
81
case 0x50c: /* Open drain */
82
if (s->id != pl061_id_luminary) {
83
goto bad_offset;
84
}
85
- return s->odr;
86
+ r = s->odr;
87
+ break;
88
case 0x510: /* Pull-up */
89
if (s->id != pl061_id_luminary) {
90
goto bad_offset;
91
}
92
- return s->pur;
93
+ r = s->pur;
94
+ break;
95
case 0x514: /* Pull-down */
96
if (s->id != pl061_id_luminary) {
97
goto bad_offset;
98
}
99
- return s->pdr;
100
+ r = s->pdr;
101
+ break;
102
case 0x518: /* Slew rate control */
103
if (s->id != pl061_id_luminary) {
104
goto bad_offset;
105
}
106
- return s->slr;
107
+ r = s->slr;
108
+ break;
109
case 0x51c: /* Digital enable */
110
if (s->id != pl061_id_luminary) {
111
goto bad_offset;
112
}
113
- return s->den;
114
+ r = s->den;
115
+ break;
116
case 0x520: /* Lock */
117
if (s->id != pl061_id_luminary) {
118
goto bad_offset;
119
}
120
- return s->locked;
121
+ r = s->locked;
122
+ break;
123
case 0x524: /* Commit */
124
if (s->id != pl061_id_luminary) {
125
goto bad_offset;
126
}
127
- return s->cr;
128
+ r = s->cr;
129
+ break;
130
case 0x528: /* Analog mode select */
131
if (s->id != pl061_id_luminary) {
132
goto bad_offset;
133
}
134
- return s->amsel;
135
+ r = s->amsel;
136
+ break;
137
case 0xfd0 ... 0xfff: /* ID registers */
138
- return s->id[(offset - 0xfd0) >> 2];
139
+ r = s->id[(offset - 0xfd0) >> 2];
140
+ break;
141
default:
142
bad_offset:
143
qemu_log_mask(LOG_GUEST_ERROR,
144
"pl061_read: Bad offset %x\n", (int)offset);
145
break;
146
}
83
}
147
- return 0;
84
/*
148
+
85
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
149
+ trace_pl061_read(DEVICE(s)->canonical_path, offset, r);
86
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
150
+ return r;
151
}
87
}
152
88
153
static void pl061_write(void *opaque, hwaddr offset,
89
-/*
154
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
90
- * Get Combiner input GPIO into irqs structure
155
PL061State *s = (PL061State *)opaque;
91
- */
156
uint8_t mask;
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
157
93
- DeviceState *dev, int ext)
158
+ trace_pl061_write(DEVICE(s)->canonical_path, offset, value);
94
-{
159
+
95
- int n;
160
switch (offset) {
96
- int max;
161
case 0 ... 0x3ff:
97
- qemu_irq *irq;
162
mask = (offset >> 2) & s->dir;
98
-
163
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
164
index XXXXXXX..XXXXXXX 100644
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
165
--- a/hw/gpio/trace-events
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
166
+++ b/hw/gpio/trace-events
102
-
167
@@ -XXX,XX +XXX,XX @@ pl061_update(const char *id, uint32_t dir, uint32_t data) "%s GPIODIR 0x%x GPIOD
103
- for (n = 0; n < max; n++) {
168
pl061_set_output(const char *id, int gpio, int level) "%s setting output %d to %d"
104
- irq[n] = qdev_get_gpio_in(dev, n);
169
pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to %d"
105
- }
170
pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
106
-}
171
+pl061_read(const char *id, uint64_t offset, uint64_t r) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
107
-
172
+pl061_write(const char *id, uint64_t offset, uint64_t value) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
108
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
173
109
0x09, 0x00, 0x00, 0x00 };
174
# sifive_gpio.c
110
175
sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
112
sysbus_connect_irq(busdev, n,
113
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
114
}
115
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
116
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
117
118
/* External Interrupt Combiner */
119
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
120
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
121
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
122
}
123
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
124
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
125
126
/* Initialize board IRQs. */
176
--
127
--
177
2.20.1
128
2.25.1
178
179
diff view generated by jsdifflib
1
From: Alexandre Iooss <erdnaxe@crans.org>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
New mini-kernel test for STM32VLDISCOVERY USART1.
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
6
Acked-by: Thomas Huth <thuth@redhat.com>
7
Acked-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210617165647.2575955-5-erdnaxe@crans.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
tests/qtest/boot-serial-test.c | 37 ++++++++++++++++++++++++++++++++++
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
12
1 file changed, 37 insertions(+)
9
1 file changed, 24 insertions(+), 9 deletions(-)
13
10
14
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qtest/boot-serial-test.c
13
--- a/hw/arm/realview.c
17
+++ b/tests/qtest/boot-serial-test.c
14
+++ b/hw/arm/realview.c
18
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_nrf51[] = {
15
@@ -XXX,XX +XXX,XX @@
19
0x1c, 0x25, 0x00, 0x40 /* 0x4000251c = UART TXD */
16
#include "hw/sysbus.h"
17
#include "hw/arm/boot.h"
18
#include "hw/arm/primecell.h"
19
+#include "hw/core/split-irq.h"
20
#include "hw/net/lan9118.h"
21
#include "hw/net/smc91c111.h"
22
#include "hw/pci/pci.h"
23
+#include "hw/qdev-core.h"
24
#include "net/net.h"
25
#include "sysemu/sysemu.h"
26
#include "hw/boards.h"
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
28
0x76d
20
};
29
};
21
30
22
+static const uint8_t kernel_stm32vldiscovery[] = {
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
23
+ 0x00, 0x00, 0x00, 0x00, /* Stack top address */
32
+ qemu_irq out1, qemu_irq out2) {
24
+ 0x1d, 0x00, 0x00, 0x00, /* Reset handler address */
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
25
+ 0x00, 0x00, 0x00, 0x00, /* NMI */
26
+ 0x00, 0x00, 0x00, 0x00, /* Hard fault */
27
+ 0x00, 0x00, 0x00, 0x00, /* Memory management fault */
28
+ 0x00, 0x00, 0x00, 0x00, /* Bus fault */
29
+ 0x00, 0x00, 0x00, 0x00, /* Usage fault */
30
+ 0x0b, 0x4b, /* ldr r3, [pc, #44] Get RCC */
31
+ 0x44, 0xf2, 0x04, 0x02, /* movw r2, #16388 */
32
+ 0x1a, 0x60, /* str r2, [r3] */
33
+ 0x0a, 0x4b, /* ldr r3, [pc, #40] Get GPIOA */
34
+ 0x1a, 0x68, /* ldr r2, [r3] */
35
+ 0x22, 0xf0, 0xf0, 0x02, /* bic r2, r2, #240 */
36
+ 0x1a, 0x60, /* str r2, [r3] */
37
+ 0x1a, 0x68, /* ldr r2, [r3] */
38
+ 0x42, 0xf0, 0xb0, 0x02, /* orr r2, r2, #176 */
39
+ 0x1a, 0x60, /* str r2, [r3] */
40
+ 0x07, 0x4b, /* ldr r3, [pc, #26] Get BAUD */
41
+ 0x45, 0x22, /* movs r2, #69 */
42
+ 0x1a, 0x60, /* str r2, [r3] */
43
+ 0x06, 0x4b, /* ldr r3, [pc, #24] Get ENABLE */
44
+ 0x42, 0xf2, 0x08, 0x02, /* movw r2, #8200 */
45
+ 0x1a, 0x60, /* str r2, [r3] */
46
+ 0x05, 0x4b, /* ldr r3, [pc, #20] Get TXD */
47
+ 0x54, 0x22, /* movs r2, 'T' */
48
+ 0x1a, 0x60, /* str r2, [r3] */
49
+ 0xfe, 0xe7, /* b . */
50
+ 0x18, 0x10, 0x02, 0x40, /* 0x40021018 = RCC */
51
+ 0x04, 0x08, 0x01, 0x40, /* 0x40010804 = GPIOA */
52
+ 0x08, 0x38, 0x01, 0x40, /* 0x40013808 = USART1 BAUD */
53
+ 0x0c, 0x38, 0x01, 0x40, /* 0x4001380c = USART1 ENABLE */
54
+ 0x04, 0x38, 0x01, 0x40 /* 0x40013804 = USART1 TXD */
55
+};
56
+
34
+
57
typedef struct testdef {
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
58
const char *arch; /* Target architecture */
36
+
59
const char *machine; /* Name of the machine */
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
60
@@ -XXX,XX +XXX,XX @@ static testdef_t tests[] = {
38
+
61
{ "aarch64", "virt", "-cpu max", "TT", sizeof(kernel_aarch64),
39
+ qdev_connect_gpio_out(splitter, 0, out1);
62
kernel_aarch64 },
40
+ qdev_connect_gpio_out(splitter, 1, out2);
63
{ "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
41
+ qdev_connect_gpio_out_named(src, outname, 0,
64
+ { "arm", "stm32vldiscovery", "", "T",
42
+ qdev_get_gpio_in(splitter, 0));
65
+ sizeof(kernel_stm32vldiscovery), kernel_stm32vldiscovery },
43
+}
66
44
+
67
{ NULL }
45
static void realview_init(MachineState *machine,
68
};
46
enum realview_board_type board_type)
47
{
48
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
49
DeviceState *dev, *sysctl, *gpio2, *pl041;
50
SysBusDevice *busdev;
51
qemu_irq pic[64];
52
- qemu_irq mmc_irq[2];
53
PCIBus *pci_bus = NULL;
54
NICInfo *nd;
55
DriveInfo *dinfo;
56
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
57
* and the PL061 has them the other way about. Also the card
58
* detect line is inverted.
59
*/
60
- mmc_irq[0] = qemu_irq_split(
61
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
62
- qdev_get_gpio_in(gpio2, 1));
63
- mmc_irq[1] = qemu_irq_split(
64
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
65
- qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
66
- qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
67
- qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
68
+ split_irq_from_named(dev, "card-read-only",
69
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
70
+ qdev_get_gpio_in(gpio2, 1));
71
+
72
+ split_irq_from_named(dev, "card-inserted",
73
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
74
+ qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
75
+
76
dinfo = drive_get(IF_SD, 0, 0);
77
if (dinfo) {
78
DeviceState *card;
69
--
79
--
70
2.20.1
80
2.25.1
71
72
diff view generated by jsdifflib
1
The stellaris board doesn't emulate the handling of the OLED
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
chipselect line correctly. Expand the comment describing this,
3
including a sketch of the theoretical correct way to do it.
4
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
7
---
7
hw/arm/stellaris.c | 56 +++++++++++++++++++++++++++++++++++++++++++++-
8
hw/arm/stellaris.c | 15 +++++++++++++--
8
1 file changed, 55 insertions(+), 1 deletion(-)
9
1 file changed, 13 insertions(+), 2 deletions(-)
9
10
10
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/arm/stellaris.c
13
--- a/hw/arm/stellaris.c
13
+++ b/hw/arm/stellaris.c
14
+++ b/hw/arm/stellaris.c
15
@@ -XXX,XX +XXX,XX @@
16
17
#include "qemu/osdep.h"
18
#include "qapi/error.h"
19
+#include "hw/core/split-irq.h"
20
#include "hw/sysbus.h"
21
#include "hw/sd/sd.h"
22
#include "hw/ssi/ssi.h"
14
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
15
DeviceState *sddev;
16
DeviceState *ssddev;
24
DeviceState *ssddev;
17
25
DriveInfo *dinfo;
18
- /* Some boards have both an OLED controller and SD card connected to
26
DeviceState *carddev;
19
+ /*
27
+ DeviceState *gpio_d_splitter;
20
+ * Some boards have both an OLED controller and SD card connected to
28
BlockBackend *blk;
21
* the same SSI port, with the SD card chip select connected to a
29
22
* GPIO pin. Technically the OLED chip select is connected to the
30
/*
23
* SSI Fss pin. We do not bother emulating that as both devices
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
24
* should never be selected simultaneously, and our OLED controller
32
&error_fatal);
25
* ignores stray 0xff commands that occur when deselecting the SD
33
26
* card.
34
ssddev = ssi_create_peripheral(bus, "ssd0323");
27
+ *
35
- gpio_out[GPIO_D][0] = qemu_irq_split(
28
+ * The h/w wiring is:
36
- qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
29
+ * - GPIO pin D0 is wired to the active-low SD card chip select
37
+
30
+ * - GPIO pin A3 is wired to the active-low OLED chip select
38
+ gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
31
+ * - The SoC wiring of the PL061 "auxiliary function" for A3 is
39
+ qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
32
+ * SSI0Fss ("frame signal"), which is an output from the SoC's
40
+ qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
33
+ * SSI controller. The SSI controller takes SSI0Fss low when it
41
+ qdev_connect_gpio_out(
34
+ * transmits a frame, so it can work as a chip-select signal.
42
+ gpio_d_splitter, 0,
35
+ * - GPIO A4 is aux-function SSI0Rx, and wired to the SD card Tx
43
+ qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0));
36
+ * (the OLED never sends data to the CPU, so no wiring needed)
44
+ qdev_connect_gpio_out(
37
+ * - GPIO A5 is aux-function SSI0Tx, and wired to the SD card Rx
45
+ gpio_d_splitter, 1,
38
+ * and the OLED display-data-in
46
qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0));
39
+ * - GPIO A2 is aux-function SSI0Clk, wired to SD card and OLED
47
+ gpio_out[GPIO_D][0] = qdev_get_gpio_in(gpio_d_splitter, 0);
40
+ * serial-clock input
48
+
41
+ * So a guest that wants to use the OLED can configure the PL061
49
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
42
+ * to make pins A2, A3, A5 aux-function, so they are connected
50
43
+ * directly to the SSI controller. When the SSI controller sends
51
/* Make sure the select pin is high. */
44
+ * data it asserts SSI0Fss which selects the OLED.
45
+ * A guest that wants to use the SD card configures A2, A4 and A5
46
+ * as aux-function, but leaves A3 as a software-controlled GPIO
47
+ * line. It asserts the SD card chip-select by using the PL061
48
+ * to control pin D0, and lets the SSI controller handle Clk, Tx
49
+ * and Rx. (The SSI controller asserts Fss during tx cycles as
50
+ * usual, but because A3 is not set to aux-function this is not
51
+ * forwarded to the OLED, and so the OLED stays unselected.)
52
+ *
53
+ * The QEMU implementation instead is:
54
+ * - GPIO pin D0 is wired to the active-low SD card chip select,
55
+ * and also to the OLED chip-select which is implemented
56
+ * as *active-high*
57
+ * - SSI controller signals go to the devices regardless of
58
+ * whether the guest programs A2, A4, A5 as aux-function or not
59
+ *
60
+ * The problem with this implementation is if the guest doesn't
61
+ * care about the SD card and only uses the OLED. In that case it
62
+ * may choose never to do anything with D0 (leaving it in its
63
+ * default floating state, which reliably leaves the card disabled
64
+ * because an SD card has a pullup on CS within the card itself),
65
+ * and only set up A2, A3, A5. This for us would mean the OLED
66
+ * never gets the chip-select assert it needs. We work around
67
+ * this with a manual raise of D0 here (despite board creation
68
+ * code being the wrong place to raise IRQ lines) to put the OLED
69
+ * into an initially selected state.
70
+ *
71
+ * In theory the right way to model this would be:
72
+ * - Implement aux-function support in the PL061, with an
73
+ * extra set of AFIN and AFOUT GPIO lines (set up so that
74
+ * if a GPIO line is in auxfn mode the main GPIO in and out
75
+ * track the AFIN and AFOUT lines)
76
+ * - Wire the AFOUT for D0 up to either a line from the
77
+ * SSI controller that's pulled low around every transmit,
78
+ * or at least to an always-0 line here on the board
79
+ * - Make the ssd0323 OLED controller chipselect active-low
80
*/
81
bus = qdev_get_child_bus(dev, "ssi");
82
83
--
52
--
84
2.20.1
53
2.25.1
85
86
diff view generated by jsdifflib
New patch
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
include/hw/irq.h | 5 -----
10
hw/core/irq.c | 15 ---------------
11
2 files changed, 20 deletions(-)
12
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/irq.h
16
+++ b/include/hw/irq.h
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
18
/* Returns a new IRQ with opposite polarity. */
19
qemu_irq qemu_irq_invert(qemu_irq irq);
20
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
23
- */
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
25
-
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
27
on an existing vector of qemu_irq. */
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/core/irq.c
32
+++ b/hw/core/irq.c
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
35
}
36
37
-static void qemu_splitirq(void *opaque, int line, int level)
38
-{
39
- struct IRQState **irq = opaque;
40
- irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
41
- irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
42
-}
43
-
44
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
45
-{
46
- qemu_irq *s = g_new0(qemu_irq, 2);
47
- s[0] = irq1;
48
- s[1] = irq2;
49
- return qemu_allocate_irq(qemu_splitirq, s, 0);
50
-}
51
-
52
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
53
{
54
int i;
55
--
56
2.25.1
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2
2
3
Add a space in the message printed when gicr_read*/gicr_write* returns
3
Describe that the gic-version influences the maximum number of CPUs.
4
MEMTX_ERROR in arm_gicv3_redist.c.
5
4
6
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
8
Message-id: 20210706211432.31902-1-rebecca@nuviainc.com
7
[PMM: minor punctuation tweaks]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
hw/intc/arm_gicv3_redist.c | 4 ++--
11
docs/system/arm/virt.rst | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
13
14
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gicv3_redist.c
16
--- a/docs/system/arm/virt.rst
17
+++ b/hw/intc/arm_gicv3_redist.c
17
+++ b/docs/system/arm/virt.rst
18
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
18
@@ -XXX,XX +XXX,XX @@ gic-version
19
if (r == MEMTX_ERROR) {
19
Valid values are:
20
qemu_log_mask(LOG_GUEST_ERROR,
20
21
"%s: invalid guest read at offset " TARGET_FMT_plx
21
``2``
22
- "size %u\n", __func__, offset, size);
22
- GICv2
23
+ " size %u\n", __func__, offset, size);
23
+ GICv2. Note that this limits the number of CPUs to 8.
24
trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset,
24
``3``
25
size, attrs.secure);
25
- GICv3
26
/* The spec requires that reserved registers are RAZ/WI;
26
+ GICv3. This allows up to 512 CPUs.
27
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
27
``host``
28
if (r == MEMTX_ERROR) {
28
Use the same GIC version the host provides, when using KVM
29
qemu_log_mask(LOG_GUEST_ERROR,
29
``max``
30
"%s: invalid guest write at offset " TARGET_FMT_plx
31
- "size %u\n", __func__, offset, size);
32
+ " size %u\n", __func__, offset, size);
33
trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data,
34
size, attrs.secure);
35
/* The spec requires that reserved registers are RAZ/WI;
36
--
30
--
37
2.20.1
31
2.25.1
38
39
diff view generated by jsdifflib
1
From: Ricardo Koller <ricarkol@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
icv_eoir_write() and icv_dir_write() ignore invalid virtual IRQ numbers
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
4
(like LPIs). The issue is that these functions check against the number
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
5
of implemented IRQs (QEMU's default is num_irq=288) which can be lower
6
than the maximum virtual IRQ number (1020 - 1). The consequence is that
7
if a hypervisor creates an LR for an IRQ between 288 and 1020, then the
8
guest is unable to deactivate the resulting IRQ. Note that other
9
functions that deal with large IRQ numbers, like icv_iar_read, check
10
against 1020 and not against num_irq.
11
5
12
Fix the checks by using GICV3_MAXIRQ (1020) instead of the number of
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
13
implemented IRQs.
7
Reviewed-by: Patrick Venture <venture@google.com>
14
8
Message-id: 20220411165842.3912945-2-wuhaotsh@google.com
15
Signed-off-by: Ricardo Koller <ricarkol@google.com>
16
Message-id: 20210702233701.3369-1-ricarkol@google.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
11
---
20
hw/intc/arm_gicv3_cpuif.c | 4 ++--
12
include/hw/misc/npcm7xx_gcr.h | 30 ++++++++++++++++++++++++++++++
21
1 file changed, 2 insertions(+), 2 deletions(-)
13
1 file changed, 30 insertions(+)
22
14
23
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/intc/arm_gicv3_cpuif.c
17
--- a/include/hw/misc/npcm7xx_gcr.h
26
+++ b/hw/intc/arm_gicv3_cpuif.c
18
+++ b/include/hw/misc/npcm7xx_gcr.h
27
@@ -XXX,XX +XXX,XX @@ static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
19
@@ -XXX,XX +XXX,XX @@
28
20
#include "exec/memory.h"
29
trace_gicv3_icv_dir_write(gicv3_redist_affid(cs), value);
21
#include "hw/sysbus.h"
30
22
31
- if (irq >= cs->gic->num_irq) {
23
+/*
32
+ if (irq >= GICV3_MAXIRQ) {
24
+ * NPCM7XX PWRON STRAP bit fields
33
/* Also catches special interrupt numbers and LPIs */
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
34
return;
26
+ * 11: System flash attached to BMC
35
}
27
+ * 10: BSP alternative pins.
36
@@ -XXX,XX +XXX,XX @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
28
+ * 9:8: Flash UART command route enabled.
37
trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
29
+ * 7: Security enabled.
38
gicv3_redist_affid(cs), value);
30
+ * 6: HI-Z state control.
39
31
+ * 5: ECC disabled.
40
- if (irq >= cs->gic->num_irq) {
32
+ * 4: Reserved
41
+ if (irq >= GICV3_MAXIRQ) {
33
+ * 3: JTAG2 enabled.
42
/* Also catches special interrupt numbers and LPIs */
34
+ * 2:0: CPU and DRAM clock frequency.
43
return;
35
+ */
44
}
36
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
37
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
38
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
39
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
40
+#define FUP_NORM_UART2 3
41
+#define FUP_PROG_UART3 2
42
+#define FUP_PROG_UART2 1
43
+#define FUP_NORM_UART3 0
44
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
45
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
46
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
47
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
48
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
49
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
50
+#define CKFRQ_SKIPINIT 0x000
51
+#define CKFRQ_DEFAULT 0x111
52
+
53
/*
54
* Number of registers in our device state structure. Don't change this without
55
* incrementing the version_id in the vmstate.
45
--
56
--
46
2.20.1
57
2.25.1
47
48
diff view generated by jsdifflib
1
From: "hnick@vmware.com" <hnick@vmware.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Signed-off-by: Nick Hudson <hnick@vmware.com>
3
This patch uses the defined fields to describe PWRON STRAPs for
4
better readability.
5
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Message-id: 20220411165842.3912945-3-wuhaotsh@google.com
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
11
---
7
target/arm/helper.c | 16 +++++++++++++---
12
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
8
1 file changed, 13 insertions(+), 3 deletions(-)
13
1 file changed, 19 insertions(+), 5 deletions(-)
9
14
10
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
11
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/helper.c
17
--- a/hw/arm/npcm7xx_boards.c
13
+++ b/target/arm/helper.c
18
+++ b/hw/arm/npcm7xx_boards.c
14
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
19
@@ -XXX,XX +XXX,XX @@
15
.access = PL1_RW, .accessfn = access_tda,
20
#include "sysemu/sysemu.h"
16
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),
21
#include "sysemu/block-backend.h"
17
.resetvalue = 0 },
22
18
- /* MDCCSR_EL0, aka DBGDSCRint. This is a read-only mirror of MDSCR_EL1.
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
19
+ /*
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
20
+ * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
21
+ * Debug Communication Channel is not implemented.
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
22
+ */
27
-#define MORI_BMC_POWER_ON_STRAPS 0x00001fff
23
+ { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64,
28
+#define NPCM7XX_POWER_ON_STRAPS_DEFAULT ( \
24
+ .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,
29
+ NPCM7XX_PWRON_STRAP_SPI0F18 | \
25
+ .access = PL0_R, .accessfn = access_tda,
30
+ NPCM7XX_PWRON_STRAP_SFAB | \
26
+ .type = ARM_CP_CONST, .resetvalue = 0 },
31
+ NPCM7XX_PWRON_STRAP_BSPA | \
27
+ /*
32
+ NPCM7XX_PWRON_STRAP_FUP(FUP_NORM_UART2) | \
28
+ * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as
33
+ NPCM7XX_PWRON_STRAP_SECEN | \
29
+ * it is unlikely a guest will care.
34
+ NPCM7XX_PWRON_STRAP_HIZ | \
30
* We don't implement the configurable EL0 access.
35
+ NPCM7XX_PWRON_STRAP_ECC | \
31
*/
36
+ NPCM7XX_PWRON_STRAP_RESERVE1 | \
32
- { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_BOTH,
37
+ NPCM7XX_PWRON_STRAP_J2EN | \
33
- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
38
+ NPCM7XX_PWRON_STRAP_CKFRQ(CKFRQ_DEFAULT))
34
+ { .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32,
39
+
35
+ .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
40
+#define NPCM750_EVB_POWER_ON_STRAPS ( \
36
.type = ARM_CP_ALIAS,
41
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_J2EN)
37
.access = PL1_R, .accessfn = access_tda,
42
+#define QUANTA_GSJ_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
38
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
43
+#define QUANTA_GBS_POWER_ON_STRAPS ( \
44
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_SFAB)
45
+#define KUDO_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
46
+#define MORI_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
47
48
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
49
39
--
50
--
40
2.20.1
51
2.25.1
41
42
diff view generated by jsdifflib